PowerPC TPREL reloc handling
authorAlan Modra <amodra@gmail.com>
Sat, 26 Aug 2017 10:56:13 +0000 (20:26 +0930)
committerAlan Modra <amodra@gmail.com>
Sat, 26 Aug 2017 11:22:07 +0000 (20:52 +0930)
Tidy how these are handled in PIEs.

* elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll.  Comment.
(ppc_elf_check_relocs): Only set DF_STATIC_TLS in shared libs.
(ppc_elf_relocate_section): Comment fix.
* elf64-ppc.c (must_be_dyn_reloc): Use bfd_link_dll.  Comment.
(ppc64_elf_check_relocs): Only set DF_STATIC_TLS in shared libs.
Support dynamic relocs for TPREL16 when non-pic too.
(dec_dynrel_count): Adjust TPREL16 handling as per check_relocs.
(ppc64_elf_relocate_section): Support dynamic relocs for TPREL16
when non-pic too.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf64-ppc.c

index cefe1f1..e785d0e 100644 (file)
@@ -1,3 +1,15 @@
+2017-08-26  Alan Modra  <amodra@gmail.com>
+
+       * elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll.  Comment.
+       (ppc_elf_check_relocs): Only set DF_STATIC_TLS in shared libs.
+       (ppc_elf_relocate_section): Comment fix.
+       * elf64-ppc.c (must_be_dyn_reloc): Use bfd_link_dll.  Comment.
+       (ppc64_elf_check_relocs): Only set DF_STATIC_TLS in shared libs.
+       Support dynamic relocs for TPREL16 when non-pic too.
+       (dec_dynrel_count): Adjust TPREL16 handling as per check_relocs.
+       (ppc64_elf_relocate_section): Support dynamic relocs for TPREL16
+       when non-pic too.
+
 2017-08-25  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf32-i386.c (elf_i386_link_hash_entry): Remove redundant
index ac3b12b..a5d8193 100644 (file)
@@ -3192,9 +3192,9 @@ struct plt_entry
   bfd_vma glink_offset;
 };
 
