summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kempf <stefan@cvs.openbsd.org>2016-05-31 17:05:05 +0000
committerStefan Kempf <stefan@cvs.openbsd.org>2016-05-31 17:05:05 +0000
commit733409e466c16a6664f6335d8c42f3dd46282923 (patch)
treefdf6e2a50674804b65094b371e82cc4520153f46
parentb28ed2ea23be8bad6ecef6234d40f511bb38aaf6 (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.h10
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/elf-bfd.h9
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/elf.c58
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/elflink.c28
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/libbfd-in.h4
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/libbfd.h4
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/linker.c10
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/targets.c3
-rw-r--r--gnu/usr.bin/binutils-2.17/include/bfdlink.h5
-rw-r--r--gnu/usr.bin/binutils-2.17/ld/ld.h5
-rw-r--r--gnu/usr.bin/binutils-2.17/ld/ldlang.c8
-rw-r--r--gnu/usr.bin/binutils-2.17/ld/ldmain.c2
-rw-r--r--gnu/usr.bin/binutils-2.17/ld/lexsup.c2
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;