[binutils patch] DWARF-5: Extend bfd/dwarf2.c parse_comp_unit()

bfd/
2017-07-04  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* dwarf2.c (struct dwarf2_debug): Add fields dwarf_line_str_buffer and
	dwarf_line_str_size.
	(struct attr_abbrev): Add field implicit_const.
	(dwarf_debug_sections): Add .debug_line_str.
	(enum dwarf_debug_section_enum): Add debug_line_str and debug_max.
	(dwarf_debug_section_assert): Add static assertion.
	(read_indirect_line_string): New.
	(read_abbrevs): Support DW_FORM_implicit_const.
	(is_str_attr): Support DW_FORM_line_strp.
	(read_attribute_value): Support DW_FORM_line_strp and
	DW_FORM_implicit_const.
	(read_attribute): Support DW_FORM_implicit_const.
	(line_info_add_include_dir, line_info_add_include_dir_stub):
	(line_info_add_file_name, read_formatted_entries): New.
	(decode_line_info, parse_comp_unit): Support DWARF 5.
	(_bfd_dwarf2_cleanup_debug_info): Free dwarf_line_str_buffer.
This commit is contained in:
Jan Kratochvil
2017-07-04 10:09:27 +02:00
parent 568fc4f4f8
commit 0041f7df74
2 changed files with 399 additions and 71 deletions

View File

@ -1,3 +1,22 @@
2017-07-04 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwarf2.c (struct dwarf2_debug): Add fields dwarf_line_str_buffer and
dwarf_line_str_size.
(struct attr_abbrev): Add field implicit_const.
(dwarf_debug_sections): Add .debug_line_str.
(enum dwarf_debug_section_enum): Add debug_line_str and debug_max.
(dwarf_debug_section_assert): Add static assertion.
(read_indirect_line_string): New.
(read_abbrevs): Support DW_FORM_implicit_const.
(is_str_attr): Support DW_FORM_line_strp.
(read_attribute_value): Support DW_FORM_line_strp and
DW_FORM_implicit_const.
(read_attribute): Support DW_FORM_implicit_const.
(line_info_add_include_dir, line_info_add_include_dir_stub):
(line_info_add_file_name, read_formatted_entries): New.
(decode_line_info, parse_comp_unit): Support DWARF 5.
(_bfd_dwarf2_cleanup_debug_info): Free dwarf_line_str_buffer.
2017-07-03 Egeyar Bagcioglu <egeyar.bagcioglu@oracle.com> 2017-07-03 Egeyar Bagcioglu <egeyar.bagcioglu@oracle.com>
* elfxx-sparc.c (_bfd_sparc_elf_finish_dynamic_symbol): Remove the * elfxx-sparc.c (_bfd_sparc_elf_finish_dynamic_symbol): Remove the

View File

