aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2011-04-26 15:28:08 +0000
committerNick Clifton <nickc@redhat.com>2011-04-26 15:28:08 +0000
commit72b016b4ac0d7532a8f173fe3472e2e88ac49d45 (patch)
treee6d8dcd1c9cabcafcfe1713f55b366a2cbeefbec /gas
parent2011-04-26 Tristan Gingold <gingold@adacore.com> (diff)
downloadbinutils-gdb-72b016b4ac0d7532a8f173fe3472e2e88ac49d45.tar.gz
binutils-gdb-72b016b4ac0d7532a8f173fe3472e2e88ac49d45.tar.bz2
binutils-gdb-72b016b4ac0d7532a8f173fe3472e2e88ac49d45.zip
* 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog32
-rw-r--r--gas/dw2gencfi.c461
-rw-r--r--gas/ehopt.c7
3 files changed, 383 insertions, 117 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9721288e967..beb3847b0a6 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 7a051e35c3b..8f6300d2a43 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 c09eb15b498..70e1a00f4e2 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;