/* 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;
/* Source location line number. */
int line;
int tag;
- bfd boolean is_linkage;
+ bfd_boolean is_linkage;
const char * name;
struct arange arange;
/* Where the symbol is defined. */
struct line_info** line_info_lookup;
struct line_info* each_line;
unsigned int num_lines;
- unsigned int index;
+ unsigned int line_index;
if (seq->line_info_lookup != NULL)
return TRUE;
return FALSE;
/* Create the line information lookup table. */
- index = num_lines;
+ line_index = num_lines;
for (each_line = seq->last_line; each_line; each_line = each_line->prev_line)
- line_info_lookup[--index] = each_line;
+ line_info_lookup[--line_index] = each_line;
- BFD_ASSERT (index == 0);
+ BFD_ASSERT (line_index == 0);
seq->num_lines = num_lines;
seq->line_info_lookup = line_info_lookup;
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;
unsigned int number_of_functions = unit->number_of_functions;
struct funcinfo *each;
struct lookup_funcinfo *entry;
- size_t index;
+ size_t func_index;
struct arange *range;
bfd_vma low_addr, high_addr;
return FALSE;
/* Populate the function info lookup table. */
- index = number_of_functions;
+ func_index = number_of_functions;
for (each = unit->function_table; each; each = each->prev_func)
{
- entry = &lookup_funcinfo_table[--index];
+ entry = &lookup_funcinfo_table[--func_index];
entry->funcinfo = each;
/* Calculate the lowest and highest address for this function entry. */
entry->high_addr = high_addr;
}
- BFD_ASSERT (index == 0);
+ BFD_ASSERT (func_index == 0);
/* Sort the function by address. */
qsort (lookup_funcinfo_table,
/* Calculate the high watermark for each function in the lookup table. */
high_addr = lookup_funcinfo_table[0].high_addr;
- for (index = 1; index < number_of_functions; index++)
+ for (func_index = 1; func_index < number_of_functions; func_index++)
{
- entry = &lookup_funcinfo_table[index];
+ entry = &lookup_funcinfo_table[func_index];
if (entry->high_addr > high_addr)
high_addr = entry->high_addr;
else
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)
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 ((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)