@ -150,6 +150,12 @@ struct dwarf2_debug
/* Length of the loaded .debug_str section. */ /* Length of the loaded .debug_str section. */
bfd_size_type dwarf_str_size; bfd_size_type dwarf_str_size;
/* Pointer to the .debug_line_str section loaded into memory. */
bfd_byte *dwarf_line_str_buffer;
/* Length of the loaded .debug_line_str section. */
bfd_size_type dwarf_line_str_size;
/* Pointer to the .debug_ranges section loaded into memory. */ /* Pointer to the .debug_ranges section loaded into memory. */
bfd_byte *dwarf_ranges_buffer; bfd_byte *dwarf_ranges_buffer;
@ -306,6 +312,7 @@ struct attr_abbrev
{ {
enum dwarf_attribute name; enum dwarf_attribute name;
enum dwarf_form form; enum dwarf_form form;
bfd_vma implicit_const;
}; };
/* Map of uncompressed DWARF debug section name to compressed one. It /* Map of uncompressed DWARF debug section name to compressed one. It
@ -329,6 +336,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
{ ".debug_static_vars", ".zdebug_static_vars" }, { ".debug_static_vars", ".zdebug_static_vars" },
{ ".debug_str", ".zdebug_str", }, { ".debug_str", ".zdebug_str", },
{ ".debug_str", ".zdebug_str", }, { ".debug_str", ".zdebug_str", },
{ ".debug_line_str", ".zdebug_line_str", },
{ ".debug_types", ".zdebug_types" }, { ".debug_types", ".zdebug_types" },
/* GNU DWARF 1 extensions */ /* GNU DWARF 1 extensions */
{ ".debug_sfnames", ".zdebug_sfnames" }, { ".debug_sfnames", ".zdebug_sfnames" },
@ -361,15 +369,21 @@ enum dwarf_debug_section_enum
debug_static_vars, debug_static_vars,
debug_str, debug_str,
debug_str_alt, debug_str_alt,
debug_line_str,
debug_types, debug_types,
debug_sfnames, debug_sfnames,
debug_srcinfo, debug_srcinfo,
debug_funcnames, debug_funcnames,
debug_typenames, debug_typenames,
debug_varnames, debug_varnames,
debug_weaknames debug_weaknames,
debug_max
}; };
/* A static assertion. */
extern int dwarf_debug_section_assert[ARRAY_SIZE (dwarf_debug_sections)
== debug_max + 1 ? 1 : -1];
#ifndef ABBREV_HASH_SIZE #ifndef ABBREV_HASH_SIZE
#define ABBREV_HASH_SIZE 121 #define ABBREV_HASH_SIZE 121
#endif #endif
@ -703,6 +717,45 @@ read_indirect_string (struct comp_unit * unit,
return str; return str;
} }
/* Like read_indirect_string but from .debug_line_str section. */
static char *
read_indirect_line_string (struct comp_unit * unit,
bfd_byte * buf,
bfd_byte * buf_end,
unsigned int * bytes_read_ptr)
{
bfd_uint64_t offset;
struct dwarf2_debug *stash = unit->stash;
char *str;
if (buf + unit->offset_size > buf_end)
{
* bytes_read_ptr = 0;
return NULL;
}
if (unit->offset_size == 4)
offset = read_4_bytes (unit->abfd, buf, buf_end);
else
offset = read_8_bytes (unit->abfd, buf, buf_end);
*bytes_read_ptr = unit->offset_size;
if (! read_section (unit->abfd, &stash->debug_sections[debug_line_str],
stash->syms, offset,
&stash->dwarf_line_str_buffer,
&stash->dwarf_line_str_size))
return NULL;
if (offset >= stash->dwarf_line_str_size)
return NULL;
str = (char *) stash->dwarf_line_str_buffer + offset;
if (*str == '\0')
return NULL;
return str;
}
/* Like read_indirect_string but uses a .debug_str located in /* Like read_indirect_string but uses a .debug_str located in
an alternate file pointed to by the .gnu_debugaltlink section. an alternate file pointed to by the .gnu_debugaltlink section.
Used to impement DW_FORM_GNU_strp_alt. */ Used to impement DW_FORM_GNU_strp_alt. */
@ -928,15 +981,28 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
abbrev_ptr += 1; abbrev_ptr += 1;
/* Now read in declarations. */ /* Now read in declarations. */
for (;;)
{
/* Initialize it just to avoid a GCC false warning. */
bfd_vma implicit_const = -1;
abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
FALSE, abbrev_end); FALSE, abbrev_end);
abbrev_ptr += bytes_read; abbrev_ptr += bytes_read;
abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
FALSE, abbrev_end); FALSE, abbrev_end);
abbrev_ptr += bytes_read; abbrev_ptr += bytes_read;
if (abbrev_form == DW_FORM_implicit_const)
while (abbrev_name)
{ {
implicit_const = _bfd_safe_read_leb128 (abfd, abbrev_ptr,
&bytes_read, TRUE,
abbrev_end);
abbrev_ptr += bytes_read;
}
if (abbrev_name == 0)
break;
if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0) if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
{ {
struct attr_abbrev *tmp; struct attr_abbrev *tmp;
@ -965,14 +1031,11 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
cur_abbrev->attrs[cur_abbrev->num_attrs].name cur_abbrev->attrs[cur_abbrev->num_attrs].name
= (enum dwarf_attribute) abbrev_name; = (enum dwarf_attribute) abbrev_name;
cur_abbrev->attrs[cur_abbrev->num_attrs++].form cur_abbrev->attrs[cur_abbrev->num_attrs].form
= (enum dwarf_form) abbrev_form; = (enum dwarf_form) abbrev_form;
abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, cur_abbrev->attrs[cur_abbrev->num_attrs].implicit_const
FALSE, abbrev_end); = implicit_const;
abbrev_ptr += bytes_read; ++cur_abbrev->num_attrs;
abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
FALSE, abbrev_end);
abbrev_ptr += bytes_read;
} }
hash_number = abbrev_number % ABBREV_HASH_SIZE; hash_number = abbrev_number % ABBREV_HASH_SIZE;
@ -1004,7 +1067,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
static inline bfd_boolean static inline bfd_boolean
is_str_attr (enum dwarf_form form) is_str_attr (enum dwarf_form form)
{ {
return form == DW_FORM_string || form == DW_FORM_strp || form == DW_FORM_GNU_strp_alt; return (form == DW_FORM_string || form == DW_FORM_strp
|| form == DW_FORM_line_strp || form == DW_FORM_GNU_strp_alt);
} }
/* Read and fill in the value of attribute ATTR as described by FORM. /* Read and fill in the value of attribute ATTR as described by FORM.
@ -1014,6 +1078,7 @@ is_str_attr (enum dwarf_form form)
static bfd_byte * static bfd_byte *
read_attribute_value (struct attribute * attr, read_attribute_value (struct attribute * attr,
unsigned form, unsigned form,
bfd_vma implicit_const,
struct comp_unit * unit, struct comp_unit * unit,
bfd_byte * info_ptr, bfd_byte * info_ptr,
bfd_byte * info_ptr_end) bfd_byte * info_ptr_end)
@ -1101,6 +1166,10 @@ read_attribute_value (struct attribute * attr,
attr->u.str = read_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read); attr->u.str = read_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
info_ptr += bytes_read; info_ptr += bytes_read;
break; break;
case DW_FORM_line_strp:
attr->u.str = read_indirect_line_string (unit, info_ptr, info_ptr_end, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_GNU_strp_alt: case DW_FORM_GNU_strp_alt:
attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read); attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
info_ptr += bytes_read; info_ptr += bytes_read;
@ -1179,7 +1248,18 @@ read_attribute_value (struct attribute * attr,
form = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, form = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
FALSE, info_ptr_end); FALSE, info_ptr_end);
info_ptr += bytes_read; info_ptr += bytes_read;
info_ptr = read_attribute_value (attr, form, unit, info_ptr, info_ptr_end); if (form == DW_FORM_implicit_const)
{
implicit_const = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
TRUE, info_ptr_end);
info_ptr += bytes_read;
}
info_ptr = read_attribute_value (attr, form, implicit_const, unit,
info_ptr, info_ptr_end);
break;
case DW_FORM_implicit_const:
attr->form = DW_FORM_sdata;
attr->u.sval = implicit_const;
break; break;
default: default:
_bfd_error_handler (_("Dwarf Error: Invalid or unhandled FORM value: %#x."), _bfd_error_handler (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
@ -1200,7 +1280,8 @@ read_attribute (struct attribute * attr,
bfd_byte * info_ptr_end) bfd_byte * info_ptr_end)
{ {
attr->name = abbrev->name; attr->name = abbrev->name;
info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr, info_ptr_end); info_ptr = read_attribute_value (attr, abbrev->form, abbrev->implicit_const,
unit, info_ptr, info_ptr_end);
return info_ptr; return info_ptr;
} }
@ -1734,6 +1815,195 @@ sort_line_sequences (struct line_info_table* table)
return TRUE; return TRUE;
} }
/* Add directory to TABLE. CUR_DIR memory ownership is taken by TABLE. */
static bfd_boolean
line_info_add_include_dir (struct line_info_table *table, char *cur_dir)
{
if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)
{
char **tmp;
bfd_size_type amt;
amt = table->num_dirs + DIR_ALLOC_CHUNK;
amt *= sizeof (char *);
tmp = (char **) bfd_realloc (table->dirs, amt);
if (tmp == NULL)
return FALSE;
table->dirs = tmp;
}
table->dirs[table->num_dirs++] = cur_dir;
return TRUE;
}
static bfd_boolean
line_info_add_include_dir_stub (struct line_info_table *table, char *cur_dir,
unsigned int dir ATTRIBUTE_UNUSED,
unsigned int time ATTRIBUTE_UNUSED,
unsigned int size ATTRIBUTE_UNUSED)
{
return line_info_add_include_dir (table, cur_dir);
}
/* Add file to TABLE. CUR_FILE memory ownership is taken by TABLE. */
static bfd_boolean
line_info_add_file_name (struct line_info_table *table, char *cur_file,
unsigned int dir, unsigned int time, unsigned int size)
{
if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
{
struct fileinfo *tmp;
bfd_size_type amt;
amt = table->num_files + FILE_ALLOC_CHUNK;
amt *= sizeof (struct fileinfo);
tmp = (struct fileinfo *) bfd_realloc (table->files, amt);
if (tmp == NULL)
return FALSE;
table->files = tmp;
}
table->files[table->num_files].name = cur_file;
table->files[table->num_files].dir = dir;
table->files[table->num_files].time = time;
table->files[table->num_files].size = size;
table->num_files++;
return TRUE;
}
/* Read directory or file name entry format, starting with byte of
format count entries, ULEB128 pairs of entry formats, ULEB128 of
entries count and the entries themselves in the described entry
format. */
static bfd_boolean
read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
bfd_byte *buf_end, struct line_info_table *table,
bfd_boolean (*callback) (struct line_info_table *table,
char *cur_file,
unsigned int dir,
unsigned int time,
unsigned int size))
{
bfd *abfd = unit->abfd;
bfd_byte format_count, formati;
bfd_vma data_count, datai;
bfd_byte *buf = *bufp;
bfd_byte *format_header_data;
unsigned int bytes_read;
format_count = read_1_byte (abfd, buf, buf_end);
buf += 1;
format_header_data = buf;
for (formati = 0; formati < format_count; formati++)
{
_bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
buf += bytes_read;
_bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
buf += bytes_read;
}
data_count = _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
buf += bytes_read;
for (datai = 0; datai < data_count; datai++)
{
bfd_byte *format = format_header_data;
struct fileinfo 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;
content_type = _bfd_safe_read_leb128 (abfd, format, &bytes_read,
FALSE, buf_end);
format += bytes_read;
switch (content_type)
{
case DW_LNCT_path:
stringp = &fe.name;
break;
case DW_LNCT_directory_index:
uintp = &fe.dir;
break;
case DW_LNCT_timestamp:
uintp = &fe.time;
break;
case DW_LNCT_size:
uintp = &fe.size;
break;
case DW_LNCT_MD5:
break;
default:
_bfd_error_handler
(_("Dwarf Error: Unknown format content type %lu."),
(unsigned long) content_type);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
form = _bfd_safe_read_leb128 (abfd, format, &bytes_read, FALSE,
buf_end);
format += bytes_read;
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;
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. */
break;
}
}
if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
return FALSE;
}
*bufp = buf;
return TRUE;
}
/* Decode the line number information for UNIT. */ /* Decode the line number information for UNIT. */
static struct line_info_table* static struct line_info_table*
@ -1815,7 +2085,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
line_end = line_ptr + lh.total_length; line_end = line_ptr + lh.total_length;
lh.version = read_2_bytes (abfd, line_ptr, line_end); lh.version = read_2_bytes (abfd, line_ptr, line_end);
if (lh.version < 2 || lh.version > 4) if (lh.version < 2 || lh.version > 5)
{ {
_bfd_error_handler _bfd_error_handler
(_("Dwarf Error: Unhandled .debug_line version %d."), lh.version); (_("Dwarf Error: Unhandled .debug_line version %d."), lh.version);
@ -1824,7 +2094,8 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
} }
line_ptr += 2; line_ptr += 2;
if (line_ptr + offset_size + (lh.version >=4 ? 6 : 5) >= line_end) if (line_ptr + offset_size + (lh.version >= 5 ? 8 : (lh.version >= 4 ? 6 : 5))
>= line_end)
{ {
_bfd_error_handler _bfd_error_handler
(_("Dwarf Error: Ran out of room reading prologue")); (_("Dwarf Error: Ran out of room reading prologue"));
@ -1832,6 +2103,26 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
return NULL; return NULL;
} }
if (lh.version >= 5)
{
unsigned int segment_selector_size;
/* Skip address size. */
read_1_byte (abfd, line_ptr, line_end);
line_ptr += 1;
segment_selector_size = read_1_byte (abfd, line_ptr, line_end);
line_ptr += 1;
if (segment_selector_size != 0)
{
_bfd_error_handler
(_("Dwarf Error: Line info unsupported segment selector size %u."),
segment_selector_size);
bfd_set_error (bfd_error_bad_value);
return NULL;
}
}
if (offset_size == 4) if (offset_size == 4)
lh.prologue_length = read_4_bytes (abfd, line_ptr, line_end); lh.prologue_length = read_4_bytes (abfd, line_ptr, line_end);
else else
@ -1887,25 +2178,27 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
line_ptr += 1; line_ptr += 1;
} }
if (lh.version >= 5)
{
/* Read directory table. */
if (!read_formatted_entries (unit, &line_ptr, line_end, table,
line_info_add_include_dir_stub))
goto fail;
/* Read file name table. */
if (!read_formatted_entries (unit, &line_ptr, line_end, table,
line_info_add_file_name))
goto fail;
}
else
{
/* Read directory table. */ /* Read directory table. */
while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL) while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
{ {
line_ptr += bytes_read; line_ptr += bytes_read;
if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0) if (!line_info_add_include_dir (table, cur_dir))
{
char **tmp;
amt = table->num_dirs + DIR_ALLOC_CHUNK;
amt *= sizeof (char *);
tmp = (char **) bfd_realloc (table->dirs, amt);
if (tmp == NULL)
goto fail; goto fail;
table->dirs = tmp;
}
table->dirs[table->num_dirs++] = cur_dir;
} }
line_ptr += bytes_read; line_ptr += bytes_read;
@ -1913,35 +2206,23 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
/* Read file name table. */ /* Read file name table. */
while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL) while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
{ {
unsigned int dir, time, size;
line_ptr += bytes_read; line_ptr += bytes_read;
if ((table->num_files % FILE_ALLOC_CHUNK) == 0) dir = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
{ line_ptr += bytes_read;
struct fileinfo *tmp; time = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
line_ptr += bytes_read;
size = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
line_ptr += bytes_read;
amt = table->num_files + FILE_ALLOC_CHUNK; if (!line_info_add_file_name (table, cur_file, dir, time, size))
amt *= sizeof (struct fileinfo);
tmp = (struct fileinfo *) bfd_realloc (table->files, amt);
if (tmp == NULL)
goto fail; goto 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);
line_ptr += bytes_read;
table->files[table->num_files].time
= _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);
line_ptr += bytes_read;
table->num_files++;
} }
line_ptr += bytes_read; line_ptr += bytes_read;
}
/* Read the statement sequences until there's nothing left. */ /* Read the statement sequences until there's nothing left. */
while (line_ptr < line_end) while (line_ptr < line_end)
@ -2987,7 +3268,8 @@ parse_comp_unit (struct dwarf2_debug *stash,
struct comp_unit* unit; struct comp_unit* unit;
unsigned int version; unsigned int version;
bfd_uint64_t abbrev_offset = 0; bfd_uint64_t abbrev_offset = 0;
unsigned int addr_size; /* Initialize it just to avoid a GCC false warning. */
unsigned int addr_size = -1;
struct abbrev_info** abbrevs; struct abbrev_info** abbrevs;
unsigned int abbrev_number, bytes_read, i; unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev; struct abbrev_info *abbrev;
@ -2999,19 +3281,11 @@ parse_comp_unit (struct dwarf2_debug *stash,
bfd_vma high_pc = 0; bfd_vma high_pc = 0;
bfd *abfd = stash->bfd_ptr; bfd *abfd = stash->bfd_ptr;
bfd_boolean high_pc_relative = FALSE; bfd_boolean high_pc_relative = FALSE;
enum dwarf_unit_type unit_type;
version = read_2_bytes (abfd, info_ptr, end_ptr); version = read_2_bytes (abfd, info_ptr, end_ptr);
info_ptr += 2; info_ptr += 2;
BFD_ASSERT (offset_size == 4 || offset_size == 8); if (version < 2 || version > 5)
if (offset_size == 4)
abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr);
else
abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr);
info_ptr += offset_size;
addr_size = read_1_byte (abfd, info_ptr, end_ptr);
info_ptr += 1;
if (version != 2 && version != 3 && version != 4)
{ {
/* PR 19872: A version number of 0 probably means that there is padding /* PR 19872: A version number of 0 probably means that there is padding
at the end of the .debug_info section. Gold puts it there when at the end of the .debug_info section. Gold puts it there when
@ -3021,12 +3295,45 @@ parse_comp_unit (struct dwarf2_debug *stash,
{ {
_bfd_error_handler _bfd_error_handler
(_("Dwarf Error: found dwarf version '%u', this reader" (_("Dwarf Error: found dwarf version '%u', this reader"
" only handles version 2, 3 and 4 information."), version); " only handles version 2, 3, 4 and 5 information."), version);
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
} }
return NULL; return NULL;
} }
if (version < 5)
unit_type = DW_UT_compile;
else
{
unit_type = read_1_byte (abfd, info_ptr, end_ptr);
info_ptr += 1;
addr_size = read_1_byte (abfd, info_ptr, end_ptr);
info_ptr += 1;
}
BFD_ASSERT (offset_size == 4 || offset_size == 8);
if (offset_size == 4)
abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr);
else
abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr);
info_ptr += offset_size;
if (version < 5)
{
addr_size = read_1_byte (abfd, info_ptr, end_ptr);
info_ptr += 1;
}
if (unit_type == DW_UT_type)
{
/* Skip type signature. */
info_ptr += 8;
/* Skip type offset. */
info_ptr += offset_size;
}
if (addr_size > sizeof (bfd_vma)) if (addr_size > sizeof (bfd_vma))
{ {
_bfd_error_handler _bfd_error_handler
@ -4576,6 +4883,8 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
free (stash->dwarf_line_buffer); free (stash->dwarf_line_buffer);
if (stash->dwarf_str_buffer) if (stash->dwarf_str_buffer)
free (stash->dwarf_str_buffer); free (stash->dwarf_str_buffer);
if (stash->dwarf_line_str_buffer)
free (stash->dwarf_line_str_buffer);
if (stash->dwarf_ranges_buffer) if (stash->dwarf_ranges_buffer)
free (stash->dwarf_ranges_buffer); free (stash->dwarf_ranges_buffer);
if (stash->info_ptr_memory) if (stash->info_ptr_memory)