[PATCH] Fix --as-needed on ppc64 (Re: Linker performance : ppc64_elf_check_directive & add_symbol_adjust)
Jakub Jelinek
jakub@redhat.com
Mon Dec 18 15:57:00 GMT 2006
Hi!
On Tue, Nov 07, 2006 at 01:55:45PM +1030, Alan Modra wrote:
> This was from a project involving thousands of input files.
> check_directives is called once per input file, and was iterating
> over all the symbols. It really only needs to process newly added
> dot symbols, so was doing an enormous amout of unnecessary work.
>
> * elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
> and union.
> (struct ppc_link_hash_entry): Add "next_dot_sym".
> (struct ppc_link_hash_table): Add "dot_syms".
> (link_hash_newfunc): Make list of syms starting with a dot.
> (ppc_get_stub_entry, adjust_opd_syms): Adjust.
> (ppc64_elf_add_symbol_hook): Don't set has_dotsym.
> (struct add_symbol_adjust_data): Delete.
> (add_symbol_adjust): Simplify params and return.
> (ppc64_elf_check_directives): Just process the "dot_syms" lists,
> not all syms.
This change broke --as-needed on ppc64, if at least one of the
--as-needed libraries is not needed and uses old style dot symbols
(in http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=219629
case that's hand written assembly within libgmp.so).
Short testcase:
echo 'int foo (int x) { return bar (x) + 1; }' | gcc -m64 -mcall-aixdesc -O2 -fpic -shared -xc - -o liba.so
echo 'int main (void) { return 0; }' | gcc -m64 -O2 -L. -o test -xc - -xnone -Wl,--as-needed -la -Wl,--no-as-needed -lc
The problem is that we start populating htab->dot_syms chain for any
library, but while the generic code undoes all it did in the hash table
when --as-needed library is not really needed, ppc64 code doesn't undo
this and therefore the chain points to freed (often reused) obstack
memory.
2006-12-18 Jakub Jelinek <jakub@redhat.com>
* elf-bfd.h (struct elf_backend_data): Add as_needed_cleanup hook.
* elfxx-target.h (elf_backend_as_needed_cleanup): Define.
(elfNN_bed): Add as_needed_cleanup hook.
* elflink.c (elf_link_add_object_symbols): Call it when reverting
hash table changes for unneeded --as-needed input.
* elf64-ppc64.c (elf_backend_as_needed_cleanup): Define.
(ppc64_elf_as_needed_cleanup): New function.
--- bfd/elf-bfd.h.jj 2006-12-18 15:01:17.000000000 +0100
+++ bfd/elf-bfd.h 2006-12-18 16:30:36.000000000 +0100
@@ -711,6 +711,13 @@ struct elf_backend_data
bfd_boolean (*check_directives)
(bfd *abfd, struct bfd_link_info *info);
+ /* The AS_NEEDED_CLEANUP function is called once per --as-needed
+ input file that was not needed by the add_symbols phase of the
+ ELF backend linker. The function must undo any target specific
+ changes in the symbol hash table. */
+ bfd_boolean (*as_needed_cleanup)
+ (bfd *abfd, struct bfd_link_info *info);
+
/* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend
linker for every symbol which is defined by a dynamic object and
referenced by a regular object. This is called after all the
--- bfd/elfxx-target.h.jj 2006-10-21 12:55:56.000000000 +0200
+++ bfd/elfxx-target.h 2006-12-18 16:31:55.000000000 +0100
@@ -372,6 +372,9 @@
#ifndef elf_backend_check_directives
#define elf_backend_check_directives 0
#endif
+#ifndef elf_backend_as_needed_cleanup
+#define elf_backend_as_needed_cleanup 0
+#endif
#ifndef elf_backend_adjust_dynamic_symbol
#define elf_backend_adjust_dynamic_symbol 0
#endif
@@ -604,6 +607,7 @@ static struct elf_backend_data elfNN_bed
elf_backend_omit_section_dynsym,
elf_backend_check_relocs,
elf_backend_check_directives,
+ elf_backend_as_needed_cleanup,
elf_backend_adjust_dynamic_symbol,
elf_backend_always_size_sections,
elf_backend_size_dynamic_sections,
--- bfd/elf64-ppc.c.jj 2006-12-18 15:01:17.000000000 +0100
+++ bfd/elf64-ppc.c 2006-12-18 16:36:05.000000000 +0100
@@ -88,6 +88,7 @@ static bfd_vma opd_entry_value
#define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol
#define elf_backend_add_symbol_hook ppc64_elf_add_symbol_hook
#define elf_backend_check_directives ppc64_elf_check_directives
+#define elf_backend_as_needed_cleanup ppc64_elf_as_needed_cleanup
#define elf_backend_archive_symbol_lookup ppc64_elf_archive_symbol_lookup
#define elf_backend_check_relocs ppc64_elf_check_relocs
#define elf_backend_gc_mark_dynamic_ref ppc64_elf_gc_mark_dynamic_ref
@@ -4247,6 +4248,17 @@ ppc64_elf_check_directives (bfd *ibfd, s
return TRUE;
}
+/* Undo hash table changes when an --as-needed input file is determined
+ not to be needed. */
+
+static bfd_boolean
+ppc64_elf_as_needed_cleanup (bfd *ibfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
+{
+ ppc_hash_table (info)->dot_syms = NULL;
+ return TRUE;
+}
+
static bfd_boolean
update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
unsigned long r_symndx, bfd_vma r_addend, int tls_type)
--- bfd/elflink.c.jj 2006-12-18 15:01:17.000000000 +0100
+++ bfd/elflink.c 2006-12-18 16:40:32.000000000 +0100
@@ -4251,6 +4251,8 @@ elf_link_add_object_symbols (bfd *abfd,
unsigned int i;
/* Restore the symbol table. */
+ if (bed->as_needed_cleanup)
+ (*bed->as_needed_cleanup) (abfd, info);
old_hash = (char *) old_tab + tabsize;
old_ent = (char *) old_hash + hashsize;
sym_hash = elf_sym_hashes (abfd);
Jakub
More information about the Binutils
mailing list