unsigned char eh_frame_p;
};
-struct dwarf2_fde_table
-{
- int num_entries;
- struct dwarf2_fde **entries;
-};
+typedef std::vector<dwarf2_fde *> dwarf2_fde_table;
/* A minimal decoding of DWARF2 compilation units. We only decode
what's needed to get to the call frame information. */
struct comp_unit
{
+ comp_unit (struct objfile *objf)
+ : abfd (objf->obfd)
+ {
+ }
+
/* Keep the bfd convenient. */
bfd *abfd;
- struct objfile *objfile;
-
/* Pointer to the .debug_frame section loaded into memory. */
- const gdb_byte *dwarf_frame_buffer;
+ const gdb_byte *dwarf_frame_buffer = nullptr;
/* Length of the loaded .debug_frame section. */
- bfd_size_type dwarf_frame_size;
+ bfd_size_type dwarf_frame_size = 0;
/* Pointer to the .debug_frame section. */
- asection *dwarf_frame_section;
+ asection *dwarf_frame_section = nullptr;
/* Base for DW_EH_PE_datarel encodings. */
- bfd_vma dbase;
+ bfd_vma dbase = 0;
/* Base for DW_EH_PE_textrel encodings. */
- bfd_vma tbase;
+ bfd_vma tbase = 0;
+
+ /* The FDE table. */
+ dwarf2_fde_table fde_table;
+
+ /* Hold data used by this module. */
+ auto_obstack obstack;
};
-static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc,
- CORE_ADDR *out_offset);
+static struct dwarf2_fde *dwarf2_frame_find_fde
+ (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile);
static int dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum,
int eh_frame_p);
class dwarf_expr_executor : public dwarf_expr_context
{
- public:
+public:
+
+ dwarf_expr_executor (dwarf2_per_objfile *per_objfile)
+ : dwarf_expr_context (per_objfile)
+ {}
struct frame_info *this_frame;
static CORE_ADDR
execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
- CORE_ADDR offset, struct frame_info *this_frame,
- CORE_ADDR initial, int initial_in_stack_memory)
+ struct frame_info *this_frame, CORE_ADDR initial,
+ int initial_in_stack_memory, dwarf2_per_objfile *per_objfile)
{
CORE_ADDR result;
- dwarf_expr_executor ctx;
+ dwarf_expr_executor ctx (per_objfile);
scoped_value_mark free_values;
ctx.this_frame = this_frame;
ctx.gdbarch = get_frame_arch (this_frame);
ctx.addr_size = addr_size;
ctx.ref_addr_size = -1;
- ctx.offset = offset;
ctx.push_address (initial, initial_in_stack_memory);
ctx.eval (exp, len);
static const gdb_byte *
execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
const gdb_byte *insn_end, struct gdbarch *gdbarch,
- CORE_ADDR pc, struct dwarf2_frame_state *fs)
+ CORE_ADDR pc, struct dwarf2_frame_state *fs,
+ CORE_ADDR text_offset)
{
int eh_frame_p = fde->eh_frame_p;
unsigned int bytes_read;
fs->pc = read_encoded_value (fde->cie->unit, fde->cie->encoding,
fde->cie->ptr_size, insn_ptr,
&bytes_read, fde->initial_location);
- /* Apply the objfile offset for relocatable objects. */
- fs->pc += fde->cie->unit->objfile->text_section_offset ();
+ /* Apply the text offset for relocatable objects. */
+ fs->pc += text_offset;
insn_ptr += bytes_read;
break;
const gdb_byte *insn_end = insns + sizeof (insns);
const gdb_byte *out = execute_cfa_program (&fde, insns, insn_end, gdbarch,
- 0, &fs);
+ 0, &fs, 0);
SELF_CHECK (out == insn_end);
SELF_CHECK (fs.pc == 0);
const gdb_byte **cfa_end_out)
{
struct dwarf2_fde *fde;
- CORE_ADDR text_offset;
+ dwarf2_per_objfile *per_objfile;
CORE_ADDR pc1 = pc;
/* Find the correct FDE. */
- fde = dwarf2_frame_find_fde (&pc1, &text_offset);
+ fde = dwarf2_frame_find_fde (&pc1, &per_objfile);
if (fde == NULL)
error (_("Could not compute CFA; needed to translate this expression"));
+ gdb_assert (per_objfile != nullptr);
+
dwarf2_frame_state fs (pc1, fde->cie);
/* Check for "quirks" - known bugs in producers. */
/* First decode all the insns in the CIE. */
execute_cfa_program (fde, fde->cie->initial_instructions,
- fde->cie->end, gdbarch, pc, &fs);
+ fde->cie->end, gdbarch, pc, &fs,
+ per_objfile->objfile->text_section_offset ());
/* Save the initialized register set. */
fs.initial = fs.regs;
/* Then decode the insns in the FDE up to our target PC. */
- execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, pc, &fs);
+ execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, pc, &fs,
+ per_objfile->objfile->text_section_offset ());
/* Calculate the CFA. */
switch (fs.regs.cfa_how)
}
case CFA_EXP:
- *text_offset_out = text_offset;
+ *text_offset_out = per_objfile->objfile->text_section_offset ();
*cfa_start_out = fs.regs.cfa_exp;
*cfa_end_out = fs.regs.cfa_exp + fs.regs.cfa_exp_len;
return 0;
/* Target address size in bytes. */
int addr_size;
- /* The .text offset. */
- CORE_ADDR text_offset;
-
- /* True if we already checked whether this frame is the bottom frame
- of a virtual tail call frame chain. */
- int checked_tailcall_bottom;
+ /* The dwarf2_per_objfile from which this frame description came. */
+ dwarf2_per_objfile *per_objfile;
/* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME
sequence. If NULL then it is a normal case with no TAILCALL_FRAME
dwarf2_tailcall_frame_unwind unwinder so this field does not apply for
them. */
void *tailcall_cache;
-
- /* The number of bytes to subtract from TAILCALL_FRAME frames frame
- base to get the SP, to simulate the return address pushed on the
- stack. */
- LONGEST entry_cfa_sp_offset;
- int entry_cfa_sp_offset_p;
};
static struct dwarf2_frame_cache *
CORE_ADDR pc1 = get_frame_address_in_block (this_frame);
/* Find the correct FDE. */
- fde = dwarf2_frame_find_fde (&pc1, &cache->text_offset);
+ fde = dwarf2_frame_find_fde (&pc1, &cache->per_objfile);
gdb_assert (fde != NULL);
+ gdb_assert (cache->per_objfile != nullptr);
/* Allocate and initialize the frame state. */
struct dwarf2_frame_state fs (pc1, fde->cie);
/* First decode all the insns in the CIE. */
execute_cfa_program (fde, fde->cie->initial_instructions,
fde->cie->end, gdbarch,
- get_frame_address_in_block (this_frame), &fs);
+ get_frame_address_in_block (this_frame), &fs,
+ cache->per_objfile->objfile->text_section_offset ());
/* Save the initialized register set. */
fs.initial = fs.regs;
in an address that's within the range of FDE locations. This
is due to the possibility of the function occupying non-contiguous
ranges. */
+ LONGEST entry_cfa_sp_offset;
+ int entry_cfa_sp_offset_p = 0;
if (get_frame_func_if_available (this_frame, &entry_pc)
&& fde->initial_location <= entry_pc
&& entry_pc < fde->initial_location + fde->address_range)
{
/* Decode the insns in the FDE up to the entry PC. */
- instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
- entry_pc, &fs);
+ instr = execute_cfa_program
+ (fde, fde->instructions, fde->end, gdbarch, entry_pc, &fs,
+ cache->per_objfile->objfile->text_section_offset ());
if (fs.regs.cfa_how == CFA_REG_OFFSET
&& (dwarf_reg_to_regnum (gdbarch, fs.regs.cfa_reg)
== gdbarch_sp_regnum (gdbarch)))
{
- cache->entry_cfa_sp_offset = fs.regs.cfa_offset;
- cache->entry_cfa_sp_offset_p = 1;
+ entry_cfa_sp_offset = fs.regs.cfa_offset;
+ entry_cfa_sp_offset_p = 1;
}
}
else
/* Then decode the insns in the FDE up to our target PC. */
execute_cfa_program (fde, instr, fde->end, gdbarch,
- get_frame_address_in_block (this_frame), &fs);
+ get_frame_address_in_block (this_frame), &fs,
+ cache->per_objfile->objfile->text_section_offset ());
try
{
case CFA_EXP:
cache->cfa =
execute_stack_op (fs.regs.cfa_exp, fs.regs.cfa_exp_len,
- cache->addr_size, cache->text_offset,
- this_frame, 0, 0);
+ cache->addr_size, this_frame, 0, 0,
+ cache->per_objfile);
break;
default:
&& fs.regs.reg[fs.retaddr_column].how == DWARF2_FRAME_REG_UNDEFINED)
cache->undefined_retaddr = 1;
+ dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
+ (entry_cfa_sp_offset_p
+ ? &entry_cfa_sp_offset : NULL));
+
return cache;
}
CORE_ADDR addr;
int realnum;
- /* Check whether THIS_FRAME is the bottom frame of a virtual tail
- call frame chain. */
- if (!cache->checked_tailcall_bottom)
- {
- cache->checked_tailcall_bottom = 1;
- dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
- (cache->entry_cfa_sp_offset_p
- ? &cache->entry_cfa_sp_offset : NULL));
- }
-
/* Non-bottom frames of a virtual tail call frames chain use
dwarf2_tailcall_frame_unwind unwinder so this code does not apply for
them. If dwarf2_tailcall_prev_register_first does not have specific value
case DWARF2_FRAME_REG_SAVED_EXP:
addr = execute_stack_op (cache->reg[regnum].loc.exp.start,
cache->reg[regnum].loc.exp.len,
- cache->addr_size, cache->text_offset,
- this_frame, cache->cfa, 1);
+ cache->addr_size,
+ this_frame, cache->cfa, 1,
+ cache->per_objfile);
return frame_unwind_got_memory (this_frame, regnum, addr);
case DWARF2_FRAME_REG_SAVED_VAL_OFFSET:
case DWARF2_FRAME_REG_SAVED_VAL_EXP:
addr = execute_stack_op (cache->reg[regnum].loc.exp.start,
cache->reg[regnum].loc.exp.len,
- cache->addr_size, cache->text_offset,
- this_frame, cache->cfa, 1);
+ cache->addr_size,
+ this_frame, cache->cfa, 1,
+ cache->per_objfile);
return frame_unwind_got_constant (this_frame, regnum, addr);
case DWARF2_FRAME_REG_UNSPECIFIED:
void
dwarf2_append_unwinders (struct gdbarch *gdbarch)
{
- /* TAILCALL_FRAME must be first to find the record by
- dwarf2_tailcall_sniffer_first. */
- frame_unwind_append_unwinder (gdbarch, &dwarf2_tailcall_frame_unwind);
-
frame_unwind_append_unwinder (gdbarch, &dwarf2_frame_unwind);
frame_unwind_append_unwinder (gdbarch, &dwarf2_signal_frame_unwind);
}
return get_frame_base (this_frame);
}
\f
-const struct objfile_key<dwarf2_fde_table,
- gdb::noop_deleter<dwarf2_fde_table>>
- dwarf2_frame_objfile_data;
-
-
-static ULONGEST
-read_initial_length (bfd *abfd, const gdb_byte *buf,
- unsigned int *bytes_read_ptr)
-{
- ULONGEST result;
-
- result = bfd_get_32 (abfd, buf);
- if (result == 0xffffffff)
- {
- result = bfd_get_64 (abfd, buf + 4);
- *bytes_read_ptr = 12;
- }
- else
- *bytes_read_ptr = 4;
-
- return result;
-}
+/* We store the frame data on the BFD. This is only done if it is
+ independent of the address space and so can be shared. */
+static const struct bfd_key<comp_unit> dwarf2_frame_bfd_data;
+
+/* If any BFD sections require relocations (note; really should be if
+ any debug info requires relocations), then we store the frame data
+ on the objfile instead, and do not share it. */
+const struct objfile_key<comp_unit> dwarf2_frame_objfile_data;
\f
/* Pointer encoding helper functions. */
return 1;
}
+/* Find an existing comp_unit for an objfile, if any. */
+
+static comp_unit *
+find_comp_unit (struct objfile *objfile)
+{
+ bfd *abfd = objfile->obfd;
+ if (gdb_bfd_requires_relocations (abfd))
+ return dwarf2_frame_bfd_data.get (abfd);
+ return dwarf2_frame_objfile_data.get (objfile);
+}
+
+/* Store the comp_unit on OBJFILE, or the corresponding BFD, as
+ appropriate. */
+
+static void
+set_comp_unit (struct objfile *objfile, struct comp_unit *unit)
+{
+ bfd *abfd = objfile->obfd;
+ if (gdb_bfd_requires_relocations (abfd))
+ return dwarf2_frame_bfd_data.set (abfd, unit);
+ return dwarf2_frame_objfile_data.set (objfile, unit);
+}
+
/* Find the FDE for *PC. Return a pointer to the FDE, and store the
initial location associated with it into *PC. */
static struct dwarf2_fde *
-dwarf2_frame_find_fde (CORE_ADDR *pc, CORE_ADDR *out_offset)
+dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile)
{
for (objfile *objfile : current_program_space->objfiles ())
{
- struct dwarf2_fde_table *fde_table;
CORE_ADDR offset;
CORE_ADDR seek_pc;
- fde_table = dwarf2_frame_objfile_data.get (objfile);
- if (fde_table == NULL)
+ comp_unit *unit = find_comp_unit (objfile);
+ if (unit == NULL)
{
dwarf2_build_frame_info (objfile);
- fde_table = dwarf2_frame_objfile_data.get (objfile);
+ unit = find_comp_unit (objfile);
}
- gdb_assert (fde_table != NULL);
+ gdb_assert (unit != NULL);
- if (fde_table->num_entries == 0)
+ dwarf2_fde_table *fde_table = &unit->fde_table;
+ if (fde_table->empty ())
continue;
gdb_assert (!objfile->section_offsets.empty ());
offset = objfile->text_section_offset ();
- gdb_assert (fde_table->num_entries > 0);
- if (*pc < offset + fde_table->entries[0]->initial_location)
+ gdb_assert (!fde_table->empty ());
+ if (*pc < offset + (*fde_table)[0]->initial_location)
continue;
seek_pc = *pc - offset;
- auto end = fde_table->entries + fde_table->num_entries;
- auto it = gdb::binary_search (fde_table->entries, end, seek_pc, bsearch_fde_cmp);
- if (it != end)
+ auto it = gdb::binary_search (fde_table->begin (), fde_table->end (),
+ seek_pc, bsearch_fde_cmp);
+ if (it != fde_table->end ())
{
*pc = (*it)->initial_location + offset;
- if (out_offset)
- *out_offset = offset;
+ if (out_per_objfile != nullptr)
+ *out_per_objfile = get_dwarf2_per_objfile (objfile);
+
return *it;
}
}
return NULL;
}
-/* Add a pointer to new FDE to the FDE_TABLE, allocating space for it. */
+/* Add FDE to FDE_TABLE. */
static void
-add_fde (struct dwarf2_fde_table *fde_table, struct dwarf2_fde *fde)
+add_fde (dwarf2_fde_table *fde_table, struct dwarf2_fde *fde)
{
if (fde->address_range == 0)
/* Discard useless FDEs. */
return;
- fde_table->num_entries += 1;
- fde_table->entries = XRESIZEVEC (struct dwarf2_fde *, fde_table->entries,
- fde_table->num_entries);
- fde_table->entries[fde_table->num_entries - 1] = fde;
+ fde_table->push_back (fde);
}
#define DW64_CIE_ID 0xffffffffffffffffULL
EH_CIE_OR_FDE_TYPE_ID = EH_CIE_TYPE_ID | EH_FDE_TYPE_ID
};
-static const gdb_byte *decode_frame_entry (struct comp_unit *unit,
+static const gdb_byte *decode_frame_entry (struct gdbarch *gdbarch,
+ struct comp_unit *unit,
const gdb_byte *start,
int eh_frame_p,
dwarf2_cie_table &cie_table,
- struct dwarf2_fde_table *fde_table,
+ dwarf2_fde_table *fde_table,
enum eh_frame_type entry_type);
/* Decode the next CIE or FDE, entry_type specifies the expected type.
Return NULL if invalid input, otherwise the next byte to be processed. */
static const gdb_byte *
-decode_frame_entry_1 (struct comp_unit *unit, const gdb_byte *start,
+decode_frame_entry_1 (struct gdbarch *gdbarch,
+ struct comp_unit *unit, const gdb_byte *start,
int eh_frame_p,
dwarf2_cie_table &cie_table,
- struct dwarf2_fde_table *fde_table,
+ dwarf2_fde_table *fde_table,
enum eh_frame_type entry_type)
{
- struct gdbarch *gdbarch = get_objfile_arch (unit->objfile);
const gdb_byte *buf, *end;
ULONGEST length;
unsigned int bytes_read;
uint64_t uleb128;
buf = start;
- length = read_initial_length (unit->abfd, buf, &bytes_read);
+ length = read_initial_length (unit->abfd, buf, &bytes_read, false);
buf += bytes_read;
end = buf + (size_t) length;
if (find_cie (cie_table, cie_pointer))
return end;
- cie = XOBNEW (&unit->objfile->objfile_obstack, struct dwarf2_cie);
+ cie = XOBNEW (&unit->obstack, struct dwarf2_cie);
cie->initial_instructions = NULL;
cie->cie_pointer = cie_pointer;
if (cie_pointer >= unit->dwarf_frame_size)
return NULL;
- fde = XOBNEW (&unit->objfile->objfile_obstack, struct dwarf2_fde);
+ fde = XOBNEW (&unit->obstack, struct dwarf2_fde);
fde->cie = find_cie (cie_table, cie_pointer);
if (fde->cie == NULL)
{
- decode_frame_entry (unit, unit->dwarf_frame_buffer + cie_pointer,
+ decode_frame_entry (gdbarch, unit,
+ unit->dwarf_frame_buffer + cie_pointer,
eh_frame_p, cie_table, fde_table,
EH_CIE_TYPE_ID);
fde->cie = find_cie (cie_table, cie_pointer);
expect an FDE or a CIE. */
static const gdb_byte *
-decode_frame_entry (struct comp_unit *unit, const gdb_byte *start,
+decode_frame_entry (struct gdbarch *gdbarch,
+ struct comp_unit *unit, const gdb_byte *start,
int eh_frame_p,
dwarf2_cie_table &cie_table,
- struct dwarf2_fde_table *fde_table,
+ dwarf2_fde_table *fde_table,
enum eh_frame_type entry_type)
{
enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE;
while (1)
{
- ret = decode_frame_entry_1 (unit, start, eh_frame_p,
+ ret = decode_frame_entry_1 (gdbarch, unit, start, eh_frame_p,
cie_table, fde_table, entry_type);
if (ret != NULL)
break;
case ALIGN4:
complaint (_("\
Corrupt data in %s:%s; align 4 workaround apparently succeeded"),
- unit->dwarf_frame_section->owner->filename,
- unit->dwarf_frame_section->name);
+ bfd_get_filename (unit->dwarf_frame_section->owner),
+ bfd_section_name (unit->dwarf_frame_section));
break;
case ALIGN8:
complaint (_("\
Corrupt data in %s:%s; align 8 workaround apparently succeeded"),
- unit->dwarf_frame_section->owner->filename,
- unit->dwarf_frame_section->name);
+ bfd_get_filename (unit->dwarf_frame_section->owner),
+ bfd_section_name (unit->dwarf_frame_section));
break;
default:
complaint (_("Corrupt data in %s:%s"),
- unit->dwarf_frame_section->owner->filename,
- unit->dwarf_frame_section->name);
+ bfd_get_filename (unit->dwarf_frame_section->owner),
+ bfd_section_name (unit->dwarf_frame_section));
break;
}
void
dwarf2_build_frame_info (struct objfile *objfile)
{
- struct comp_unit *unit;
const gdb_byte *frame_ptr;
dwarf2_cie_table cie_table;
- struct dwarf2_fde_table fde_table;
- struct dwarf2_fde_table *fde_table2;
+ dwarf2_fde_table fde_table;
- fde_table.num_entries = 0;
- fde_table.entries = NULL;
+ struct gdbarch *gdbarch = objfile->arch ();
/* Build a minimal decoding of the DWARF2 compilation unit. */
- unit = XOBNEW (&objfile->objfile_obstack, comp_unit);
- unit->abfd = objfile->obfd;
- unit->objfile = objfile;
- unit->dbase = 0;
- unit->tbase = 0;
+ std::unique_ptr<comp_unit> unit (new comp_unit (objfile));
if (objfile->separate_debug_objfile_backlink == 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, 1,
+ frame_ptr = decode_frame_entry (gdbarch, unit.get (),
+ frame_ptr, 1,
cie_table, &fde_table,
EH_CIE_OR_FDE_TYPE_ID);
}
warning (_("skipping .eh_frame info of %s: %s"),
objfile_name (objfile), e.what ());
- if (fde_table.num_entries != 0)
- {
- xfree (fde_table.entries);
- fde_table.entries = NULL;
- fde_table.num_entries = 0;
- }
+ fde_table.clear ();
/* The cie_table is discarded below. */
}
&unit->dwarf_frame_size);
if (unit->dwarf_frame_size)
{
- int num_old_fde_entries = fde_table.num_entries;
+ size_t num_old_fde_entries = fde_table.size ();
try
{
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 (gdbarch, unit.get (), frame_ptr, 0,
cie_table, &fde_table,
EH_CIE_OR_FDE_TYPE_ID);
}
warning (_("skipping .debug_frame info of %s: %s"),
objfile_name (objfile), e.what ());
- if (fde_table.num_entries != 0)
- {
- fde_table.num_entries = num_old_fde_entries;
- if (num_old_fde_entries == 0)
- {
- xfree (fde_table.entries);
- fde_table.entries = NULL;
- }
- else
- {
- fde_table.entries
- = XRESIZEVEC (struct dwarf2_fde *, fde_table.entries,
- fde_table.num_entries);
- }
- }
- fde_table.num_entries = num_old_fde_entries;
+ fde_table.resize (num_old_fde_entries);
}
}
- /* Copy fde_table to obstack: it is needed at runtime. */
- fde_table2 = XOBNEW (&objfile->objfile_obstack, struct dwarf2_fde_table);
-
- 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;
+
+ /* Prepare FDE table for lookups. */
+ std::sort (fde_table.begin (), fde_table.end (), fde_is_less_than);
+
+ /* 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 (struct dwarf2_fde *fde : fde_table)
{
- struct dwarf2_fde *fde_prev = NULL;
- struct dwarf2_fde *first_non_zero_fde = NULL;
- int i;
-
- /* Prepare FDE table for lookups. */
- std::sort (fde_table.entries, fde_table.entries + fde_table.num_entries,
- fde_is_less_than);
-
- /* 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++)
+ if (fde->initial_location != 0)
{
- struct dwarf2_fde *fde = fde_table.entries[i];
-
- if (fde->initial_location != 0)
- {
- first_non_zero_fde = fde;
- break;
- }
+ 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
- = (struct dwarf2_fde **) obstack_finish (&objfile->objfile_obstack);
+ /* 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. */
+ for (struct dwarf2_fde *fde : fde_table)
+ {
+ 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;
- /* Discard the original fde_table. */
- xfree (fde_table.entries);
+ unit->fde_table.push_back (fde);
+ fde_prev = fde;
}
+ unit->fde_table.shrink_to_fit ();
- dwarf2_frame_objfile_data.set (objfile, fde_table2);
+ set_comp_unit (objfile, unit.release ());
}
/* Handle 'maintenance show dwarf unwinders'. */