XCOFF: add support for TLS relocations on hidden symbols
authorClément Chigot <clement.chigot@atos.net>
Fri, 17 Dec 2021 13:46:01 +0000 (14:46 +0100)
committerClément Chigot <clement.chigot@atos.net>
Mon, 10 Jan 2022 08:14:57 +0000 (09:14 +0100)
This patch adds support for TLS relocation targeting C_HIDEXT symbols.
In gas, TLS relocations, except R_TLSM and R_TLMSL, must keep the value
of their target symbol.
In ld, it simply ensures that internal TLS symbols are added to the
linker hash table for xcoff_reloc_type_tls.

It also improves the tests made by both.

bfd/ChangeLog:

* coff-rs6000.c (xcoff_howto_table): Fix name of R_TLSML.
(xcoff_reloc_type_tls): Replace the error when h is NULL by
an assert.
(xcoff_complain_overflow_unsigned_func): Adjust comments.
* coff64-rs6000.c (xcoff64_howto_table): Fix name of R_TLSML.
* xcofflink.c (xcoff_link_add_symbols_to_hash_table): New
function.
(xcoff_link_add_symbols): Add C_HIDEXT TLS symbols to the linker
hash table.

gas/ChangeLog:

* config/tc-ppc.c (md_apply_fix): Enable support for TLS
relocation over internal symbols.
* testsuite/gas/ppc/aix.exp: Replace xcoff-tlms by xcoff-tls.
* testsuite/gas/ppc/xcoff-tlsm-32.d: Removed.
* testsuite/gas/ppc/xcoff-tlsm-64.d: Removed.
* testsuite/gas/ppc/xcoff-tlsm.s: Removed.
* testsuite/gas/ppc/xcoff-tls-32.d: New test.
* testsuite/gas/ppc/xcoff-tls-64.d: New test.
* testsuite/gas/ppc/xcoff-tls.s: New test.

ld/ChangeLog:

* testsuite/ld-powerpc/aix52.exp: Improve aix-tls-reloc test.
* testsuite/ld-powerpc/aix-tls-reloc.s: Likewise.
* testsuite/ld-powerpc/aix-tls-reloc-32.d: Removed.
* testsuite/ld-powerpc/aix-tls-reloc-64.d: Removed.
* testsuite/ld-powerpc/aix-tls-reloc-32.dd: New test.
* testsuite/ld-powerpc/aix-tls-reloc-32.dt: New test.
* testsuite/ld-powerpc/aix-tls-reloc-64.dd: New test.
* testsuite/ld-powerpc/aix-tls-reloc-64.dt: New test.