-/* Of those relocs that might be copied as dynamic relocs, this function
-   selects those that must be copied when linking a shared library,
-   even when the symbol is local.  */
+/* Of those relocs that might be copied as dynamic relocs, this
+   function selects those that must be copied when linking a shared
+   library or PIE, even when the symbol is local.  */
 
 static int
 must_be_dyn_reloc (struct bfd_link_info *info,
@@ -3203,6 +3203,10 @@ must_be_dyn_reloc (struct bfd_link_info *info,
   switch (r_type)
     {
     default:
+      /* Only relative relocs can be resolved when the object load
+        address isn't fixed.  DTPREL32 is excluded because the
+        dynamic linker needs to differentiate global dynamic from
+        local dynamic __tls_index pairs when PPC_OPT_TLS is set.  */
       return 1;
 
     case R_PPC_REL24:
@@ -3217,7 +3221,9 @@ must_be_dyn_reloc (struct bfd_link_info *info,
     case R_PPC_TPREL16_LO:
     case R_PPC_TPREL16_HI:
     case R_PPC_TPREL16_HA:
-      return !bfd_link_executable (info);
+      /* These relocations are relative but in a shared library the
+        linker doesn't know the thread pointer base.  */
+      return bfd_link_dll (info);
     }
 }
 
@@ -4151,7 +4157,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_GOT_TPREL16_LO:
        case R_PPC_GOT_TPREL16_HI:
        case R_PPC_GOT_TPREL16_HA:
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          tls_type = TLS_TLS | TLS_TPREL;
          goto dogottls;
@@ -4430,13 +4436,13 @@ ppc_elf_check_relocs (bfd *abfd,
            return FALSE;
          break;
 
-         /* We shouldn't really be seeing these.  */
+         /* We shouldn't really be seeing TPREL32.  */
        case R_PPC_TPREL32:
        case R_PPC_TPREL16:
        case R_PPC_TPREL16_LO:
        case R_PPC_TPREL16_HI:
        case R_PPC_TPREL16_HA:
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          goto dodyn;
 
@@ -8783,8 +8789,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
          if (htab->elf.tls_sec != NULL)
            addend -= htab->elf.tls_sec->vma + TP_OFFSET;
          /* The TPREL16 relocs shouldn't really be used in shared
-            libs as they will result in DT_TEXTREL being set, but
-            support them anyway.  */
+            libs or with non-local symbols as that will result in
+            DT_TEXTREL being set, but support them anyway.  */
          goto dodyn;
 
        case R_PPC_TPREL32:
index f0fde1d..7245038 100644 (file)
@@ -3785,9 +3785,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
    calls may use the function descriptor symbol, ie. "bl foo".  This
    behaves exactly as "bl .foo".  */
 
-/* Of those relocs that might be copied as dynamic relocs, this function
-   selects those that must be copied when linking a shared library,
-   even when the symbol is local.  */
+/* Of those relocs that might be copied as dynamic relocs, this
+   function selects those that must be copied when linking a shared
+   library or PIE, even when the symbol is local.  */
 
 static int
 must_be_dyn_reloc (struct bfd_link_info *info,
@@ -3796,6 +3796,10 @@ must_be_dyn_reloc (struct bfd_link_info *info,
   switch (r_type)
     {
     default:
+      /* Only relative relocs can be resolved when the object load
+        address isn't fixed.  DTPREL64 is excluded because the
+        dynamic linker needs to differentiate global dynamic from
+        local dynamic __tls_index pairs when PPC64_OPT_TLS is set.  */
       return 1;
 
     case R_PPC64_REL32:
@@ -3816,7 +3820,9 @@ must_be_dyn_reloc (struct bfd_link_info *info,
     case R_PPC64_TPREL16_HIGHEST:
     case R_PPC64_TPREL16_HIGHESTA:
     case R_PPC64_TPREL64:
-      return !bfd_link_executable (info);
+      /* These relocations are relative but in a shared library the
+        linker doesn't know the thread pointer base.  */
+      return bfd_link_dll (info);
     }
 }
 
@@ -5496,7 +5502,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT_TPREL16_LO_DS:
        case R_PPC64_GOT_TPREL16_HI:
        case R_PPC64_GOT_TPREL16_HA:
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          tls_type = TLS_TLS | TLS_TPREL;
          goto dogottls;
@@ -5758,7 +5764,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_PPC64_TPREL64:
          tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          goto dotlstoc;
 
@@ -5834,12 +5840,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_TPREL16_HIGHERA:
        case R_PPC64_TPREL16_HIGHEST:
        case R_PPC64_TPREL16_HIGHESTA:
-         if (bfd_link_pic (info))
-           {
-             info->flags |= DF_STATIC_TLS;
-             goto dodyn;
-           }
-         break;
+         if (bfd_link_dll (info))
+           info->flags |= DF_STATIC_TLS;
+         goto dodyn;
 
        case R_PPC64_ADDR64:
          if (opd_sym_map != NULL
@@ -7798,9 +7801,6 @@ dec_dynrel_count (bfd_vma r_info,
     case R_PPC64_TPREL16_HIGHERA:
     case R_PPC64_TPREL16_HIGHEST:
     case R_PPC64_TPREL16_HIGHESTA:
-      if (!bfd_link_pic (info))
-       return TRUE;
-
     case R_PPC64_TPREL64:
     case R_PPC64_DTPMOD64:
     case R_PPC64_DTPREL64:
@@ -14882,12 +14882,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            }
          if (htab->elf.tls_sec != NULL)
            addend -= htab->elf.tls_sec->vma + TP_OFFSET;
-         if (bfd_link_pic (info))
-           /* The TPREL16 relocs shouldn't really be used in shared
-              libs as they will result in DT_TEXTREL being set, but
-              support them anyway.  */
-           goto dodyn;
-         break;
+         /* The TPREL16 relocs shouldn't really be used in shared
+            libs or with non-local symbols as that will result in
+            DT_TEXTREL being set, but support them anyway.  */
+         goto dodyn;
 
        case R_PPC64_DTPREL16:
        case R_PPC64_DTPREL16_LO: