* 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:
Nick Clifton 2011-04-26 15:28:08 +00:00
parent 4964e065b4
commit 72b016b4ac
14 changed files with 522 additions and 123 deletions

View File

@ -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.

View File

@ -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 */

View File

@ -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.

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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)} :

View File

@ -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)} :

View File

@ -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
View 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

View 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
View 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
View 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

View File

@ -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"}