19 files changed:
bfd/coff-rs6000.c
bfd/coff64-rs6000.c
bfd/xcofflink.c
gas/config/tc-ppc.c
gas/testsuite/gas/ppc/aix.exp
gas/testsuite/gas/ppc/xcoff-tls-32.d [new file with mode: 0644]
gas/testsuite/gas/ppc/xcoff-tls-64.d [new file with mode: 0644]
gas/testsuite/gas/ppc/xcoff-tls.s [new file with mode: 0644]
gas/testsuite/gas/ppc/xcoff-tlsm-32.d [deleted file]
gas/testsuite/gas/ppc/xcoff-tlsm-64.d [deleted file]
gas/testsuite/gas/ppc/xcoff-tlsm.s [deleted file]
ld/testsuite/ld-powerpc/aix-tls-reloc-32.d [deleted file]
ld/testsuite/ld-powerpc/aix-tls-reloc-32.dd [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-tls-reloc-32.dt [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-tls-reloc-64.d [deleted file]
ld/testsuite/ld-powerpc/aix-tls-reloc-64.dd [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-tls-reloc-64.dt [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-tls-reloc.s
ld/testsuite/ld-powerpc/aix52.exp

index 3248670db277e8c6c77eec98a5bfbd7d8b3f3e33..97e84a443b0041b7e1eb8f132f8886b54a5e877b 100644 (file)
@@ -1106,7 +1106,7 @@ reloc_howto_type xcoff_howto_table[] =
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
-        "R_TLSM",              /* name */
+        "R_TLSML",             /* name */
         true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
@@ -3236,27 +3236,19 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED,
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
 
-  /* FIXME: R_TLSML is targeting a internal TOC symbol, which will
-     make the following checks failing. It should be moved with
-     R_TLSM bellow once it works.  */
+  /* R_TLSML is handled by the loader but must be from a
+     TOC entry targeting itslef.  This is already verified in
+     xcoff_link_add_symbols.
+     The value must be 0.  */
   if (howto->type == R_TLSML)
     {
       *relocation = 0;
       return true;
     }
 
-  /* FIXME: h is sometimes null, if the TLS symbol is not exported.  */
-  if (!h)
-    {
-      char vaddr_buf[128];
-
-      sprintf_vma (vaddr_buf, rel->r_vaddr);
-      _bfd_error_handler
-       (_("%pB: TLS relocation at 0x%s over internal symbols (C_HIDEXT) not yet possible\n"),
-        input_bfd, vaddr_buf);
-      return false;
-    }
-
+  /* The target symbol should always be available even if it's not
+     exported.  */
+  BFD_ASSERT (h != NULL);
 
   /* TLS relocations must target a TLS symbol.  */
   if (h->smclas != XMC_TL && h->smclas != XMC_UL)
@@ -3286,9 +3278,8 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED,
       return false;
     }
 
-  /* R_TLSM and R_TLSML are relocations used by the loader.
-     The value must be 0.
-     FIXME: move R_TLSML here.  */
+  /* R_TLSM are relocations used by the loader.
+     The value must be 0.  */
   if (howto->type == R_TLSM)
     {
       *relocation = 0;
@@ -3621,10 +3612,10 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd,
    R_TLS_LE:
    Thread-local storage relocation using local-exec model.
 
-   R_TLS:
+   R_TLSM:
    Tread-local storage relocation used by the loader.
 
-   R_TLSM:
+   R_TLSML:
    Tread-local storage relocation used by the loader.
 
    R_TOCU:
index 6698f4345d86c8e9bbe40c7d052b958fc63f4f9b..01326d4503df3a9cd66fd3229f07c6a9d355b4b9 100644 (file)
@@ -1350,7 +1350,7 @@ reloc_howto_type xcoff64_howto_table[] =
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
-        "R_TLSM",              /* name */
+        "R_TLSML",             /* name */
         true,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
index a838c4b772690c2ffe35d7292823311a75adcd56..ba07ba7f04546c0bce16441baf3c09634e202cf7 100644 (file)
@@ -1178,6 +1178,26 @@ xcoff_find_reloc (struct internal_reloc *relocs,
   return min;
 }
 
+/* Return true if the symbol has to be added to the linker hash
+   table.  */
+static bool
+xcoff_link_add_symbols_to_hash_table (struct internal_syment sym,
+                                     union internal_auxent aux)
+{
+  /* External symbols must be added.  */
+  if (EXTERN_SYM_P (sym.n_sclass))
+    return true;
+
+  /* Hidden TLS symbols must be added to verify TLS relocations
+     in xcoff_reloc_type_tls.  */
+  if (sym.n_sclass == C_HIDEXT
+      && ((aux.x_csect.x_smclas == XMC_TL
+          || aux.x_csect.x_smclas == XMC_UL)))
+    return true;
+
+  return false;
+}
+
 /* Add all the symbols from an object file to the hash table.
 
    XCOFF is a weird format.  A normal XCOFF .o files will have three
@@ -1551,6 +1571,11 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
             32 bit has a csect length of 4 for TOC
             64 bit has a csect length of 8 for TOC
 
+            An exception is made for TOC entries with a R_TLSML
+            relocation.  This relocation is made for the loader.
+            We must check that the referenced symbol is the TOC entry
+            itself.
+
             The conditions to get past the if-check are not that bad.
             They are what is used to create the TOC csects in the first
             place.  */
@@ -1580,7 +1605,8 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                 64 bit R_POS r_size is 63  */
              if (relindx < enclosing->reloc_count
                  && rel->r_vaddr == (bfd_vma) sym.n_value
-                 && rel->r_type == R_POS
+                 && (rel->r_type == R_POS ||
+                     rel->r_type == R_TLSML)
                  && ((bfd_xcoff_is_xcoff32 (abfd)
                       && rel->r_size == 31)
                      || (bfd_xcoff_is_xcoff64 (abfd)
@@ -1652,6 +1678,22 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                          set_toc = h;
                        }
                    }
+                 else if (rel->r_type == R_TLSML)
+                   {
+                       csect_index = ((esym
+                                       - (bfd_byte *) obj_coff_external_syms (abfd))
+                                      / symesz);
+                       if (((unsigned long) rel->r_symndx) != csect_index)
+                         {
+                           _bfd_error_handler
+                             /* xgettext:c-format */
+                             (_("%pB: TOC entry `%s' has a R_TLSML"
+                                "relocation not targeting itself"),
+                              abfd, name);
+                           bfd_set_error (bfd_error_bad_value);
+                           goto error_return;
+                         }
+                   }
                }
            }
 
@@ -1749,9 +1791,10 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
            if (first_csect == NULL)
              first_csect = csect;
 
-           /* If this symbol is external, we treat it as starting at the
-              beginning of the newly created section.  */
-           if (EXTERN_SYM_P (sym.n_sclass))
+           /* If this symbol must be added to the linker hash table,
+              we treat it as starting at the beginning of the newly
+              created section.  */
+           if (xcoff_link_add_symbols_to_hash_table (sym, aux))
              {
                section = csect;
                value = 0;
@@ -1847,7 +1890,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
          if (first_csect == NULL)
            first_csect = csect;
 
-         if (EXTERN_SYM_P (sym.n_sclass))
+         if (xcoff_link_add_symbols_to_hash_table (sym, aux))
            {
              csect->flags |= SEC_IS_COMMON;
              csect->size = 0;
@@ -1888,7 +1931,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
       /* Now we have enough information to add the symbol to the
         linker hash table.  */
 
-      if (EXTERN_SYM_P (sym.n_sclass))
+      if (xcoff_link_add_symbols_to_hash_table (sym, aux))
        {
          bool copy, ok;
          flagword flags;
index c7af7b76e0810aac4e3f91fd0551d1b4b44069e8..159d3155b4ca6980173bf3d9098ca22edb7589e5 100644 (file)
@@ -7426,22 +7426,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
        case BFD_RELOC_PPC64_TLSM:
          gas_assert (fixP->fx_addsy != NULL);
          S_SET_THREAD_LOCAL (fixP->fx_addsy);
-         fieldval = 0;
          break;
 
-         /* TLSML relocations are targeting a XMC_TC symbol named
-            "_$TLSML". We can't check earlier because the relocation
-            can target any symbol name which will be latter .rename
-            to "_$TLSML".  */
+         /* Officially, R_TLSML relocations must be from a TOC entry
+            targeting itself. In practice, this TOC entry is always
+            named (or .rename) "_$TLSML".
+            Thus, as it doesn't seem possible to retrieve the symbol
+            being relocated here, we simply check that the symbol
+            targeted by R_TLSML is indeed a TOC entry named "_$TLSML".
+            FIXME: Find a way to correctly check R_TLSML relocations
+            as described above.  */
        case BFD_RELOC_PPC_TLSML:
        case BFD_RELOC_PPC64_TLSML:
          gas_assert (fixP->fx_addsy != NULL);
-         if (strcmp (symbol_get_tc (fixP->fx_addsy)->real_name, "_$TLSML") != 0)
-           {
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("R_TLSML relocation doesn't target a "
-                             "symbol named \"_$TLSML\". %s"), S_GET_NAME(fixP->fx_addsy));
-           }
+         if ((symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TC
+              || symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TE)
+             && strcmp (symbol_get_tc (fixP->fx_addsy)->real_name, "_$TLSML") != 0)
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("R_TLSML relocation doesn't target a "
+                           "TOC entry named \"_$TLSML\": %s"), S_GET_NAME(fixP->fx_addsy));
          fieldval = 0;
          break;
 
@@ -7519,12 +7522,15 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
       *valP = value;
     }
   else if (fixP->fx_r_type == BFD_RELOC_PPC_TLSM
-          || fixP->fx_r_type == BFD_RELOC_PPC64_TLSM)
+          || fixP->fx_r_type == BFD_RELOC_PPC64_TLSM
+          || fixP->fx_r_type == BFD_RELOC_PPC_TLSML
+          || fixP->fx_r_type == BFD_RELOC_PPC64_TLSML)
     /* AIX ld expects the section contents for these relocations
        to be zero.  Arrange for that to occur when
        bfd_install_relocation is called.  */
     fixP->fx_addnumber = (- bfd_section_vma (S_GET_SEGMENT (fixP->fx_addsy))
-                         - S_GET_VALUE (fixP->fx_addsy));
+                         - S_GET_VALUE (fixP->fx_addsy)
+                         - fieldval);
   else
     fixP->fx_addnumber = 0;
 #endif
index 85ed06e8a3854e74860afea0d19aafc0781d5cba..78f29f0674df9657a5c8320c74f60da1d53e0fdb 100644 (file)
@@ -79,8 +79,8 @@ if { [istarget "powerpc*-*-aix*"] || [istarget "rs6000-*-aix*"] } then {
     run_dump_test "xcoff-function-1-32"
     run_dump_test "xcoff-function-1-64"
 
-    run_dump_test "xcoff-tlsm-32"
-    run_dump_test "xcoff-tlsm-64"
+    run_dump_test "xcoff-tls-32"
+    run_dump_test "xcoff-tls-64"
 
     run_dump_test "xcoff-stsym-32"
     run_dump_test "xcoff-stsym-64"
diff --git a/gas/testsuite/gas/ppc/xcoff-tls-32.d b/gas/testsuite/gas/ppc/xcoff-tls-32.d
new file mode 100644 (file)
index 0000000..eb71df0
--- /dev/null
@@ -0,0 +1,106 @@
+#as: -a32
+#source: xcoff-tls.s
+#objdump: -Dr
+#name: XCOFF TLS relocation (32 bit)
+
+.*
+Disassembly of section .data:
+
+00000000 <TOC>:
+   0:  00 00 00 58.*
+                       0: R_TLS        tdata_ext.*
+
+00000004 <.tdata_ext_gd>:
+   4:  00 00 00 00.*
+                       4: R_TLSM       tdata_ext.*
+
+00000008 <tdata_ext_ld>:
+   8:  00 00 00 58.*
+                       8: R_TLS_LD     tdata_ext.*
+
+0000000c <tdata_ext_ie>:
+   c:  00 00 00 58.*
+                       c: R_TLS_IE     tdata_ext.*
+
+00000010 <tdata_ext_le>:
+  10:  00 00 00 58.*
+                       10: R_TLS_LE    tdata_ext.*
+
+00000014 <tdata_int1_gd>:
+  14:  00 00 00 5c.*
+                       14: R_TLS       tdata_int_csect.*
+
+00000018 <.tdata_int1_gd>:
+  18:  00 00 00 00.*
+                       18: R_TLSM      tdata_int_csect.*
+
+0000001c <tdata_int1_ld>:
+  1c:  00 00 00 5c.*
+                       1c: R_TLS_LD    tdata_int_csect.*
+
+00000020 <tdata_int1_ie>:
+  20:  00 00 00 5c.*
+                       20: R_TLS_IE    tdata_int_csect.*
+
+00000024 <tdata_int1_le>:
+  24:  00 00 00 5c.*
+                       24: R_TLS_LE    tdata_int_csect.*
+
+00000028 <tdata_int2_gd>:
+  28:  00 00 00 60.*
+                       28: R_TLS       tdata_int_csect.*
+
+0000002c <.tdata_int2_gd>:
+  2c:  00 00 00 00.*
+                       2c: R_TLSM      tdata_int_csect.*
+
+00000030 <tdata_int2_ld>:
+  30:  00 00 00 60.*
+                       30: R_TLS_LD    tdata_int_csect.*
+
+00000034 <tdata_int2_ie>:
+  34:  00 00 00 60.*
+                       34: R_TLS_IE    tdata_int_csect.*
+
+00000038 <tdata_int2_le>:
+  38:  00 00 00 60.*
+                       38: R_TLS_LE    tdata_int_csect.*
+
+0000003c <tbss_ext_gd>:
+  3c:  00 00 00 68.*
+                       3c: R_TLS       tbss_ext.*
+
+00000040 <.tbss_ext_gd>:
+  40:  00 00 00 00.*
+                       40: R_TLSM      tbss_ext.*
+
+00000044 <tbss_ext_ld>:
+  44:  00 00 00 68.*
+                       44: R_TLS_LD    tbss_ext.*
+
+00000048 <tbss_ext_ie>:
+  48:  00 00 00 68.*
+                       48: R_TLS_IE    tbss_ext.*
+
+0000004c <tbss_ext_le>:
+  4c:  00 00 00 68.*
+                       4c: R_TLS_LE    tbss_ext.*
+
+00000050 <_\$TLSML>:
+       ...
+                       50: R_TLSML     _\$TLSML.*
+
+Disassembly of section .tdata:
+
+00000058 <tdata_ext>:
+  58:  00 00 00 01     .long 0x1
+
+0000005c <tdata_int_csect>:
+  5c:  00 00 00 02     .long 0x2
+  60:  00 00 00 03     .long 0x3
+  64:.*
+
+Disassembly of section .tbss:
+
+00000068 <tbss_ext>:
+       ...
diff --git a/gas/testsuite/gas/ppc/xcoff-tls-64.d b/gas/testsuite/gas/ppc/xcoff-tls-64.d
new file mode 100644 (file)
index 0000000..7f3b6eb
--- /dev/null
@@ -0,0 +1,124 @@
+#as: -a64
+#source: xcoff-tls.s
+#objdump: -Dr
+#name: XCOFF TLS relocation (64 bit)
+
+.*
+
+
+Disassembly of section .data:
+
+0000000000000000 <TOC>:
+   0:  00 00 00 00.*
+                       0: R_TLS        tdata_ext.*
+   4:  00 00 00 a8.*
+
+0000000000000008 <.tdata_ext_gd>:
+       ...
+                       8: R_TLSM       tdata_ext.*
+
+0000000000000010 <tdata_ext_ld>:
+  10:  00 00 00 00.*
+                       10: R_TLS_LD    tdata_ext.*
+  14:  00 00 00 a8.*
+
+0000000000000018 <tdata_ext_ie>:
+  18:  00 00 00 00.*
+                       18: R_TLS_IE    tdata_ext.*
+  1c:  00 00 00 a8.*
+
+0000000000000020 <tdata_ext_le>:
+  20:  00 00 00 00.*
+                       20: R_TLS_LE    tdata_ext.*
+  24:  00 00 00 a8.*
+
+0000000000000028 <tdata_int1_gd>:
+  28:  00 00 00 00.*
+                       28: R_TLS       tdata_int_csect.*
+  2c:  00 00 00 ac.*
+
+0000000000000030 <.tdata_int1_gd>:
+       ...
+                       30: R_TLSM      tdata_int_csect.*
+
+0000000000000038 <tdata_int1_ld>:
+  38:  00 00 00 00.*
+                       38: R_TLS_LD    tdata_int_csect.*
+  3c:  00 00 00 ac.*
+
+0000000000000040 <tdata_int1_ie>:
+  40:  00 00 00 00.*
+                       40: R_TLS_IE    tdata_int_csect.*
+  44:  00 00 00 ac.*
+
+0000000000000048 <tdata_int1_le>:
+  48:  00 00 00 00.*
+                       48: R_TLS_LE    tdata_int_csect.*
+  4c:  00 00 00 ac.*
+
+0000000000000050 <tdata_int2_gd>:
+  50:  00 00 00 00.*
+                       50: R_TLS       tdata_int_csect.*
+  54:  00 00 00 b0.*
+
+0000000000000058 <.tdata_int2_gd>:
+       ...
+                       58: R_TLSM      tdata_int_csect.*
+
+0000000000000060 <tdata_int2_ld>:
+  60:  00 00 00 00.*
+                       60: R_TLS_LD    tdata_int_csect.*
+  64:  00 00 00 b0.*
+
+0000000000000068 <tdata_int2_ie>:
+  68:  00 00 00 00.*
+                       68: R_TLS_IE    tdata_int_csect.*
+  6c:  00 00 00 b0.*
+
+0000000000000070 <tdata_int2_le>:
+  70:  00 00 00 00.*
+                       70: R_TLS_LE    tdata_int_csect.*
+  74:  00 00 00 b0.*
+
+0000000000000078 <tbss_ext_gd>:
+  78:  00 00 00 00.*
+                       78: R_TLS       tbss_ext.*
+  7c:  00 00 00 b8.*
+
+0000000000000080 <.tbss_ext_gd>:
+       ...
+                       80: R_TLSM      tbss_ext.*
+
+0000000000000088 <tbss_ext_ld>:
+  88:  00 00 00 00.*
+                       88: R_TLS_LD    tbss_ext.*
+  8c:  00 00 00 b8.*
+
+0000000000000090 <tbss_ext_ie>:
+  90:  00 00 00 00.*
+                       90: R_TLS_IE    tbss_ext.*
+  94:  00 00 00 b8.*
+
+0000000000000098 <tbss_ext_le>:
+  98:  00 00 00 00.*
+                       98: R_TLS_LE    tbss_ext.*
+  9c:  00 00 00 b8.*
+
+00000000000000a0 <_\$TLSML>:
+       ...
+                       a0: R_TLSML     _\$TLSML-0xa0
+
+Disassembly of section .tdata:
+
+00000000000000a8 <tdata_ext>:
+  a8:  00 00 00 01     .long 0x1
+
+00000000000000ac <tdata_int_csect>:
+  ac:  00 00 00 02     .long 0x2
+  b0:  00 00 00 03     .long 0x3
+  b4:.*
+
+Disassembly of section .tbss:
+
+00000000000000b8 <tbss_ext>:
+       ...
diff --git a/gas/testsuite/gas/ppc/xcoff-tls.s b/gas/testsuite/gas/ppc/xcoff-tls.s
new file mode 100644 (file)
index 0000000..83e77f1
--- /dev/null
@@ -0,0 +1,57 @@
+# An external tdata symbol
+  .globl tdata_ext[TL]
+  .csect tdata_ext[TL]
+  .long 1
+
+  .csect tdata_int_csect[TL]
+# A first internal tdata symbol
+tdata_int1:
+  .long 2
+# A second internal tdata symbol
+tdata_int2:
+  .long 3
+
+# Two external tbss symbols.
+# XCOFF doesn't seem to allow internal tbss
+# (or bss) symbols.
+  .comm tbss_ext[UL],8
+
+  .toc
+# TC entries targeting the external tdata symbol
+# Their value should be "tdata_ext" address,
+# except TLSM value which must be 0.
+# Their relocations should target it.
+  .tc  tdata_ext_gd[TC],tdata_ext[TL]
+  .tc .tdata_ext_gd[TC],tdata_ext[TL]@m
+  .tc  tdata_ext_ld[TC],tdata_ext[TL]@ld
+  .tc  tdata_ext_ie[TC],tdata_ext[TL]@ie
+  .tc  tdata_ext_le[TC],tdata_ext[TL]@le
+
+# TC entries targeting internal tdata symbols.
+# Their value should be "tdata_int1" or "tdata_int2"
+# addresses, except TLSM value which must be 0.
+# Their relocations should target "tdata_int_csect".
+  .tc  tdata_int1_gd[TC],tdata_int1
+  .tc .tdata_int1_gd[TC],tdata_int1@m
+  .tc  tdata_int1_ld[TC],tdata_int1@ld
+  .tc  tdata_int1_ie[TC],tdata_int1@ie
+  .tc  tdata_int1_le[TC],tdata_int1@le
+  .tc  tdata_int2_gd[TC],tdata_int2
+  .tc .tdata_int2_gd[TC],tdata_int2@m
+  .tc  tdata_int2_ld[TC],tdata_int2@ld
+  .tc  tdata_int2_ie[TC],tdata_int2@ie
+  .tc  tdata_int2_le[TC],tdata_int2@le
+
+# TC entries targeting the external tdata symbol
+# Their value should be "tbss_ext" address,
+# except TLSM value which must be 0.
+# Their relocations should target "tbss_ext".
+  .tc  tbss_ext_gd[TC],tbss_ext[UL]
+  .tc .tbss_ext_gd[TC],tbss_ext[UL]@m
+  .tc  tbss_ext_ld[TC],tbss_ext[UL]@ld
+  .tc  tbss_ext_ie[TC],tbss_ext[UL]@ie
+  .tc  tbss_ext_le[TC],tbss_ext[UL]@le
+
+# Module entry
+  .tc  mh[TC],mh[TC]@ml
+.rename mh[TC], "_$TLSML" # Symbol for the module handle
diff --git a/gas/testsuite/gas/ppc/xcoff-tlsm-32.d b/gas/testsuite/gas/ppc/xcoff-tlsm-32.d
deleted file mode 100644 (file)
index a09dd1a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#as: -a32
-#source: xcoff-tlsm.s
-#objdump: -Dr
-#name: XCOFF TLSM relocation (32 bit)
-
-.*
-Disassembly of section .data:
-
-00000000 <TOC>:
-   0:  00 00 00 10.*
-                       0: R_TLS        foo_tdata-0x10
-
-00000004 <.foo_tdata>:
-   4:  00 00 00 00.*
-                       4: R_TLSM       foo_tdata-0x10
-
-00000008 <foo_tbss>:
-   8:  00 00 00 20.*
-                       8: R_TLS        foo_tbss-0x20
-
-0000000c <.foo_tbss>:
-   c:  00 00 00 00.*
-                       c: R_TLSM       foo_tbss-0x20
-
-Disassembly of section .tdata:
-
-00000010 <foo_tdata>:
-  10:  00 00 00 01.*
-       ...
-
-Disassembly of section .tbss:
-
-00000020 <foo_tbss>:
-       ...
diff --git a/gas/testsuite/gas/ppc/xcoff-tlsm-64.d b/gas/testsuite/gas/ppc/xcoff-tlsm-64.d
deleted file mode 100644 (file)
index f447a51..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#as: -a64
-#source: xcoff-tlsm.s
-#objdump: -Dr
-#name: XCOFF TLSM relocation (64 bit)
-
-.*
-Disassembly of section .data:
-
-0000000000000000 <TOC>:
-   0:  00 00 00 00.*
-                       0: R_TLS        foo_tdata-0x20
-   4:  00 00 00 20.*
-
-0000000000000008 <.foo_tdata>:
-       ...
-                       8: R_TLSM       foo_tdata-0x20
-
-0000000000000010 <foo_tbss>:
-  10:  00 00 00 00.*
-                       10: R_TLS       foo_tbss-0x30
-  14:  00 00 00 30.*
-
-0000000000000018 <.foo_tbss>:
-       ...
-                       18: R_TLSM      foo_tbss-0x30
-
-Disassembly of section .tdata:
-
-0000000000000020 <foo_tdata>:
-  20:  00 00 00 01.*
-       ...
-
-Disassembly of section .tbss:
-
-0000000000000030 <foo_tbss>:
-       ...
diff --git a/gas/testsuite/gas/ppc/xcoff-tlsm.s b/gas/testsuite/gas/ppc/xcoff-tlsm.s
deleted file mode 100644 (file)
index 0c857bf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-  .csect foo_tdata[TL],4
-  .align 2
-foo_tdata:
-  .long        1
-
-  .comm foo_tbss[UL],8
-
-  .toc
-  .tc foo_tdata[TC],foo_tdata[TL]
-  .tc .foo_tdata[TC],foo_tdata[TL]@m
-  .tc foo_tbss[TC],foo_tbss[UL]
-  .tc .foo_tbss[TC],foo_tbss[UL]@m
diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-32.d b/ld/testsuite/ld-powerpc/aix-tls-reloc-32.d
deleted file mode 100644 (file)
index 5103de5..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#source: aix-tls-reloc.s
-#as: -a32
-#ld: -b32 -shared -bE:aix-tls-reloc.ex
-#objdump: -dr
-#target: [is_xcoff_format]
-
-.*
-
-Disassembly of section \.text:
-
-.* <\.foo>:
-.*:    80 82 00 00     l       r4,0\(r2\)
-.*: R_TOC      gd-.*
-.*:    80 62 00 04     l       r3,4\(r2\)
-.*: R_TOC      .gd-.*
-.*:    48 00 00 03     bla     0 <\.foo-.*>
-.*: R_BA_26    __tls_get_addr
-.*:    80 62 00 0c     l       r3,12\(r2\)
-.*: R_TOC      _\$TLSML-.*
-.*:    48 00 00 03     bla     0 <\.foo-.*>
-.*: R_BA_26    __tls_get_mod
-.*:    80 82 00 08     l       r4,8\(r2\)
-.*: R_TOC      ld-.*
-.*:    7c a3 22 14     cax     r5,r3,r4
-.*:    48 00 00 03     bla     0 <\.foo-.*>
-.*: R_BA_26    __get_tpointer
-.*:    80 82 00 10     l       r4,16\(r2\)
-.*: R_TOC      ie-.*
-.*:    7c a3 22 14     cax     r5,r3,r4
-.*:    48 00 00 03     bla     0 <\.foo-.*>
-.*: R_BA_26    __get_tpointer
-.*:    80 82 00 14     l       r4,20\(r2\)
-.*: R_TOC      le-.*
-.*:    7c a3 22 14     cax     r5,r3,r4
-.*
diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-32.dd b/ld/testsuite/ld-powerpc/aix-tls-reloc-32.dd
new file mode 100644 (file)
index 0000000..001a7f0
--- /dev/null
@@ -0,0 +1,101 @@
+#source: aix-tls-reloc.s
+#as: -a32
+#ld: -b32 -shared -bE:aix-tls-reloc.ex
+#objdump: -dr -j.data
+#target: [is_xcoff_format]
+
+.*
+
+
+Disassembly of section .data:
+
+.* <foo>:
+.*
+.*
+.*
+.*
+.*
+
+.* <TOC>:
+.*:    ff ff 88 00 .*
+.*: R_TLS      tdata_ext.*
+
+.* <.tdata_ext_gd>:
+.*:    00 00 00 00 .*
+.*: R_TLSM     tdata_ext.*
+
+.* <tdata_ext_ld>:
+.*:    ff ff 88 00 .*
+.*: R_TLS_LD   tdata_ext.*
+
+.* <tdata_ext_ie>:
+.*:    ff ff 88 00 .*
+.*: R_TLS_IE   tdata_ext.*
+
+.* <tdata_ext_le>:
+.*:    ff ff 88 00 .*
+.*: R_TLS_LE   tdata_ext.*
+
+.* <tdata_int1_gd>:
+.*:    ff ff 88 04 .*
+.*: R_TLS      tdata_int_csect.*
+
+.* <.tdata_int1_gd>:
+.*:    00 00 00 00 .*
+.*: R_TLSM     tdata_int_csect.*
+
+.* <tdata_int1_ld>:
+.*:    ff ff 88 04 .*
+.*: R_TLS_LD   tdata_int_csect.*
+
+.* <tdata_int1_ie>:
+.*:    ff ff 88 04 .*
+.*: R_TLS_IE   tdata_int_csect.*
+
+.* <tdata_int1_le>:
+.*:    ff ff 88 04 .*
+.*: R_TLS_LE   tdata_int_csect.*
+
+.* <tdata_int2_gd>:
+.*:    ff ff 88 08 .*
+.*: R_TLS      tdata_int_csect.*
+
+.* <.tdata_int2_gd>:
+.*:    00 00 00 00 .*
+.*: R_TLSM     tdata_int_csect.*
+
+.* <tdata_int2_ld>:
+.*:    ff ff 88 08 .*
+.*: R_TLS_LD   tdata_int_csect.*
+
+.* <tdata_int2_ie>:
+.*:    ff ff 88 08 .*
+.*: R_TLS_IE   tdata_int_csect.*
+
+.* <tdata_int2_le>:
+.*:    ff ff 88 08 .*
+.*: R_TLS_LE   tdata_int_csect.*
+
+.* <tbss_ext_gd>:
+.*:    ff ff 88 10 .*
+.*: R_TLS      tbss_ext.*
+
+.* <.tbss_ext_gd>:
+.*:    00 00 00 00 .*
+.*: R_TLSM     tbss_ext.*
+
+.* <tbss_ext_ld>:
+.*:    ff ff 88 10 .*
+.*: R_TLS_LD   tbss_ext.*
+
+.* <tbss_ext_ie>:
+.*:    ff ff 88 10 .*
+.*: R_TLS_IE   tbss_ext.*
+
+.* <tbss_ext_le>:
+.*:    ff ff 88 10 .*
+.*: R_TLS_LE   tbss_ext.*
+
+.* <_\$TLSML>:
+       ...
+.*: R_TLSML    _\$TLSML.*
diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-32.dt b/ld/testsuite/ld-powerpc/aix-tls-reloc-32.dt
new file mode 100644 (file)
index 0000000..91ceb66
--- /dev/null
@@ -0,0 +1,18 @@
+
+tmpdir/aix-tls-reloc.so:     file format aixcoff-rs6000
+
+
+Disassembly of section .tdata:
+
+ffff8800 <tdata_ext>:
+ffff8800:      00 00 00 01     .long 0x1
+
+ffff8804 <tdata_int_csect>:
+ffff8804:      00 00 00 02     .long 0x2
+ffff8808:      00 00 00 03     .long 0x3
+ffff880c:      00 00 00 00     .long 0x0
+
+Disassembly of section .tbss:
+
+ffff8810 <tbss_ext>:
+       ...
diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-64.d b/ld/testsuite/ld-powerpc/aix-tls-reloc-64.d
deleted file mode 100644 (file)
index 71f6302..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#source: aix-tls-reloc.s
-#as: -a32
-#ld: -b32 -shared -bE:aix-tls-reloc.ex
-#objdump: -dr
-#target: [is_xcoff_format]
-
-.*
-
-Disassembly of section \.text:
-
-.* <\.foo>:
-.*:    e8 82 00 00     ld      r4,0\(r2\)
-.*: R_TOC      gd-.*
-.*:    e8 62 00 08     ld      r3,8\(r2\)
-.*: R_TOC      .gd-.*
-.*:    48 00 00 03     bla     0 <\.foo-.*>
-.*: R_BA_26    __tls_get_addr
-.*:    e8 62 00 18     ld      r3,24\(r2\)
-.*: R_TOC      _\$TLSML-.*
-.*:    48 00 00 03     bla     0 <\.foo-.*>
-.*: R_BA_26    __tls_get_mod
-.*:    80 82 00 10     lwz     r4,16\(r2\)
-.*: R_TOC      ld-.*
-.*:    7c a3 22 14     add     r5,r3,r4
-.*:    e8 82 00 20     ld      r4,32\(r2\)
-.*: R_TOC      ie-.*
-.*:    7c a4 6a 14     add     r5,r4,r13
-.*:    e8 82 00 28     ld      r4,40\(r2\)
-.*: R_TOC      le-.*
-.*:    7c a3 6a 14     add     r5,r3,r13
-.*
diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-64.dd b/ld/testsuite/ld-powerpc/aix-tls-reloc-64.dd
new file mode 100644 (file)
index 0000000..dc0c48d
--- /dev/null
@@ -0,0 +1,119 @@
+#source: aix-tls-reloc.s
+#as: -a64
+#ld: -b64 -shared -bE:aix-tls-reloc.ex
+#objdump: -dr -j.data
+#target: [is_xcoff_format]
+
+.*
+
+
+Disassembly of section .data:
+
+.* <foo>:
+.*
+.*
+.*
+.*
+.*
+.*
+.*
+
+.* <TOC>:
+.*:    ff ff ff ff .*
+.*: R_TLS      tdata_ext.*
+.*:    ff ff 88 00 .*
+
+.* <.tdata_ext_gd>:
+       ...
+.*: R_TLSM     tdata_ext.*
+
+.*<tdata_ext_ld>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LD   tdata_ext.*
+.*:    ff ff 88 00 .*
+
+.* <tdata_ext_ie>:
+.*:    ff ff ff ff .*
+.*: R_TLS_IE   tdata_ext.*
+.*:    ff ff 88 00 .*
+
+.* <tdata_ext_le>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LE   tdata_ext.*
+.*:    ff ff 88 00 .*
+
+.* <tdata_int1_gd>:
+.*:    ff ff ff ff .*
+.*: R_TLS      tdata_int_csect.*
+.*:    ff ff 88 04 .*
+
+.* <.tdata_int1_gd>:
+       ...
+.*: R_TLSM     tdata_int_csect.*
+
+.* <tdata_int1_ld>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LD   tdata_int_csect.*
+.*:    ff ff 88 04 .*
+
+.* <tdata_int1_ie>:
+.*:    ff ff ff ff .*
+.*: R_TLS_IE   tdata_int_csect.*
+.*:    ff ff 88 04 .*
+
+.* <tdata_int1_le>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LE   tdata_int_csect.*
+.*:    ff ff 88 04 .*
+
+.* <tdata_int2_gd>:
+.*:    ff ff ff ff .*
+.*: R_TLS      tdata_int_csect.*
+.*:    ff ff 88 08 .*
+
+.* <.tdata_int2_gd>:
+       ...
+.*: R_TLSM     tdata_int_csect.*
+
+.* <tdata_int2_ld>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LD   tdata_int_csect.*
+.*:    ff ff 88 08 .*
+
+.* <tdata_int2_ie>:
+.*:    ff ff ff ff .*
+.*: R_TLS_IE   tdata_int_csect.*
+.*:    ff ff 88 08 .*
+
+.* <tdata_int2_le>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LE   tdata_int_csect.*
+.*:    ff ff 88 08 .*
+
+.* <tbss_ext_gd>:
+.*:    ff ff ff ff .*
+.*: R_TLS      tbss_ext.*
+.*:    ff ff 88 10 .*
+
+.* <.tbss_ext_gd>:
+       ...
+.*: R_TLSM     tbss_ext.*
+
+.* <tbss_ext_ld>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LD   tbss_ext.*
+.*:    ff ff 88 10 .*
+
+.* <tbss_ext_ie>:
+.*:    ff ff ff ff .*
+.*: R_TLS_IE   tbss_ext.*
+.*:    ff ff 88 10 .*
+
+.* <tbss_ext_le>:
+.*:    ff ff ff ff .*
+.*: R_TLS_LE   tbss_ext.*
+.*:    ff ff 88 10 .*
+
+.* <_\$TLSML>:
+       ...
+.*: R_TLSML    _\$TLSML.*
diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-64.dt b/ld/testsuite/ld-powerpc/aix-tls-reloc-64.dt
new file mode 100644 (file)
index 0000000..9ddc573
--- /dev/null
@@ -0,0 +1,23 @@
+#source: aix-tls-reloc.s
+#as: -a64
+#ld: -b64 -shared -bE:aix-tls-reloc.ex
+#objdump: -d -j.tdata -j.tbss
+#target: [is_xcoff_format]
+
+.*
+
+
+Disassembly of section .tdata:
+
+ffffffffffff8800 <tdata_ext>:
+ffffffffffff8800:.*
+
+ffffffffffff8804 <tdata_int_csect>:
+ffffffffffff8804:.*
+ffffffffffff8808:.*
+ffffffffffff880c:.*
+
+Disassembly of section .tbss:
+
+ffffffffffff8810 <tbss_ext>:
+       ...
index 62ef73cdc34366634b3fab18d9e71bd9903a4891..062fc9498468bc9a153dcada5297046012991915 100644 (file)
-  .globl bar[TL]
-  .csect bar[TL]
+# An external tdata symbol
+  .globl tdata_ext[TL]
+  .csect tdata_ext[TL]
   .long 1
 
+  .csect tdata_int_csect[TL]
+# A first internal tdata symbol
+tdata_int1:
+  .long 2
+# A second internal tdata symbol
+tdata_int2:
+  .long 3
+
+# Two external tbss symbols.
+# XCOFF doesn't seem to allow internal tbss
+# (or bss) symbols.
+  .comm tbss_ext[UL],8
+
   .toc
-  .tc gd[TC],bar[TL]
-  .tc .gd[TC],bar[TL]@m
-  .tc ld[TC],bar[TL]@ld
-  .tc mh[TC],mh[TC]@ml
-  .tc ie[TC],bar[TL]@ie
-  .tc le[TC],bar[TL]@le
+# TC entries targeting the external tdata symbol
+# Their value should be "tdata_ext" address,
+# except TLSM value which must be 0.
+# Their relocations should target it.
+  .tc  tdata_ext_gd[TC],tdata_ext[TL]
+  .tc .tdata_ext_gd[TC],tdata_ext[TL]@m
+  .tc  tdata_ext_ld[TC],tdata_ext[TL]@ld
+  .tc  tdata_ext_ie[TC],tdata_ext[TL]@ie
+  .tc  tdata_ext_le[TC],tdata_ext[TL]@le
 
-  .globl foo
-  .globl .foo
-  .csect foo[DS],3
-foo:
-  .if size == 32
-  .long        .foo, TOC[tc0], 0
-  .else
-  .llong .foo, TOC[tc0], 0
-  .endif
+# TC entries targeting internal tdata symbols.
+# Their value should be "tdata_int1" or "tdata_int2"
+# addresses, except TLSM value which must be 0.
+# Their relocations should target "tdata_int_csect".
+  .tc  tdata_int1_gd[TC],tdata_int1
+  .tc .tdata_int1_gd[TC],tdata_int1@m
+  .tc  tdata_int1_ld[TC],tdata_int1@ld
+  .tc  tdata_int1_ie[TC],tdata_int1@ie
+  .tc  tdata_int1_le[TC],tdata_int1@le
+  .tc  tdata_int2_gd[TC],tdata_int2
+  .tc .tdata_int2_gd[TC],tdata_int2@m
+  .tc  tdata_int2_ld[TC],tdata_int2@ld
+  .tc  tdata_int2_ie[TC],tdata_int2@ie
+  .tc  tdata_int2_le[TC],tdata_int2@le
 
-  .csect foo[PR]
-.foo:
-  #GD
+# TC entries targeting the external tdata symbol
+# Their value should be "tbss_ext" address,
+# except TLSM value which must be 0.
+# Their relocations should target "tbss_ext".
+  .tc  tbss_ext_gd[TC],tbss_ext[UL]
+  .tc .tbss_ext_gd[TC],tbss_ext[UL]@m
+  .tc  tbss_ext_ld[TC],tbss_ext[UL]@ld
+  .tc  tbss_ext_ie[TC],tbss_ext[UL]@ie
+  .tc  tbss_ext_le[TC],tbss_ext[UL]@le
+
+# Module entry
+  .tc  mh[TC],mh[TC]@ml
+  .rename mh[TC], "_$TLSML" # Symbol for the module handle
+
+# Macros
+  .macro gd_macro,sym
   .if size == 32
-  lwz 4, gd[TC](2)
-  lwz 3, .gd[TC](2)
+  lwz 4, \sym\()[TC](2)
+  lwz 3, .\sym\()[TC](2)
   .else
-  ld 4, gd[TC](2)
-  ld 3, .gd[TC](2)
+  ld 4, \sym\()[TC](2)
+  ld 3, .\sym\()[TC](2)
   .endif
   bla __tls_get_addr
+  .endm
 
-  #LD
+  .macro ld_macro, sym
   .if size == 32
-  lwz 3, mh[TC](2)
+  lwz 4, \sym\()[TC](2)
   .else
-  ld 3, mh[TC](2)
+  ld 4, \sym\()[TC](2)
   .endif
-  bla __tls_get_mod
-  lwz 4, ld[TC](2)
   add 5,3,4
+  .endm
 
-  #IE
+  .macro ie_macro, sym
   .if size == 32
   bla __get_tpointer
-  lwz 4, ie[TC](2)
+  lwz 4, \sym\()[TC](2)
   add 5,3,4
   .else
-  ld 4, ie[TC](2)
+  ld 4, \sym\()[TC](2)
   add 5,4,13
   .endif
+  .endm
 
-  #LE
+  .macro le_macro, sym
   .if size == 32
   bla __get_tpointer
-  lwz 4, le[TC](2)
+  lwz 4, \sym\()[TC](2)
   add 5,3,4
   .else
-  ld 4, le[TC](2)
+  ld 4, \sym\()[TC](2)
   add 5,3,13
   .endif
+  .endm
+
+
+# As TLS relocations are made in for TC symbols,
+# this function only aims to avoid garbage collection
+# of these symbols, especially hidden ones.
+  .globl foo
+  .globl .foo
+  .csect foo[DS],3
+foo:
+  .if size == 32
+  .long        .foo, TOC[tc0], 0
+  .else
+  .llong .foo, TOC[tc0], 0
+  .endif
+
+  .csect foo[PR]
+.foo:
+  # External syms
+  #GD
+  gd_macro tdata_ext_gd
+  gd_macro tdata_int1_gd
+  gd_macro tdata_int2_gd
+  gd_macro tbss_ext_gd
+
+  #LD
+  .if size == 32
+  lwz 3, mh[TC](2)
+  .else
+  ld 3, mh[TC](2)
+  .endif
+  bla __tls_get_mod
+  ld_macro tdata_ext_ld
+  ld_macro tdata_int1_ld
+  ld_macro tdata_int2_ld
+  ld_macro tbss_ext_ld
 
-.rename mh[TC], "_$TLSML" # Symbol for the module handle
+  #IE
+  ie_macro tdata_ext_ie
+  ie_macro tdata_int1_ie
+  ie_macro tdata_int2_ie
+  ie_macro tbss_ext_ie
+
+  #LE
+  le_macro tdata_ext_le
+  le_macro tdata_int1_le
+  le_macro tdata_int2_le
+  le_macro tbss_ext_le
index 8dccce50ff5130f72f8d134f79e28b762af5f9fe..b49f3f5e1cf50c82b930000aa9825ee002297283 100644 (file)
@@ -284,7 +284,8 @@ set aix7tests {
 
     {"TLS relocations" "-shared -bE:aix-tls-reloc.ex"
        "" {aix-tls-reloc.s}
-       {{objdump -dr aix-tls-reloc-SIZE.d}}
+       {{objdump {-dr -j.data} aix-tls-reloc-SIZE.dd}
+        {objdump {-dr -j.tdata -j.tbss} aix-tls-reloc-SIZE.dt}}
        "aix-tls-reloc.so"}
 
     {"TLS section" "-shared -bE:aix-tls-section.ex"