|
|
|
|
diff -rup binutils.orig/bfd/dwarf2.c binutils-2.25.1/bfd/dwarf2.c
|
|
|
|
|
--- binutils.orig/bfd/dwarf2.c 2017-01-16 14:48:05.110778762 +0000
|
|
|
|
|
+++ binutils-2.25.1/bfd/dwarf2.c 2017-01-16 14:51:04.915885225 +0000
|
|
|
|
|
@@ -144,16 +144,16 @@ struct dwarf2_debug
|
|
|
|
|
/* Length of the loaded .debug_str section. */
|
|
|
|
|
bfd_size_type dwarf_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;
|
|
|
|
|
|
|
|
|
|
- /* Length of the loaded .debug_ranges section. */
|
|
|
|
|
+ /* Length of the loaded .debug_ranges section. */
|
|
|
|
|
bfd_size_type dwarf_ranges_size;
|
|
|
|
|
|
|
|
|
|
/* If the most recent call to bfd_find_nearest_line was given an
|
|
|
|
|
address in an inlined function, preserve a pointer into the
|
|
|
|
|
calling chain for subsequent calls to bfd_find_inliner_info to
|
|
|
|
|
- use. */
|
|
|
|
|
+ use. */
|
|
|
|
|
struct funcinfo *inliner_chain;
|
|
|
|
|
|
|
|
|
|
/* Section VMAs at the time the stash was built. */
|
|
|
|
|
@@ -212,9 +212,12 @@ struct comp_unit
|
|
|
|
|
/* Keep the bfd convenient (for memory allocation). */
|
|
|
|
|
bfd *abfd;
|
|
|
|
|
|
|
|
|
|
- /* The lowest and highest addresses contained in this compilation
|
|
|
|
|
- unit as specified in the compilation unit header. */
|
|
|
|
|
+ /* Linked list of the low and high address ranges contained in this
|
|
|
|
|
+ compilation unit as specified in the compilation unit header. */
|
|
|
|
|
struct arange arange;
|
|
|
|
|
+ /* A single arange containing the lowest and highest
|
|
|
|
|
+ addresses covered by the compilation unit. */
|
|
|
|
|
+ struct arange minmax;
|
|
|
|
|
|
|
|
|
|
/* The DW_AT_name attribute (for error messages). */
|
|
|
|
|
char *name;
|
|
|
|
|
@@ -256,6 +259,12 @@ struct comp_unit
|
|
|
|
|
/* A list of the functions found in this comp. unit. */
|
|
|
|
|
struct funcinfo *function_table;
|
|
|
|
|
|
|
|
|
|
+ /* A table of function information references searchable by address. */
|
|
|
|
|
+ struct lookup_funcinfo *lookup_funcinfo_table;
|
|
|
|
|
+
|
|
|
|
|
+ /* Number of functions in the function_table and sorted_function_table. */
|
|
|
|
|
+ bfd_size_type number_of_functions;
|
|
|
|
|
+
|
|
|
|
|
/* A list of the variables found in this comp. unit. */
|
|
|
|
|
struct varinfo *variable_table;
|
|
|
|
|
|
|
|
|
|
@@ -390,7 +399,7 @@ struct info_hash_table
|
|
|
|
|
struct bfd_hash_table base;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
-/* Function to create a new entry in info hash table. */
|
|
|
|
|
+/* Function to create a new entry in info hash table. */
|
|
|
|
|
|
|
|
|
|
static struct bfd_hash_entry *
|
|
|
|
|
info_hash_table_newfunc (struct bfd_hash_entry *entry,
|
|
|
|
|
@@ -476,7 +485,7 @@ insert_info_hash_table (struct info_hash
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Look up an info entry list from an info hash table. Return NULL
|
|
|
|
|
- if there is none. */
|
|
|
|
|
+ if there is none. */
|
|
|
|
|
|
|
|
|
|
static struct info_list_node *
|
|
|
|
|
lookup_info_hash_table (struct info_hash_table *hash_table, const char *key)
|
|
|
|
|
@@ -517,8 +526,8 @@ read_section (bfd * abfd,
|
|
|
|
|
}
|
|
|
|
|
if (! msec)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler) (_("Dwarf Error: Can't find %s section."),
|
|
|
|
|
- sec->uncompressed_name);
|
|
|
|
|
+ _bfd_error_handler (_("Dwarf Error: Can't find %s section."),
|
|
|
|
|
+ sec->uncompressed_name);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
@@ -546,9 +555,10 @@ read_section (bfd * abfd,
|
|
|
|
|
that the client wants. Validate it here to avoid trouble later. */
|
|
|
|
|
if (offset != 0 && offset >= *section_size)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler) (_("Dwarf Error: Offset (%lu)"
|
|
|
|
|
- " greater than or equal to %s size (%lu)."),
|
|
|
|
|
- (long) offset, section_name, *section_size);
|
|
|
|
|
+ /* xgettext: c-format */
|
|
|
|
|
+ _bfd_error_handler (_("Dwarf Error: Offset (%lu)"
|
|
|
|
|
+ " greater than or equal to %s size (%lu)."),
|
|
|
|
|
+ (long) offset, section_name, *section_size);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
@@ -1157,8 +1167,8 @@ read_attribute_value (struct attribute *
|
|
|
|
|
info_ptr = read_attribute_value (attr, form, unit, info_ptr, info_ptr_end);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
- (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
|
|
|
|
|
- form);
|
|
|
|
|
+ _bfd_error_handler (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
|
|
|
|
|
+ form);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
@@ -1213,22 +1223,22 @@ non_mangled (int lang)
|
|
|
|
|
|
|
|
|
|
struct line_info
|
|
|
|
|
{
|
|
|
|
|
- struct line_info* prev_line;
|
|
|
|
|
- bfd_vma address;
|
|
|
|
|
- char *filename;
|
|
|
|
|
- unsigned int line;
|
|
|
|
|
- unsigned int column;
|
|
|
|
|
- unsigned int discriminator;
|
|
|
|
|
- unsigned char op_index;
|
|
|
|
|
- unsigned char end_sequence; /* End of (sequential) code sequence. */
|
|
|
|
|
+ struct line_info * prev_line;
|
|
|
|
|
+ bfd_vma address;
|
|
|
|
|
+ char * filename;
|
|
|
|
|
+ unsigned int line;
|
|
|
|
|
+ unsigned int column;
|
|
|
|
|
+ unsigned int discriminator;
|
|
|
|
|
+ unsigned char op_index;
|
|
|
|
|
+ unsigned char end_sequence; /* End of (sequential) code sequence. */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct fileinfo
|
|
|
|
|
{
|
|
|
|
|
- char *name;
|
|
|
|
|
- unsigned int dir;
|
|
|
|
|
- unsigned int time;
|
|
|
|
|
- unsigned int size;
|
|
|
|
|
+ char * name;
|
|
|
|
|
+ unsigned int dir;
|
|
|
|
|
+ unsigned int time;
|
|
|
|
|
+ unsigned int size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct line_sequence
|
|
|
|
|
@@ -1236,11 +1246,13 @@ struct line_sequence
|
|
|
|
|
bfd_vma low_pc;
|
|
|
|
|
struct line_sequence* prev_sequence;
|
|
|
|
|
struct line_info* last_line; /* Largest VMA. */
|
|
|
|
|
+ struct line_info** line_info_lookup;
|
|
|
|
|
+ bfd_size_type num_lines;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct line_info_table
|
|
|
|
|
{
|
|
|
|
|
- bfd* abfd;
|
|
|
|
|
+ bfd * abfd;
|
|
|
|
|
unsigned int num_files;
|
|
|
|
|
unsigned int num_dirs;
|
|
|
|
|
unsigned int num_sequences;
|
|
|
|
|
@@ -1259,23 +1271,37 @@ struct line_info_table
|
|
|
|
|
struct funcinfo
|
|
|
|
|
{
|
|
|
|
|
/* Pointer to previous function in list of all functions. */
|
|
|
|
|
- struct funcinfo *prev_func;
|
|
|
|
|
+ struct funcinfo * prev_func;
|
|
|
|
|
/* Pointer to function one scope higher. */
|
|
|
|
|
- struct funcinfo *caller_func;
|
|
|
|
|
+ struct funcinfo * caller_func;
|
|
|
|
|
/* Source location file name where caller_func inlines this func. */
|
|
|
|
|
- char *caller_file;
|
|
|
|
|
+ char * caller_file;
|
|
|
|
|
/* Source location file name. */
|
|
|
|
|
- char *file;
|
|
|
|
|
+ char * file;
|
|
|
|
|
/* Source location line number where caller_func inlines this func. */
|
|
|
|
|
- int caller_line;
|
|
|
|
|
+ int caller_line;
|
|
|
|
|
/* Source location line number. */
|
|
|
|
|
- int line;
|
|
|
|
|
- int tag;
|
|
|
|
|
- bfd_boolean is_linkage;
|
|
|
|
|
- const char *name;
|
|
|
|
|
- struct arange arange;
|
|
|
|
|
+ int line;
|
|
|
|
|
+ int tag;
|
|
|
|
|
+ bfd_boolean is_linkage;
|
|
|
|
|
+ const char * name;
|
|
|
|
|
+ struct arange arange;
|
|
|
|
|
/* Where the symbol is defined. */
|
|
|
|
|
- asection *sec;
|
|
|
|
|
+ asection * sec;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct lookup_funcinfo
|
|
|
|
|
+{
|
|
|
|
|
+ /* Function information corresponding to this lookup table entry. */
|
|
|
|
|
+ struct funcinfo * funcinfo;
|
|
|
|
|
+
|
|
|
|
|
+ /* The lowest address for this specific function. */
|
|
|
|
|
+ bfd_vma low_addr;
|
|
|
|
|
+
|
|
|
|
|
+ /* The highest address of this function before the lookup table is sorted.
|
|
|
|
|
+ The highest address of all prior functions after the lookup table is
|
|
|
|
|
+ sorted, which is used for binary search. */
|
|
|
|
|
+ bfd_vma high_addr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct varinfo
|
|
|
|
|
@@ -1446,7 +1472,7 @@ concat_filename (struct line_info_table
|
|
|
|
|
{
|
|
|
|
|
/* FILE == 0 means unknown. */
|
|
|
|
|
if (file)
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: mangled line number section (bad file number)."));
|
|
|
|
|
return strdup ("<unknown>");
|
|
|
|
|
}
|
|
|
|
|
@@ -1502,7 +1528,7 @@ concat_filename (struct line_info_table
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
-arange_add (const struct comp_unit *unit, struct arange *first_arange,
|
|
|
|
|
+arange_add (struct comp_unit *unit, struct arange *first_arange,
|
|
|
|
|
bfd_vma low_pc, bfd_vma high_pc)
|
|
|
|
|
{
|
|
|
|
|
struct arange *arange;
|
|
|
|
|
@@ -1514,11 +1540,16 @@ arange_add (const struct comp_unit *unit
|
|
|
|
|
/* If the first arange is empty, use it. */
|
|
|
|
|
if (first_arange->high == 0)
|
|
|
|
|
{
|
|
|
|
|
- first_arange->low = low_pc;
|
|
|
|
|
- first_arange->high = high_pc;
|
|
|
|
|
+ unit->minmax.low = first_arange->low = low_pc;
|
|
|
|
|
+ unit->minmax.high = first_arange->high = high_pc;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (unit->minmax.low > low_pc)
|
|
|
|
|
+ unit->minmax.low = low_pc;
|
|
|
|
|
+ if (unit->minmax.high < high_pc)
|
|
|
|
|
+ unit->minmax.high = high_pc;
|
|
|
|
|
+
|
|
|
|
|
/* Next see if we can cheaply extend an existing range. */
|
|
|
|
|
arange = first_arange;
|
|
|
|
|
do
|
|
|
|
|
@@ -1538,7 +1569,7 @@ arange_add (const struct comp_unit *unit
|
|
|
|
|
while (arange);
|
|
|
|
|
|
|
|
|
|
/* Need to allocate a new arange and insert it into the arange list.
|
|
|
|
|
- Order isn't significant, so just insert after the first arange. */
|
|
|
|
|
+ Order isn't significant, so just insert after the first arange. */
|
|
|
|
|
arange = (struct arange *) bfd_alloc (unit->abfd, sizeof (*arange));
|
|
|
|
|
if (arange == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
@@ -1578,17 +1609,62 @@ compare_sequences (const void* a, const
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* Construct the line information table for quick lookup. */
|
|
|
|
|
+
|
|
|
|
|
+static bfd_boolean
|
|
|
|
|
+build_line_info_table (struct line_info_table * table,
|
|
|
|
|
+ struct line_sequence * seq)
|
|
|
|
|
+{
|
|
|
|
|
+ bfd_size_type amt;
|
|
|
|
|
+ struct line_info** line_info_lookup;
|
|
|
|
|
+ struct line_info* each_line;
|
|
|
|
|
+ unsigned int num_lines;
|
|
|
|
|
+ unsigned int line_index;
|
|
|
|
|
+
|
|
|
|
|
+ if (seq->line_info_lookup != NULL)
|
|
|
|
|
+ return TRUE;
|
|
|
|
|
+
|
|
|
|
|
+ /* Count the number of line information entries. We could do this while
|
|
|
|
|
+ scanning the debug information, but some entries may be added via
|
|
|
|
|
+ lcl_head without having a sequence handy to increment the number of
|
|
|
|
|
+ lines. */
|
|
|
|
|
+ num_lines = 0;
|
|
|
|
|
+ for (each_line = seq->last_line; each_line; each_line = each_line->prev_line)
|
|
|
|
|
+ num_lines++;
|
|
|
|
|
+
|
|
|
|
|
+ if (num_lines == 0)
|
|
|
|
|
+ return TRUE;
|
|
|
|
|
+
|
|
|
|
|
+ /* Allocate space for the line information lookup table. */
|
|
|
|
|
+ amt = sizeof (struct line_info*) * num_lines;
|
|
|
|
|
+ line_info_lookup = (struct line_info**) bfd_alloc (table->abfd, amt);
|
|
|
|
|
+ if (line_info_lookup == NULL)
|
|
|
|
|
+ return FALSE;
|
|
|
|
|
+
|
|
|
|
|
+ /* Create the line information lookup table. */
|
|
|
|
|
+ line_index = num_lines;
|
|
|
|
|
+ for (each_line = seq->last_line; each_line; each_line = each_line->prev_line)
|
|
|
|
|
+ line_info_lookup[--line_index] = each_line;
|
|
|
|
|
+
|
|
|
|
|
+ BFD_ASSERT (line_index == 0);
|
|
|
|
|
+
|
|
|
|
|
+ seq->num_lines = num_lines;
|
|
|
|
|
+ seq->line_info_lookup = line_info_lookup;
|
|
|
|
|
+
|
|
|
|
|
+ return TRUE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
/* Sort the line sequences for quick lookup. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
sort_line_sequences (struct line_info_table* table)
|
|
|
|
|
{
|
|
|
|
|
- bfd_size_type amt;
|
|
|
|
|
- struct line_sequence* sequences;
|
|
|
|
|
- struct line_sequence* seq;
|
|
|
|
|
- unsigned int n = 0;
|
|
|
|
|
- unsigned int num_sequences = table->num_sequences;
|
|
|
|
|
- bfd_vma last_high_pc;
|
|
|
|
|
+ bfd_size_type amt;
|
|
|
|
|
+ struct line_sequence* sequences;
|
|
|
|
|
+ struct line_sequence* seq;
|
|
|
|
|
+ unsigned int n = 0;
|
|
|
|
|
+ unsigned int num_sequences = table->num_sequences;
|
|
|
|
|
+ bfd_vma last_high_pc;
|
|
|
|
|
|
|
|
|
|
if (num_sequences == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
@@ -1609,6 +1685,8 @@ sort_line_sequences (struct line_info_ta
|
|
|
|
|
sequences[n].low_pc = seq->low_pc;
|
|
|
|
|
sequences[n].prev_sequence = NULL;
|
|
|
|
|
sequences[n].last_line = seq->last_line;
|
|
|
|
|
+ sequences[n].line_info_lookup = NULL;
|
|
|
|
|
+ sequences[n].num_lines = 0;
|
|
|
|
|
seq = seq->prev_sequence;
|
|
|
|
|
free (last_seq);
|
|
|
|
|
}
|
|
|
|
|
@@ -1687,7 +1765,7 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
|
|
|
|
|
if (stash->dwarf_line_size < 16)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Line info section is too small (%ld)"),
|
|
|
|
|
(long) stash->dwarf_line_size);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
@@ -1716,7 +1794,8 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
|
|
|
|
|
if (lh.total_length > stash->dwarf_line_size)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
+ /* xgettext: c-format */
|
|
|
|
|
(_("Dwarf Error: Line info data is bigger (0x%lx) than the section (0x%lx)"),
|
|
|
|
|
(long) lh.total_length, (long) stash->dwarf_line_size);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
@@ -1728,7 +1807,7 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
lh.version = read_2_bytes (abfd, line_ptr, line_end);
|
|
|
|
|
if (lh.version < 2 || lh.version > 4)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Unhandled .debug_line version %d."), lh.version);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -1737,7 +1816,7 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
|
|
|
|
|
if (line_ptr + offset_size + (lh.version >=4 ? 6 : 5) >= line_end)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Ran out of room reading prologue"));
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -1762,7 +1841,7 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
|
|
|
|
|
if (lh.maximum_ops_per_insn == 0)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Invalid maximum operations per instruction."));
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -1782,7 +1861,7 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
|
|
|
|
|
if (line_ptr + (lh.opcode_base - 1) >= line_end)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler) (_("Dwarf Error: Ran out of room reading opcodes"));
|
|
|
|
|
+ _bfd_error_handler (_("Dwarf Error: Ran out of room reading opcodes"));
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
@@ -1969,7 +2048,7 @@ decode_line_info (struct comp_unit *unit
|
|
|
|
|
line_ptr += exop_len - 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: mangled line number section."));
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
line_fail:
|
|
|
|
|
@@ -2089,7 +2168,7 @@ lookup_address_in_line_info_table (struc
|
|
|
|
|
unsigned int *discriminator_ptr)
|
|
|
|
|
{
|
|
|
|
|
struct line_sequence *seq = NULL;
|
|
|
|
|
- struct line_info *each_line;
|
|
|
|
|
+ struct line_info *info;
|
|
|
|
|
int low, high, mid;
|
|
|
|
|
|
|
|
|
|
/* Binary search the array of sequences. */
|
|
|
|
|
@@ -2107,26 +2186,43 @@ lookup_address_in_line_info_table (struc
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- if (seq && addr >= seq->low_pc && addr < seq->last_line->address)
|
|
|
|
|
+ /* Check for a valid sequence. */
|
|
|
|
|
+ if (!seq || addr < seq->low_pc || addr >= seq->last_line->address)
|
|
|
|
|
+ goto fail;
|
|
|
|
|
+
|
|
|
|
|
+ if (!build_line_info_table (table, seq))
|
|
|
|
|
+ goto fail;
|
|
|
|
|
+
|
|
|
|
|
+ /* Binary search the array of line information. */
|
|
|
|
|
+ low = 0;
|
|
|
|
|
+ high = seq->num_lines;
|
|
|
|
|
+ info = NULL;
|
|
|
|
|
+ while (low < high)
|
|
|
|
|
{
|
|
|
|
|
- /* Note: seq->last_line should be a descendingly sorted list. */
|
|
|
|
|
- for (each_line = seq->last_line;
|
|
|
|
|
- each_line;
|
|
|
|
|
- each_line = each_line->prev_line)
|
|
|
|
|
- if (addr >= each_line->address)
|
|
|
|
|
- break;
|
|
|
|
|
+ mid = (low + high) / 2;
|
|
|
|
|
+ info = seq->line_info_lookup[mid];
|
|
|
|
|
+ if (addr < info->address)
|
|
|
|
|
+ high = mid;
|
|
|
|
|
+ else if (addr >= seq->line_info_lookup[mid + 1]->address)
|
|
|
|
|
+ low = mid + 1;
|
|
|
|
|
+ else
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
- if (each_line
|
|
|
|
|
- && !(each_line->end_sequence || each_line == seq->last_line))
|
|
|
|
|
- {
|
|
|
|
|
- *filename_ptr = each_line->filename;
|
|
|
|
|
- *linenumber_ptr = each_line->line;
|
|
|
|
|
- if (discriminator_ptr)
|
|
|
|
|
- *discriminator_ptr = each_line->discriminator;
|
|
|
|
|
- return seq->last_line->address - seq->low_pc;
|
|
|
|
|
- }
|
|
|
|
|
+ /* Check for a valid line information entry. */
|
|
|
|
|
+ if (info
|
|
|
|
|
+ && addr >= info->address
|
|
|
|
|
+ && addr < seq->line_info_lookup[mid + 1]->address
|
|
|
|
|
+ && !(info->end_sequence || info == seq->last_line))
|
|
|
|
|
+ {
|
|
|
|
|
+ *filename_ptr = info->filename;
|
|
|
|
|
+ *linenumber_ptr = info->line;
|
|
|
|
|
+ if (discriminator_ptr)
|
|
|
|
|
+ *discriminator_ptr = info->discriminator;
|
|
|
|
|
+ return seq->last_line->address - seq->low_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+fail:
|
|
|
|
|
*filename_ptr = NULL;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -2134,16 +2230,102 @@ lookup_address_in_line_info_table (struc
|
|
|
|
|
/* Read in the .debug_ranges section for future reference. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
-read_debug_ranges (struct comp_unit *unit)
|
|
|
|
|
+read_debug_ranges (struct comp_unit * unit)
|
|
|
|
|
{
|
|
|
|
|
- struct dwarf2_debug *stash = unit->stash;
|
|
|
|
|
+ struct dwarf2_debug * stash = unit->stash;
|
|
|
|
|
+
|
|
|
|
|
return read_section (unit->abfd, &stash->debug_sections[debug_ranges],
|
|
|
|
|
stash->syms, 0,
|
|
|
|
|
- &stash->dwarf_ranges_buffer, &stash->dwarf_ranges_size);
|
|
|
|
|
+ &stash->dwarf_ranges_buffer,
|
|
|
|
|
+ &stash->dwarf_ranges_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Function table functions. */
|
|
|
|
|
|
|
|
|
|
+static int
|
|
|
|
|
+compare_lookup_funcinfos (const void * a, const void * b)
|
|
|
|
|
+{
|
|
|
|
|
+ const struct lookup_funcinfo * lookup1 = a;
|
|
|
|
|
+ const struct lookup_funcinfo * lookup2 = b;
|
|
|
|
|
+
|
|
|
|
|
+ if (lookup1->low_addr < lookup2->low_addr)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ if (lookup1->low_addr > lookup2->low_addr)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ if (lookup1->high_addr < lookup2->high_addr)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ if (lookup1->high_addr > lookup2->high_addr)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static bfd_boolean
|
|
|
|
|
+build_lookup_funcinfo_table (struct comp_unit * unit)
|
|
|
|
|
+{
|
|
|
|
|
+ struct lookup_funcinfo *lookup_funcinfo_table = unit->lookup_funcinfo_table;
|
|
|
|
|
+ unsigned int number_of_functions = unit->number_of_functions;
|
|
|
|
|
+ struct funcinfo *each;
|
|
|
|
|
+ struct lookup_funcinfo *entry;
|
|
|
|
|
+ size_t func_index;
|
|
|
|
|
+ struct arange *range;
|
|
|
|
|
+ bfd_vma low_addr, high_addr;
|
|
|
|
|
+
|
|
|
|
|
+ if (lookup_funcinfo_table || number_of_functions == 0)
|
|
|
|
|
+ return TRUE;
|
|
|
|
|
+
|
|
|
|
|
+ /* Create the function info lookup table. */
|
|
|
|
|
+ lookup_funcinfo_table = (struct lookup_funcinfo *)
|
|
|
|
|
+ bfd_malloc (number_of_functions * sizeof (struct lookup_funcinfo));
|
|
|
|
|
+ if (lookup_funcinfo_table == NULL)
|
|
|
|
|
+ return FALSE;
|
|
|
|
|
+
|
|
|
|
|
+ /* Populate the function info lookup table. */
|
|
|
|
|
+ func_index = number_of_functions;
|
|
|
|
|
+ for (each = unit->function_table; each; each = each->prev_func)
|
|
|
|
|
+ {
|
|
|
|
|
+ entry = &lookup_funcinfo_table[--func_index];
|
|
|
|
|
+ entry->funcinfo = each;
|
|
|
|
|
+
|
|
|
|
|
+ /* Calculate the lowest and highest address for this function entry. */
|
|
|
|
|
+ low_addr = entry->funcinfo->arange.low;
|
|
|
|
|
+ high_addr = entry->funcinfo->arange.high;
|
|
|
|
|
+
|
|
|
|
|
+ for (range = entry->funcinfo->arange.next; range; range = range->next)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (range->low < low_addr)
|
|
|
|
|
+ low_addr = range->low;
|
|
|
|
|
+ if (range->high > high_addr)
|
|
|
|
|
+ high_addr = range->high;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ entry->low_addr = low_addr;
|
|
|
|
|
+ entry->high_addr = high_addr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ BFD_ASSERT (func_index == 0);
|
|
|
|
|
+
|
|
|
|
|
+ /* Sort the function by address. */
|
|
|
|
|
+ qsort (lookup_funcinfo_table,
|
|
|
|
|
+ number_of_functions,
|
|
|
|
|
+ sizeof (struct lookup_funcinfo),
|
|
|
|
|
+ compare_lookup_funcinfos);
|
|
|
|
|
+
|
|
|
|
|
+ /* Calculate the high watermark for each function in the lookup table. */
|
|
|
|
|
+ high_addr = lookup_funcinfo_table[0].high_addr;
|
|
|
|
|
+ for (func_index = 1; func_index < number_of_functions; func_index++)
|
|
|
|
|
+ {
|
|
|
|
|
+ entry = &lookup_funcinfo_table[func_index];
|
|
|
|
|
+ if (entry->high_addr > high_addr)
|
|
|
|
|
+ high_addr = entry->high_addr;
|
|
|
|
|
+ else
|
|
|
|
|
+ entry->high_addr = high_addr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ unit->lookup_funcinfo_table = lookup_funcinfo_table;
|
|
|
|
|
+ return TRUE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
/* If ADDR is within UNIT's function tables, set FUNCTION_PTR, and return
|
|
|
|
|
TRUE. Note that we need to find the function that has the smallest range
|
|
|
|
|
that contains ADDR, to handle inlined functions without depending upon
|
|
|
|
|
@@ -2154,37 +2336,77 @@ lookup_address_in_function_table (struct
|
|
|
|
|
bfd_vma addr,
|
|
|
|
|
struct funcinfo **function_ptr)
|
|
|
|
|
{
|
|
|
|
|
- struct funcinfo* each_func;
|
|
|
|
|
+ unsigned int number_of_functions = unit->number_of_functions;
|
|
|
|
|
+ struct lookup_funcinfo* lookup_funcinfo = NULL;
|
|
|
|
|
+ struct funcinfo* funcinfo = NULL;
|
|
|
|
|
struct funcinfo* best_fit = NULL;
|
|
|
|
|
bfd_vma best_fit_len = 0;
|
|
|
|
|
+ bfd_size_type low, high, mid, first;
|
|
|
|
|
struct arange *arange;
|
|
|
|
|
|
|
|
|
|
- for (each_func = unit->function_table;
|
|
|
|
|
- each_func;
|
|
|
|
|
- each_func = each_func->prev_func)
|
|
|
|
|
+ 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;
|
|
|
|
|
+ high = number_of_functions;
|
|
|
|
|
+ first = high;
|
|
|
|
|
+ while (low < high)
|
|
|
|
|
{
|
|
|
|
|
- for (arange = &each_func->arange;
|
|
|
|
|
- arange;
|
|
|
|
|
- arange = arange->next)
|
|
|
|
|
+ mid = (low + high) / 2;
|
|
|
|
|
+ lookup_funcinfo = &unit->lookup_funcinfo_table[mid];
|
|
|
|
|
+ if (addr < lookup_funcinfo->low_addr)
|
|
|
|
|
+ high = mid;
|
|
|
|
|
+ else if (addr >= lookup_funcinfo->high_addr)
|
|
|
|
|
+ low = mid + 1;
|
|
|
|
|
+ else
|
|
|
|
|
+ high = first = mid;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Find the 'best' match for the address. The prior algorithm defined the
|
|
|
|
|
+ best match as the function with the smallest address range containing
|
|
|
|
|
+ the specified address. This definition should probably be changed to the
|
|
|
|
|
+ innermost inline routine containing the address, but right now we want
|
|
|
|
|
+ to get the same results we did before. */
|
|
|
|
|
+ while (first < number_of_functions)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (addr < unit->lookup_funcinfo_table[first].low_addr)
|
|
|
|
|
+ break;
|
|
|
|
|
+ funcinfo = unit->lookup_funcinfo_table[first].funcinfo;
|
|
|
|
|
+
|
|
|
|
|
+ for (arange = &funcinfo->arange; arange; arange = arange->next)
|
|
|
|
|
{
|
|
|
|
|
- if (addr >= arange->low && addr < arange->high)
|
|
|
|
|
+ if (addr < arange->low || addr >= arange->high)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ if (!best_fit
|
|
|
|
|
+ || arange->high - arange->low < best_fit_len
|
|
|
|
|
+ /* The following comparison is designed to return the same
|
|
|
|
|
+ match as the previous algorithm for routines which have the
|
|
|
|
|
+ same best fit length. */
|
|
|
|
|
+ || (arange->high - arange->low == best_fit_len
|
|
|
|
|
+ && funcinfo > best_fit))
|
|
|
|
|
{
|
|
|
|
|
- if (!best_fit
|
|
|
|
|
- || arange->high - arange->low < best_fit_len)
|
|
|
|
|
- {
|
|
|
|
|
- best_fit = each_func;
|
|
|
|
|
- best_fit_len = arange->high - arange->low;
|
|
|
|
|
- }
|
|
|
|
|
+ best_fit = funcinfo;
|
|
|
|
|
+ best_fit_len = arange->high - arange->low;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- if (best_fit)
|
|
|
|
|
- {
|
|
|
|
|
- *function_ptr = best_fit;
|
|
|
|
|
- return TRUE;
|
|
|
|
|
+ first++;
|
|
|
|
|
}
|
|
|
|
|
- return FALSE;
|
|
|
|
|
+
|
|
|
|
|
+ if (!best_fit)
|
|
|
|
|
+ return FALSE;
|
|
|
|
|
+
|
|
|
|
|
+ *function_ptr = best_fit;
|
|
|
|
|
+ return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If SYM at ADDR is within function table of UNIT, set FILENAME_PTR
|
|
|
|
|
@@ -2269,8 +2491,8 @@ lookup_symbol_in_variable_table (struct
|
|
|
|
|
*linenumber_ptr = each->line;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
- else
|
|
|
|
|
- return FALSE;
|
|
|
|
|
+
|
|
|
|
|
+ return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
@@ -2326,7 +2548,7 @@ find_abstract_instance_name (struct comp
|
|
|
|
|
info_ptr = read_alt_indirect_ref (unit, die_ref);
|
|
|
|
|
if (info_ptr == NULL)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Unable to read alt ref %u."), die_ref);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -2350,7 +2572,7 @@ find_abstract_instance_name (struct comp
|
|
|
|
|
abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
|
|
|
|
|
if (! abbrev)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
}
|
|
|
|
|
@@ -2494,7 +2716,7 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
|
|
abbrev = lookup_abbrev (abbrev_number,unit->abbrevs);
|
|
|
|
|
if (! abbrev)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: Could not find abbrev number %u."),
|
|
|
|
|
abbrev_number);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
@@ -2513,6 +2735,7 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
|
|
func->tag = abbrev->tag;
|
|
|
|
|
func->prev_func = unit->function_table;
|
|
|
|
|
unit->function_table = func;
|
|
|
|
|
+ unit->number_of_functions++;
|
|
|
|
|
BFD_ASSERT (!unit->cached);
|
|
|
|
|
|
|
|
|
|
if (func->tag == DW_TAG_inlined_subroutine)
|
|
|
|
|
@@ -2766,7 +2989,8 @@ parse_comp_unit (struct dwarf2_debug *st
|
|
|
|
|
|
|
|
|
|
if (addr_size > sizeof (bfd_vma))
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
+ /* xgettext: c-format */
|
|
|
|
|
(_("Dwarf Error: found address size '%u', this reader"
|
|
|
|
|
" can not handle sizes greater than '%u'."),
|
|
|
|
|
addr_size,
|
|
|
|
|
@@ -2777,7 +3001,7 @@ parse_comp_unit (struct dwarf2_debug *st
|
|
|
|
|
|
|
|
|
|
if (addr_size != 2 && addr_size != 4 && addr_size != 8)
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
("Dwarf Error: found address size '%u', this reader"
|
|
|
|
|
" can only handle address sizes '2', '4' and '8'.", addr_size);
|
|
|
|
|
bfd_set_error (bfd_error_bad_value);
|
|
|
|
|
@@ -2845,7 +3069,7 @@ parse_comp_unit (struct dwarf2_debug *st
|
|
|
|
|
low_pc = attr.u.val;
|
|
|
|
|
/* If the compilation unit DIE has a DW_AT_low_pc attribute,
|
|
|
|
|
this is the base address to use when reading location
|
|
|
|
|
- lists or range lists. */
|
|
|
|
|
+ lists or range lists. */
|
|
|
|
|
if (abbrev->tag == DW_TAG_compile_unit)
|
|
|
|
|
unit->base_address = low_pc;
|
|
|
|
|
break;
|
|
|
|
|
@@ -2867,7 +3091,7 @@ parse_comp_unit (struct dwarf2_debug *st
|
|
|
|
|
/* PR 17512: file: 1fe726be. */
|
|
|
|
|
if (! is_str_attr (attr.form))
|
|
|
|
|
{
|
|
|
|
|
- (*_bfd_error_handler)
|
|
|
|
|
+ _bfd_error_handler
|
|
|
|
|
(_("Dwarf Error: DW_AT_comp_dir attribute encountered with a non-string form."));
|
|
|
|
|
comp_dir = NULL;
|
|
|
|
|
}
|
|
|
|
|
@@ -2919,6 +3143,11 @@ comp_unit_contains_address (struct comp_
|
|
|
|
|
if (unit->error)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
+ if (unit->minmax.high < addr || unit->minmax.low > addr)
|
|
|
|
|
+ return FALSE;
|
|
|
|
|
+
|
|
|
|
|
+ /* We know that the address *might* be contained within this comp
|
|
|
|
|
+ unit, but we cannot be sure until we check the specific ranges. */
|
|
|
|
|
arange = &unit->arange;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
@@ -3116,7 +3345,7 @@ comp_unit_hash_info (struct dwarf2_debug
|
|
|
|
|
each_func && okay;
|
|
|
|
|
each_func = each_func->prev_func)
|
|
|
|
|
{
|
|
|
|
|
- /* Skip nameless functions. */
|
|
|
|
|
+ /* Skip nameless functions. */
|
|
|
|
|
if (each_func->name)
|
|
|
|
|
/* There is no need to copy name string into hash table as
|
|
|
|
|
name string is either in the dwarf string buffer or
|
|
|
|
|
@@ -3498,7 +3727,7 @@ stash_maybe_update_info_hash_tables (str
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-/* Check consistency of info hash tables. This is for debugging only. */
|
|
|
|
|
+/* Check consistency of info hash tables. This is for debugging only. */
|
|
|
|
|
|
|
|
|
|
static void ATTRIBUTE_UNUSED
|
|
|
|
|
stash_verify_info_hash_table (struct dwarf2_debug *stash)
|
|
|
|
|
@@ -3930,7 +4159,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
|
|
|
|
|
stash_maybe_enable_info_hash_tables (abfd, stash);
|
|
|
|
|
|
|
|
|
|
/* Keep info hash table up to date if they are available. Note that we
|
|
|
|
|
- may disable the hash tables if there is any error duing update. */
|
|
|
|
|
+ may disable the hash tables if there is any error duing update. */
|
|
|
|
|
if (stash->info_hash_status == STASH_INFO_HASH_ON)
|
|
|
|
|
stash_maybe_update_info_hash_tables (stash);
|
|
|
|
|
|
|
|
|
|
@@ -4222,6 +4451,12 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abf
|
|
|
|
|
function_table = function_table->prev_func;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (each->lookup_funcinfo_table)
|
|
|
|
|
+ {
|
|
|
|
|
+ free (each->lookup_funcinfo_table);
|
|
|
|
|
+ each->lookup_funcinfo_table = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
while (variable_table)
|
|
|
|
|
{
|
|
|
|
|
if (variable_table->file)
|
|
|
|
|
diff -rup binutils.orig/binutils/objdump.c binutils-2.25.1/binutils/objdump.c
|
|
|
|
|
--- binutils.orig/binutils/objdump.c 2017-01-16 14:48:06.214761408 +0000
|
|
|
|
|
+++ binutils-2.25.1/binutils/objdump.c 2017-01-16 14:50:19.313618730 +0000
|
|
|
|
|
@@ -3439,7 +3439,7 @@ display_any_bfd (bfd *file, int level)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-display_file (char *filename, char *target)
|
|
|
|
|
+display_file (char *filename, char *target, bfd_boolean last_file)
|
|
|
|
|
{
|
|
|
|
|
bfd *file;
|
|
|
|
|
|
|
|
|
|
@@ -3458,7 +3458,14 @@ display_file (char *filename, char *targ
|
|
|
|
|
|
|
|
|
|
display_any_bfd (file, 0);
|
|
|
|
|
|
|
|
|
|
- bfd_close (file);
|
|
|
|
|
+ /* This is an optimization to improve the speed of objdump, especially when
|
|
|
|
|
+ dumping a file with lots of associated debug informatiom. Closing such
|
|
|
|
|
+ a file can take a non-trivial amount of time as there are lots of lists
|
|
|
|
|
+ to walk and buffers to free. This is only really necessary however if
|
|
|
|
|
+ we are about to load another file. Otherwise, if we are about to exit,
|
|
|
|
|
+ then we can save (a lot of) time by not bothering to do any tidying up. */
|
|
|
|
|
+ if (! last_file)
|
|
|
|
|
+ bfd_close (file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
@@ -3736,10 +3743,13 @@ main (int argc, char **argv)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (optind == argc)
|
|
|
|
|
- display_file ("a.out", target);
|
|
|
|
|
+ display_file ("a.out", target, TRUE);
|
|
|
|
|
else
|
|
|
|
|
for (; optind < argc;)
|
|
|
|
|
- display_file (argv[optind++], target);
|
|
|
|
|
+ {
|
|
|
|
|
+ display_file (argv[optind], target, optind == argc - 1);
|
|
|
|
|
+ optind++;
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free_only_list ();
|
|
|
|
|
|