This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 5/5] PR ld/20828: Reorder the symbol sweep stage of section GC


Complement commit 81ff47b3a546 ("PR ld/20828: Fix linker script symbols 
wrongly forced local with section GC") and move the symbol sweep stage 
of section GC from `elf_gc_sweep' to `bfd_elf_size_dynamic_sections', 
avoiding the need to clear the `forced_local' marker, problematic for 
targets that have special processing in their `elf_backend_hide_symbol' 
handler.  Set `mark' instead in `bfd_elf_record_link_assignment' and, 
matching changes from commit 3bd43ebcb602 ("ld --gc-sections fail with 
__tls_get_addr_opt"), also in PowerPC `__tls_get_addr_opt' handling 
code, removing a:

FAIL: PR ld/20828 dynamic symbols with section GC (version script)

test suite failure with the `score-elf' target.

The rationale is it is enough if symbols are swept at the beginning of 
`bfd_elf_size_dynamic_sections' as it is only in this function that the 
size of the GOT, the dynamic symbol table and other dynamic sections is 
determined, which will depend on the number of symbols making it to the 
dynamic symbol table.  It is also appropriate to do the sweep at this 
point as it is already after any changes have been made to symbols with 
`bfd_elf_record_link_assignment', and not possible any earlier as calls 
to that function are only made just beforehand -- barring audit entry 
processing -- via `gld${EMULATION_NAME}_find_statement_assignment' 
invoked from `gld${EMULATION_NAME}_before_allocation' which is the ELF 
handler for `ldemul_before_allocation'.

	bfd/
	PR ld/20828
	* elflink.c (bfd_elf_record_link_assignment): Revert last 
	change and don't ever clear `forced_local'.  Set `mark' 
	unconditionally.
	(elf_gc_sweep_symbol_info, elf_gc_sweep_symbol): Reorder within
	file.
	(elf_gc_sweep): Move the call to `elf_gc_sweep_symbol'...
	(bfd_elf_size_dynamic_sections): ... here.
	* elf32-ppc.c (ppc_elf_tls_setup): Don't clear `forced_local'
	and set `mark' instead in `__tls_get_addr_opt' processing.
	* elf64-ppc.c (ppc64_elf_tls_setup): Likewise.
---
 The `score-elf' target turned out problematic because it has non-trivial 
code in `s3_bfd_score_elf_hide_symbol' and `s7_bfd_score_elf_hide_symbol' 
(which interestingly enough are both identical down to individual 
characters, even though these handlers are dispatched from common 
`_bfd_score_elf_hide_symbol' code) for GOT accounting, all of which would 
have to be undone if the hiding of a symbol were to be undone.  There are 
some other targets which do extra stuff in their `elf_backend_hide_symbol' 
handlers as well, all of which has led me to conclude that clearing the 
`forced_local' marker is not a good idea after all and we need to redesign 
code such that we don't hide a symbol until we are absolutely sure it is 
going to be its final state.

 I've scheduled this change after the Solaris 2 anonymous version script 
support bug fix so that there are no failures across the PR ld/20828 tests
after this change.

 No regressions across my usual targets.  OK to apply and backport to 
2.28?

  Maciej

binutils-bfd-elf-gc-sweep-symbols-in-size-dynamic-sections.diff
Index: binutils/bfd/elf32-ppc.c
===================================================================
--- binutils.orig/bfd/elf32-ppc.c	2017-01-16 19:07:42.000000000 +0000
+++ binutils/bfd/elf32-ppc.c	2017-01-21 04:07:37.891052348 +0000
@@ -5287,7 +5287,7 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd
 		  tga->root.type = bfd_link_hash_indirect;
 		  tga->root.u.i.link = &opt->root;
 		  ppc_elf_copy_indirect_symbol (info, opt, tga);
-		  opt->forced_local = 0;
+		  opt->mark = 1;
 		  if (opt->dynindx != -1)
 		    {
 		      /* Use __tls_get_addr_opt in dynamic relocations.  */
Index: binutils/bfd/elf64-ppc.c
===================================================================
--- binutils.orig/bfd/elf64-ppc.c	2017-01-16 19:07:43.000000000 +0000
+++ binutils/bfd/elf64-ppc.c	2017-01-21 04:07:30.777545315 +0000
@@ -8324,7 +8324,7 @@ ppc64_elf_tls_setup (struct bfd_link_inf
 		  tga_fd->root.type = bfd_link_hash_indirect;
 		  tga_fd->root.u.i.link = &opt_fd->root;
 		  ppc64_elf_copy_indirect_symbol (info, opt_fd, tga_fd);
-		  opt_fd->forced_local = 0;
+		  opt_fd->mark = 1;
 		  if (opt_fd->dynindx != -1)
 		    {
 		      /* Use __tls_get_addr_opt in dynamic relocations.  */
@@ -8341,7 +8341,7 @@ ppc64_elf_tls_setup (struct bfd_link_inf
 		      tga->root.type = bfd_link_hash_indirect;
 		      tga->root.u.i.link = &opt->root;
 		      ppc64_elf_copy_indirect_symbol (info, opt, tga);
-		      opt->forced_local = 0;
+		      opt->mark = 1;
 		      _bfd_elf_link_hash_hide_symbol (info, opt,
 						      tga->forced_local);
 		      htab->tls_get_addr = (struct ppc_link_hash_entry *) opt;
Index: binutils/bfd/elflink.c
===================================================================
--- binutils.orig/bfd/elflink.c	2017-01-20 23:54:23.624477307 +0000
+++ binutils/bfd/elflink.c	2017-01-21 03:47:47.528807062 +0000
@@ -671,17 +671,15 @@ bfd_elf_record_link_assignment (bfd *out
 
   /* If this symbol is not being provided by the linker script, and it is
      currently defined by a dynamic object, but not by a regular object,
-     then undo any forced local marking that may have been set by input
-     section garbage collection and clear out any version information
-     because the symbol will not be associated with the dynamic object
-     any more.  */
+     then clear out any version information because the symbol will not be
+     associated with the dynamic object any more.  */
   if (!provide
       && h->def_dynamic
       && !h->def_regular)
-    {
-      h->forced_local = 0;
-      h->verinfo.verdef = NULL;
-    }
+    h->verinfo.verdef = NULL;
+
+  /* Make sure this symbol is not garbage collected.  */
+  h->mark = 1;
 
   h->def_regular = 1;
 
@@ -5876,6 +5874,38 @@ bfd_elf_stack_segment_size (bfd *output_
   return TRUE;
 }
 
+/* Sweep symbols in swept sections.  Called via elf_link_hash_traverse.  */
+
+struct elf_gc_sweep_symbol_info
+{
+  struct bfd_link_info *info;
+  void (*hide_symbol) (struct bfd_link_info *, struct elf_link_hash_entry *,
+		       bfd_boolean);
+};
+
+static bfd_boolean
+elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
+{
+  if (!h->mark
+      && (((h->root.type == bfd_link_hash_defined
+	    || h->root.type == bfd_link_hash_defweak)
+	   && !((h->def_regular || ELF_COMMON_DEF_P (h))
+		&& h->root.u.def.section->gc_mark))
+	  || h->root.type == bfd_link_hash_undefined
+	  || h->root.type == bfd_link_hash_undefweak))
+    {
+      struct elf_gc_sweep_symbol_info *inf;
+
+      inf = (struct elf_gc_sweep_symbol_info *) data;
+      (*inf->hide_symbol) (inf->info, h, TRUE);
+      h->def_regular = 0;
+      h->ref_regular = 0;
+      h->ref_regular_nonweak = 0;
+    }
+
+  return TRUE;
+}
+
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
    called by the ELF linker emulation before_allocation routine.  We
    must set the sizes of the sections before the linker sets the
@@ -5906,6 +5936,22 @@ bfd_elf_size_dynamic_sections (bfd *outp
 
   bed = get_elf_backend_data (output_bfd);
 
+  if (info->gc_sections && bed->can_gc_sections)
+    {
+      struct elf_gc_sweep_symbol_info sweep_info;
+      unsigned long section_sym_count;
+
+      /* Remove the symbols that were in the swept sections from the
+	 dynamic symbol table.  GCFIXME: Anyone know how to get them
+	 out of the static symbol table as well?  */
+      sweep_info.info = info;
+      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+			      &sweep_info);
+
+      _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+    }
+
   /* Any syms created from now on start with -1 in
      got.refcount/offset and plt.refcount/offset.  */
   elf_hash_table (info)->init_got_refcount
@@ -12853,38 +12899,6 @@ _bfd_elf_gc_mark_extra_sections (struct 
   return TRUE;
 }
 
-/* Sweep symbols in swept sections.  Called via elf_link_hash_traverse.  */
-
-struct elf_gc_sweep_symbol_info
-{
-  struct bfd_link_info *info;
-  void (*hide_symbol) (struct bfd_link_info *, struct elf_link_hash_entry *,
-		       bfd_boolean);
-};
-
-static bfd_boolean
-elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
-{
-  if (!h->mark
-      && (((h->root.type == bfd_link_hash_defined
-	    || h->root.type == bfd_link_hash_defweak)
-	   && !((h->def_regular || ELF_COMMON_DEF_P (h))
-		&& h->root.u.def.section->gc_mark))
-	  || h->root.type == bfd_link_hash_undefined
-	  || h->root.type == bfd_link_hash_undefweak))
-    {
-      struct elf_gc_sweep_symbol_info *inf;
-
-      inf = (struct elf_gc_sweep_symbol_info *) data;
-      (*inf->hide_symbol) (inf->info, h, TRUE);
-      h->def_regular = 0;
-      h->ref_regular = 0;
-      h->ref_regular_nonweak = 0;
-    }
-
-  return TRUE;
-}
-
 /* The sweep phase of garbage collection.  Remove all garbage sections.  */
 
 typedef bfd_boolean (*gc_sweep_hook_fn)
@@ -12896,8 +12910,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link
   bfd *sub;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   gc_sweep_hook_fn gc_sweep_hook = bed->gc_sweep_hook;
-  unsigned long section_sym_count;
-  struct elf_gc_sweep_symbol_info sweep_info;
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
@@ -12963,15 +12975,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link
 	}
     }
 
-  /* Remove the symbols that were in the swept sections from the dynamic
-     symbol table.  GCFIXME: Anyone know how to get them out of the
-     static symbol table as well?  */
-  sweep_info.info = info;
-  sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
-  elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
-			  &sweep_info);
-
-  _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
   return TRUE;
 }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]