This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfa] DW_CFA_set_loc support
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org, Mark Kettenis <kettenis at gnu dot org>
- Date: Fri, 6 Oct 2006 15:21:15 -0400
- Subject: [rfa] DW_CFA_set_loc support
As discussed on gdb@; I eventually figured out a reasonable way to
implement this. Comments welcome. Unfortunately, I can't really test
it: the broken versions of GCC didn't just generate DW_CFA_set_loc,
but in fact _bogus_ set_locs, as per
http://sourceware.org/ml/binutils/2006-09/msg00295.html
(I think that the bogosity comes from a bug in binutils that Jakub
since fixed).
But I'd rather have this merged if it looks right, since it is clearly
better than what's there now, at least if anyone else is reasonably
confident that I got it right.
--
Daniel Jacobowitz
CodeSourcery
2006-10-06 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2-frame.c (struct comp_unit): Move higher.
(dwarf2_frame_find_fde): Optionally return the unit. Adjust
callers.
(read_encoded_value): Take a unit and function base. Correct a
typo. Handle DW_EH_PE_funcrel.
(execute_cfa_program): Take a unit and fde. Use read_encoded_value.
Apply offsets. Update callers.
(add_fde): Don't adjust the objfile data, just the unit.
(dwarf2_build_frame_info): Allocate a comp_unit as the per-objfile
data.
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.63
diff -u -p -r1.63 dwarf2-frame.c
--- dwarf2-frame.c 28 May 2006 05:56:50 -0000 1.63
+++ dwarf2-frame.c 6 Oct 2006 19:09:17 -0000
@@ -1,6 +1,6 @@
/* Frame unwinder for frames with DWARF Call Frame Information.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Mark Kettenis.
@@ -100,7 +100,45 @@ struct dwarf2_fde
struct dwarf2_fde *next;
};
-static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc);
+/* A minimal decoding of DWARF2 compilation units. We only decode
+ what's needed to get to the call frame information. */
+
+struct comp_unit
+{
+ /* Keep the bfd convenient. */
+ bfd *abfd;
+
+ 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;
+
+ /* Length of the loaded .debug_frame section. */
+ unsigned long dwarf_frame_size;
+
+ /* Pointer to the .debug_frame section. */
+ asection *dwarf_frame_section;
+
+ /* Base for DW_EH_PE_datarel encodings. */
+ bfd_vma dbase;
+
+ /* Base for DW_EH_PE_textrel encodings. */
+ bfd_vma tbase;
+
+ /* FDE list. */
+ struct dwarf2_fde *fde;
+};
+
+static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc,
+ struct comp_unit **unit_p);
+static CORE_ADDR read_encoded_value (struct comp_unit *unit,
+ gdb_byte encoding,
+ gdb_byte *buf,
+ unsigned int *bytes_read_ptr,
+ CORE_ADDR func_base);
/* Structure describing a frame state. */
@@ -279,7 +317,8 @@ execute_stack_op (gdb_byte *exp, ULONGES
static void
-execute_cfa_program (gdb_byte *insn_ptr, gdb_byte *insn_end,
+execute_cfa_program (struct comp_unit *unit, struct dwarf2_fde *fde,
+ gdb_byte *insn_ptr, gdb_byte *insn_end,
struct frame_info *next_frame,
struct dwarf2_frame_state *fs, int eh_frame_p)
{
@@ -330,7 +369,14 @@ register %s (#%d) at 0x%s"),
switch (insn)
{
case DW_CFA_set_loc:
- fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read);
+ fs->pc = read_encoded_value (unit, fde->cie->encoding,
+ insn_ptr, &bytes_read,
+ fde->initial_location);
+ /* Always apply the objfile offset. We can do this because
+ if the code used DW_EH_PE_absptr, it probably wasn't
+ relocatable, so the offset should be zero. */
+ fs->pc += ANOFFSET (unit->objfile->section_offsets,
+ SECT_OFF_TEXT (unit->objfile));
insn_ptr += bytes_read;
break;
@@ -742,6 +788,7 @@ dwarf2_frame_cache (struct frame_info *n
struct dwarf2_frame_cache *cache;
struct dwarf2_frame_state *fs;
struct dwarf2_fde *fde;
+ struct comp_unit *unit;
if (*this_cache)
return *this_cache;
@@ -773,7 +820,7 @@ dwarf2_frame_cache (struct frame_info *n
fs->pc = frame_unwind_address_in_block (next_frame);
/* Find the correct FDE. */
- fde = dwarf2_frame_find_fde (&fs->pc);
+ fde = dwarf2_frame_find_fde (&fs->pc, &unit);
gdb_assert (fde != NULL);
/* Extract any interesting information from the CIE. */
@@ -782,7 +829,7 @@ dwarf2_frame_cache (struct frame_info *n
fs->retaddr_column = fde->cie->return_address_register;
/* First decode all the insns in the CIE. */
- execute_cfa_program (fde->cie->initial_instructions,
+ execute_cfa_program (unit, fde, fde->cie->initial_instructions,
fde->cie->end, next_frame, fs, fde->eh_frame_p);
/* Save the initialized register set. */
@@ -790,7 +837,7 @@ dwarf2_frame_cache (struct frame_info *n
fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs);
/* Then decode the insns in the FDE up to our target PC. */
- execute_cfa_program (fde->instructions, fde->end, next_frame, fs,
+ execute_cfa_program (unit, fde, fde->instructions, fde->end, next_frame, fs,
fde->eh_frame_p);
/* Caclulate the CFA. */
@@ -1106,7 +1153,7 @@ dwarf2_frame_sniffer (struct frame_info
function. frame_pc_unwind(), for a no-return next function, can
end up returning something past the end of this function's body. */
CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame);
- struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr);
+ struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr, NULL);
if (!fde)
return NULL;
@@ -1150,41 +1197,12 @@ const struct frame_base *
dwarf2_frame_base_sniffer (struct frame_info *next_frame)
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
- if (dwarf2_frame_find_fde (&pc))
+ if (dwarf2_frame_find_fde (&pc, NULL))
return &dwarf2_frame_base;
return NULL;
}
-/* A minimal decoding of DWARF2 compilation units. We only decode
- what's needed to get to the call frame information. */
-
-struct comp_unit
-{
- /* Keep the bfd convenient. */
- bfd *abfd;
-
- 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;
-
- /* Length of the loaded .debug_frame section. */
- unsigned long dwarf_frame_size;
-
- /* Pointer to the .debug_frame section. */
- asection *dwarf_frame_section;
-
- /* Base for DW_EH_PE_datarel encodings. */
- bfd_vma dbase;
-
- /* Base for DW_EH_PE_textrel encodings. */
- bfd_vma tbase;
-};
-
const struct objfile_data *dwarf2_frame_objfile_data;
static unsigned int
@@ -1335,7 +1353,8 @@ size_of_encoded_value (gdb_byte encoding
static CORE_ADDR
read_encoded_value (struct comp_unit *unit, gdb_byte encoding,
- gdb_byte *buf, unsigned int *bytes_read_ptr)
+ gdb_byte *buf, unsigned int *bytes_read_ptr,
+ CORE_ADDR func_start)
{
int ptr_len = size_of_encoded_value (DW_EH_PE_absptr);
ptrdiff_t offset;
@@ -1355,7 +1374,7 @@ read_encoded_value (struct comp_unit *un
base = 0;
break;
case DW_EH_PE_pcrel:
- base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section);
+ base = bfd_get_section_vma (unit->abfd, unit->dwarf_frame_section);
base += (buf - unit->dwarf_frame_buffer);
break;
case DW_EH_PE_datarel:
@@ -1365,12 +1384,7 @@ read_encoded_value (struct comp_unit *un
base = unit->tbase;
break;
case DW_EH_PE_funcrel:
- /* FIXME: kettenis/20040501: For now just pretend
- DW_EH_PE_funcrel is equivalent to DW_EH_PE_absptr. For
- reading the initial location of an FDE it should be treated
- as such, and currently that's the only place where this code
- is used. */
- base = 0;
+ base = func_start;
break;
case DW_EH_PE_aligned:
base = 0;
@@ -1455,31 +1469,36 @@ add_cie (struct comp_unit *unit, struct
}
/* Find the FDE for *PC. Return a pointer to the FDE, and store the
- inital location associated with it into *PC. */
+ inital location associated with it into *PC. Store the associated
+ file information into *UNIT_P if non-NULL. */
static struct dwarf2_fde *
-dwarf2_frame_find_fde (CORE_ADDR *pc)
+dwarf2_frame_find_fde (CORE_ADDR *pc, struct comp_unit **unit_p)
{
struct objfile *objfile;
ALL_OBJFILES (objfile)
{
+ struct comp_unit *unit;
struct dwarf2_fde *fde;
CORE_ADDR offset;
- fde = objfile_data (objfile, dwarf2_frame_objfile_data);
- if (fde == NULL)
+ unit = objfile_data (objfile, dwarf2_frame_objfile_data);
+ if (unit == NULL || unit->fde == NULL)
continue;
gdb_assert (objfile->section_offsets);
offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ fde = unit->fde;
while (fde)
{
if (*pc >= fde->initial_location + offset
&& *pc < fde->initial_location + offset + fde->address_range)
{
*pc = fde->initial_location + offset;
+ if (unit_p)
+ *unit_p = unit;
return fde;
}
@@ -1493,8 +1512,8 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
static void
add_fde (struct comp_unit *unit, struct dwarf2_fde *fde)
{
- fde->next = objfile_data (unit->objfile, dwarf2_frame_objfile_data);
- set_objfile_data (unit->objfile, dwarf2_frame_objfile_data, fde);
+ fde->next = unit->fde;
+ unit->fde = fde;
}
#ifdef CC_HAS_LONG_LONG
@@ -1658,7 +1677,7 @@ decode_frame_entry_1 (struct comp_unit *
{
/* Skip. Avoid indirection since we throw away the result. */
gdb_byte encoding = (*buf++) & ~DW_EH_PE_indirect;
- read_encoded_value (unit, encoding, buf, &bytes_read);
+ read_encoded_value (unit, encoding, buf, &bytes_read, 0);
buf += bytes_read;
augmentation++;
}
@@ -1725,11 +1744,12 @@ decode_frame_entry_1 (struct comp_unit *
gdb_assert (fde->cie != NULL);
fde->initial_location =
- read_encoded_value (unit, fde->cie->encoding, buf, &bytes_read);
+ read_encoded_value (unit, fde->cie->encoding, buf, &bytes_read, 0);
buf += bytes_read;
fde->address_range =
- read_encoded_value (unit, fde->cie->encoding & 0x0f, buf, &bytes_read);
+ read_encoded_value (unit, fde->cie->encoding & 0x0f, buf, &bytes_read,
+ 0);
buf += bytes_read;
/* A 'z' augmentation in the CIE implies the presence of an
@@ -1863,14 +1883,18 @@ extern gdb_byte *dwarf2_read_section (st
void
dwarf2_build_frame_info (struct objfile *objfile)
{
- struct comp_unit unit;
+ struct comp_unit *unit;
gdb_byte *frame_ptr;
/* Build a minimal decoding of the DWARF2 compilation unit. */
- unit.abfd = objfile->obfd;
- unit.objfile = objfile;
- unit.dbase = 0;
- unit.tbase = 0;
+ unit = (struct comp_unit *) obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct comp_unit));
+ unit->abfd = objfile->obfd;
+ unit->objfile = objfile;
+ unit->dbase = 0;
+ unit->tbase = 0;
+ unit->fde = NULL;
+ set_objfile_data (objfile, dwarf2_frame_objfile_data, unit);
/* First add the information from the .eh_frame section. That way,
the FDEs from that section are searched last. */
@@ -1878,43 +1902,43 @@ dwarf2_build_frame_info (struct objfile
{
asection *got, *txt;
- unit.cie = NULL;
- unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
- dwarf_eh_frame_section);
+ unit->cie = NULL;
+ unit->dwarf_frame_buffer = dwarf2_read_section (objfile,
+ dwarf_eh_frame_section);
- unit.dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section);
- unit.dwarf_frame_section = dwarf_eh_frame_section;
+ unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section);
+ unit->dwarf_frame_section = dwarf_eh_frame_section;
/* 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
DW_EH_PE_datarel encoding. */
- got = bfd_get_section_by_name (unit.abfd, ".got");
+ got = bfd_get_section_by_name (unit->abfd, ".got");
if (got)
- unit.dbase = got->vma;
+ unit->dbase = got->vma;
/* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64
so far. */
- txt = bfd_get_section_by_name (unit.abfd, ".text");
+ txt = bfd_get_section_by_name (unit->abfd, ".text");
if (txt)
- unit.tbase = txt->vma;
+ unit->tbase = txt->vma;
- 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 = unit->dwarf_frame_buffer;
+ while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size)
+ frame_ptr = decode_frame_entry (unit, frame_ptr, 1);
}
if (dwarf_frame_section)
{
- unit.cie = NULL;
- unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
+ unit->cie = NULL;
+ unit->dwarf_frame_buffer = dwarf2_read_section (objfile,
dwarf_frame_section);
- unit.dwarf_frame_size = bfd_get_section_size (dwarf_frame_section);
- unit.dwarf_frame_section = dwarf_frame_section;
+ unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section);
+ unit->dwarf_frame_section = dwarf_frame_section;
- 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 = unit->dwarf_frame_buffer;
+ while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size)
+ frame_ptr = decode_frame_entry (unit, frame_ptr, 0);
}
}