aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/coffcode.h5
-rw-r--r--gas/ChangeLog32
-rw-r--r--gas/dw2gencfi.c461
-rw-r--r--gas/ehopt.c7
-rw-r--r--ld/ChangeLog5
-rw-r--r--ld/scripttempl/pe.sc4
-rw-r--r--ld/scripttempl/pep.sc4
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-pe/cfi.d36
-rw-r--r--ld/testsuite/ld-pe/cfi32.d28
-rw-r--r--ld/testsuite/ld-pe/cfia.s26
-rw-r--r--ld/testsuite/ld-pe/cfib.s16
-rw-r--r--ld/testsuite/ld-pe/pe.exp6
14 files changed, 521 insertions, 122 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7a4b5bd..93cdda0 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 9db86b5..b8b856e 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -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 */
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9721288..beb3847 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 7a051e3..8f6300d 100644
--- a/gas/dw2gencfi.c
+++ b/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;
-
- /* 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)
- {
- struct cfi_insn_data *first;
-
- 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;
- 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);
+ 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)
+ fde->handled = 0;
}
}
diff --git a/gas/ehopt.c b/gas/ehopt.c
index c09eb15..70e1a00 100644
--- a/gas/ehopt.c
+++ b/gas/ehopt.c
@@ -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;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b25a87f..dfbb582 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc
index 7d52cc5..a82d08c 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -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)} :
diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc
index 8fa5f05..b8315c5 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -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)} :
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 7a09d41..1fd011e 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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
diff --git a/ld/testsuite/ld-pe/cfi.d b/ld/testsuite/ld-pe/cfi.d
new file mode 100644
index 0000000..6c5042b
--- /dev/null
+++ b/ld/testsuite/ld-pe/cfi.d
@@ -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
diff --git a/ld/testsuite/ld-pe/cfi32.d b/ld/testsuite/ld-pe/cfi32.d
new file mode 100644
index 0000000..d13fb1a
--- /dev/null
+++ b/ld/testsuite/ld-pe/cfi32.d
@@ -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
diff --git a/ld/testsuite/ld-pe/cfia.s b/ld/testsuite/ld-pe/cfia.s
new file mode 100644
index 0000000..d1ea51d
--- /dev/null
+++ b/ld/testsuite/ld-pe/cfia.s
@@ -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
+
diff --git a/ld/testsuite/ld-pe/cfib.s b/ld/testsuite/ld-pe/cfib.s
new file mode 100644
index 0000000..9b761cf
--- /dev/null
+++ b/ld/testsuite/ld-pe/cfib.s
@@ -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
diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp
index 183c5c6..c72c3b1 100644
--- a/ld/testsuite/ld-pe/pe.exp
+++ b/ld/testsuite/ld-pe/pe.exp
@@ -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"}