X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2-frame.c;h=33d001c799109b47bea2f55ad782ad53ecc4dec8;hb=dde59185267c8f3df6c3aa19d132277f45143c79;hp=fb5b08b6cb4d393a4c5b185a7ce5c803afa6440a;hpb=5af949e350b923403600c1da34774b49a77c925c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index fb5b08b6cb..33d001c799 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -1,6 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -22,7 +22,7 @@ #include "defs.h" #include "dwarf2expr.h" -#include "elf/dwarf2.h" +#include "dwarf2.h" #include "frame.h" #include "frame-base.h" #include "frame-unwind.h" @@ -86,7 +86,14 @@ struct dwarf2_cie /* The version recorded in the CIE. */ unsigned char version; - struct dwarf2_cie *next; + /* The segment size. */ + unsigned char segment_size; +}; + +struct dwarf2_cie_table +{ + int num_entries; + struct dwarf2_cie **entries; }; /* Frame Description Entry (FDE). */ @@ -109,8 +116,12 @@ struct dwarf2_fde /* True if this FDE is read from a .eh_frame instead of a .debug_frame section. */ unsigned char eh_frame_p; +}; - struct dwarf2_fde *next; +struct dwarf2_fde_table +{ + int num_entries; + struct dwarf2_fde **entries; }; /* A minimal decoding of DWARF2 compilation units. We only decode @@ -123,9 +134,6 @@ struct comp_unit struct objfile *objfile; - /* Linked list of CIEs for this object. */ - struct dwarf2_cie *cie; - /* Pointer to the .debug_frame section loaded into memory. */ gdb_byte *dwarf_frame_buffer; @@ -304,6 +312,15 @@ no_get_frame_base (void *baton, gdb_byte **start, size_t *length) _("Support for DW_OP_fbreg is unimplemented")); } +/* Helper function for execute_stack_op. */ + +static CORE_ADDR +no_get_frame_cfa (void *baton) +{ + internal_error (__FILE__, __LINE__, + _("Support for DW_OP_call_frame_cfa is unimplemented")); +} + static CORE_ADDR no_get_tls_address (void *baton, CORE_ADDR offset) { @@ -343,28 +360,40 @@ register %s (#%d) at %s"), static CORE_ADDR execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size, - struct frame_info *this_frame, CORE_ADDR initial) + struct frame_info *this_frame, CORE_ADDR initial, + int initial_in_stack_memory) { struct dwarf_expr_context *ctx; CORE_ADDR result; + struct cleanup *old_chain; ctx = new_dwarf_expr_context (); + old_chain = make_cleanup_free_dwarf_expr_context (ctx); + ctx->gdbarch = get_frame_arch (this_frame); ctx->addr_size = addr_size; ctx->baton = this_frame; ctx->read_reg = read_reg; ctx->read_mem = read_mem; ctx->get_frame_base = no_get_frame_base; + ctx->get_frame_cfa = no_get_frame_cfa; ctx->get_tls_address = no_get_tls_address; - dwarf_expr_push (ctx, initial); + dwarf_expr_push (ctx, initial, initial_in_stack_memory); dwarf_expr_eval (ctx, exp, len); result = dwarf_expr_fetch (ctx, 0); - if (ctx->in_reg) + if (ctx->location == DWARF_VALUE_REGISTER) result = read_reg (this_frame, result); + else if (ctx->location != DWARF_VALUE_MEMORY) + { + /* This is actually invalid DWARF, but if we ever do run across + it somehow, we might as well support it. So, instead, report + it as unimplemented. */ + error (_("Not implemented: computing unwound register using explicit value operator")); + } - free_dwarf_expr_context (ctx); + do_cleanups (old_chain); return result; } @@ -379,6 +408,7 @@ execute_cfa_program (struct dwarf2_fde *fde, gdb_byte *insn_ptr, CORE_ADDR pc = get_frame_pc (this_frame); int bytes_read; struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); while (insn_ptr < insn_end && fs->pc <= pc) { @@ -418,17 +448,17 @@ execute_cfa_program (struct dwarf2_fde *fde, gdb_byte *insn_ptr, break; case DW_CFA_advance_loc1: - utmp = extract_unsigned_integer (insn_ptr, 1); + utmp = extract_unsigned_integer (insn_ptr, 1, byte_order); fs->pc += utmp * fs->code_align; insn_ptr++; break; case DW_CFA_advance_loc2: - utmp = extract_unsigned_integer (insn_ptr, 2); + utmp = extract_unsigned_integer (insn_ptr, 2, byte_order); fs->pc += utmp * fs->code_align; insn_ptr += 2; break; case DW_CFA_advance_loc4: - utmp = extract_unsigned_integer (insn_ptr, 4); + utmp = extract_unsigned_integer (insn_ptr, 4, byte_order); fs->pc += utmp * fs->code_align; insn_ptr += 4; break; @@ -812,43 +842,33 @@ static void dwarf2_frame_find_quirks (struct dwarf2_frame_state *fs, struct dwarf2_fde *fde) { - static const char *arm_idents[] = { - "ARM C Compiler, ADS", - "Thumb C Compiler, ADS", - "ARM C++ Compiler, ADS", - "Thumb C++ Compiler, ADS", - "ARM/Thumb C/C++ Compiler, RVCT" - }; - int i; - struct symtab *s; s = find_pc_symtab (fs->pc); - if (s == NULL || s->producer == NULL) + if (s == NULL) return; - for (i = 0; i < ARRAY_SIZE (arm_idents); i++) - if (strncmp (s->producer, arm_idents[i], strlen (arm_idents[i])) == 0) - { - if (fde->cie->version == 1) - fs->armcc_cfa_offsets_sf = 1; - - if (fde->cie->version == 1) - fs->armcc_cfa_offsets_reversed = 1; - - /* The reversed offset problem is present in some compilers - using DWARF3, but it was eventually fixed. Check the ARM - defined augmentations, which are in the format "armcc" followed - by a list of one-character options. The "+" option means - this problem is fixed (no quirk needed). If the armcc - augmentation is missing, the quirk is needed. */ - if (fde->cie->version == 3 - && (strncmp (fde->cie->augmentation, "armcc", 5) != 0 - || strchr (fde->cie->augmentation + 5, '+') == NULL)) - fs->armcc_cfa_offsets_reversed = 1; - - return; - } + if (producer_is_realview (s->producer)) + { + if (fde->cie->version == 1) + fs->armcc_cfa_offsets_sf = 1; + + if (fde->cie->version == 1) + fs->armcc_cfa_offsets_reversed = 1; + + /* The reversed offset problem is present in some compilers + using DWARF3, but it was eventually fixed. Check the ARM + defined augmentations, which are in the format "armcc" followed + by a list of one-character options. The "+" option means + this problem is fixed (no quirk needed). If the armcc + augmentation is missing, the quirk is needed. */ + if (fde->cie->version == 3 + && (strncmp (fde->cie->augmentation, "armcc", 5) != 0 + || strchr (fde->cie->augmentation + 5, '+') == NULL)) + fs->armcc_cfa_offsets_reversed = 1; + + return; + } } @@ -949,7 +969,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) case CFA_EXP: cache->cfa = execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len, - cache->addr_size, this_frame, 0); + cache->addr_size, this_frame, 0, 0); break; default: @@ -1105,7 +1125,7 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - cache->addr_size, this_frame, cache->cfa); + cache->addr_size, this_frame, cache->cfa, 1); return frame_unwind_got_memory (this_frame, regnum, addr); case DWARF2_FRAME_REG_SAVED_VAL_OFFSET: @@ -1115,7 +1135,7 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_VAL_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - cache->addr_size, this_frame, cache->cfa); + cache->addr_size, this_frame, cache->cfa, 1); return frame_unwind_got_constant (this_frame, regnum, addr); case DWARF2_FRAME_REG_UNSPECIFIED: @@ -1241,6 +1261,23 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame) return NULL; } + +/* Compute the CFA for THIS_FRAME, but only if THIS_FRAME came from + the DWARF unwinder. This is used to implement + DW_OP_call_frame_cfa. */ + +CORE_ADDR +dwarf2_frame_cfa (struct frame_info *this_frame) +{ + while (get_frame_type (this_frame) == INLINE_FRAME) + this_frame = get_prev_frame (this_frame); + /* This restriction could be lifted if other unwinders are known to + compute the frame base in a way compatible with the DWARF + unwinder. */ + if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind)) + error (_("can't compute CFA for this frame")); + return get_frame_base (this_frame); +} const struct objfile_data *dwarf2_frame_objfile_data; @@ -1463,31 +1500,64 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding, } -/* GCC uses a single CIE for all FDEs in a .debug_frame section. - That's why we use a simple linked list here. */ +static int +bsearch_cie_cmp (const void *key, const void *element) +{ + ULONGEST cie_pointer = *(ULONGEST *) key; + struct dwarf2_cie *cie = *(struct dwarf2_cie **) element; + + if (cie_pointer == cie->cie_pointer) + return 0; + + return (cie_pointer < cie->cie_pointer) ? -1 : 1; +} +/* Find CIE with the given CIE_POINTER in CIE_TABLE. */ static struct dwarf2_cie * -find_cie (struct comp_unit *unit, ULONGEST cie_pointer) +find_cie (struct dwarf2_cie_table *cie_table, ULONGEST cie_pointer) { - struct dwarf2_cie *cie = unit->cie; + struct dwarf2_cie **p_cie; - while (cie) + /* The C standard (ISO/IEC 9899:TC2) requires the BASE argument to + bsearch be non-NULL. */ + if (cie_table->entries == NULL) { - if (cie->cie_pointer == cie_pointer) - return cie; - - cie = cie->next; + gdb_assert (cie_table->num_entries == 0); + return NULL; } + p_cie = bsearch (&cie_pointer, cie_table->entries, cie_table->num_entries, + sizeof (cie_table->entries[0]), bsearch_cie_cmp); + if (p_cie != NULL) + return *p_cie; return NULL; } +/* Add a pointer to new CIE to the CIE_TABLE, allocating space for it. */ static void -add_cie (struct comp_unit *unit, struct dwarf2_cie *cie) +add_cie (struct dwarf2_cie_table *cie_table, struct dwarf2_cie *cie) { - cie->next = unit->cie; - unit->cie = cie; - cie->unit = unit; + const int n = cie_table->num_entries; + + gdb_assert (n < 1 + || cie_table->entries[n - 1]->cie_pointer < cie->cie_pointer); + + cie_table->entries = + xrealloc (cie_table->entries, (n + 1) * sizeof (cie_table->entries[0])); + cie_table->entries[n] = cie; + cie_table->num_entries = n + 1; +} + +static int +bsearch_fde_cmp (const void *key, const void *element) +{ + CORE_ADDR seek_pc = *(CORE_ADDR *) key; + struct dwarf2_fde *fde = *(struct dwarf2_fde **) element; + if (seek_pc < fde->initial_location) + return -1; + if (seek_pc < fde->initial_location + fde->address_range) + return 0; + return 1; } /* Find the FDE for *PC. Return a pointer to the FDE, and store the @@ -1500,37 +1570,54 @@ dwarf2_frame_find_fde (CORE_ADDR *pc) ALL_OBJFILES (objfile) { - struct dwarf2_fde *fde; + struct dwarf2_fde_table *fde_table; + struct dwarf2_fde **p_fde; CORE_ADDR offset; + CORE_ADDR seek_pc; - fde = objfile_data (objfile, dwarf2_frame_objfile_data); - if (fde == NULL) + fde_table = objfile_data (objfile, dwarf2_frame_objfile_data); + if (fde_table == NULL) + { + dwarf2_build_frame_info (objfile); + fde_table = objfile_data (objfile, dwarf2_frame_objfile_data); + } + gdb_assert (fde_table != NULL); + + if (fde_table->num_entries == 0) continue; gdb_assert (objfile->section_offsets); offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - while (fde) - { - if (*pc >= fde->initial_location + offset - && *pc < fde->initial_location + offset + fde->address_range) - { - *pc = fde->initial_location + offset; - return fde; - } - - fde = fde->next; - } + gdb_assert (fde_table->num_entries > 0); + if (*pc < offset + fde_table->entries[0]->initial_location) + continue; + + seek_pc = *pc - offset; + p_fde = bsearch (&seek_pc, fde_table->entries, fde_table->num_entries, + sizeof (fde_table->entries[0]), bsearch_fde_cmp); + if (p_fde != NULL) + { + *pc = (*p_fde)->initial_location + offset; + return *p_fde; + } } - return NULL; } +/* Add a pointer to new FDE to the FDE_TABLE, allocating space for it. */ static void -add_fde (struct comp_unit *unit, struct dwarf2_fde *fde) +add_fde (struct dwarf2_fde_table *fde_table, struct dwarf2_fde *fde) { - fde->next = objfile_data (unit->objfile, dwarf2_frame_objfile_data); - set_objfile_data (unit->objfile, dwarf2_frame_objfile_data, fde); + if (fde->address_range == 0) + /* Discard useless FDEs. */ + return; + + fde_table->num_entries += 1; + fde_table->entries = + xrealloc (fde_table->entries, + fde_table->num_entries * sizeof (fde_table->entries[0])); + fde_table->entries[fde_table->num_entries - 1] = fde; } #ifdef CC_HAS_LONG_LONG @@ -1540,12 +1627,16 @@ add_fde (struct comp_unit *unit, struct dwarf2_fde *fde) #endif static gdb_byte *decode_frame_entry (struct comp_unit *unit, gdb_byte *start, - int eh_frame_p); + int eh_frame_p, + struct dwarf2_cie_table *cie_table, + struct dwarf2_fde_table *fde_table); /* Decode the next CIE or FDE. Return NULL if invalid input, otherwise the next byte to be processed. */ static gdb_byte * -decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) +decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, + struct dwarf2_cie_table *cie_table, + struct dwarf2_fde_table *fde_table) { struct gdbarch *gdbarch = get_objfile_arch (unit->objfile); gdb_byte *buf, *end; @@ -1600,7 +1691,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) cie_pointer = start - unit->dwarf_frame_buffer; /* Check whether we've already read it. */ - if (find_cie (unit, cie_pointer)) + if (find_cie (cie_table, cie_pointer)) return end; cie = (struct dwarf2_cie *) @@ -1626,7 +1717,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) /* Check version number. */ cie_version = read_1_byte (unit->abfd, buf); - if (cie_version != 1 && cie_version != 3) + if (cie_version != 1 && cie_version != 3 && cie_version != 4) return NULL; cie->version = cie_version; buf += 1; @@ -1650,6 +1741,20 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) augmentation += 2; } + if (cie->version >= 4) + { + /* FIXME: check that this is the same as from the CU header. */ + cie->addr_size = read_1_byte (unit->abfd, buf); + ++buf; + cie->segment_size = read_1_byte (unit->abfd, buf); + ++buf; + } + else + { + cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + cie->segment_size = 0; + } + cie->code_alignment_factor = read_unsigned_leb128 (unit->abfd, buf, &bytes_read); buf += bytes_read; @@ -1737,8 +1842,9 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) cie->initial_instructions = buf; cie->end = end; + cie->unit = unit; - add_cie (unit, cie); + add_cie (cie_table, cie); } else { @@ -1762,12 +1868,12 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) fde = (struct dwarf2_fde *) obstack_alloc (&unit->objfile->objfile_obstack, sizeof (struct dwarf2_fde)); - fde->cie = find_cie (unit, cie_pointer); + fde->cie = find_cie (cie_table, cie_pointer); if (fde->cie == NULL) { decode_frame_entry (unit, unit->dwarf_frame_buffer + cie_pointer, - eh_frame_p); - fde->cie = find_cie (unit, cie_pointer); + eh_frame_p, cie_table, fde_table); + fde->cie = find_cie (cie_table, cie_pointer); } gdb_assert (fde->cie != NULL); @@ -1801,7 +1907,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) fde->eh_frame_p = eh_frame_p; - add_fde (unit, fde); + add_fde (fde_table, fde); } return end; @@ -1809,7 +1915,9 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) /* Read a CIE or FDE in BUF and decode it. */ static gdb_byte * -decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) +decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, + struct dwarf2_cie_table *cie_table, + struct dwarf2_fde_table *fde_table) { enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE; gdb_byte *ret; @@ -1818,7 +1926,8 @@ decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) while (1) { - ret = decode_frame_entry_1 (unit, start, eh_frame_p); + ret = decode_frame_entry_1 (unit, start, eh_frame_p, + cie_table, fde_table); if (ret != NULL) break; @@ -1904,11 +2013,41 @@ decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) extern void dwarf2_get_section_info (struct objfile *, const char *, asection **, gdb_byte **, bfd_size_type *); +static int +qsort_fde_cmp (const void *a, const void *b) +{ + struct dwarf2_fde *aa = *(struct dwarf2_fde **)a; + struct dwarf2_fde *bb = *(struct dwarf2_fde **)b; + + if (aa->initial_location == bb->initial_location) + { + if (aa->address_range != bb->address_range + && aa->eh_frame_p == 0 && bb->eh_frame_p == 0) + /* Linker bug, e.g. gold/10400. + Work around it by keeping stable sort order. */ + return (a < b) ? -1 : 1; + else + /* Put eh_frame entries after debug_frame ones. */ + return aa->eh_frame_p - bb->eh_frame_p; + } + + return (aa->initial_location < bb->initial_location) ? -1 : 1; +} + void dwarf2_build_frame_info (struct objfile *objfile) { struct comp_unit *unit; gdb_byte *frame_ptr; + struct dwarf2_cie_table cie_table; + struct dwarf2_fde_table fde_table; + struct dwarf2_fde_table *fde_table2; + + cie_table.num_entries = 0; + cie_table.entries = NULL; + + fde_table.num_entries = 0; + fde_table.entries = NULL; /* Build a minimal decoding of the DWARF2 compilation unit. */ unit = (struct comp_unit *) obstack_alloc (&objfile->objfile_obstack, @@ -1918,8 +2057,6 @@ dwarf2_build_frame_info (struct objfile *objfile) unit->dbase = 0; unit->tbase = 0; - /* First add the information from the .eh_frame section. That way, - the FDEs from that section are searched last. */ dwarf2_get_section_info (objfile, ".eh_frame", &unit->dwarf_frame_section, &unit->dwarf_frame_buffer, @@ -1928,7 +2065,6 @@ dwarf2_build_frame_info (struct objfile *objfile) { asection *got, *txt; - unit->cie = NULL; /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base that is used for the i386/amd64 target, which currently is the only target in GCC that supports/uses the @@ -1945,7 +2081,16 @@ dwarf2_build_frame_info (struct objfile *objfile) frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) - frame_ptr = decode_frame_entry (unit, frame_ptr, 1); + frame_ptr = decode_frame_entry (unit, frame_ptr, 1, + &cie_table, &fde_table); + + if (cie_table.num_entries != 0) + { + /* Reinit cie_table: debug_frame has different CIEs. */ + xfree (cie_table.entries); + cie_table.num_entries = 0; + cie_table.entries = NULL; + } } dwarf2_get_section_info (objfile, ".debug_frame", @@ -1954,12 +2099,92 @@ dwarf2_build_frame_info (struct objfile *objfile) &unit->dwarf_frame_size); if (unit->dwarf_frame_size) { - unit->cie = NULL; - frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) - frame_ptr = decode_frame_entry (unit, frame_ptr, 0); + frame_ptr = decode_frame_entry (unit, frame_ptr, 0, + &cie_table, &fde_table); + } + + /* Discard the cie_table, it is no longer needed. */ + if (cie_table.num_entries != 0) + { + xfree (cie_table.entries); + cie_table.entries = NULL; /* Paranoia. */ + cie_table.num_entries = 0; /* Paranoia. */ + } + + /* Copy fde_table to obstack: it is needed at runtime. */ + fde_table2 = (struct dwarf2_fde_table *) + obstack_alloc (&objfile->objfile_obstack, sizeof (*fde_table2)); + + if (fde_table.num_entries == 0) + { + fde_table2->entries = NULL; + fde_table2->num_entries = 0; } + else + { + struct dwarf2_fde *fde_prev = NULL; + struct dwarf2_fde *first_non_zero_fde = NULL; + int i; + + /* Prepare FDE table for lookups. */ + qsort (fde_table.entries, fde_table.num_entries, + sizeof (fde_table.entries[0]), qsort_fde_cmp); + + /* Check for leftovers from --gc-sections. The GNU linker sets + the relevant symbols to zero, but doesn't zero the FDE *end* + ranges because there's no relocation there. It's (offset, + length), not (start, end). On targets where address zero is + just another valid address this can be a problem, since the + FDEs appear to be non-empty in the output --- we could pick + out the wrong FDE. To work around this, when overlaps are + detected, we prefer FDEs that do not start at zero. + + Start by finding the first FDE with non-zero start. Below + we'll discard all FDEs that start at zero and overlap this + one. */ + for (i = 0; i < fde_table.num_entries; i++) + { + struct dwarf2_fde *fde = fde_table.entries[i]; + + if (fde->initial_location != 0) + { + first_non_zero_fde = fde; + break; + } + } + + /* Since we'll be doing bsearch, squeeze out identical (except + for eh_frame_p) fde entries so bsearch result is predictable. + Also discard leftovers from --gc-sections. */ + fde_table2->num_entries = 0; + for (i = 0; i < fde_table.num_entries; i++) + { + struct dwarf2_fde *fde = fde_table.entries[i]; + + if (fde->initial_location == 0 + && first_non_zero_fde != NULL + && (first_non_zero_fde->initial_location + < fde->initial_location + fde->address_range)) + continue; + + if (fde_prev != NULL + && fde_prev->initial_location == fde->initial_location) + continue; + + obstack_grow (&objfile->objfile_obstack, &fde_table.entries[i], + sizeof (fde_table.entries[0])); + ++fde_table2->num_entries; + fde_prev = fde; + } + fde_table2->entries = obstack_finish (&objfile->objfile_obstack); + + /* Discard the original fde_table. */ + xfree (fde_table.entries); + } + + set_objfile_data (objfile, dwarf2_frame_objfile_data, fde_table2); } /* Provide a prototype to silence -Wmissing-prototypes. */