/* DWARF 2 support.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2017 Free Software Foundation, Inc.
Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
(gavin@cygnus.com).
/* Pointer to the end of the .debug_info section memory buffer. */
bfd_byte *info_ptr_end;
+ /* Pointer to the original bfd for which debug was loaded. This is what
+ we use to compare and so check that the cached debug data is still
+ valid - it saves having to possibly dereference the gnu_debuglink each
+ time. */
+ bfd *orig_bfd;
+
/* Pointer to the bfd, section and address of the beginning of the
section. The bfd might be different than expected because of
gnu_debuglink sections. */
abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
abbrev_end = stash->dwarf_abbrev_buffer + stash->dwarf_abbrev_size;
- abbrev_number = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
+ FALSE, abbrev_end);
abbrev_ptr += bytes_read;
/* Loop until we reach an abbrev number of 0. */
/* Read in abbrev header. */
cur_abbrev->number = abbrev_number;
cur_abbrev->tag = (enum dwarf_tag)
- safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
+ FALSE, abbrev_end);
abbrev_ptr += bytes_read;
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr, abbrev_end);
abbrev_ptr += 1;
/* Now read in declarations. */
- abbrev_name = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
+ FALSE, abbrev_end);
abbrev_ptr += bytes_read;
- abbrev_form = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
+ FALSE, abbrev_end);
abbrev_ptr += bytes_read;
while (abbrev_name)
= (enum dwarf_attribute) abbrev_name;
cur_abbrev->attrs[cur_abbrev->num_attrs++].form
= (enum dwarf_form) abbrev_form;
- abbrev_name = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
+ FALSE, abbrev_end);
abbrev_ptr += bytes_read;
- abbrev_form = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
+ FALSE, abbrev_end);
abbrev_ptr += bytes_read;
}
if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
>= stash->dwarf_abbrev_size)
break;
- abbrev_number = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
+ abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr,
+ &bytes_read, FALSE, abbrev_end);
abbrev_ptr += bytes_read;
if (lookup_abbrev (abbrev_number, abbrevs) != NULL)
break;
blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
if (blk == NULL)
return NULL;
- blk->size = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
+ blk->size = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, info_ptr_end);
info_ptr += bytes_read;
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
info_ptr += blk->size;
attr->u.val = 1;
break;
case DW_FORM_sdata:
- attr->u.sval = safe_read_leb128 (abfd, info_ptr, &bytes_read, TRUE, info_ptr_end);
+ attr->u.sval = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ TRUE, info_ptr_end);
info_ptr += bytes_read;
break;
case DW_FORM_udata:
- attr->u.val = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
+ attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, info_ptr_end);
info_ptr += bytes_read;
break;
case DW_FORM_ref1:
info_ptr += 8;
break;
case DW_FORM_ref_udata:
- attr->u.val = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
+ attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, info_ptr_end);
info_ptr += bytes_read;
break;
case DW_FORM_indirect:
- form = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
+ form = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, info_ptr_end);
info_ptr += bytes_read;
info_ptr = read_attribute_value (attr, form, unit, info_ptr, info_ptr_end);
break;
table->files[table->num_files].name = cur_file;
table->files[table->num_files].dir =
- safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
line_ptr += bytes_read;
- table->files[table->num_files].time = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ 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 = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ 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++;
}
else switch (op_code)
{
case DW_LNS_extended_op:
- exop_len = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ exop_len = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
extended_op = read_1_byte (abfd, line_ptr, line_end);
line_ptr += 1;
}
table->files[table->num_files].name = cur_file;
table->files[table->num_files].dir =
- safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
table->files[table->num_files].time =
- safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
table->files[table->num_files].size =
- safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
table->num_files++;
break;
case DW_LNE_set_discriminator:
discriminator =
- safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
break;
case DW_LNE_HP_source_file_correlation:
case DW_LNS_advance_pc:
if (lh.maximum_ops_per_insn == 1)
address += (lh.minimum_instruction_length
- * safe_read_leb128 (abfd, line_ptr, &bytes_read,
- FALSE, line_end));
+ * _bfd_safe_read_leb128 (abfd, line_ptr,
+ &bytes_read,
+ FALSE, line_end));
else
{
- bfd_vma adjust = safe_read_leb128 (abfd, line_ptr, &bytes_read,
- FALSE, line_end);
+ bfd_vma adjust = _bfd_safe_read_leb128 (abfd, line_ptr,
+ &bytes_read,
+ FALSE, line_end);
address = ((op_index + adjust) / lh.maximum_ops_per_insn
* lh.minimum_instruction_length);
op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
line_ptr += bytes_read;
break;
case DW_LNS_advance_line:
- line += safe_read_leb128 (abfd, line_ptr, &bytes_read, TRUE, line_end);
+ line += _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ TRUE, line_end);
line_ptr += bytes_read;
break;
case DW_LNS_set_file:
/* The file and directory tables are 0
based, the references are 1 based. */
- file = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ file = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
if (filename)
free (filename);
break;
}
case DW_LNS_set_column:
- column = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ column = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
break;
case DW_LNS_negate_stmt:
/* Unknown standard opcode, ignore it. */
for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
{
- (void) safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
+ (void) _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
+ FALSE, line_end);
line_ptr += bytes_read;
}
break;
bfd_size_type low, high, mid, first;
struct arange *arange;
+ if (number_of_functions == 0)
+ return FALSE;
+
if (!build_lookup_funcinfo_table (unit))
return FALSE;
+ if (unit->lookup_funcinfo_table[number_of_functions - 1].high_addr < addr)
+ return FALSE;
+
/* Find the first function in the lookup table which may contain the
specified address. */
low = 0;
info_ptr_end = unit->end_ptr;
}
- abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
+ abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, info_ptr_end);
info_ptr += bytes_read;
if (abbrev_number)
if (info_ptr >= info_ptr_end)
goto fail;
- abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
+ abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, info_ptr_end);
info_ptr += bytes_read;
if (! abbrev_number)
continue;
}
- abbrev = lookup_abbrev (abbrev_number,unit->abbrevs);
+ abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
if (! abbrev)
{
- _bfd_error_handler
- (_("Dwarf Error: Could not find abbrev number %u."),
- abbrev_number);
+ static unsigned int previous_failed_abbrev = -1U;
+
+ /* Avoid multiple reports of the same missing abbrev. */
+ if (abbrev_number != previous_failed_abbrev)
+ {
+ _bfd_error_handler
+ (_("Dwarf Error: Could not find abbrev number %u."),
+ abbrev_number);
+ previous_failed_abbrev = abbrev_number;
+ }
bfd_set_error (bfd_error_bad_value);
goto fail;
}
func->tag = abbrev->tag;
func->prev_func = unit->function_table;
unit->function_table = func;
- unit->number_of_functions++;
+ unit->number_of_functions++;
BFD_ASSERT (!unit->cached);
if (func->tag == DW_TAG_inlined_subroutine)
var->stack = 1;
var->prev_var = unit->variable_table;
unit->variable_table = var;
- BFD_ASSERT (!unit->cached);
+ /* PR 18205: Missing debug information can cause this
+ var to be attached to an already cached unit. */
}
/* No inline function in scope at this nesting level. */
if (! abbrevs)
return NULL;
- abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, end_ptr);
+ abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
+ FALSE, end_ptr);
info_ptr += bytes_read;
if (! abbrev_number)
{
if (stash != NULL)
{
- if (section_vma_same (abfd, stash))
- return TRUE;
+ if (stash->orig_bfd == abfd
+ && section_vma_same (abfd, stash))
+ {
+ /* Check that we did previously find some debug information
+ before attempting to make use of it. */
+ if (stash->bfd_ptr != NULL)
+ {
+ if (do_place && !place_sections (abfd, stash))
+ return FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
_bfd_dwarf2_cleanup_debug_info (abfd, pinfo);
memset (stash, 0, amt);
}
if (! stash)
return FALSE;
}
+ stash->orig_bfd = abfd;
stash->debug_sections = debug_sections;
stash->syms = symbols;
if (!save_section_vma (abfd, stash))
msec = find_debug_info (debug_bfd, debug_sections, NULL);
if (msec == NULL && abfd == debug_bfd)
{
- char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
+ char * debug_filename;
+
+ debug_filename = bfd_follow_build_id_debuglink (abfd, DEBUGDIR);
+ if (debug_filename == NULL)
+ debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
if (debug_filename == NULL)
/* No dwarf2 info, and no gnu_debuglink to follow.
{
BFD_ASSERT (section != NULL && functionname_ptr != NULL);
addr = offset;
+
+ /* If we have no SYMBOL but the section we're looking at is not a
+ code section, then take a look through the list of symbols to see
+ if we have a symbol at the address we're looking for. If we do
+ then use this to look up line information. This will allow us to
+ give file and line results for data symbols. We exclude code
+ symbols here, if we look up a function symbol and then look up the
+ line information we'll actually return the line number for the
+ opening '{' rather than the function definition line. This is
+ because looking up by symbol uses the line table, in which the
+ first line for a function is usually the opening '{', while
+ looking up the function by section + offset uses the
+ DW_AT_decl_line from the function DW_TAG_subprogram for the line,
+ which will be the line of the function name. */
+ if (symbols != NULL && (section->flags & SEC_CODE) == 0)
+ {
+ asymbol **tmp;
+
+ for (tmp = symbols; (*tmp) != NULL; ++tmp)
+ if ((*tmp)->the_bfd == abfd
+ && (*tmp)->section == section
+ && (*tmp)->value == offset
+ && ((*tmp)->flags & BSF_SECTION_SYM) == 0)
+ {
+ symbol = *tmp;
+ do_line = TRUE;
+ /* For local symbols, keep going in the hope we find a
+ global. */
+ if ((symbol->flags & BSF_GLOBAL) != 0)
+ break;
+ }
+ }
}
if (section->output_section)
{
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)