* Makefile.in (dwarf2-frame.o): Add complaints_h.
* dwarf2-frame.c: Include complaints.h. (decode_frame_entry_1): Rename from decode_frame_entry; tidy variable initialization; return NULL on error. (decode_frame_entry): New.
This commit is contained in:
parent
c4a095243b
commit
6896c0c737
3 changed files with 138 additions and 18 deletions
|
@ -1,3 +1,11 @@
|
|||
2003-07-11 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* Makefile.in (dwarf2-frame.o): Add complaints_h.
|
||||
* dwarf2-frame.c: Include complaints.h.
|
||||
(decode_frame_entry_1): Rename from decode_frame_entry; tidy
|
||||
variable initialization; return NULL on error.
|
||||
(decode_frame_entry): New.
|
||||
|
||||
2003-07-11 Andrew Cagney <cagney@redhat.com>
|
||||
|
||||
* frame.h (frame_address_in_block): Delete declaration.
|
||||
|
|
|
@ -1680,7 +1680,7 @@ dwarf2loc.o: dwarf2loc.c $(defs_h) $(ui_out_h) $(value_h) $(frame_h) \
|
|||
dwarf2-frame.o: $(defs_h) $(dwarf2expr_h) $(elf_dwarf2_h) $(frame_h) \
|
||||
$(frame_base_h) $(frame_unwind_h) $(gdbcore_h) $(gdbtypes_h) \
|
||||
$(symtab_h) $(objfiles_h) $(regcache_h) $(gdb_assert_h) \
|
||||
$(gdb_string_h) $(dwarf2_frame_h)
|
||||
$(gdb_string_h) $(dwarf2_frame_h) $(complaints_h)
|
||||
dwarf2read.o: dwarf2read.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
|
||||
$(symfile_h) $(objfiles_h) $(elf_dwarf2_h) $(buildsym_h) \
|
||||
$(demangle_h) $(expression_h) $(filenames_h) $(macrotab_h) \
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "gdb_assert.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "complaints.h"
|
||||
#include "dwarf2-frame.h"
|
||||
|
||||
/* Call Frame Information (CFI). */
|
||||
|
@ -1058,35 +1059,44 @@ add_fde (struct comp_unit *unit, struct dwarf2_fde *fde)
|
|||
#define DW64_CIE_ID ~0
|
||||
#endif
|
||||
|
||||
/* Read a CIE or FDE in BUF and decode it. */
|
||||
static char *decode_frame_entry (struct comp_unit *unit, char *start,
|
||||
int eh_frame_p);
|
||||
|
||||
/* Decode the next CIE or FDE. Return NULL if invalid input, otherwise
|
||||
the next byte to be processed. */
|
||||
static char *
|
||||
decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
|
||||
decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p)
|
||||
{
|
||||
char *buf;
|
||||
LONGEST length;
|
||||
unsigned int bytes_read;
|
||||
int dwarf64_p = 0;
|
||||
ULONGEST cie_id = DW_CIE_ID;
|
||||
int dwarf64_p;
|
||||
ULONGEST cie_id;
|
||||
ULONGEST cie_pointer;
|
||||
char *start = buf;
|
||||
char *end;
|
||||
|
||||
buf = start;
|
||||
length = read_initial_length (unit->abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
end = buf + length;
|
||||
|
||||
/* Are we still within the section? */
|
||||
if (end > unit->dwarf_frame_buffer + unit->dwarf_frame_size)
|
||||
return NULL;
|
||||
|
||||
if (length == 0)
|
||||
return end;
|
||||
|
||||
if (bytes_read == 12)
|
||||
dwarf64_p = 1;
|
||||
/* Distinguish between 32 and 64-bit encoded frame info. */
|
||||
dwarf64_p = (bytes_read == 12);
|
||||
|
||||
/* In a .eh_frame section, zero is used to distinguish CIEs from
|
||||
FDEs. */
|
||||
/* In a .eh_frame section, zero is used to distinguish CIEs from FDEs. */
|
||||
if (eh_frame_p)
|
||||
cie_id = 0;
|
||||
else if (dwarf64_p)
|
||||
cie_id = DW64_CIE_ID;
|
||||
else
|
||||
cie_id = DW_CIE_ID;
|
||||
|
||||
if (dwarf64_p)
|
||||
{
|
||||
|
@ -1124,7 +1134,8 @@ decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
|
|||
cie->encoding = encoding_for_size (unit->addr_size);
|
||||
|
||||
/* Check version number. */
|
||||
gdb_assert (read_1_byte (unit->abfd, buf) == DW_CIE_VERSION);
|
||||
if (read_1_byte (unit->abfd, buf) != DW_CIE_VERSION)
|
||||
return NULL;
|
||||
buf += 1;
|
||||
|
||||
/* Interpret the interesting bits of the augmentation. */
|
||||
|
@ -1159,6 +1170,8 @@ decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
|
|||
|
||||
length = read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
|
||||
buf += bytes_read;
|
||||
if (buf > end)
|
||||
return NULL;
|
||||
cie->initial_instructions = buf + length;
|
||||
augmentation++;
|
||||
}
|
||||
|
@ -1211,16 +1224,20 @@ decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
|
|||
/* This is a FDE. */
|
||||
struct dwarf2_fde *fde;
|
||||
|
||||
/* In an .eh_frame section, the CIE pointer is the delta between the
|
||||
address within the FDE where the CIE pointer is stored and the
|
||||
address of the CIE. Convert it to an offset into the .eh_frame
|
||||
section. */
|
||||
if (eh_frame_p)
|
||||
{
|
||||
/* In an .eh_frame section, the CIE pointer is the delta
|
||||
between the address within the FDE where the CIE pointer
|
||||
is stored and the address of the CIE. Convert it to an
|
||||
offset into the .eh_frame section. */
|
||||
cie_pointer = buf - unit->dwarf_frame_buffer - cie_pointer;
|
||||
cie_pointer -= (dwarf64_p ? 8 : 4);
|
||||
}
|
||||
|
||||
/* In either case, validate the result is still within the section. */
|
||||
if (cie_pointer >= unit->dwarf_frame_size)
|
||||
return NULL;
|
||||
|
||||
fde = (struct dwarf2_fde *)
|
||||
obstack_alloc (&unit->objfile->psymbol_obstack,
|
||||
sizeof (struct dwarf2_fde));
|
||||
|
@ -1252,6 +1269,8 @@ decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
|
|||
|
||||
length = read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
|
||||
buf += bytes_read + length;
|
||||
if (buf > end)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fde->instructions = buf;
|
||||
|
@ -1262,6 +1281,99 @@ decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
|
|||
|
||||
return end;
|
||||
}
|
||||
|
||||
/* Read a CIE or FDE in BUF and decode it. */
|
||||
static char *
|
||||
decode_frame_entry (struct comp_unit *unit, char *start, int eh_frame_p)
|
||||
{
|
||||
enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE;
|
||||
char *ret;
|
||||
const char *msg;
|
||||
ptrdiff_t start_offset;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ret = decode_frame_entry_1 (unit, start, eh_frame_p);
|
||||
if (ret != NULL)
|
||||
break;
|
||||
|
||||
/* We have corrupt input data of some form. */
|
||||
|
||||
/* ??? Try, weakly, to work around compiler/assembler/linker bugs
|
||||
and mismatches wrt padding and alignment of debug sections. */
|
||||
/* Note that there is no requirement in the standard for any
|
||||
alignment at all in the frame unwind sections. Testing for
|
||||
alignment before trying to interpret data would be incorrect.
|
||||
|
||||
However, GCC traditionally arranged for frame sections to be
|
||||
sized such that the FDE length and CIE fields happen to be
|
||||
aligned (in theory, for performance). This, unfortunately,
|
||||
was done with .align directives, which had the side effect of
|
||||
forcing the section to be aligned by the linker.
|
||||
|
||||
This becomes a problem when you have some other producer that
|
||||
creates frame sections that are not as strictly aligned. That
|
||||
produces a hole in the frame info that gets filled by the
|
||||
linker with zeros.
|
||||
|
||||
The GCC behaviour is arguably a bug, but it's effectively now
|
||||
part of the ABI, so we're now stuck with it, at least at the
|
||||
object file level. A smart linker may decide, in the process
|
||||
of compressing duplicate CIE information, that it can rewrite
|
||||
the entire output section without this extra padding. */
|
||||
|
||||
start_offset = start - unit->dwarf_frame_buffer;
|
||||
if (workaround < ALIGN4 && (start_offset & 3) != 0)
|
||||
{
|
||||
start += 4 - (start_offset & 3);
|
||||
workaround = ALIGN4;
|
||||
continue;
|
||||
}
|
||||
if (workaround < ALIGN8 && (start_offset & 7) != 0)
|
||||
{
|
||||
start += 8 - (start_offset & 7);
|
||||
workaround = ALIGN8;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Nothing left to try. Arrange to return as if we've consumed
|
||||
the entire input section. Hopefully we'll get valid info from
|
||||
the other of .debug_frame/.eh_frame. */
|
||||
workaround = FAIL;
|
||||
ret = unit->dwarf_frame_buffer + unit->dwarf_frame_size;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (workaround)
|
||||
{
|
||||
case NONE:
|
||||
break;
|
||||
|
||||
case ALIGN4:
|
||||
complaint (&symfile_complaints,
|
||||
"Corrupt data in %s:%s; align 4 workaround apparently succeeded",
|
||||
unit->dwarf_frame_section->owner->filename,
|
||||
unit->dwarf_frame_section->name);
|
||||
break;
|
||||
|
||||
case ALIGN8:
|
||||
complaint (&symfile_complaints,
|
||||
"Corrupt data in %s:%s; align 8 workaround apparently succeeded",
|
||||
unit->dwarf_frame_section->owner->filename,
|
||||
unit->dwarf_frame_section->name);
|
||||
break;
|
||||
|
||||
default:
|
||||
complaint (&symfile_complaints,
|
||||
"Corrupt data in %s:%s",
|
||||
unit->dwarf_frame_section->owner->filename,
|
||||
unit->dwarf_frame_section->name);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FIXME: kettenis/20030504: This still needs to be integrated with
|
||||
|
@ -1307,9 +1419,9 @@ dwarf2_build_frame_info (struct objfile *objfile)
|
|||
unit.dwarf_frame_section = dwarf_eh_frame_section;
|
||||
|
||||
/* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base
|
||||
that for the i386/amd64 target, which currently is the only
|
||||
target in GCC that supports/uses the DW_EH_PE_datarel
|
||||
encoding. */
|
||||
that 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");
|
||||
if (got)
|
||||
unit.dbase = got->vma;
|
||||
|
|
Loading…
Reference in a new issue