binutils/binutils-2.27-objdump-improvements.2.patch

695 lines
23 KiB
Diff
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff -rup binutils.orig/bfd/dwarf2.c binutils-2.27/bfd/dwarf2.c
--- binutils.orig/bfd/dwarf2.c 2017-01-09 10:55:15.558436986 +0000
+++ binutils-2.27/bfd/dwarf2.c 2017-01-09 13:40:38.642944116 +0000
@@ -1,5 +1,5 @@
/* 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).
@@ -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;
@@ -396,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,
@@ -482,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)
@@ -523,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;
}
@@ -552,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;
}
@@ -1011,7 +1015,7 @@ read_attribute_value (struct attribute *
if (info_ptr >= info_ptr_end && form != DW_FORM_flag_present)
{
- (*_bfd_error_handler) (_("Dwarf Error: Info pointer extends beyond end of attributes"));
+ _bfd_error_handler (_("Dwarf Error: Info pointer extends beyond end of attributes"));
bfd_set_error (bfd_error_bad_value);
return info_ptr;
}
@@ -1163,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;
}
@@ -1219,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
@@ -1248,7 +1252,7 @@ struct line_sequence
struct line_info_table
{
- bfd* abfd;
+ bfd * abfd;
unsigned int num_files;
unsigned int num_dirs;
unsigned int num_sequences;
@@ -1267,37 +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;
+ struct funcinfo * funcinfo;
/* The lowest address for this specific function. */
- bfd_vma low_addr;
+ 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;
+ 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
@@ -1468,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>");
}
@@ -1524,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;
@@ -1536,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
@@ -1560,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;
@@ -1603,20 +1612,22 @@ compare_sequences (const void* a, const
/* Construct the line information table for quick lookup. */
static bfd_boolean
-build_line_info_table (struct line_info_table* table, struct line_sequence *seq)
+build_line_info_table (struct line_info_table * table,
+ struct line_sequence * seq)
{
- bfd_size_type amt;
+ bfd_size_type amt;
struct line_info** line_info_lookup;
- struct line_info* each_line;
- unsigned int num_lines;
- unsigned int index;
+ 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. */
+ 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++;
@@ -1631,11 +1642,11 @@ build_line_info_table (struct line_info_
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;
@@ -1648,12 +1659,12 @@ build_line_info_table (struct line_info_
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;
@@ -1754,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);
@@ -1783,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);
@@ -1795,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;
@@ -1804,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;
@@ -1829,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;
@@ -1849,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;
}
@@ -2036,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:
@@ -2218,45 +2230,44 @@ fail:
/* 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)
+compare_lookup_funcinfos (const void * a, const void * b)
{
- const struct lookup_funcinfo *lookup1 = a;
- const struct lookup_funcinfo *lookup2 = b;
- int result;
+ const struct lookup_funcinfo * lookup1 = a;
+ const struct lookup_funcinfo * lookup2 = b;
if (lookup1->low_addr < lookup2->low_addr)
- result = -1;
- else if (lookup1->low_addr > lookup2->low_addr)
- result = 1;
- else if (lookup1->high_addr < lookup2->high_addr)
- result = -1;
- else if (lookup1->high_addr > lookup1->high_addr)
- result = 1;
- else
- result = 0;
+ 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 result;
+ return 0;
}
static bfd_boolean
-build_lookup_funcinfo_table (struct comp_unit *unit)
+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 index;
+ size_t func_index;
struct arange *range;
bfd_vma low_addr, high_addr;
@@ -2270,10 +2281,10 @@ build_lookup_funcinfo_table (struct comp
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. */
@@ -2281,30 +2292,30 @@ build_lookup_funcinfo_table (struct comp
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;
- }
+ {
+ 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 (index == 0);
+ BFD_ASSERT (func_index == 0);
/* Sort the function by address. */
qsort (lookup_funcinfo_table,
- number_of_functions,
- sizeof (struct lookup_funcinfo),
- compare_lookup_funcinfos);
+ 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 (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
@@ -2333,9 +2344,15 @@ lookup_address_in_function_table (struct
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;
@@ -2474,8 +2491,8 @@ lookup_symbol_in_variable_table (struct
*linenumber_ptr = each->line;
return TRUE;
}
- else
- return FALSE;
+
+ return FALSE;
}
static char *
@@ -2531,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;
@@ -2555,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);
}
@@ -2699,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);
@@ -2969,7 +2986,7 @@ parse_comp_unit (struct dwarf2_debug *st
an error, just return a NULL. */
if (version)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("Dwarf Error: found dwarf version '%u', this reader"
" only handles version 2, 3 and 4 information."), version);
bfd_set_error (bfd_error_bad_value);
@@ -2979,7 +2996,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,
@@ -2990,7 +3008,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);
@@ -3016,8 +3034,8 @@ parse_comp_unit (struct dwarf2_debug *st
abbrev = lookup_abbrev (abbrev_number, abbrevs);
if (! abbrev)
{
- (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."),
- abbrev_number);
+ _bfd_error_handler (_("Dwarf Error: Could not find abbrev number %u."),
+ abbrev_number);
bfd_set_error (bfd_error_bad_value);
return NULL;
}
@@ -3059,7 +3077,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;
@@ -3081,7 +3099,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;
}
@@ -3133,6 +3151,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
{
@@ -3330,7 +3353,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
@@ -3712,7 +3735,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)
@@ -4146,7 +4169,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);
diff -rup binutils.orig/binutils/objdump.c binutils-2.27/binutils/objdump.c
--- binutils.orig/binutils/objdump.c 2017-01-09 10:55:15.771433447 +0000
+++ binutils-2.27/binutils/objdump.c 2017-01-09 13:36:45.936970981 +0000
@@ -3603,7 +3603,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;
@@ -3622,7 +3622,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
@@ -3900,10 +3907,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 ();