[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