bfd,sparc: fix the .dynsym sh_index when stripping all symbols in ld
authorJose E. Marchesi <jose.marchesi@oracle.com>
Thu, 4 Oct 2018 09:12:48 +0000 (02:12 -0700)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Thu, 4 Oct 2018 09:58:39 +0000 (11:58 +0200)
The SPARC ELF BFD backend uses a hack in order to accomodate the
STT_REGISTER symbols mandated by the SPARC V9 ABI for 64-bit objects.
The hack works as follows:

- Early in `size_dynamic_symbols', it adds the dynamic STT_REGISTER
  symbols and the corresponding DT_SPARC_REGISTER tags if needed,
  i.e. if the input object has been annotated by the assembler to use
  any of the global registers requiring annotations by the ABI.

  The STT_REGISTER symbols are not local, but nevertheless they are
  added to the end of the dynlocal linked list (eek, yes) to be fixed
  "later".  This is done so the symbols are emitted in the symtab.

- Consequently, when the `sh_info' field of the .dynsym section is
  calculated in `bfd_elf_final_link' to be `local_dynsymcount + 1', it
  may have the wrong value, since the real first global symbol is the
  first STT_REGISTER symbol.

- However, this temporary inconsistency is fixed in the
  `elf64_sparc_output_arch_syms' backend hook: the sh_index is
  adjusted to its rightful value.  So all is well and good.

However the 2015 changeset

commit 8539e4e89eb4c54bb6668582cd709765a3803588
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Jan 15 19:42:59 2015 +1030

    Fix ARM fail of gap test

    ld-elf/gap test was failing due to the ARM backend attempting to output
    arch symbols when ld -s (strip all symbols) is in force.  This patch
    stops that happening and tidies the code a little.

made the `elf_backend_output_arch_syms' backend hook to not be called
when all symbols are to be stripped.  This resulted in an incorrect
sh_index for .dynsym when a link is performed with -s (strip_all), in
64-bit sparc ELF objects.

This patch moves the sh_index adjusting code from the target
`output_arch_syms' to `finish_dynamic_sections'.  It also removes the
strip_all check from `elf64_sparc_output_arch_syms', as the function
is no longer called in that case.

Tested in sparc64-linux-gnu and sparc-linux-gnu.
No regressions observed.

bfd/ChangeLog:

2018-10-04  Jose E. Marchesi  <jose.marchesi@oracle.com>

* elf64-sparc.c (elf64_sparc_output_arch_syms): Do not correct the
impact of STT_REGISTER symbols in the dynsym sh_index here...
* elfxx-sparc.c (_bfd_sparc_elf_finish_dynamic_sections): ... but
do it here.

bfd/ChangeLog
bfd/elf64-sparc.c
bfd/elfxx-sparc.c

index d2b5a57fe78e3baebe508c844f9867ecc5492879..cc82ff164264eb271b6541d38c6f6ae6dbc78845 100644 (file)
@@ -1,3 +1,10 @@
+2018-10-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * elf64-sparc.c (elf64_sparc_output_arch_syms): Do notcorrect the
+       impact of STT_REGISTER symbols in the dynsym sh_index here...
+       * elfxx-sparc.c (_bfd_sparc_elf_finish_dynamic_sections): ...but
+       do it here.
+
 2018-10-03  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/23658
index 41e1b7acf7e07b6fccdf04b296921014b13ae27d..958ce44690ebea7343a61306fa27bcf101e1ff10 100644 (file)
@@ -582,29 +582,6 @@ elf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED,
     _bfd_sparc_elf_hash_table(info)->app_regs;
   Elf_Internal_Sym sym;
 
-  /* We arranged in size_dynamic_sections to put the STT_REGISTER entries
-     at the end of the dynlocal list, so they came at the end of the local
-     symbols in the symtab.  Except that they aren't STB_LOCAL, so we need
-     to back up symtab->sh_info.  */
-  if (elf_hash_table (info)->dynlocal)
-    {
-      bfd * dynobj = elf_hash_table (info)->dynobj;
-      asection *dynsymsec = bfd_get_linker_section (dynobj, ".dynsym");
-      struct elf_link_local_dynamic_entry *e;
-
-      for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
-       if (e->input_indx == -1)
-         break;
-      if (e)
-       {
-         elf_section_data (dynsymsec->output_section)->this_hdr.sh_info
-           = e->dynindx;
-       }
-    }
-
-  if (info->strip == strip_all)
-    return TRUE;
-
   for (reg = 0; reg < 4; reg++)
     if (app_regs [reg].name != NULL)
       {
index bf143c400f443221877bdeabb7aa9db52c8f05a1..e5430fd55ded3a14a65ff6d7f25d13c255f3ca16 100644 (file)
@@ -4792,7 +4792,25 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i
   htab = _bfd_sparc_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
   dynobj = htab->elf.dynobj;
-
+  
+  /* We arranged in size_dynamic_sections to put the STT_REGISTER
+     entries at the end of the dynlocal list, so they came at the end
+     of the local symbols in the symtab.  Except that they aren't
+     STB_LOCAL, so we need to back up symtab->sh_info.  */
+  if (ABI_64_P (output_bfd)
+      && elf_hash_table (info)->dynlocal)
+    {
+      asection *dynsymsec = bfd_get_linker_section (dynobj, ".dynsym");
+      struct elf_link_local_dynamic_entry *e;
+      
+      for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+       if (e->input_indx == -1)
+         break;
+      if (e)
+       elf_section_data (dynsymsec->output_section)->this_hdr.sh_info
+         = e->dynindx;
+    }
+  
   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)