/* A pointer to the memory block allocated for info_ptr. Neither
info_ptr nor sec_info_ptr are guaranteed to stay pointing to the
- beginning of the malloc block. This is used only to free the
- memory later. */
+ beginning of the malloc block. */
bfd_byte *info_ptr_memory;
/* Pointer to the symbol table. */
by its reference. */
bfd_byte *info_ptr_unit;
- /* Pointer to the start of the debug section, for DW_FORM_ref_addr. */
- bfd_byte *sec_info_ptr;
-
/* The offset into .debug_line of the line number table. */
unsigned long line_offset;
{
asection *msec;
const char *section_name = sec->uncompressed_name;
+ bfd_byte *contents = *section_buffer;
/* The section may have already been read. */
- if (*section_buffer == NULL)
+ if (contents == NULL)
{
msec = bfd_get_section_by_name (abfd, section_name);
if (! msec)
}
*section_size = msec->rawsize ? msec->rawsize : msec->size;
- if (syms)
- {
- *section_buffer
- = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms);
- if (! *section_buffer)
- return FALSE;
- }
- else
- {
- *section_buffer = (bfd_byte *) bfd_malloc (*section_size);
- if (! *section_buffer)
- return FALSE;
- if (! bfd_get_section_contents (abfd, msec, *section_buffer,
- 0, *section_size))
- return FALSE;
- }
-
- /* Paranoia - if we are reading in a string section, make sure that it
- is NUL terminated. This is to prevent string functions from running
- off the end of the buffer. Note - knowing the size of the buffer is
- not enough as some functions, eg strchr, do not have a range limited
- equivalent.
-
- FIXME: We ought to use a flag in the dwarf_debug_sections[] table to
- determine the nature of a debug section, rather than checking the
- section name as we do here. */
- if (*section_size > 0
- && (*section_buffer)[*section_size - 1] != 0
- && (strstr (section_name, "_str") || strstr (section_name, "names")))
+ /* Paranoia - alloc one extra so that we can make sure a string
+ section is NUL terminated. */
+ contents = (bfd_byte *) bfd_malloc (*section_size + 1);
+ if (contents == NULL)
+ return FALSE;
+ if (syms
+ ? !bfd_simple_get_relocated_section_contents (abfd, msec, contents,
+ syms)
+ : !bfd_get_section_contents (abfd, msec, contents, 0, *section_size))
{
- bfd_byte * new_buffer = malloc (*section_size + 1);
-
- _bfd_error_handler (_("warning: dwarf string section '%s' is not NUL terminated"),
- section_name);
- memcpy (new_buffer, *section_buffer, *section_size);
- new_buffer[*section_size] = 0;
- free (*section_buffer);
- *section_buffer = new_buffer;
+ free (contents);
+ return FALSE;
}
+ contents[*section_size] = 0;
+ *section_buffer = contents;
}
/* It is possible to get a bad value for the offset into the section
}
filename = table->files[file - 1].name;
+ if (filename == NULL)
+ return strdup ("<unknown>");
if (!IS_ABSOLUTE_PATH (filename))
{
return FALSE;
}
+ /* PR 22210. Paranoia check. Don't bother running the loop
+ if we know that we are going to run out of buffer. */
+ if (data_count > (bfd_vma) (buf_end - buf))
+ {
+ _bfd_error_handler (_("Dwarf Error: data count (%Lx) larger than buffer size."),
+ data_count);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
for (datai = 0; datai < data_count; datai++)
{
bfd_byte *format = format_header_data;
struct fileinfo fe;
+ memset (&fe, 0, sizeof fe);
for (formati = 0; formati < format_count; formati++)
{
bfd_vma content_type, form;
char *string_trash;
char **stringp = &string_trash;
unsigned int uint_trash, *uintp = &uint_trash;
+ struct attribute attr;
content_type = _bfd_safe_read_leb128 (abfd, format, &bytes_read,
FALSE, buf_end);
form = _bfd_safe_read_leb128 (abfd, format, &bytes_read, FALSE,
buf_end);
format += bytes_read;
+
+ buf = read_attribute_value (&attr, form, 0, unit, buf, buf_end);
+ if (buf == NULL)
+ return FALSE;
switch (form)
{
case DW_FORM_string:
- *stringp = read_string (abfd, buf, buf_end, &bytes_read);
- buf += bytes_read;
- break;
-
case DW_FORM_line_strp:
- *stringp = read_indirect_line_string (unit, buf, buf_end, &bytes_read);
- buf += bytes_read;
+ *stringp = attr.u.str;
break;
case DW_FORM_data1:
- *uintp = read_1_byte (abfd, buf, buf_end);
- buf += 1;
- break;
-
case DW_FORM_data2:
- *uintp = read_2_bytes (abfd, buf, buf_end);
- buf += 2;
- break;
-
case DW_FORM_data4:
- *uintp = read_4_bytes (abfd, buf, buf_end);
- buf += 4;
- break;
-
case DW_FORM_data8:
- *uintp = read_8_bytes (abfd, buf, buf_end);
- buf += 8;
- break;
-
case DW_FORM_udata:
- *uintp = _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE,
- buf_end);
- buf += bytes_read;
- break;
-
- case DW_FORM_block:
- /* It is valid only for DW_LNCT_timestamp which is ignored by
- current GDB. */
+ *uintp = attr.u.val;
break;
}
}
unsigned int discriminator = 0;
int is_stmt = lh.default_is_stmt;
int end_sequence = 0;
+ unsigned int dir, xtime, size;
/* eraxxon@alumni.rice.edu: Against the DWARF2 specs, some
compilers generate address sequences that are wildly out of
order using DW_LNE_set_address (e.g. Intel C++ 6.0 compiler
bfd_vma high_pc = 0;
/* Decode the table. */
- while (! end_sequence)
+ while (!end_sequence && line_ptr < line_end)
{
op_code = read_1_byte (abfd, line_ptr, line_end);
line_ptr += 1;
case DW_LNE_define_file:
cur_file = read_string (abfd, line_ptr, line_end, &bytes_read);
line_ptr += bytes_read;
- if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
- {
- struct fileinfo *tmp;
-
- amt = table->num_files + FILE_ALLOC_CHUNK;
- amt *= sizeof (struct fileinfo);
- tmp = (struct fileinfo *) bfd_realloc (table->files, amt);
- if (tmp == NULL)
- goto line_fail;
- table->files = tmp;
- }
- table->files[table->num_files].name = cur_file;
- table->files[table->num_files].dir =
- _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
- FALSE, line_end);
+ dir = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
- table->files[table->num_files].time =
- _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
- FALSE, line_end);
+ xtime = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
- table->files[table->num_files].size =
- _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
- FALSE, line_end);
+ size = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
- table->num_files++;
+ if (!line_info_add_file_name (table, cur_file, dir,
+ xtime, size))
+ goto line_fail;
break;
case DW_LNE_set_discriminator:
discriminator =
if (attr_ptr->form == DW_FORM_ref_addr)
{
/* We only support DW_FORM_ref_addr within the same file, so
- any relocations should be resolved already. */
- if (!die_ref)
+ any relocations should be resolved already. Check this by
+ testing for a zero die_ref; There can't be a valid reference
+ to the header of a .debug_info section.
+ DW_FORM_ref_addr is an offset relative to .debug_info.
+ Normally when using the GNU linker this is accomplished by
+ emitting a symbolic reference to a label, because .debug_info
+ sections are linked at zero. When there are multiple section
+ groups containing .debug_info, as there might be in a
+ relocatable object file, it would be reasonable to assume that
+ a symbolic reference to a label in any .debug_info section
+ might be used. Since we lay out multiple .debug_info
+ sections at non-zero VMAs (see place_sections), and read
+ them contiguously into stash->info_ptr_memory, that means
+ the reference is relative to stash->info_ptr_memory. */
+ size_t total;
+
+ info_ptr = unit->stash->info_ptr_memory;
+ info_ptr_end = unit->stash->info_ptr_end;
+ total = info_ptr_end - info_ptr;
+ if (!die_ref || die_ref >= total)
{
_bfd_error_handler
- (_("Dwarf Error: Abstract instance DIE ref zero."));
+ (_("Dwarf Error: Invalid abstract instance DIE ref."));
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
-
- info_ptr = unit->sec_info_ptr + die_ref;
- info_ptr_end = unit->end_ptr;
+ info_ptr += die_ref;
/* Now find the CU containing this pointer. */
if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr)
- ;
+ info_ptr_end = unit->end_ptr;
else
{
/* Check other CUs to see if they contain the abbrev. */
break;
if (u)
- unit = u;
+ {
+ unit = u;
+ info_ptr_end = unit->end_ptr;
+ }
/* else FIXME: What do we do now ? */
}
}
}
else
{
- info_ptr = unit->info_ptr_unit + die_ref;
+ /* DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8 or
+ DW_FORM_ref_udata. These are all references relative to the
+ start of the current CU. */
+ size_t total;
+
+ info_ptr = unit->info_ptr_unit;
info_ptr_end = unit->end_ptr;
+ total = info_ptr_end - info_ptr;
+ if (!die_ref || die_ref >= total)
+ {
+ _bfd_error_handler
+ (_("Dwarf Error: Invalid abstract instance DIE ref."));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ info_ptr += die_ref;
}
abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
switch (attr.name)
{
case DW_AT_name:
- var->name = attr.u.str;
+ if (is_str_attr (attr.form))
+ var->name = attr.u.str;
break;
case DW_AT_decl_file:
unit->end_ptr = end_ptr;
unit->stash = stash;
unit->info_ptr_unit = info_ptr_unit;
- unit->sec_info_ptr = stash->sec_info_ptr;
for (i = 0; i < abbrev->num_attrs; ++i)
{
break;
case DW_AT_name:
- unit->name = attr.u.str;
+ if (is_str_attr (attr.form))
+ unit->name = attr.u.str;
break;
case DW_AT_low_pc: