* dw2gencfi.c (dwcfi_seg_list): New struct.
(dwcfi_hash): New static hash variable. (get_debugseg_name): New. (alloc_debugseg_item): New. (make_debug_seg): New. (dwcfi_hash_insert): New. (dwcfi_hash_find): New. (dwcfi_hash_find_or_make): New. (cfi_insn_data): New member cur_seg. (cie_entry): Likewise. (fde_entry): New cseg and handled members. (alloc_fde_entry): Initialize cseg member. (alloc_cfi_insn_data): Initialize cur_seg member. (dot_cfi_sections): Compare for beginning of section names via strncmp. (get_cfi_seg): New. (cfi_finish): Treat link-once sections. (is_now_linkonce_segment): New local helper. (output_cie): Ignore cie entries not member of current segment. (output_fde): Likewise. (select_cie_for_fde): Likewise. (cfi_change_reg_numbers): Add new argument for current segment and ignore insn elements, if not part of current segment. * ehopt.c (get_cie_info): Use strncmp for section name matching. (heck_eh_frame): Likewise. * coffcode.h (sec_to_styp_flags): Allow linkonce for debugging sections. * scripttempl/pe.sc: Handle .eh_frame($|.)* sections. * scripttempl/pep.sc: Likewise. * ld-pe/pe.exp: Add cfi/cfi32 tests. * ld-pe/cfi.d: New. * ld-pe/cfi32.d: New. * ld-pe/cfia.s: New. * ld-pe/cfib.s: New.
This commit is contained in:
parent
4964e065b4
commit
72b016b4ac
@ -1,3 +1,8 @@
|
||||
2011-04-26 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
* coffcode.h (sec_to_styp_flags): Allow linkonce for
|
||||
debugging sections.
|
||||
|
||||
2011-04-26 Tristan Gingold <gingold@adacore.com>
|
||||
|
||||
* coff64-rs6000.c: Convert to ISO-C. Remove PARAMS and PTR macros.
|
||||
|
@ -658,7 +658,10 @@ sec_to_styp_flags (const char *sec_name, flagword sec_flags)
|
||||
|
||||
/* FIXME: There is no gas syntax to specify the debug section flag. */
|
||||
if (is_dbg)
|
||||
sec_flags = SEC_DEBUGGING | SEC_READONLY;
|
||||
{
|
||||
sec_flags &= (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
|
||||
sec_flags |= SEC_DEBUGGING | SEC_READONLY;
|
||||
}
|
||||
|
||||
/* skip LOAD */
|
||||
/* READONLY later */
|
||||
|
@ -1,3 +1,33 @@
|
||||
2011-04-26 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
* dw2gencfi.c (dwcfi_seg_list): New struct.
|
||||
(dwcfi_hash): New static hash variable.
|
||||
(get_debugseg_name): New.
|
||||
(alloc_debugseg_item): New.
|
||||
(make_debug_seg): New.
|
||||
(dwcfi_hash_insert): New.
|
||||
(dwcfi_hash_find): New.
|
||||
(dwcfi_hash_find_or_make): New.
|
||||
(cfi_insn_data): New member cur_seg.
|
||||
(cie_entry): Likewise.
|
||||
(fde_entry): New cseg and handled members.
|
||||
(alloc_fde_entry): Initialize cseg member.
|
||||
(alloc_cfi_insn_data): Initialize cur_seg member.
|
||||
(dot_cfi_sections): Compare for beginning of
|
||||
section names via strncmp.
|
||||
(get_cfi_seg): New.
|
||||
(cfi_finish): Treat link-once sections.
|
||||
(is_now_linkonce_segment): New local helper.
|
||||
(output_cie): Ignore cie entries not member of current
|
||||
segment.
|
||||
(output_fde): Likewise.
|
||||
(select_cie_for_fde): Likewise.
|
||||
(cfi_change_reg_numbers): Add new argument for current segment
|
||||
and ignore insn elements, if not part of current segment.
|
||||
* ehopt.c (get_cie_info): Use strncmp for
|
||||
section name matching.
|
||||
(heck_eh_frame): Likewise.
|
||||
|
||||
2011-04-20 Catherine Moore <clm@codesourcery.com>
|
||||
David Ung <davidu@mips.com>
|
||||
|
||||
@ -11,7 +41,7 @@
|
||||
(nops_for_24k): New.
|
||||
(nops_for_insn): Call nops_for_24k.
|
||||
(append_insn): Move O_constant expression handling.
|
||||
|
||||
|
||||
2011-04-20 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* hash.c (set_gas_hash_table_size): Use bfd_hash_set_default_size.
|
||||
|
463
gas/dw2gencfi.c
463
gas/dw2gencfi.c
@ -1,5 +1,5 @@
|
||||
/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
|
||||
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Michal Ludvig <mludvig@suse.cz>
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef CFI_DIFF_LSDA_OK
|
||||
# define CFI_DIFF_LSDA_OK CFI_DIFF_EXPR_OK
|
||||
#define CFI_DIFF_LSDA_OK CFI_DIFF_EXPR_OK
|
||||
#endif
|
||||
|
||||
#if CFI_DIFF_EXPR_OK == 1 && CFI_DIFF_LSDA_OK == 0
|
||||
@ -46,36 +46,188 @@
|
||||
|
||||
/* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
|
||||
of the CIE. Default to 1 if not otherwise specified. */
|
||||
#ifndef DWARF2_LINE_MIN_INSN_LENGTH
|
||||
# define DWARF2_LINE_MIN_INSN_LENGTH 1
|
||||
#ifndef DWARF2_LINE_MIN_INSN_LENGTH
|
||||
#define DWARF2_LINE_MIN_INSN_LENGTH 1
|
||||
#endif
|
||||
|
||||
/* By default, use 32-bit relocations from .eh_frame into .text. */
|
||||
#ifndef DWARF2_FDE_RELOC_SIZE
|
||||
# define DWARF2_FDE_RELOC_SIZE 4
|
||||
#define DWARF2_FDE_RELOC_SIZE 4
|
||||
#endif
|
||||
|
||||
/* By default, use a read-only .eh_frame section. */
|
||||
#ifndef DWARF2_EH_FRAME_READ_ONLY
|
||||
# define DWARF2_EH_FRAME_READ_ONLY SEC_READONLY
|
||||
#define DWARF2_EH_FRAME_READ_ONLY SEC_READONLY
|
||||
#endif
|
||||
|
||||
#ifndef EH_FRAME_ALIGNMENT
|
||||
# define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
|
||||
#define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
|
||||
#endif
|
||||
|
||||
#ifndef tc_cfi_frame_initial_instructions
|
||||
# define tc_cfi_frame_initial_instructions() ((void)0)
|
||||
#define tc_cfi_frame_initial_instructions() ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef DWARF2_FORMAT
|
||||
# define DWARF2_FORMAT(SEC) dwarf2_format_32bit
|
||||
#define DWARF2_FORMAT(SEC) dwarf2_format_32bit
|
||||
#endif
|
||||
|
||||
#ifndef DWARF2_ADDR_SIZE
|
||||
# define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
|
||||
#define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
|
||||
#endif
|
||||
|
||||
/* Private segment collection list. */
|
||||
struct dwcfi_seg_list
|
||||
{
|
||||
segT seg;
|
||||
int subseg;
|
||||
char * seg_name;
|
||||
};
|
||||
|
||||
#define FRAME_NAME ".eh_frame"
|
||||
|
||||
static struct hash_control *dwcfi_hash;
|
||||
|
||||
/* Build based on segment the derived .debug_...
|
||||
segment name containing origin segment's postfix name part. */
|
||||
|
||||
static char *
|
||||
get_debugseg_name (segT seg, const char *base_name)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (!seg)
|
||||
name = "";
|
||||
else
|
||||
{
|
||||
const char * dollar;
|
||||
const char * dot;
|
||||
|
||||
name = bfd_get_section_name (stdoutput, seg);
|
||||
|
||||
dollar = strchr (name, '$');
|
||||
dot = strchr (name + 1, '.');
|
||||
|
||||
if (!dollar && !dot)
|
||||
name = "";
|
||||
else if (!dollar)
|
||||
name = dot;
|
||||
else if (!dot)
|
||||
name = dollar;
|
||||
else if (dot < dollar)
|
||||
name = dot;
|
||||
else
|
||||
name = dollar;
|
||||
}
|
||||
|
||||
return concat (base_name, name, NULL);
|
||||
}
|
||||
|
||||
/* Allocate a dwcfi_seg_list structure. */
|
||||
|
||||
static struct dwcfi_seg_list *
|
||||
alloc_debugseg_item (segT seg, int subseg, char *name)
|
||||
{
|
||||
struct dwcfi_seg_list *r;
|
||||
|
||||
r = (struct dwcfi_seg_list *)
|
||||
xmalloc (sizeof (struct dwcfi_seg_list) + strlen (name));
|
||||
r->seg = seg;
|
||||
r->subseg = subseg;
|
||||
r->seg_name = name;
|
||||
return r;
|
||||
}
|
||||
|
||||
static segT
|
||||
is_now_linkonce_segment (void)
|
||||
{
|
||||
#if defined (TE_PE) || defined (TE_PEP)
|
||||
if ((bfd_get_section_flags (stdoutput, now_seg)
|
||||
& (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
|
||||
| SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
|
||||
| SEC_LINK_DUPLICATES_SAME_CONTENTS)) != 0)
|
||||
return now_seg;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generate debug... segment with same linkonce properties
|
||||
of based segment. */
|
||||
|
||||
static segT
|
||||
make_debug_seg (segT cseg, char *name, int sflags)
|
||||
{
|
||||
segT save_seg = now_seg;
|
||||
int save_subseg = now_subseg;
|
||||
segT r;
|
||||
flagword flags;
|
||||
|
||||
r = subseg_new (name, 0);
|
||||
|
||||
/* Check if code segment is marked as linked once. */
|
||||
if (!cseg)
|
||||
flags = 0;
|
||||
else
|
||||
flags = bfd_get_section_flags (stdoutput, cseg)
|
||||
& (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
|
||||
| SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
|
||||
| SEC_LINK_DUPLICATES_SAME_CONTENTS);
|
||||
|
||||
/* Add standard section flags. */
|
||||
flags |= sflags;
|
||||
|
||||
/* Apply possibly linked once flags to new generated segment, too. */
|
||||
if (!bfd_set_section_flags (stdoutput, r, flags))
|
||||
as_bad (_("bfd_set_section_flags: %s"),
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
|
||||
/* Restore to previous segment. */
|
||||
if (save_seg != NULL)
|
||||
subseg_set (save_seg, save_subseg);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
dwcfi_hash_insert (const char *name, struct dwcfi_seg_list *item)
|
||||
{
|
||||
const char *error_string;
|
||||
|
||||
if ((error_string = hash_jam (dwcfi_hash, name, (char *) item)))
|
||||
as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
|
||||
name, error_string);
|
||||
}
|
||||
|
||||
static struct dwcfi_seg_list *
|
||||
dwcfi_hash_find (char *name)
|
||||
{
|
||||
return (struct dwcfi_seg_list *) hash_find (dwcfi_hash, name);
|
||||
}
|
||||
|
||||
static struct dwcfi_seg_list *
|
||||
dwcfi_hash_find_or_make (segT cseg, const char *base_name, int flags)
|
||||
{
|
||||
struct dwcfi_seg_list *item;
|
||||
char *name;
|
||||
|
||||
/* Initialize dwcfi_hash once. */
|
||||
if (!dwcfi_hash)
|
||||
dwcfi_hash = hash_new ();
|
||||
|
||||
name = get_debugseg_name (cseg, base_name);
|
||||
|
||||
item = dwcfi_hash_find (name);
|
||||
if (!item)
|
||||
{
|
||||
item = alloc_debugseg_item (make_debug_seg (cseg, name, flags), 0, name);
|
||||
|
||||
dwcfi_hash_insert (item->seg_name, item);
|
||||
}
|
||||
else
|
||||
free (name);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/* ??? Share this with dwarf2cfg.c. */
|
||||
#ifndef TC_DWARF2_EMIT_OFFSET
|
||||
#define TC_DWARF2_EMIT_OFFSET generic_dwarf2_emit_offset
|
||||
@ -94,7 +246,8 @@ generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct cfi_escape_data {
|
||||
struct cfi_escape_data
|
||||
{
|
||||
struct cfi_escape_data *next;
|
||||
expressionS exp;
|
||||
};
|
||||
@ -102,14 +255,18 @@ struct cfi_escape_data {
|
||||
struct cfi_insn_data
|
||||
{
|
||||
struct cfi_insn_data *next;
|
||||
segT cur_seg;
|
||||
int insn;
|
||||
union {
|
||||
struct {
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned reg;
|
||||
offsetT offset;
|
||||
} ri;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
unsigned reg1;
|
||||
unsigned reg2;
|
||||
} rr;
|
||||
@ -117,14 +274,16 @@ struct cfi_insn_data
|
||||
unsigned r;
|
||||
offsetT i;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
symbolS *lab1;
|
||||
symbolS *lab2;
|
||||
} ll;
|
||||
|
||||
struct cfi_escape_data *esc;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
unsigned reg, encoding;
|
||||
expressionS exp;
|
||||
} ea;
|
||||
@ -134,6 +293,7 @@ struct cfi_insn_data
|
||||
struct fde_entry
|
||||
{
|
||||
struct fde_entry *next;
|
||||
segT cseg;
|
||||
symbolS *start_address;
|
||||
symbolS *end_address;
|
||||
struct cfi_insn_data *data;
|
||||
@ -144,11 +304,13 @@ struct fde_entry
|
||||
expressionS lsda;
|
||||
unsigned int return_column;
|
||||
unsigned int signal_frame;
|
||||
int handled;
|
||||
};
|
||||
|
||||
struct cie_entry
|
||||
{
|
||||
struct cie_entry *next;
|
||||
segT cur_seg;
|
||||
symbolS *start_address;
|
||||
unsigned int return_column;
|
||||
unsigned int signal_frame;
|
||||
@ -158,8 +320,8 @@ struct cie_entry
|
||||
struct cfi_insn_data *first, *last;
|
||||
};
|
||||
|
||||
|
||||
/* List of FDE entries. */
|
||||
|
||||
static struct fde_entry *all_fde_data;
|
||||
static struct fde_entry **last_fde_data = &all_fde_data;
|
||||
|
||||
@ -195,7 +357,8 @@ alloc_fde_entry (void)
|
||||
frchain_now->frch_cfi_data->cur_fde_data = fde;
|
||||
*last_fde_data = fde;
|
||||
last_fde_data = &fde->next;
|
||||
|
||||
fde->cseg = is_now_linkonce_segment ();
|
||||
fde->handled = 0;
|
||||
fde->last = &fde->data;
|
||||
fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
|
||||
fde->per_encoding = DW_EH_PE_omit;
|
||||
@ -219,13 +382,14 @@ alloc_cfi_insn_data (void)
|
||||
|
||||
*cur_fde_data->last = insn;
|
||||
cur_fde_data->last = &insn->next;
|
||||
insn->cur_seg = is_now_linkonce_segment ();
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Construct a new FDE structure that begins at LABEL. */
|
||||
|
||||
void
|
||||
void
|
||||
cfi_new_fde (symbolS *label)
|
||||
{
|
||||
struct fde_entry *fde = alloc_fde_entry ();
|
||||
@ -235,7 +399,7 @@ cfi_new_fde (symbolS *label)
|
||||
|
||||
/* End the currently open FDE. */
|
||||
|
||||
void
|
||||
void
|
||||
cfi_end_fde (symbolS *label)
|
||||
{
|
||||
frchain_now->frch_cfi_data->cur_fde_data->end_address = label;
|
||||
@ -254,7 +418,7 @@ cfi_set_return_column (unsigned regno)
|
||||
/* Universal functions to store new instructions. */
|
||||
|
||||
static void
|
||||
cfi_add_CFA_insn(int insn)
|
||||
cfi_add_CFA_insn (int insn)
|
||||
{
|
||||
struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
|
||||
|
||||
@ -471,7 +635,7 @@ cfi_parse_separator (void)
|
||||
|
||||
#ifndef tc_parse_to_dw2regnum
|
||||
static void
|
||||
tc_parse_to_dw2regnum(expressionS *exp)
|
||||
tc_parse_to_dw2regnum (expressionS *exp)
|
||||
{
|
||||
# ifdef tc_regname_to_dw2regnum
|
||||
SKIP_WHITESPACE ();
|
||||
@ -853,7 +1017,7 @@ dot_cfi_val_encoded_addr (int ignored ATTRIBUTE_UNUSED)
|
||||
|
||||
insn_ptr = alloc_cfi_insn_data ();
|
||||
insn_ptr->insn = CFI_val_encoded_addr;
|
||||
|
||||
|
||||
insn_ptr->u.ea.reg = cfi_parse_reg ();
|
||||
|
||||
cfi_parse_separator ();
|
||||
@ -916,9 +1080,10 @@ dot_cfi_sections (int ignored ATTRIBUTE_UNUSED)
|
||||
name = input_line_pointer;
|
||||
c = get_symbol_end ();
|
||||
|
||||
if (strcmp (name, ".eh_frame") == 0)
|
||||
if (strncmp (name, ".eh_frame", sizeof ".eh_frame") == 0
|
||||
&& name[9] != '_')
|
||||
sections |= CFI_EMIT_eh_frame;
|
||||
else if (strcmp (name, ".debug_frame") == 0)
|
||||
else if (strncmp (name, ".debug_frame", sizeof ".debug_frame") == 0)
|
||||
sections |= CFI_EMIT_debug_frame;
|
||||
else
|
||||
{
|
||||
@ -1250,7 +1415,7 @@ output_cfi_insn (struct cfi_insn_data *insn)
|
||||
emit_expr (&insn->u.ea.exp, encoding_size);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@ -1384,8 +1549,14 @@ output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align)
|
||||
out_one (enc);
|
||||
|
||||
if (cie->first)
|
||||
for (i = cie->first; i != cie->last; i = i->next)
|
||||
output_cfi_insn (i);
|
||||
{
|
||||
for (i = cie->first; i != cie->last; i = i->next)
|
||||
{
|
||||
if (i->cur_seg != cie->cur_seg)
|
||||
continue;
|
||||
output_cfi_insn (i);
|
||||
}
|
||||
}
|
||||
|
||||
frag_align (align, DW_CFA_nop, 0);
|
||||
symbol_set_value_now (end_address);
|
||||
@ -1492,7 +1663,10 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
|
||||
}
|
||||
|
||||
for (; first; first = first->next)
|
||||
output_cfi_insn (first);
|
||||
{
|
||||
if (first->cur_seg == fde->cseg)
|
||||
output_cfi_insn (first);
|
||||
}
|
||||
|
||||
frag_align (align, DW_CFA_nop, 0);
|
||||
symbol_set_value_now (end_address);
|
||||
@ -1507,7 +1681,8 @@ select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame,
|
||||
|
||||
for (cie = cie_root; cie; cie = cie->next)
|
||||
{
|
||||
if (cie->return_column != fde->return_column
|
||||
if (cie->cur_seg != fde->cseg
|
||||
|| cie->return_column != fde->return_column
|
||||
|| cie->signal_frame != fde->signal_frame
|
||||
|| cie->per_encoding != fde->per_encoding
|
||||
|| cie->lsda_encoding != fde->lsda_encoding)
|
||||
@ -1605,6 +1780,7 @@ select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame,
|
||||
cie = (struct cie_entry *) xmalloc (sizeof (struct cie_entry));
|
||||
cie->next = cie_root;
|
||||
cie_root = cie;
|
||||
cie->cur_seg = fde->cseg;
|
||||
cie->return_column = fde->return_column;
|
||||
cie->signal_frame = fde->signal_frame;
|
||||
cie->per_encoding = fde->per_encoding;
|
||||
@ -1629,130 +1805,189 @@ select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame,
|
||||
|
||||
#ifdef md_reg_eh_frame_to_debug_frame
|
||||
static void
|
||||
cfi_change_reg_numbers (struct cfi_insn_data *insn)
|
||||
cfi_change_reg_numbers (struct cfi_insn_data *insn, segT ccseg)
|
||||
{
|
||||
for (; insn; insn = insn->next)
|
||||
switch (insn->insn)
|
||||
{
|
||||
case DW_CFA_advance_loc:
|
||||
case DW_CFA_def_cfa_offset:
|
||||
case DW_CFA_remember_state:
|
||||
case DW_CFA_restore_state:
|
||||
case DW_CFA_GNU_window_save:
|
||||
case CFI_escape:
|
||||
break;
|
||||
{
|
||||
if (insn->cur_seg != ccseg)
|
||||
continue;
|
||||
switch (insn->insn)
|
||||
{
|
||||
case DW_CFA_advance_loc:
|
||||
case DW_CFA_def_cfa_offset:
|
||||
case DW_CFA_remember_state:
|
||||
case DW_CFA_restore_state:
|
||||
case DW_CFA_GNU_window_save:
|
||||
case CFI_escape:
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa:
|
||||
case DW_CFA_offset:
|
||||
insn->u.ri.reg = md_reg_eh_frame_to_debug_frame (insn->u.ri.reg);
|
||||
break;
|
||||
case DW_CFA_def_cfa:
|
||||
case DW_CFA_offset:
|
||||
insn->u.ri.reg = md_reg_eh_frame_to_debug_frame (insn->u.ri.reg);
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa_register:
|
||||
case DW_CFA_undefined:
|
||||
case DW_CFA_same_value:
|
||||
case DW_CFA_restore:
|
||||
insn->u.r = md_reg_eh_frame_to_debug_frame (insn->u.r);
|
||||
break;
|
||||
case DW_CFA_def_cfa_register:
|
||||
case DW_CFA_undefined:
|
||||
case DW_CFA_same_value:
|
||||
case DW_CFA_restore:
|
||||
insn->u.r = md_reg_eh_frame_to_debug_frame (insn->u.r);
|
||||
break;
|
||||
|
||||
case DW_CFA_register:
|
||||
insn->u.rr.reg1 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg1);
|
||||
insn->u.rr.reg2 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg2);
|
||||
break;
|
||||
case DW_CFA_register:
|
||||
insn->u.rr.reg1 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg1);
|
||||
insn->u.rr.reg2 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg2);
|
||||
break;
|
||||
|
||||
case CFI_val_encoded_addr:
|
||||
insn->u.ea.reg = md_reg_eh_frame_to_debug_frame (insn->u.ea.reg);
|
||||
break;
|
||||
case CFI_val_encoded_addr:
|
||||
insn->u.ea.reg = md_reg_eh_frame_to_debug_frame (insn->u.ea.reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define cfi_change_reg_numbers(insn) do { } while (0)
|
||||
#define cfi_change_reg_numbers(insn, cseg) do { } while (0)
|
||||
#endif
|
||||
|
||||
static segT
|
||||
get_cfi_seg (segT cseg, const char *base, flagword flags, int align)
|
||||
{
|
||||
struct dwcfi_seg_list *l;
|
||||
|
||||
l = dwcfi_hash_find_or_make (cseg, base, flags);
|
||||
|
||||
subseg_set (l->seg, l->subseg);
|
||||
record_alignment (l->seg, align);
|
||||
return l->seg;
|
||||
}
|
||||
|
||||
void
|
||||
cfi_finish (void)
|
||||
{
|
||||
segT cfi_seg;
|
||||
struct cie_entry *cie, *cie_next;
|
||||
segT cfi_seg, ccseg;
|
||||
struct fde_entry *fde;
|
||||
int save_flag_traditional_format;
|
||||
struct cfi_insn_data *first;
|
||||
int save_flag_traditional_format, seek_next_seg;
|
||||
|
||||
if (all_fde_data == 0)
|
||||
return;
|
||||
|
||||
if ((cfi_sections & CFI_EMIT_eh_frame) != 0)
|
||||
{
|
||||
/* Open .eh_frame section. */
|
||||
cfi_seg = subseg_new (".eh_frame", 0);
|
||||
bfd_set_section_flags (stdoutput, cfi_seg,
|
||||
SEC_ALLOC | SEC_LOAD | SEC_DATA
|
||||
| DWARF2_EH_FRAME_READ_ONLY);
|
||||
subseg_set (cfi_seg, 0);
|
||||
record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
|
||||
|
||||
#ifdef md_fix_up_eh_frame
|
||||
md_fix_up_eh_frame (cfi_seg);
|
||||
#endif
|
||||
|
||||
/* Make sure check_eh_frame doesn't do anything with our output. */
|
||||
save_flag_traditional_format = flag_traditional_format;
|
||||
flag_traditional_format = 1;
|
||||
|
||||
for (fde = all_fde_data; fde ; fde = fde->next)
|
||||
{
|
||||
struct cfi_insn_data *first;
|
||||
struct cie_entry *cie;
|
||||
|
||||
if (fde->end_address == NULL)
|
||||
do
|
||||
{
|
||||
ccseg = NULL;
|
||||
cfi_seg = NULL;
|
||||
seek_next_seg = 0;
|
||||
for (cie = cie_root; cie; cie = cie_next)
|
||||
{
|
||||
as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
|
||||
fde->end_address = fde->start_address;
|
||||
cie_next = cie->next;
|
||||
free ((void *) cie);
|
||||
}
|
||||
cie_root = NULL;
|
||||
|
||||
cie = select_cie_for_fde (fde, TRUE, &first, 2);
|
||||
output_fde (fde, cie, TRUE, first,
|
||||
fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
|
||||
for (fde = all_fde_data; fde ; fde = fde->next)
|
||||
{
|
||||
if (fde->handled != 0)
|
||||
continue;
|
||||
if (seek_next_seg && fde->cseg != ccseg)
|
||||
{
|
||||
seek_next_seg = 2;
|
||||
continue;
|
||||
}
|
||||
if (!seek_next_seg)
|
||||
{
|
||||
ccseg = fde->cseg;
|
||||
/* Open .eh_frame section. */
|
||||
cfi_seg = get_cfi_seg (ccseg, ".eh_frame",
|
||||
SEC_ALLOC | SEC_LOAD | SEC_DATA
|
||||
| DWARF2_EH_FRAME_READ_ONLY,
|
||||
EH_FRAME_ALIGNMENT);
|
||||
#ifdef md_fix_up_eh_frame
|
||||
md_fix_up_eh_frame (cfi_seg);
|
||||
#endif
|
||||
seek_next_seg = 1;
|
||||
}
|
||||
fde->handled = 1;
|
||||
|
||||
if (fde->end_address == NULL)
|
||||
{
|
||||
as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
|
||||
fde->end_address = fde->start_address;
|
||||
}
|
||||
|
||||
cie = select_cie_for_fde (fde, TRUE, &first, 2);
|
||||
output_fde (fde, cie, TRUE, first,
|
||||
fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
|
||||
}
|
||||
}
|
||||
while (seek_next_seg == 2);
|
||||
|
||||
for (fde = all_fde_data; fde ; fde = fde->next)
|
||||
fde->handled = 0;
|
||||
|
||||
flag_traditional_format = save_flag_traditional_format;
|
||||
}
|
||||
|
||||
if ((cfi_sections & CFI_EMIT_debug_frame) != 0)
|
||||
{
|
||||
struct cie_entry *cie, *cie_next;
|
||||
int alignment = ffs (DWARF2_ADDR_SIZE (stdoutput)) - 1;
|
||||
|
||||
for (cie = cie_root; cie; cie = cie_next)
|
||||
{
|
||||
cie_next = cie->next;
|
||||
free ((void *) cie);
|
||||
}
|
||||
cie_root = NULL;
|
||||
do
|
||||
{
|
||||
ccseg = NULL;
|
||||
cfi_seg = NULL;
|
||||
seek_next_seg = 0;
|
||||
for (cie = cie_root; cie; cie = cie_next)
|
||||
{
|
||||
cie_next = cie->next;
|
||||
free ((void *) cie);
|
||||
}
|
||||
cie_root = NULL;
|
||||
|
||||
/* Open .debug_frame section. */
|
||||
cfi_seg = subseg_new (".debug_frame", 0);
|
||||
bfd_set_section_flags (stdoutput, cfi_seg,
|
||||
SEC_READONLY | SEC_DEBUGGING);
|
||||
subseg_set (cfi_seg, 0);
|
||||
record_alignment (cfi_seg, alignment);
|
||||
for (fde = all_fde_data; fde ; fde = fde->next)
|
||||
{
|
||||
if (fde->handled != 0)
|
||||
continue;
|
||||
if (seek_next_seg && fde->cseg != ccseg)
|
||||
{
|
||||
seek_next_seg = 2;
|
||||
continue;
|
||||
}
|
||||
if (!seek_next_seg)
|
||||
{
|
||||
ccseg = fde->cseg;
|
||||
/* Open .debug_frame section. */
|
||||
cfi_seg = get_cfi_seg (ccseg, ".debug_frame",
|
||||
SEC_READONLY | SEC_DEBUGGING,
|
||||
alignment);
|
||||
seek_next_seg = 1;
|
||||
}
|
||||
fde->handled = 1;
|
||||
if (fde->end_address == NULL)
|
||||
{
|
||||
as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
|
||||
fde->end_address = fde->start_address;
|
||||
}
|
||||
|
||||
fde->per_encoding = DW_EH_PE_omit;
|
||||
fde->lsda_encoding = DW_EH_PE_omit;
|
||||
cfi_change_reg_numbers (fde->data, ccseg);
|
||||
cie = select_cie_for_fde (fde, FALSE, &first, alignment);
|
||||
output_fde (fde, cie, FALSE, first, alignment);
|
||||
}
|
||||
}
|
||||
while (seek_next_seg == 2);
|
||||
|
||||
for (fde = all_fde_data; fde ; fde = fde->next)
|
||||
{
|
||||
struct cfi_insn_data *first;
|
||||
|
||||
if (fde->end_address == NULL)
|
||||
{
|
||||
as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
|
||||
fde->end_address = fde->start_address;
|
||||
}
|
||||
|
||||
fde->per_encoding = DW_EH_PE_omit;
|
||||
fde->lsda_encoding = DW_EH_PE_omit;
|
||||
cfi_change_reg_numbers (fde->data);
|
||||
cie = select_cie_for_fde (fde, FALSE, &first, alignment);
|
||||
output_fde (fde, cie, FALSE, first, alignment);
|
||||
}
|
||||
fde->handled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ get_cie_info (struct cie_info *info)
|
||||
|
||||
/* First make sure that the CIE Identifier Tag is 0/-1. */
|
||||
|
||||
if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
|
||||
if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
|
||||
CIE_id = (char)0xff;
|
||||
else
|
||||
CIE_id = 0;
|
||||
@ -285,9 +285,10 @@ check_eh_frame (expressionS *exp, unsigned int *pnbytes)
|
||||
#endif
|
||||
|
||||
/* Select the proper section data. */
|
||||
if (strcmp (segment_name (now_seg), ".eh_frame") == 0)
|
||||
if (strncmp (segment_name (now_seg), ".eh_frame", 9) == 0
|
||||
&& segment_name (now_seg)[9] != '_')
|
||||
d = &eh_frame_data;
|
||||
else if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
|
||||
else if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
|
||||
d = &debug_frame_data;
|
||||
else
|
||||
return 0;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2011-04-26 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
* scripttempl/pe.sc: Handle .eh_frame($|.)* sections.
|
||||
* scripttempl/pep.sc: Likewise.
|
||||
|
||||
2011-04-24 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/12365
|
||||
|
@ -115,7 +115,7 @@ SECTIONS
|
||||
|
||||
.eh_frame ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.eh_frame)
|
||||
*(.eh_frame*)
|
||||
}
|
||||
|
||||
.pdata ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
@ -250,7 +250,7 @@ SECTIONS
|
||||
|
||||
.debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
|
||||
{
|
||||
*(.debug_frame)
|
||||
*(.debug_frame*)
|
||||
}
|
||||
|
||||
.debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
|
||||
|
@ -116,7 +116,7 @@ SECTIONS
|
||||
|
||||
.eh_frame ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
{
|
||||
*(.eh_frame)
|
||||
*(.eh_frame*)
|
||||
}
|
||||
|
||||
.pdata ${RELOCATING+BLOCK(__section_alignment__)} :
|
||||
@ -256,7 +256,7 @@ SECTIONS
|
||||
|
||||
.debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
|
||||
{
|
||||
*(.debug_frame)
|
||||
*(.debug_frame*)
|
||||
}
|
||||
|
||||
.debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
|
||||
|
@ -1,3 +1,11 @@
|
||||
2011-04-26 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
* ld-pe/pe.exp: Add cfi/cfi32 tests.
|
||||
* ld-pe/cfi.d: New.
|
||||
* ld-pe/cfi32.d: New.
|
||||
* ld-pe/cfia.s: New.
|
||||
* ld-pe/cfib.s: New.
|
||||
|
||||
2011-04-21 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/12694
|
||||
|
36
ld/testsuite/ld-pe/cfi.d
Normal file
36
ld/testsuite/ld-pe/cfi.d
Normal file
@ -0,0 +1,36 @@
|
||||
#source: cfia.s
|
||||
#source: cfib.s
|
||||
#ld: --file-align 1 --section-align 1
|
||||
#objdump: -Wf
|
||||
|
||||
#...
|
||||
00000004 00000014 ffffffff CIE
|
||||
Version: 1
|
||||
Augmentation: ""
|
||||
Code alignment factor: 1
|
||||
Data alignment factor: \-8
|
||||
Return address column: 32
|
||||
|
||||
DW_CFA_def_cfa: r7 \(rsp\) ofs 8
|
||||
DW_CFA_offset: r32 \(xmm15\) at cfa\-8
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
|
||||
0000001c 00000024 00000004 FDE cie=00000004 pc=.*
|
||||
DW_CFA_advance_loc: 4 to .*
|
||||
DW_CFA_def_cfa_offset: 16
|
||||
DW_CFA_offset: r6 \(rbp\) at cfa\-16
|
||||
DW_CFA_advance_loc: 4 to .*
|
||||
^ DW_CFA_def_cfa: r7 \(rsp\) ofs 8
|
||||
DW_CFA_restore: r6 \(rbp\)
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
#pass
|
28
ld/testsuite/ld-pe/cfi32.d
Normal file
28
ld/testsuite/ld-pe/cfi32.d
Normal file
@ -0,0 +1,28 @@
|
||||
#source: cfia.s
|
||||
#source: cfib.s
|
||||
#ld: --file-align 1 --section-align 1
|
||||
#objdump: -Wf
|
||||
|
||||
#...
|
||||
00000000 00000010 ffffffff CIE
|
||||
Version: 1
|
||||
Augmentation: ""
|
||||
Code alignment factor: 1
|
||||
Data alignment factor: \-4
|
||||
Return address column: 8
|
||||
|
||||
DW_CFA_def_cfa: r4 \(esp\) ofs 4
|
||||
DW_CFA_offset: r8 \(eip\) at cfa\-4
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
|
||||
00000014 00000018 00000000 FDE cie=00000000 pc=.*
|
||||
DW_CFA_advance_loc: 4 to .*
|
||||
DW_CFA_def_cfa_offset: 16
|
||||
DW_CFA_offset: r6 \(esi\) at cfa\-16
|
||||
DW_CFA_advance_loc: 4 to .*
|
||||
DW_CFA_def_cfa: r7 \(edi\) ofs 8
|
||||
DW_CFA_restore: r6 \(esi\)
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
#pass
|
26
ld/testsuite/ld-pe/cfia.s
Normal file
26
ld/testsuite/ld-pe/cfia.s
Normal file
@ -0,0 +1,26 @@
|
||||
.globl _mainCRTStartup
|
||||
.globl _start
|
||||
.text
|
||||
_mainCRTStartup:
|
||||
mainCRTStartup:
|
||||
_start:
|
||||
start:
|
||||
.long -1
|
||||
|
||||
.cfi_sections .debug_frame
|
||||
.section .text$abc,"x"
|
||||
.linkonce discard
|
||||
.align 2
|
||||
.globl _tst
|
||||
.def _tst; .scl 2; .type 32; .endef
|
||||
_tst:
|
||||
.cfi_startproc
|
||||
.long 0
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
.long 1
|
||||
.cfi_def_cfa 7, 8
|
||||
.cfi_restore 6
|
||||
.long 2
|
||||
.cfi_endproc
|
||||
|
16
ld/testsuite/ld-pe/cfib.s
Normal file
16
ld/testsuite/ld-pe/cfib.s
Normal file
@ -0,0 +1,16 @@
|
||||
.cfi_sections .debug_frame
|
||||
.section .text$abc,"x"
|
||||
.linkonce discard
|
||||
.align 2
|
||||
.globl _tst
|
||||
.def _tst; .scl 2; .type 32; .endef
|
||||
_tst:
|
||||
.cfi_startproc
|
||||
.long 0
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
.long 1
|
||||
.cfi_def_cfa 7, 8
|
||||
.cfi_restore 6
|
||||
.long 2
|
||||
.cfi_endproc
|
@ -77,6 +77,12 @@ run_dump_test "longsecn-5"
|
||||
run_dump_test "orphan"
|
||||
run_dump_test "orphan_nu"
|
||||
|
||||
if {[istarget x86_64-*-mingw*] } {
|
||||
run_dump_test "cfi"
|
||||
} elseif {[istarget i*86-*-cygwin*] || [istarget i*86-*-mingw*] } {
|
||||
run_dump_test "cfi32"
|
||||
}
|
||||
|
||||
set foreign_sym_test {
|
||||
{"non-C aligned common" "" "" {non-c-lang-syms.s}
|
||||
{{nm -C non-c-lang-syms.d}} "non-c-lang-syms.x"}
|
||||
|
Loading…
Reference in New Issue
Block a user