mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-26 13:56:22 +08:00
PR24623, DWARF errors
PR 24623 * dwarf2.c (stash_comp_unit): New function, extracted from.. (_bfd_dwarf2_find_nearest_line): ..here. (find_abstract_instance): Parse comp units and decode line info as needed.
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
2019-08-14 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR 24623
|
||||||
|
* dwarf2.c (stash_comp_unit): New function, extracted from..
|
||||||
|
(_bfd_dwarf2_find_nearest_line): ..here.
|
||||||
|
(find_abstract_instance): Parse comp units and decode line info
|
||||||
|
as needed.
|
||||||
|
|
||||||
2019-08-14 Alan Modra <amodra@gmail.com>
|
2019-08-14 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* dwarf2.c (comp_unit_maybe_decode_line_info): Declare.
|
* dwarf2.c (comp_unit_maybe_decode_line_info): Declare.
|
||||||
|
193
bfd/dwarf2.c
193
bfd/dwarf2.c
@ -2804,6 +2804,7 @@ lookup_symbol_in_variable_table (struct comp_unit *unit,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct comp_unit *stash_comp_unit (struct dwarf2_debug *);
|
||||||
static bfd_boolean comp_unit_maybe_decode_line_info (struct comp_unit *,
|
static bfd_boolean comp_unit_maybe_decode_line_info (struct comp_unit *,
|
||||||
struct dwarf2_debug *);
|
struct dwarf2_debug *);
|
||||||
|
|
||||||
@ -2877,13 +2878,27 @@ find_abstract_instance (struct comp_unit * unit,
|
|||||||
if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
|
if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (u)
|
while (u == NULL)
|
||||||
{
|
{
|
||||||
|
u = stash_comp_unit (unit->stash);
|
||||||
|
if (u == NULL)
|
||||||
|
break;
|
||||||
|
if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
|
||||||
|
break;
|
||||||
|
u = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u == NULL)
|
||||||
|
{
|
||||||
|
_bfd_error_handler
|
||||||
|
(_("DWARF error: unable to locate abstract instance DIE ref %"
|
||||||
|
PRIu64), (uint64_t) die_ref);
|
||||||
|
bfd_set_error (bfd_error_bad_value);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
unit = u;
|
unit = u;
|
||||||
info_ptr_end = unit->end_ptr;
|
info_ptr_end = unit->end_ptr;
|
||||||
}
|
}
|
||||||
/* else FIXME: What do we do now ? */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
|
else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
|
||||||
{
|
{
|
||||||
@ -2982,6 +2997,8 @@ find_abstract_instance (struct comp_unit * unit,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DW_AT_decl_file:
|
case DW_AT_decl_file:
|
||||||
|
if (!comp_unit_maybe_decode_line_info (unit, unit->stash))
|
||||||
|
return FALSE;
|
||||||
*filename_ptr = concat_filename (unit->line_table,
|
*filename_ptr = concat_filename (unit->line_table,
|
||||||
attr.u.val);
|
attr.u.val);
|
||||||
break;
|
break;
|
||||||
@ -3334,7 +3351,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a DWARF2 compilation unit starting at INFO_PTR. This
|
/* Parse a DWARF2 compilation unit starting at INFO_PTR. UNIT_LENGTH
|
||||||
includes the compilation unit header that proceeds the DIE's, but
|
includes the compilation unit header that proceeds the DIE's, but
|
||||||
does not include the length field that precedes each compilation
|
does not include the length field that precedes each compilation
|
||||||
unit header. END_PTR points one past the end of this comp unit.
|
unit header. END_PTR points one past the end of this comp unit.
|
||||||
@ -4451,6 +4468,90 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse the next DWARF2 compilation unit at STASH->INFO_PTR. */
|
||||||
|
|
||||||
|
static struct comp_unit *
|
||||||
|
stash_comp_unit (struct dwarf2_debug *stash)
|
||||||
|
{
|
||||||
|
bfd_size_type length;
|
||||||
|
unsigned int offset_size;
|
||||||
|
bfd_byte *info_ptr_unit = stash->info_ptr;
|
||||||
|
|
||||||
|
if (stash->info_ptr >= stash->info_ptr_end)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr,
|
||||||
|
stash->info_ptr_end);
|
||||||
|
/* A 0xffffff length is the DWARF3 way of indicating
|
||||||
|
we use 64-bit offsets, instead of 32-bit offsets. */
|
||||||
|
if (length == 0xffffffff)
|
||||||
|
{
|
||||||
|
offset_size = 8;
|
||||||
|
length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4,
|
||||||
|
stash->info_ptr_end);
|
||||||
|
stash->info_ptr += 12;
|
||||||
|
}
|
||||||
|
/* A zero length is the IRIX way of indicating 64-bit offsets,
|
||||||
|
mostly because the 64-bit length will generally fit in 32
|
||||||
|
bits, and the endianness helps. */
|
||||||
|
else if (length == 0)
|
||||||
|
{
|
||||||
|
offset_size = 8;
|
||||||
|
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4,
|
||||||
|
stash->info_ptr_end);
|
||||||
|
stash->info_ptr += 8;
|
||||||
|
}
|
||||||
|
/* In the absence of the hints above, we assume 32-bit DWARF2
|
||||||
|
offsets even for targets with 64-bit addresses, because:
|
||||||
|
a) most of the time these targets will not have generated
|
||||||
|
more than 2Gb of debug info and so will not need 64-bit
|
||||||
|
offsets,
|
||||||
|
and
|
||||||
|
b) if they do use 64-bit offsets but they are not using
|
||||||
|
the size hints that are tested for above then they are
|
||||||
|
not conforming to the DWARF3 standard anyway. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset_size = 4;
|
||||||
|
stash->info_ptr += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length != 0
|
||||||
|
&& stash->info_ptr + length <= stash->info_ptr_end
|
||||||
|
&& stash->info_ptr + length > stash->info_ptr)
|
||||||
|
{
|
||||||
|
struct comp_unit *each = parse_comp_unit (stash, length, info_ptr_unit,
|
||||||
|
offset_size);
|
||||||
|
if (each)
|
||||||
|
{
|
||||||
|
if (stash->all_comp_units)
|
||||||
|
stash->all_comp_units->prev_unit = each;
|
||||||
|
else
|
||||||
|
stash->last_comp_unit = each;
|
||||||
|
|
||||||
|
each->next_unit = stash->all_comp_units;
|
||||||
|
stash->all_comp_units = each;
|
||||||
|
|
||||||
|
stash->info_ptr += length;
|
||||||
|
|
||||||
|
if ((bfd_size_type) (stash->info_ptr - stash->sec_info_ptr)
|
||||||
|
== stash->sec->size)
|
||||||
|
{
|
||||||
|
stash->sec = find_debug_info (stash->bfd_ptr,
|
||||||
|
stash->debug_sections,
|
||||||
|
stash->sec);
|
||||||
|
stash->sec_info_ptr = stash->info_ptr;
|
||||||
|
}
|
||||||
|
return each;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't trust any of the DWARF info after a corrupted length or
|
||||||
|
parse error. */
|
||||||
|
stash->info_ptr = stash->info_ptr_end;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Scan the debug information in PINFO looking for a DW_TAG_subprogram
|
/* Scan the debug information in PINFO looking for a DW_TAG_subprogram
|
||||||
abbrev with a DW_AT_low_pc attached to it. Then lookup that same
|
abbrev with a DW_AT_low_pc attached to it. Then lookup that same
|
||||||
symbol in SYMBOLS and return the difference between the low_pc and
|
symbol in SYMBOLS and return the difference between the low_pc and
|
||||||
@ -4699,79 +4800,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read each remaining comp. units checking each as they are read. */
|
/* Read each remaining comp. units checking each as they are read. */
|
||||||
while (stash->info_ptr < stash->info_ptr_end)
|
while ((each = stash_comp_unit (stash)) != NULL)
|
||||||
{
|
{
|
||||||
bfd_vma length;
|
|
||||||
unsigned int offset_size;
|
|
||||||
bfd_byte *info_ptr_unit = stash->info_ptr;
|
|
||||||
|
|
||||||
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr, stash->info_ptr_end);
|
|
||||||
/* A 0xffffff length is the DWARF3 way of indicating
|
|
||||||
we use 64-bit offsets, instead of 32-bit offsets. */
|
|
||||||
if (length == 0xffffffff)
|
|
||||||
{
|
|
||||||
offset_size = 8;
|
|
||||||
length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
|
|
||||||
stash->info_ptr += 12;
|
|
||||||
}
|
|
||||||
/* A zero length is the IRIX way of indicating 64-bit offsets,
|
|
||||||
mostly because the 64-bit length will generally fit in 32
|
|
||||||
bits, and the endianness helps. */
|
|
||||||
else if (length == 0)
|
|
||||||
{
|
|
||||||
offset_size = 8;
|
|
||||||
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
|
|
||||||
stash->info_ptr += 8;
|
|
||||||
}
|
|
||||||
/* In the absence of the hints above, we assume 32-bit DWARF2
|
|
||||||
offsets even for targets with 64-bit addresses, because:
|
|
||||||
a) most of the time these targets will not have generated
|
|
||||||
more than 2Gb of debug info and so will not need 64-bit
|
|
||||||
offsets,
|
|
||||||
and
|
|
||||||
b) if they do use 64-bit offsets but they are not using
|
|
||||||
the size hints that are tested for above then they are
|
|
||||||
not conforming to the DWARF3 standard anyway. */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offset_size = 4;
|
|
||||||
stash->info_ptr += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length > 0)
|
|
||||||
{
|
|
||||||
bfd_byte * new_ptr;
|
|
||||||
|
|
||||||
/* PR 21151 */
|
|
||||||
if (stash->info_ptr + length > stash->info_ptr_end)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
each = parse_comp_unit (stash, length, info_ptr_unit,
|
|
||||||
offset_size);
|
|
||||||
if (!each)
|
|
||||||
/* The dwarf information is damaged, don't trust it any
|
|
||||||
more. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
new_ptr = stash->info_ptr + length;
|
|
||||||
/* PR 17512: file: 1500698c. */
|
|
||||||
if (new_ptr < stash->info_ptr)
|
|
||||||
{
|
|
||||||
/* A corrupt length value - do not trust the info any more. */
|
|
||||||
found = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stash->info_ptr = new_ptr;
|
|
||||||
|
|
||||||
if (stash->all_comp_units)
|
|
||||||
stash->all_comp_units->prev_unit = each;
|
|
||||||
else
|
|
||||||
stash->last_comp_unit = each;
|
|
||||||
|
|
||||||
each->next_unit = stash->all_comp_units;
|
|
||||||
stash->all_comp_units = each;
|
|
||||||
|
|
||||||
/* DW_AT_low_pc and DW_AT_high_pc are optional for
|
/* DW_AT_low_pc and DW_AT_high_pc are optional for
|
||||||
compilation units. If we don't have them (i.e.,
|
compilation units. If we don't have them (i.e.,
|
||||||
unit->high == 0), we need to consult the line info table
|
unit->high == 0), we need to consult the line info table
|
||||||
@ -4795,17 +4825,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
|
|||||||
discriminator_ptr,
|
discriminator_ptr,
|
||||||
stash) != 0);
|
stash) != 0);
|
||||||
|
|
||||||
if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
|
|
||||||
== stash->sec->size)
|
|
||||||
{
|
|
||||||
stash->sec = find_debug_info (stash->bfd_ptr, debug_sections,
|
|
||||||
stash->sec);
|
|
||||||
stash->sec_info_ptr = stash->info_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
goto done;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
Reference in New Issue
Block a user