diff options
author | Stefan Kempf <stefan@cvs.openbsd.org> | 2016-05-31 17:05:05 +0000 |
---|---|---|
committer | Stefan Kempf <stefan@cvs.openbsd.org> | 2016-05-31 17:05:05 +0000 |
commit | 733409e466c16a6664f6335d8c42f3dd46282923 (patch) | |
tree | fdf6e2a50674804b65094b371e82cc4520153f46 | |
parent | b28ed2ea23be8bad6ecef6234d40f511bb38aaf6 (diff) |
Port over binutils fix for PR ld/3111.
This greatly speeds up up linking of object files that contain
lots of dwarf2 symbols by caching symbol tables.
Original patch before binutils was switched to GPLv3 from:
https://sourceware.org/ml/binutils/2006-08/msg00334.html
Aaron Miller made us aware of that diff and adapted it to our
in-tree binutils. Many thanks!
Ports build testing on amd64 by krw@
ok deraadt@ krw@
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h | 10 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/elf-bfd.h | 9 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/elf.c | 58 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/elflink.c | 28 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/libbfd-in.h | 4 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/libbfd.h | 4 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/linker.c | 10 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/bfd/targets.c | 3 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/include/bfdlink.h | 5 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/ld/ld.h | 5 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/ld/ldlang.c | 8 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/ld/ldmain.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils-2.17/ld/lexsup.c | 2 |
13 files changed, 94 insertions, 54 deletions
diff --git a/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h b/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h index 996449e12a5..1b4cef83dc1 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h +++ b/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h @@ -5069,7 +5069,8 @@ typedef struct bfd_target /* Check if SEC has been already linked during a reloceatable or final link. */ - void (*_section_already_linked) (bfd *, struct bfd_section *); + void (*_section_already_linked) (bfd *, struct bfd_section *, + struct bfd_link_info *); /* Routines to handle dynamic symbols and relocs. */ #define BFD_JUMP_TABLE_DYNAMIC(NAME) \ @@ -5129,10 +5130,11 @@ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); #define bfd_link_split_section(abfd, sec) \ BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) -void bfd_section_already_linked (bfd *abfd, asection *sec); +void bfd_section_already_linked (bfd *abfd, asection *sec, + struct bfd_link_info *info); -#define bfd_section_already_linked(abfd, sec) \ - BFD_SEND (abfd, _section_already_linked, (abfd, sec)) +#define bfd_section_already_linked(abfd, sec, info) \ + BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) /* Extracted from simple.c. */ bfd_byte *bfd_simple_get_relocated_section_contents diff --git a/gnu/usr.bin/binutils-2.17/bfd/elf-bfd.h b/gnu/usr.bin/binutils-2.17/bfd/elf-bfd.h index d9c12c418c8..190886b1982 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/elf-bfd.h +++ b/gnu/usr.bin/binutils-2.17/bfd/elf-bfd.h @@ -1374,6 +1374,9 @@ struct elf_obj_tdata /* Used to determine if we are creating an executable. */ bfd_boolean executable; + + /* Symbol buffer. */ + Elf_Internal_Sym *symbuf; }; #define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) @@ -1506,11 +1509,11 @@ extern bfd_boolean _bfd_elf_match_sections_by_type extern bfd_boolean bfd_elf_is_group_section (bfd *, const struct bfd_section *); extern void _bfd_elf_section_already_linked - (bfd *, struct bfd_section *); + (bfd *, struct bfd_section *, struct bfd_link_info *); extern void bfd_elf_set_group_contents (bfd *, asection *, void *); extern asection *_bfd_elf_check_kept_section - (asection *); + (asection *, struct bfd_link_info *); extern void _bfd_elf_link_just_syms (asection *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_copy_private_header_data @@ -1706,7 +1709,7 @@ extern bfd_boolean _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean); extern bfd_boolean bfd_elf_match_symbols_in_sections - (asection *sec1, asection *sec2); + (asection *, asection *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_setup_sections (bfd *); diff --git a/gnu/usr.bin/binutils-2.17/bfd/elf.c b/gnu/usr.bin/binutils-2.17/bfd/elf.c index aead5b11d50..c73238b0c28 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/elf.c +++ b/gnu/usr.bin/binutils-2.17/bfd/elf.c @@ -3106,7 +3106,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) s, s->owner); /* Point to the kept section if it has the same size as the discarded one. */ - kept = _bfd_elf_check_kept_section (s); + kept = _bfd_elf_check_kept_section (s, link_info); if (kept == NULL) { bfd_set_error (bfd_error_bad_value); @@ -8694,7 +8694,8 @@ elf_sym_name_compare (const void *arg1, const void *arg2) symbols. */ bfd_boolean -bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2) +bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, + struct bfd_link_info *info) { bfd *bfd1, *bfd2; const struct elf_backend_data *bed1, *bed2; @@ -8752,21 +8753,37 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2) if (symcount1 == 0 || symcount2 == 0) return FALSE; - isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0, - NULL, NULL, NULL); - isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0, - NULL, NULL, NULL); - result = FALSE; - if (isymbuf1 == NULL || isymbuf2 == NULL) - goto done; + isymbuf1 = elf_tdata (bfd1)->symbuf; + isymbuf2 = elf_tdata (bfd2)->symbuf; - /* Sort symbols by binding and section. Global definitions are at - the beginning. */ - qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym), - elf_sort_elf_symbol); - qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym), - elf_sort_elf_symbol); + if (isymbuf1 == NULL) + { + isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0, + NULL, NULL, NULL); + if (isymbuf1 == NULL) + goto done; + /* Sort symbols by binding and section. Global definitions are at + the beginning. */ + qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym), + elf_sort_elf_symbol); + if (!info->reduce_memory_overheads) + elf_tdata (bfd1)->symbuf = isymbuf1; + } + + if (isymbuf2 == NULL) + { + isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0, + NULL, NULL, NULL); + if (isymbuf2 == NULL) + goto done; + /* Sort symbols by binding and section. Global definitions are at + the beginning. */ + qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym), + elf_sort_elf_symbol); + if (!info->reduce_memory_overheads) + elf_tdata (bfd2)->symbuf = isymbuf2; + } /* Count definitions in the section. */ count1 = 0; @@ -8850,10 +8867,13 @@ done: free (symtable1); if (symtable2) free (symtable2); - if (isymbuf1) - free (isymbuf1); - if (isymbuf2) - free (isymbuf2); + if (info->reduce_memory_overheads) + { + if (isymbuf1) + free (isymbuf1); + if (isymbuf2) + free (isymbuf2); + } return result; } diff --git a/gnu/usr.bin/binutils-2.17/bfd/elflink.c b/gnu/usr.bin/binutils-2.17/bfd/elflink.c index 34ff98f60c4..b035b8e1590 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/elflink.c +++ b/gnu/usr.bin/binutils-2.17/bfd/elflink.c @@ -6767,14 +6767,15 @@ _bfd_elf_default_action_discarded (asection *sec) /* Find a match between a section and a member of a section group. */ static asection * -match_group_member (asection *sec, asection *group) +match_group_member (asection *sec, asection *group, + struct bfd_link_info *info) { asection *first = elf_next_in_group (group); asection *s = first; while (s != NULL) { - if (bfd_elf_match_symbols_in_sections (s, sec)) + if (bfd_elf_match_symbols_in_sections (s, sec, info)) return s; s = elf_next_in_group (s); @@ -6790,7 +6791,7 @@ match_group_member (asection *sec, asection *group) NULL. */ asection * -_bfd_elf_check_kept_section (asection *sec) +_bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info) { asection *kept; @@ -6798,7 +6799,7 @@ _bfd_elf_check_kept_section (asection *sec) if (kept != NULL) { if (elf_sec_group (sec) != NULL) - kept = match_group_member (sec, kept); + kept = match_group_member (sec, kept, info); if (kept != NULL && sec->size != kept->size) kept = NULL; } @@ -7151,7 +7152,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) { asection *kept; - kept = _bfd_elf_check_kept_section (sec); + kept = _bfd_elf_check_kept_section (sec, + finfo->info); if (kept != NULL) { *ps = kept; @@ -8281,6 +8283,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } + /* Free symbol buffer if needed. */ + if (!info->reduce_memory_overheads) + { + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + if (elf_tdata (sub)->symbuf) + free (elf_tdata (sub)->symbuf); + } + /* Output any global symbols that got converted to local in a version script or due to symbol visibility. We do this in a separate step since ELF requires all local symbols to appear @@ -9725,7 +9735,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) } void -_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec) +_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec, + struct bfd_link_info *info) { flagword flags; const char *name, *p; @@ -9891,7 +9902,8 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec) if ((l->sec->flags & SEC_GROUP) == 0 && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL && bfd_elf_match_symbols_in_sections (l->sec, - elf_next_in_group (sec))) + elf_next_in_group (sec), + info)) { elf_next_in_group (sec)->output_section = bfd_abs_section_ptr; elf_next_in_group (sec)->kept_section = l->sec; @@ -9912,7 +9924,7 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec) if (first != NULL && elf_next_in_group (first) == first - && bfd_elf_match_symbols_in_sections (first, sec)) + && bfd_elf_match_symbols_in_sections (first, sec, info)) { sec->output_section = bfd_abs_section_ptr; sec->kept_section = l->sec; diff --git a/gnu/usr.bin/binutils-2.17/bfd/libbfd-in.h b/gnu/usr.bin/binutils-2.17/bfd/libbfd-in.h index 3a7e81a7b7f..6a337f48d65 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/libbfd-in.h +++ b/gnu/usr.bin/binutils-2.17/bfd/libbfd-in.h @@ -408,7 +408,7 @@ extern bfd_boolean _bfd_generic_set_section_contents #define _bfd_nolink_bfd_link_split_section \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ - ((void (*) (bfd *, struct bfd_section *)) bfd_void) + ((void (*) (bfd *, struct bfd_section *, struct bfd_link_info *)) bfd_void) /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC @@ -522,7 +522,7 @@ extern bfd_boolean _bfd_generic_link_split_section (bfd *, struct bfd_section *); extern void _bfd_generic_section_already_linked - (bfd *, struct bfd_section *); + (bfd *, struct bfd_section *, struct bfd_link_info *); /* Generic reloc_link_order processing routine. */ extern bfd_boolean _bfd_generic_reloc_link_order diff --git a/gnu/usr.bin/binutils-2.17/bfd/libbfd.h b/gnu/usr.bin/binutils-2.17/bfd/libbfd.h index fb237440b29..24964899c91 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/libbfd.h +++ b/gnu/usr.bin/binutils-2.17/bfd/libbfd.h @@ -413,7 +413,7 @@ extern bfd_boolean _bfd_generic_set_section_contents #define _bfd_nolink_bfd_link_split_section \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ - ((void (*) (bfd *, struct bfd_section *)) bfd_void) + ((void (*) (bfd *, struct bfd_section *, struct bfd_link_info *)) bfd_void) /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC @@ -527,7 +527,7 @@ extern bfd_boolean _bfd_generic_link_split_section (bfd *, struct bfd_section *); extern void _bfd_generic_section_already_linked - (bfd *, struct bfd_section *); + (bfd *, struct bfd_section *, struct bfd_link_info *); /* Generic reloc_link_order processing routine. */ extern bfd_boolean _bfd_generic_reloc_link_order diff --git a/gnu/usr.bin/binutils-2.17/bfd/linker.c b/gnu/usr.bin/binutils-2.17/bfd/linker.c index 14eeae4df0c..049596a23d0 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/linker.c +++ b/gnu/usr.bin/binutils-2.17/bfd/linker.c @@ -2877,14 +2877,15 @@ FUNCTION bfd_section_already_linked SYNOPSIS - void bfd_section_already_linked (bfd *abfd, asection *sec); + void bfd_section_already_linked (bfd *abfd, asection *sec, + struct bfd_link_info *info); DESCRIPTION Check if @var{sec} has been already linked during a reloceatable or final link. -.#define bfd_section_already_linked(abfd, sec) \ -. BFD_SEND (abfd, _section_already_linked, (abfd, sec)) +.#define bfd_section_already_linked(abfd, sec, info) \ +. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) . */ @@ -2970,7 +2971,8 @@ bfd_section_already_linked_table_free (void) /* This is used on non-ELF inputs. */ void -_bfd_generic_section_already_linked (bfd *abfd, asection *sec) +_bfd_generic_section_already_linked (bfd *abfd, asection *sec, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { flagword flags; const char *name; diff --git a/gnu/usr.bin/binutils-2.17/bfd/targets.c b/gnu/usr.bin/binutils-2.17/bfd/targets.c index 774aa32fb1e..299d9c89021 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/targets.c +++ b/gnu/usr.bin/binutils-2.17/bfd/targets.c @@ -481,7 +481,8 @@ BFD_JUMP_TABLE macros. . . {* Check if SEC has been already linked during a reloceatable or . final link. *} -. void (*_section_already_linked) (bfd *, struct bfd_section *); +. void (*_section_already_linked) (bfd *, struct bfd_section *, +. struct bfd_link_info *); . . {* Routines to handle dynamic symbols and relocs. *} .#define BFD_JUMP_TABLE_DYNAMIC(NAME) \ diff --git a/gnu/usr.bin/binutils-2.17/include/bfdlink.h b/gnu/usr.bin/binutils-2.17/include/bfdlink.h index bca23a05d2f..f8e9a2dd6ae 100644 --- a/gnu/usr.bin/binutils-2.17/include/bfdlink.h +++ b/gnu/usr.bin/binutils-2.17/include/bfdlink.h @@ -327,6 +327,11 @@ struct bfd_link_info /* TRUE if unreferenced sections should be removed. */ unsigned int gc_sections: 1; + /* If TRUE reduce memory overheads, at the expense of speed. This will + cause map file generation to use an O(N^2) algorithm and disable + caching ELF symbol buffer. */ + unsigned int reduce_memory_overheads: 1; + /* What to do with unresolved symbols in an object file. When producing executables the default is GENERATE_ERROR. When producing shared libraries the default is IGNORE. The diff --git a/gnu/usr.bin/binutils-2.17/ld/ld.h b/gnu/usr.bin/binutils-2.17/ld/ld.h index bf4e50351a5..6c6b3b13284 100644 --- a/gnu/usr.bin/binutils-2.17/ld/ld.h +++ b/gnu/usr.bin/binutils-2.17/ld/ld.h @@ -200,11 +200,6 @@ typedef struct { behaviour of the linker. The new default behaviour is to reject such input files. */ bfd_boolean accept_unknown_input_arch; - - /* If TRUE reduce memory overheads, at the expense of speed. - This will cause map file generation to use an O(N^2) algorithm. */ - bfd_boolean reduce_memory_overheads; - } args_type; extern args_type command_line; diff --git a/gnu/usr.bin/binutils-2.17/ld/ldlang.c b/gnu/usr.bin/binutils-2.17/ld/ldlang.c index 099a4ccb507..a1a9682d1ab 100644 --- a/gnu/usr.bin/binutils-2.17/ld/ldlang.c +++ b/gnu/usr.bin/binutils-2.17/ld/ldlang.c @@ -1670,7 +1670,7 @@ lang_map (void) fprintf (config.map_file, _("\nLinker script and memory map\n\n")); - if (! command_line.reduce_memory_overheads) + if (! link_info.reduce_memory_overheads) { obstack_begin (&map_obstack, 1000); for (p = link_info.input_bfds; p != (bfd *) NULL; p = p->link_next) @@ -1746,7 +1746,7 @@ init_os (lang_output_section_statement_type *s, asection *isec) } s->bfd_section->output_section = s->bfd_section; s->bfd_section->output_offset = 0; - if (!command_line.reduce_memory_overheads) + if (!link_info.reduce_memory_overheads) { fat_section_userdata_type *new = stat_alloc (sizeof (fat_section_userdata_type)); @@ -1840,7 +1840,7 @@ section_already_linked (bfd *abfd, asection *sec, void *data) } if (!(abfd->flags & DYNAMIC)) - bfd_section_already_linked (abfd, sec); + bfd_section_already_linked (abfd, sec, &link_info); } /* The wild routines. @@ -3564,7 +3564,7 @@ print_input_section (asection *i) if (i->output_section != NULL && i->output_section->owner == output_bfd) { - if (command_line.reduce_memory_overheads) + if (link_info.reduce_memory_overheads) bfd_link_hash_traverse (link_info.hash, print_one_symbol, i); else print_all_symbols (i); diff --git a/gnu/usr.bin/binutils-2.17/ld/ldmain.c b/gnu/usr.bin/binutils-2.17/ld/ldmain.c index 1fee6f8673c..db8fae7398d 100644 --- a/gnu/usr.bin/binutils-2.17/ld/ldmain.c +++ b/gnu/usr.bin/binutils-2.17/ld/ldmain.c @@ -261,7 +261,6 @@ main (int argc, char **argv) command_line.warn_mismatch = TRUE; command_line.check_section_addresses = TRUE; command_line.accept_unknown_input_arch = FALSE; - command_line.reduce_memory_overheads = FALSE; sort_section = none; @@ -325,6 +324,7 @@ main (int argc, char **argv) link_info.relax_pass = 1; link_info.warn_shared_textrel = FALSE; link_info.gc_sections = FALSE; + link_info.reduce_memory_overheads = FALSE; ldfile_add_arch (""); diff --git a/gnu/usr.bin/binutils-2.17/ld/lexsup.c b/gnu/usr.bin/binutils-2.17/ld/lexsup.c index 654edb52f27..dda6ffe861f 100644 --- a/gnu/usr.bin/binutils-2.17/ld/lexsup.c +++ b/gnu/usr.bin/binutils-2.17/ld/lexsup.c @@ -1350,7 +1350,7 @@ parse_args (unsigned argc, char **argv) break; case OPTION_REDUCE_MEMORY_OVERHEADS: - command_line.reduce_memory_overheads = TRUE; + link_info.reduce_memory_overheads = TRUE; if (config.hash_table_size == 0) config.hash_table_size = 1021; break; |