/* 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.
/* The version recorded in the CIE. */
unsigned char version;
+
+ /* The segment size. */
+ unsigned char segment_size;
};
struct dwarf2_cie_table
unwinder. */
{
int size = register_size (gdbarch, 0);
+
dwarf2_frame_state_alloc_regs (&fs->regs, 32);
for (reg = 8; reg < 16; reg++)
{
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;
+ }
}
\f
select the FDE of the previous function. */
CORE_ADDR block_addr = get_frame_address_in_block (this_frame);
struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr);
+
if (!fde)
return 0;
dwarf2_frame_base_sniffer (struct frame_info *this_frame)
{
CORE_ADDR block_addr = get_frame_address_in_block (this_frame);
+
if (dwarf2_frame_find_fde (&block_addr))
return &dwarf2_frame_base;
{
ULONGEST value;
gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
+
*bytes_read_ptr += read_uleb128 (buf, end_buf, &value) - buf;
return base + value;
}
{
LONGEST value;
gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
+
*bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf;
return base + value;
}
{
struct dwarf2_cie **p_cie;
+ /* The C standard (ISO/IEC 9899:TC2) requires the BASE argument to
+ bsearch be non-NULL. */
+ if (cie_table->entries == NULL)
+ {
+ 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)
{
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)
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);
/* 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;
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;
{
enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE;
gdb_byte *ret;
- const char *msg;
ptrdiff_t start_offset;
while (1)
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;
cie_table.num_entries = 0; /* Paranoia. */
}
- if (fde_table.num_entries != 0)
+ /* 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)
{
- struct dwarf2_fde_table *fde_table2;
- int i, j;
+ 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);
- /* Copy fde_table to obstack: it is needed at runtime. */
- fde_table2 = (struct dwarf2_fde_table *)
- obstack_alloc (&objfile->objfile_obstack, sizeof (*fde_table2));
+ /* 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];
- /* Since we'll be doing bsearch, squeeze out identical (except for
- eh_frame_p) fde entries so bsearch result is predictable. */
- for (i = 0, j = 0; j < fde_table.num_entries; ++i)
- {
- const int k = j;
-
- obstack_grow (&objfile->objfile_obstack, &fde_table.entries[j],
- sizeof (fde_table.entries[0]));
- while (++j < fde_table.num_entries
- && (fde_table.entries[k]->initial_location
- == fde_table.entries[j]->initial_location))
- /* Skip. */;
- }
+ 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);
- fde_table2->num_entries = i;
- set_objfile_data (objfile, dwarf2_frame_objfile_data, fde_table2);
/* 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. */