diff --git a/SOURCES/binutils-2.25.1-gold-resolving-to-hidden-symbols.patch b/SOURCES/binutils-2.25.1-gold-resolving-to-hidden-symbols.patch new file mode 100644 index 0000000..8769fd9 --- /dev/null +++ b/SOURCES/binutils-2.25.1-gold-resolving-to-hidden-symbols.patch @@ -0,0 +1,22 @@ +--- binutils.orig/gold/resolve.cc 2017-01-16 13:36:00.782976888 +0000 ++++ binutils-2.25.1/gold/resolve.cc 2017-01-16 13:36:25.438655203 +0000 +@@ -279,15 +279,10 @@ Symbol_table::resolve(Sized_symbol + && (to->visibility() == elfcpp::STV_HIDDEN + || to->visibility() == elfcpp::STV_INTERNAL)) + { +- // A dynamic object cannot reference a hidden or internal symbol +- // defined in another object. +- gold_warning(_("%s symbol '%s' in %s is referenced by DSO %s"), +- (to->visibility() == elfcpp::STV_HIDDEN +- ? "hidden" +- : "internal"), +- to->demangled_name().c_str(), +- to->object()->name().c_str(), +- object->name().c_str()); ++ // The symbol is hidden, so a reference from a shared object ++ // cannot bind to it. We tried issuing a warning in this case, ++ // but that produces false positives when the symbol is ++ // actually resolved in a different shared object (PR 15574). + return; + } + else diff --git a/SOURCES/binutils-2.25.1-objdump-speedup.patch b/SOURCES/binutils-2.25.1-objdump-speedup.patch new file mode 100644 index 0000000..da276b6 --- /dev/null +++ b/SOURCES/binutils-2.25.1-objdump-speedup.patch @@ -0,0 +1,874 @@ +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; + } +@@ -1005,7 +1015,7 @@ read_attribute_value (struct attribute * + + if (info_ptr >= info_ptr_end) + { +- (*_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; + } +@@ -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 (""); + } +@@ -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) +@@ -2757,7 +2980,7 @@ parse_comp_unit (struct dwarf2_debug *st + + if (version != 2 && version != 3 && version != 4) + { +- (*_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); +@@ -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); +@@ -2802,8 +3026,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 0; + } +@@ -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 (); + diff --git a/SOURCES/binutils-2.25.1-ppc-stub-counting.patch b/SOURCES/binutils-2.25.1-ppc-stub-counting.patch new file mode 100644 index 0000000..30fe624 --- /dev/null +++ b/SOURCES/binutils-2.25.1-ppc-stub-counting.patch @@ -0,0 +1,50 @@ +--- binutils.orig/bfd/elf64-ppc.c 2017-04-26 18:13:33.128533528 +0100 ++++ binutils-2.25.1/bfd/elf64-ppc.c 2017-04-27 08:25:36.008300396 +0100 +@@ -12087,6 +12087,13 @@ ppc64_elf_size_stubs (struct bfd_link_in + + group_sections (htab, stub_group_size, stubs_always_before_branch); + ++#define STUB_SHRINK_ITER 20 ++ /* Loop until no stubs added. After iteration 20 of this loop we may ++ exit on a stub section shrinking. This is to break out of a ++ pathological case where adding stubs on one iteration decreases ++ section gaps (perhaps due to alignment), which then requires ++ fewer or smaller stubs on the next iteration. */ ++ + while (1) + { + bfd *input_bfd; +@@ -12404,7 +12411,10 @@ ppc64_elf_size_stubs (struct bfd_link_in + stub_sec = stub_sec->next) + if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) + { +- stub_sec->rawsize = stub_sec->size; ++ if (htab->stub_iteration <= STUB_SHRINK_ITER ++ || stub_sec->rawsize < stub_sec->size) ++ /* Past STUB_SHRINK_ITER, rawsize is the max size seen. */ ++ stub_sec->rawsize = stub_sec->size; + stub_sec->size = 0; + stub_sec->reloc_count = 0; + stub_sec->flags &= ~SEC_RELOC; +@@ -12461,7 +12471,9 @@ ppc64_elf_size_stubs (struct bfd_link_in + stub_sec != NULL; + stub_sec = stub_sec->next) + if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 +- && stub_sec->rawsize != stub_sec->size) ++ && stub_sec->rawsize != stub_sec->size ++ && (htab->stub_iteration <= STUB_SHRINK_ITER ++ || stub_sec->rawsize < stub_sec->size)) + break; + + /* Exit from this loop when no stubs have been added, and no stubs +@@ -12939,7 +12951,9 @@ ppc64_elf_build_stubs (struct bfd_link_i + if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) + { + stub_sec_count += 1; +- if (stub_sec->rawsize != stub_sec->size) ++ if (stub_sec->rawsize != stub_sec->size ++ && (htab->stub_iteration <= STUB_SHRINK_ITER ++ || stub_sec->rawsize < stub_sec->size)) + break; + } + diff --git a/SOURCES/binutils-2.25.1-s390-plt.patch b/SOURCES/binutils-2.25.1-s390-plt.patch new file mode 100644 index 0000000..467a79b --- /dev/null +++ b/SOURCES/binutils-2.25.1-s390-plt.patch @@ -0,0 +1,110 @@ +diff -rup binutils.orig/bfd/elf32-s390.c binutils-2.25.1/bfd/elf32-s390.c +--- binutils.orig/bfd/elf32-s390.c 2017-05-09 11:06:34.741540539 +0100 ++++ binutils-2.25.1/bfd/elf32-s390.c 2017-05-09 11:08:21.140239839 +0100 +@@ -2728,7 +2728,7 @@ elf_s390_relocate_section (bfd *output_b + && s390_is_ifunc_symbol_p (h) + && h->def_regular) + { +- if (!info->shared || !h->non_got_ref) ++ if (!info->shared) + { + /* For a non-shared object STT_GNU_IFUNC symbol must + go through PLT. */ +diff -rup binutils.orig/bfd/elf64-s390.c binutils-2.25.1/bfd/elf64-s390.c +--- binutils.orig/bfd/elf64-s390.c 2017-05-09 11:06:34.711540906 +0100 ++++ binutils-2.25.1/bfd/elf64-s390.c 2017-05-09 11:09:23.495477558 +0100 +@@ -2693,10 +2693,11 @@ elf_s390_relocate_section (bfd *output_b + && s390_is_ifunc_symbol_p (h) + && h->def_regular) + { +- if (!info->shared || !h->non_got_ref) ++ if (!info->shared) + { +- /* For a non-shared object STT_GNU_IFUNC symbol must +- go through PLT. */ ++ /* For a non-shared object the symbol will not ++ change. Hence we can write the address of the ++ target IPLT slot now. */ + relocation = (htab->elf.iplt->output_section->vma + + htab->elf.iplt->output_offset + + h ->plt.offset); +diff -rup binutils.orig/bfd/elf-s390-common.c binutils-2.25.1/bfd/elf-s390-common.c +--- binutils.orig/bfd/elf-s390-common.c 2017-05-09 11:06:34.715540857 +0100 ++++ binutils-2.25.1/bfd/elf-s390-common.c 2017-05-09 11:07:34.079815141 +0100 +@@ -159,9 +159,7 @@ keep: + h->type = STT_FUNC; + } + +- /* We need dynamic relocation for STT_GNU_IFUNC symbol only when +- there is a non-GOT reference in a shared object. */ +- if (!info->shared || !h->non_got_ref) ++ if (!info->shared) + *head = NULL; + + /* Finally, allocate space. */ +diff -rupN binutils.orig/ld/testsuite/ld-s390/pltoffset-1.dd binutils-2.25.1/ld/testsuite/ld-s390/pltoffset-1.dd +--- binutils.orig/ld/testsuite/ld-s390/pltoffset-1.dd 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.25.1/ld/testsuite/ld-s390/pltoffset-1.dd 2017-05-09 11:16:02.644598050 +0100 +@@ -0,0 +1,8 @@ ++tmpdir/pltoffset-1: file format elf64-s390 ++ ++Disassembly of section .text: ++ ++.* <.text>: ++.*: 00 00 00 00 [ ]*.long 0x00000000 ++.*: e3 10 f0 38 00 24 [ ]*stg %r1,56\(%r15\) ++.*: c0 10 00 00 00 27 [ ]*larl %r1,58 <_GLOBAL_OFFSET_TABLE_> +diff -rupN binutils.orig/ld/testsuite/ld-s390/pltoffset-1.ld binutils-2.25.1/ld/testsuite/ld-s390/pltoffset-1.ld +--- binutils.orig/ld/testsuite/ld-s390/pltoffset-1.ld 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.25.1/ld/testsuite/ld-s390/pltoffset-1.ld 2017-05-09 11:16:02.644598050 +0100 +@@ -0,0 +1,34 @@ ++SECTIONS ++{ ++ .text : { ++ . = . + 4; ++ *(.plt) ++ } ++ .test : { ++ *(.text) ++ *(.got) ++ *(.got.plt) ++ *(.rodata) ++ *(.eh_frame) ++ *(.interp) ++ *(.data) ++ *(.bss) ++ } ++ ++ /* For old binutils which otherwise complain about nonrepresentable ++ sections. */ ++ .dynsym : { *(.dynsym) } ++ .gnu.version : { *(.gnu.version) } ++ ++ /DISCARD/ : { ++ *(.rela.text) ++ *(.rela.plt) ++ *(.rela.got.plt) ++ *(.rela.data) ++ *(.rela.rodata) ++ *(.rela.bss) ++ *(.rela.text) ++ *(.comment*) ++ *(.note*) ++ } ++} +diff -rupN binutils.orig/ld/testsuite/ld-s390/pltoffset-1.s binutils-2.25.1/ld/testsuite/ld-s390/pltoffset-1.s +--- binutils.orig/ld/testsuite/ld-s390/pltoffset-1.s 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.25.1/ld/testsuite/ld-s390/pltoffset-1.s 2017-05-09 11:16:02.645598038 +0100 +@@ -0,0 +1,12 @@ ++ .file "hello.c" ++.text ++ .align 8 ++.globl main ++ .type main, @function ++main: ++ brasl %r5,foo@PLT ++ br %r4 ++ .size main, .-main ++ ++.globl foo ++foo: .long 123 diff --git a/SOURCES/binutils-rh1406430.patch b/SOURCES/binutils-rh1406430.patch new file mode 100644 index 0000000..db0f9b8 --- /dev/null +++ b/SOURCES/binutils-rh1406430.patch @@ -0,0 +1,22 @@ +--- binutils.orig/bfd/elf64-s390.c 2017-01-06 10:25:00.803925177 +0000 ++++ binutils-2.25.1/bfd/elf64-s390.c 2017-01-06 10:26:29.124842261 +0000 +@@ -2690,6 +2690,19 @@ elf_s390_relocate_section (bfd *output_b + case R_390_PC64: + + if (h != NULL ++ && info->pie ++ && !h->def_regular) ++ { ++ _bfd_error_handler (_("%B: `%s' non-PLT reloc for symbol defined " ++ "in shared library and accessed " ++ "from executable " ++ "(rebuild file with -fPIC ?)"), ++ input_bfd, h->root.root.string); ++ bfd_set_error (bfd_error_bad_value); ++ return FALSE; ++ } ++ ++ if (h != NULL + && s390_is_ifunc_symbol_p (h) + && h->def_regular) + { diff --git a/SPECS/binutils.spec b/SPECS/binutils.spec index 1296bf9..33134f4 100644 --- a/SPECS/binutils.spec +++ b/SPECS/binutils.spec @@ -22,7 +22,7 @@ Version: 2.25.1 # Note: The Release string *must* be different from that used by any of the # devtoolset binutils associated with this release. That is why ".base" # has been appended here. See BZ 1337617 for more details. -Release: 22.base%{?dist} +Release: 31.base%{?dist} License: GPLv3+ Group: Development/Tools URL: http://sources.redhat.com/binutils @@ -72,6 +72,16 @@ Patch24: binutils-rh1162655.patch Patch25: binutils-2.25.1-aarch64-arch-extension.patch # Add support for the Z13 extensions to IBM's S390 architecture Patch26: binutils-2.25.1-s390-z13.patch +# Make linking fail when PIE and non-PIE S390 binaries are combined. +Patch27: binutils-rh1406430.patch +# Stop GOLD from warning about references to hidden symbols in shared links. +Patch28: binutils-2.25.1-gold-resolving-to-hidden-symbols.patch +# Speed up combining source code listings with disassembly output. +Patch29: binutils-2.25.1-objdump-speedup.patch +# Fix counting PowerPC stubs. +Patch30: binutils-2.25.1-ppc-stub-counting.patch +# Fix s390 PLT entry allocation. +Patch31: binutils-2.25.1-s390-plt.patch # A *temporary* patch to disable checking for valid PowerPC64 TLBIE # instructions. This allows the PPC kernel to be built. See: @@ -224,6 +234,11 @@ touch */configure %patch24 -p1 %patch25 -p1 %patch26 -p1 +# %patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 # TEMPORARY patch. %patch999 -p1 @@ -505,6 +520,35 @@ exit 0 %endif # %{isnative} %changelog +* Tue May 09 2017 Nick Clifton 2.25.1-31.base +- Fix generation of PLT entries for s390 binaries. + (#1440168) + +* Thu May 04 2017 Nick Clifton 2.25.1-28-base +- Disable fix for 1406430. It breaks building real s390 executables. + (#1447209) + (#1406430) + +* Thu Apr 27 2017 Nick Clifton 2.25.1-27-base +- Fix infnite loop in linker when counting PowerPC stubs. + (#1406498) + +* Mon Jan 16 2017 Nick Clifton 2.25.1-26-base +- Speed up displaying disassembly when mixed with source code. + (#1311352) + +* Mon Jan 16 2017 Nick Clifton 2.25.1-25-base +- Fix GOLD so that it will not warn about references to hidden symbols in shared objects. + (#1326710) + +* Fri Jan 06 2017 Nick Clifton 2.25.1-24-base +- Fix thinko in previous patch. + (#1406430) + +* Fri Jan 06 2017 Nick Clifton 2.25.1-23-base +- Add code to detect attempts to link PIE and non-PIE S390 binaries. + (#1406430) + * Mon Aug 08 2016 Nick Clifton 2.25.1-22-base - Fix date format bug in changelog which was preventing package build.