summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2004-12-27 21:05:11 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2004-12-27 21:05:11 +0000
commit311c1ff761b379d3153990352c7db19847b1e55b (patch)
tree256097d36fd4820b27384584e1b480afd8166131 /gnu/usr.bin/binutils
parente444e031e285774704f9c5be30a382edc9f713d7 (diff)
Don't crash on intermixed 32-bit and 64-bit DWARF sections.
Diffstat (limited to 'gnu/usr.bin/binutils')
-rw-r--r--gnu/usr.bin/binutils/gdb/dwarf2read.c175
1 files changed, 90 insertions, 85 deletions
diff --git a/gnu/usr.bin/binutils/gdb/dwarf2read.c b/gnu/usr.bin/binutils/gdb/dwarf2read.c
index 420bea094bd..96f9e0f8551 100644
--- a/gnu/usr.bin/binutils/gdb/dwarf2read.c
+++ b/gnu/usr.bin/binutils/gdb/dwarf2read.c
@@ -1,4 +1,5 @@
/* DWARF 2 debugging format support for GDB.
+
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004
Free Software Foundation, Inc.
@@ -219,43 +220,40 @@ asection *dwarf_eh_frame_section;
/* The data in a compilation unit header, after target2host
translation, looks like this. */
struct comp_unit_head
- {
- unsigned long length;
- short version;
- unsigned int abbrev_offset;
- unsigned char addr_size;
- unsigned char signed_addr_p;
- unsigned int offset_size; /* size of file offsets; either 4 or 8 */
- unsigned int initial_length_size; /* size of the length field; either
- 4 or 12 */
-
- /* Offset to the first byte of this compilation unit header in the
- * .debug_info section, for resolving relative reference dies. */
-
- unsigned int offset;
-
- /* Pointer to this compilation unit header in the .debug_info
- * section */
-
- char *cu_head_ptr;
+{
+ unsigned long length;
+ short version;
+ unsigned int abbrev_offset;
+ unsigned char addr_size;
+ unsigned char signed_addr_p;
- /* Pointer to the first die of this compilatio unit. This will
- * be the first byte following the compilation unit header. */
+ /* Size of file offsets; either 4 or 8. */
+ unsigned int offset_size;
- char *first_die_ptr;
+ /* Size of the length field; either 4 or 12. */
+ unsigned int initial_length_size;
- /* Pointer to the next compilation unit header in the program. */
+ /* Offset to the first byte of this compilation unit header in the
+ .debug_info section, for resolving relative reference dies. */
+ unsigned int offset;
- struct comp_unit_head *next;
+ /* Pointer to this compilation unit header in the .debug_info
+ section. */
+ char *cu_head_ptr;
- /* Base address of this compilation unit. */
+ /* Pointer to the first die of this compilation unit. This will be
+ the first byte following the compilation unit header. */
+ char *first_die_ptr;
- CORE_ADDR base_address;
+ /* Pointer to the next compilation unit header in the program. */
+ struct comp_unit_head *next;
- /* Non-zero if base_address has been set. */
+ /* Base address of this compilation unit. */
+ CORE_ADDR base_address;
- int base_known;
- };
+ /* Non-zero if base_address has been set. */
+ int base_known;
+};
/* Fixed size for the DIE hash table. */
#ifndef REF_HASH_SIZE
@@ -1245,6 +1243,7 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
struct comp_unit_head cu_header;
int bytes_read;
+ cu_header.initial_length_size = 0;
entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
&bytes_read);
pubnames_ptr += bytes_read;
@@ -1263,7 +1262,7 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
#endif
/* Read in the comp unit header information from the debug_info at
- info_ptr. */
+ info_ptr. */
static char *
read_comp_unit_head (struct comp_unit_head *cu_header,
@@ -1271,6 +1270,7 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
{
int signed_addr;
int bytes_read;
+
cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
&bytes_read);
info_ptr += bytes_read;
@@ -1535,6 +1535,9 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
+ info_ptr = beg_of_comp_unit + cu.header.length
+ + cu.header.initial_length_size;
+
if (comp_unit_die.has_stmt_list)
{
/* Get the list of files included in the current compilation unit,
@@ -1542,9 +1545,6 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst);
}
- info_ptr = beg_of_comp_unit + cu.header.length
- + cu.header.initial_length_size;
-
do_cleanups (back_to_inner);
}
do_cleanups (back_to);
@@ -1634,6 +1634,7 @@ create_all_comp_units (struct objfile *objfile)
/* Read just enough information to find out where the next
compilation unit is. */
+ cu_header.initial_length_size = 0;
cu_header.length = read_initial_length (objfile->obfd, info_ptr,
&cu_header, &bytes_read);
@@ -5841,18 +5842,18 @@ read_address (bfd *abfd, char *buf, struct dwarf2_cu *cu, int *bytes_read)
sense for the 32-bit format, this initial zero can be considered to
be an escape value which indicates the presence of the older 64-bit
format. As written, the code can't detect (old format) lengths
- greater than 4GB. If it becomes necessary to handle lengths somewhat
- larger than 4GB, we could allow other small values (such as the
- non-sensical values of 1, 2, and 3) to also be used as escape values
- indicating the presence of the old format.
+ greater than 4GB. If it becomes necessary to handle lengths
+ somewhat larger than 4GB, we could allow other small values (such
+ as the non-sensical values of 1, 2, and 3) to also be used as
+ escape values indicating the presence of the old format.
- The value returned via bytes_read should be used to increment
- the relevant pointer after calling read_initial_length().
+ The value returned via bytes_read should be used to increment the
+ relevant pointer after calling read_initial_length().
As a side effect, this function sets the fields initial_length_size
and offset_size in cu_header to the values appropriate for the
length field. (The format of the initial length field determines
- the width of file offsets to be fetched later with fetch_offset().)
+ the width of file offsets to be fetched later with read_offset().)
[ Note: read_initial_length() and read_offset() are based on the
document entitled "DWARF Debugging Information Format", revision
@@ -5864,8 +5865,8 @@ read_address (bfd *abfd, char *buf, struct dwarf2_cu *cu, int *bytes_read)
This document is only a draft and is subject to change. (So beware.)
Details regarding the older, non-standard 64-bit format were
- determined empirically by examining 64-bit ELF files produced
- by the SGI toolchain on an IRIX 6.5 machine.
+ determined empirically by examining 64-bit ELF files produced by
+ the SGI toolchain on an IRIX 6.5 machine.
- Kevin, July 16, 2002
] */
@@ -5874,47 +5875,45 @@ static LONGEST
read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
int *bytes_read)
{
- LONGEST retval = 0;
-
- retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ LONGEST length = bfd_get_32 (abfd, (bfd_byte *) buf);
- if (retval == 0xffffffff)
+ if (length == 0xffffffff)
{
- retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+ length = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
*bytes_read = 12;
- if (cu_header != NULL)
- {
- cu_header->initial_length_size = 12;
- cu_header->offset_size = 8;
- }
}
- else if (retval == 0)
+ else if (length == 0)
{
- /* Handle (non-standard) 64-bit DWARF2 formats such as that used
- by IRIX. */
- retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ /* Handle the (non-standard) 64-bit DWARF2 format used by IRIX. */
+ length = bfd_get_64 (abfd, (bfd_byte *) buf);
*bytes_read = 8;
- if (cu_header != NULL)
- {
- cu_header->initial_length_size = 8;
- cu_header->offset_size = 8;
- }
}
else
{
*bytes_read = 4;
- if (cu_header != NULL)
- {
- cu_header->initial_length_size = 4;
- cu_header->offset_size = 4;
- }
}
- return retval;
+ if (cu_header)
+ {
+ gdb_assert (cu_header->initial_length_size == 0
+ || cu_header->initial_length_size == 4
+ || cu_header->initial_length_size == 8
+ || cu_header->initial_length_size == 12);
+
+ if (cu_header->initial_length_size != 0
+ && cu_header->initial_length_size != *bytes_read)
+ complaint (&symfile_complaints,
+ "intermixed 32-bit and 64-bit DWARF sections");
+
+ cu_header->initial_length_size = *bytes_read;
+ cu_header->offset_size = (*bytes_read == 4) ? 4 : 8;
+ }
+
+ return length;
}
/* Read an offset from the data stream. The size of the offset is
- given by cu_header->offset_size. */
+ given by cu_header->offset_size. */
static LONGEST
read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
@@ -5938,7 +5937,7 @@ read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
bfd_get_filename (abfd));
}
- return retval;
+ return retval;
}
static char *
@@ -6272,8 +6271,8 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
return 0;
}
- /* Make sure that at least there's room for the total_length field. That
- could be 12 bytes long, but we're just going to fudge that. */
+ /* Make sure that at least there's room for the total_length field.
+ That could be 12 bytes long, but we're just going to fudge that. */
if (offset + 4 >= dwarf2_per_objfile->line_size)
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
@@ -6287,8 +6286,9 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
line_ptr = dwarf2_per_objfile->line_buffer + offset;
- /* read in the header */
- lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+ /* Read in the header. */
+ lh->total_length =
+ read_initial_length (abfd, line_ptr, &cu->header, &bytes_read);
line_ptr += bytes_read;
if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer
+ dwarf2_per_objfile->line_size))
@@ -6321,7 +6321,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
line_ptr += 1;
}
- /* Read directory table */
+ /* Read directory table. */
while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
line_ptr += bytes_read;
@@ -6329,7 +6329,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
}
line_ptr += bytes_read;
- /* Read file name table */
+ /* Read file name table. */
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
unsigned int dir_index, mod_time, length;
@@ -6457,6 +6457,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
are 1-based. */
struct file_entry *fe = &lh->file_names[file - 1];
char *dir;
+
if (fe->dir_index)
dir = lh->include_dirs[fe->dir_index - 1];
else
@@ -6464,14 +6465,15 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
dwarf2_start_subfile (fe->name, dir);
}
- /* Decode the table. */
+ /* Decode the table. */
while (!end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
if (op_code >= lh->opcode_base)
- { /* Special operand. */
+ {
+ /* Special operand. */
adj_opcode = op_code - lh->opcode_base;
address += (adj_opcode / lh->line_range)
* lh->minimum_instruction_length;
@@ -6479,7 +6481,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p)
{
- /* append row to matrix using current values */
+ /* Append row to matrix using current values. */
record_line (current_subfile, line,
check_cu_functions (address, cu));
}
@@ -6548,11 +6550,12 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
break;
case DW_LNS_set_file:
{
- /* lh->include_dirs and lh->file_names are 0-based,
- but the directory and file name numbers in the
- statement program are 1-based. */
+ /* The arrays lh->include_dirs and lh->file_names are
+ 0-based, but the directory and file name numbers in
+ the statement program are 1-based. */
struct file_entry *fe;
char *dir;
+
file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
fe = &lh->file_names[file - 1];
@@ -6576,9 +6579,9 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
break;
/* Add to the address register of the state machine the
address increment value corresponding to special opcode
- 255. Ie, this value is scaled by the minimum instruction
- length since special opcode 255 would have scaled the
- the increment. */
+ 255. I.e., this value is scaled by the minimum
+ instruction length since special opcode 255 would have
+ scaled the the increment. */
case DW_LNS_const_add_pc:
address += (lh->minimum_instruction_length
* ((255 - lh->opcode_base) / lh->line_range));
@@ -6588,8 +6591,10 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
line_ptr += 2;
break;
default:
- { /* Unknown standard opcode, ignore it. */
+ {
+ /* Unknown standard opcode, ignore it. */
int i;
+
for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
{
(void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);