[ARM] Add TLS relocations for FDPIC.
authorChristophe Lyon <christophe.lyon@st.com>
Tue, 20 Mar 2018 09:55:29 +0000 (10:55 +0100)
committerChristophe Lyon <christophe.lyon@linaro.org>
Wed, 25 Apr 2018 20:57:02 +0000 (20:57 +0000)
Define and handle TLS relocations for FDPIC in BFD and gas.

In gas, the new relocations are rejected if the --fdpic option was not
specified.

We also define the __tdata_start symbol to mark the start of the
.tdata section. This allows FDPIC static binaries to find the start of
.tdata section, since phdr->p_vaddr of TLS segment is not a valid
value for FDPIC.

2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
Mickaël Guêné  <mickael.guene@st.com>

bfd/:
* bfd-in2.h (BFD_RELOC_ARM_TLS_GD32_FDPIC)
(BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC): New
relocations.
* elf32-arm.c (elf32_arm_howto_table_2): Add R_ARM_TLS_GD32_FDPIC,
R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC relocations.
(elf32_arm_reloc_map): Add R_ARM_TLS_GD32_FDPIC,
R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC.
(struct elf32_arm_link_hash_table): Update comment.
(elf32_arm_final_link_relocate): Handle TLS FDPIC relocations.
(IS_ARM_TLS_RELOC): Likewise.
(elf32_arm_check_relocs): Likewise.
(allocate_dynrelocs_for_symbol): Likewise.
(elf32_arm_size_dynamic_sections): Update comment.
* reloc.c: Add BFD_RELOC_ARM_TLS_GD32_FDPIC,
BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC.

gas/
* config/tc-arm.c (reloc_names): Add TLSGD_FDPIC, TLSLDM_FDPIC,
GOTTPOFF_FDIC relocations.
(md_apply_fix): Handle the new TLS FDPIC relocations.
(tc_gen_reloc): Likewise.
(arm_fix_adjustable): Likewise.

include/
* elf/arm.h: Add R_ARM_TLS_GD32_FDPIC, R_ARM_TLS_LDM32_FDPIC,
R_ARM_TLS_IE32_FDPIC.

ld/
* scripttempl/elf.sc: Define __tdata_start for .tdata section.

bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-arm.c
bfd/reloc.c
gas/ChangeLog
gas/config/tc-arm.c
include/ChangeLog
include/elf/arm.h
ld/ChangeLog
ld/scripttempl/elf.sc

index 11c4297227ac8f3a121f94ca9b6fce1b9333a34a..3e5415e4238f3db3dcf6e2159cce0585471542db 100644 (file)
@@ -1,3 +1,22 @@
+2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
+       Mickaël Guêné  <mickael.guene@st.com>
+
+       * bfd-in2.h (BFD_RELOC_ARM_TLS_GD32_FDPIC)
+       (BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC): New
+       relocations.
+       * elf32-arm.c (elf32_arm_howto_table_2): Add R_ARM_TLS_GD32_FDPIC,
+       R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC relocations.
+       (elf32_arm_reloc_map): Add R_ARM_TLS_GD32_FDPIC,
+       R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC.
+       (struct elf32_arm_link_hash_table): Update comment.
+       (elf32_arm_final_link_relocate): Handle TLS FDPIC relocations.
+       (IS_ARM_TLS_RELOC): Likewise.
+       (elf32_arm_check_relocs): Likewise.
+       (allocate_dynrelocs_for_symbol): Likewise.
+       (elf32_arm_size_dynamic_sections): Update comment.
+       * reloc.c: Add BFD_RELOC_ARM_TLS_GD32_FDPIC,
+       BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC.
+
 2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
        Mickaël Guêné  <mickael.guene@st.com>
 
index f58c2f73396278a6c2fef310e1ecca62f37cebd8..927dc9d9f9036ac2ee1ce0c9c3d06b358d7444bf 100644 (file)
@@ -3531,6 +3531,9 @@ pc-relative or some form of GOT-indirect relocation.  */
   BFD_RELOC_ARM_GOTOFFFUNCDESC,
   BFD_RELOC_ARM_FUNCDESC,
   BFD_RELOC_ARM_FUNCDESC_VALUE,
+  BFD_RELOC_ARM_TLS_GD32_FDPIC,
+  BFD_RELOC_ARM_TLS_LDM32_FDPIC,
+  BFD_RELOC_ARM_TLS_IE32_FDPIC,
 
 /* Relocations for setting up GOTs and PLTs for shared libraries.  */
   BFD_RELOC_ARM_JUMP_SLOT,
index 9eb12e2fed786e9d3a03ca9db3a1063d9e7249a1..fb29c0c0108df1453bd46ad4911331d22eae6010 100644 (file)
@@ -1746,7 +1746,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
 };
 
 /* 160 onwards: */
-static reloc_howto_type elf32_arm_howto_table_2[5] =
+static reloc_howto_type elf32_arm_howto_table_2[8] =
 {
   HOWTO (R_ARM_IRELATIVE,      /* type */
         0,                     /* rightshift */
@@ -1813,6 +1813,45 @@ static reloc_howto_type elf32_arm_howto_table_2[5] =
         0,                     /* src_mask */
         0xffffffff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
+  HOWTO (R_ARM_TLS_GD32_FDPIC, /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_ARM_TLS_GD32_FDPIC",/* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
+  HOWTO (R_ARM_TLS_LDM32_FDPIC,        /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_ARM_TLS_LDM32_FDPIC",/* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
+  HOWTO (R_ARM_TLS_IE32_FDPIC, /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_ARM_TLS_IE32_FDPIC",/* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 };
 
 /* 249-255 extended, currently unused, relocations:  */
@@ -1970,6 +2009,9 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
     {BFD_RELOC_ARM_GOTOFFFUNCDESC,   R_ARM_GOTOFFFUNCDESC},
     {BFD_RELOC_ARM_FUNCDESC,         R_ARM_FUNCDESC},
     {BFD_RELOC_ARM_FUNCDESC_VALUE,   R_ARM_FUNCDESC_VALUE},
+    {BFD_RELOC_ARM_TLS_GD32_FDPIC,   R_ARM_TLS_GD32_FDPIC},
+    {BFD_RELOC_ARM_TLS_LDM32_FDPIC,  R_ARM_TLS_LDM32_FDPIC},
+    {BFD_RELOC_ARM_TLS_IE32_FDPIC,   R_ARM_TLS_IE32_FDPIC},
     {BFD_RELOC_VTABLE_INHERIT,      R_ARM_GNU_VTINHERIT},
     {BFD_RELOC_VTABLE_ENTRY,        R_ARM_GNU_VTENTRY},
     {BFD_RELOC_ARM_MOVW,            R_ARM_MOVW_ABS_NC},
@@ -3280,7 +3322,7 @@ struct elf32_arm_link_hash_table
   /* Offset in .plt section of tls_arm_trampoline.  */
   bfd_vma tls_trampoline;
 
-  /* Data for R_ARM_TLS_LDM32 relocations.  */
+  /* Data for R_ARM_TLS_LDM32/R_ARM_TLS_LDM32_FDPIC relocations.  */
   union
   {
     bfd_signed_vma refcount;
@@ -11523,6 +11565,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                                       rel->r_addend);
 
     case R_ARM_TLS_LDM32:
+    case R_ARM_TLS_LDM32_FDPIC:
       {
        bfd_vma off;
 
@@ -11561,7 +11604,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            globals->tls_ldm_got.offset |= 1;
          }
 
-       if (globals->fdpic_p)
+       if (r_type == R_ARM_TLS_LDM32_FDPIC)
          {
            bfd_put_32(output_bfd,
                       globals->root.sgot->output_offset + off,
@@ -11584,7 +11627,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
     case R_ARM_TLS_CALL:
     case R_ARM_THM_TLS_CALL:
     case R_ARM_TLS_GD32:
+    case R_ARM_TLS_GD32_FDPIC:
     case R_ARM_TLS_IE32:
+    case R_ARM_TLS_IE32_FDPIC:
     case R_ARM_TLS_GOTDESC:
     case R_ARM_TLS_DESCSEQ:
     case R_ARM_THM_TLS_DESCSEQ:
@@ -11772,7 +11817,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
              local_got_offsets[r_symndx] |= 1;
          }
 
-       if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32)
+       if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32 && r_type != R_ARM_TLS_GD32_FDPIC)
          off += 8;
        else if (tls_type & GOT_TLS_GDESC)
          off = offplt;
@@ -11931,8 +11976,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                   - (input_section->output_section->vma
                      + input_section->output_offset + rel->r_offset));
 
-       if (globals->fdpic_p && (r_type == R_ARM_TLS_GD32 ||
-                                r_type == R_ARM_TLS_IE32))
+       if (globals->fdpic_p && (r_type == R_ARM_TLS_GD32_FDPIC ||
+                                r_type == R_ARM_TLS_IE32_FDPIC))
          {
            /* For FDPIC relocations, resolve to the offset of the GOT
               entry from the start of GOT.  */
@@ -12845,13 +12890,16 @@ arm_add_to_rel (bfd *            abfd,
 
 #define IS_ARM_TLS_RELOC(R_TYPE)       \
   ((R_TYPE) == R_ARM_TLS_GD32          \
+   || (R_TYPE) == R_ARM_TLS_GD32_FDPIC  \
    || (R_TYPE) == R_ARM_TLS_LDO32      \
    || (R_TYPE) == R_ARM_TLS_LDM32      \
+   || (R_TYPE) == R_ARM_TLS_LDM32_FDPIC        \
    || (R_TYPE) == R_ARM_TLS_DTPOFF32   \
    || (R_TYPE) == R_ARM_TLS_DTPMOD32   \
    || (R_TYPE) == R_ARM_TLS_TPOFF32    \
    || (R_TYPE) == R_ARM_TLS_LE32       \
    || (R_TYPE) == R_ARM_TLS_IE32       \
+   || (R_TYPE) == R_ARM_TLS_IE32_FDPIC \
    || IS_ARM_TLS_GNU_RELOC (R_TYPE))
 
 /* Specific set of relocations for the gnu tls dialect.  */
@@ -15077,7 +15125,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
          case R_ARM_GOT32:
          case R_ARM_GOT_PREL:
          case R_ARM_TLS_GD32:
+         case R_ARM_TLS_GD32_FDPIC:
          case R_ARM_TLS_IE32:
+         case R_ARM_TLS_IE32_FDPIC:
          case R_ARM_TLS_GOTDESC:
          case R_ARM_TLS_DESCSEQ:
          case R_ARM_THM_TLS_DESCSEQ:
@@ -15090,8 +15140,10 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
              switch (r_type)
                {
                case R_ARM_TLS_GD32: tls_type = GOT_TLS_GD; break;
+               case R_ARM_TLS_GD32_FDPIC: tls_type = GOT_TLS_GD; break;
 
                case R_ARM_TLS_IE32: tls_type = GOT_TLS_IE; break;
+               case R_ARM_TLS_IE32_FDPIC: tls_type = GOT_TLS_IE; break;
 
                case R_ARM_TLS_GOTDESC:
                case R_ARM_TLS_CALL: case R_ARM_THM_TLS_CALL:
@@ -15149,7 +15201,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
            /* Fall through.  */
 
          case R_ARM_TLS_LDM32:
-           if (r_type == R_ARM_TLS_LDM32)
+         case R_ARM_TLS_LDM32_FDPIC:
+           if (r_type == R_ARM_TLS_LDM32 || r_type == R_ARM_TLS_LDM32_FDPIC)
                htab->tls_ldm_got.refcount++;
            /* Fall through.  */
 
@@ -16078,15 +16131,17 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
 
              if (tls_type & GOT_TLS_GD)
                {
-                 /* R_ARM_TLS_GD32 needs 2 consecutive GOT slots.  If
-                    the symbol is both GD and GDESC, got.offset may
-                    have been overwritten.  */
+                 /* R_ARM_TLS_GD32 and R_ARM_TLS_GD32_FDPIC need two
+                    consecutive GOT slots.  If the symbol is both GD
+                    and GDESC, got.offset may have been
+                    overwritten.  */
                  h->got.offset = s->size;
                  s->size += 8;
                }
 
              if (tls_type & GOT_TLS_IE)
-               /* R_ARM_TLS_IE32 needs one GOT slot.  */
+               /* R_ARM_TLS_IE32/R_ARM_TLS_IE32_FDPIC need one GOT
+                  slot.  */
                s->size += 4;
            }
 
@@ -16689,7 +16744,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
   if (htab->tls_ldm_got.refcount > 0)
     {
       /* Allocate two GOT entries and one dynamic relocation (if necessary)
-        for R_ARM_TLS_LDM32 relocations.  */
+        for R_ARM_TLS_LDM32/R_ARM_TLS_LDM32_FDPIC relocations.  */
       htab->tls_ldm_got.offset = htab->root.sgot->size;
       htab->root.sgot->size += 8;
       if (bfd_link_pic (info))
index e78e582c1f301b579bb0dde3d7d910d69619c02a..f7e34a993aef31faabb2bcf463e1f9e51d1ece69 100644 (file)
@@ -3215,6 +3215,12 @@ ENUMX
   BFD_RELOC_ARM_FUNCDESC
 ENUMX
   BFD_RELOC_ARM_FUNCDESC_VALUE
+ENUMX
+  BFD_RELOC_ARM_TLS_GD32_FDPIC
+ENUMX
+  BFD_RELOC_ARM_TLS_LDM32_FDPIC
+ENUMX
+  BFD_RELOC_ARM_TLS_IE32_FDPIC
 ENUMDOC
   ARM FDPIC specific relocations.
 
index 122daaaf0c851e98db15adf47ef443e51e653e65..ce832e919d9add8ea9eb1d4f62194d0a57d0a3ee 100644 (file)
@@ -1,3 +1,12 @@
+2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
+       Mickaël Guêné  <mickael.guene@st.com>
+
+       * config/tc-arm.c (reloc_names): Add TLSGD_FDPIC, TLSLDM_FDPIC,
+       GOTTPOFF_FDIC relocations.
+       (md_apply_fix): Handle the new TLS FDPIC relocations.
+       (tc_gen_reloc): Likewise.
+       (arm_fix_adjustable): Likewise.
+
 2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
        Mickaël Guêné  <mickael.guene@st.com>
 
index 33a88bb3145cd414badc21839fc459c21fa008a4..760afab4213f457bdca3a5c833285770de8b27a6 100644 (file)
@@ -19309,7 +19309,10 @@ static struct reloc_entry reloc_names[] =
   { "gotofffuncdesc", BFD_RELOC_ARM_GOTOFFFUNCDESC },
        { "GOTOFFFUNCDESC", BFD_RELOC_ARM_GOTOFFFUNCDESC },
   { "funcdesc", BFD_RELOC_ARM_FUNCDESC },
-       { "FUNCDESC", BFD_RELOC_ARM_FUNCDESC }
+       { "FUNCDESC", BFD_RELOC_ARM_FUNCDESC },
+   { "tlsgd_fdpic", BFD_RELOC_ARM_TLS_GD32_FDPIC },      { "TLSGD_FDPIC", BFD_RELOC_ARM_TLS_GD32_FDPIC },
+   { "tlsldm_fdpic", BFD_RELOC_ARM_TLS_LDM32_FDPIC },    { "TLSLDM_FDPIC", BFD_RELOC_ARM_TLS_LDM32_FDPIC },
+   { "gottpoff_fdpic", BFD_RELOC_ARM_TLS_IE32_FDPIC },   { "GOTTPOFF_FDIC", BFD_RELOC_ARM_TLS_IE32_FDPIC },
 };
 #endif
 
@@ -23982,6 +23985,21 @@ md_apply_fix (fixS *   fixP,
       S_SET_THREAD_LOCAL (fixP->fx_addsy);
       break;
 
+      /* Same handling as above, but with the arm_fdpic guard.  */
+    case BFD_RELOC_ARM_TLS_GD32_FDPIC:
+    case BFD_RELOC_ARM_TLS_IE32_FDPIC:
+    case BFD_RELOC_ARM_TLS_LDM32_FDPIC:
+      if (arm_fdpic)
+       {
+         S_SET_THREAD_LOCAL (fixP->fx_addsy);
+       }
+      else
+       {
+         as_bad_where (fixP->fx_file, fixP->fx_line,
+                       _("Relocation supported only in FDPIC mode"));
+       }
+      break;
+
     case BFD_RELOC_ARM_GOT32:
     case BFD_RELOC_ARM_GOTOFF:
       break;
@@ -24783,9 +24801,12 @@ tc_gen_reloc (asection *section, fixS *fixp)
 
     case BFD_RELOC_ARM_TLS_GOTDESC:
     case BFD_RELOC_ARM_TLS_GD32:
+    case BFD_RELOC_ARM_TLS_GD32_FDPIC:
     case BFD_RELOC_ARM_TLS_LE32:
     case BFD_RELOC_ARM_TLS_IE32:
+    case BFD_RELOC_ARM_TLS_IE32_FDPIC:
     case BFD_RELOC_ARM_TLS_LDM32:
+    case BFD_RELOC_ARM_TLS_LDM32_FDPIC:
       /* BFD will include the symbol's address in the addend.
         But we don't want that, so subtract it out again here.  */
       if (!S_IS_COMMON (fixp->fx_addsy))
@@ -25051,9 +25072,12 @@ arm_fix_adjustable (fixS * fixP)
       || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
       || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
+      || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32_FDPIC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
+      || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32_FDPIC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
+      || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32_FDPIC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GOTDESC
       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_CALL
index 6b52420fa4004bae4c84ed61eb1e0bca10a2d775..3e45748e7d500e0467f0fa0525d1f62d5d2f544d 100644 (file)
@@ -1,3 +1,9 @@
+2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
+       Mickaël Guêné  <mickael.guene@st.com>
+
+       * elf/arm.h: Add R_ARM_TLS_GD32_FDPIC, R_ARM_TLS_LDM32_FDPIC,
+       R_ARM_TLS_IE32_FDPIC.
+
 2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
        Mickaël Guêné  <mickael.guene@st.com>
 
index 158f7b1652ce4da5a473634c105907159947bfc3..fdae08aed705fed84d1a63199be4f3cf805aa5a5 100644 (file)
@@ -244,6 +244,9 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
   RELOC_NUMBER (R_ARM_GOTOFFFUNCDESC,  162)
   RELOC_NUMBER (R_ARM_FUNCDESC,        163)
   RELOC_NUMBER (R_ARM_FUNCDESC_VALUE,  164)
+  RELOC_NUMBER (R_ARM_TLS_GD32_FDPIC,   165)
+  RELOC_NUMBER (R_ARM_TLS_LDM32_FDPIC,  166)
+  RELOC_NUMBER (R_ARM_TLS_IE32_FDPIC,   167)
 
   /* Extensions?  R=read-only?  */
   RELOC_NUMBER (R_ARM_RXPC25,          249)
index d9900b5ebb00a63544fcb90dd39d709fd54d2bbe..30de4cbe6636c3e8f83000c16fa7ab4f9ac5ed39 100644 (file)
@@ -1,3 +1,8 @@
+2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
+       Mickaël Guêné  <mickael.guene@st.com>
+
+       * scripttempl/elf.sc: Define __tdata_start for .tdata section.
+
 2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
        Mickaël Guêné  <mickael.guene@st.com>
 
index 9787ab5dac20a5c7dd429a9aeedea0efcc402e83..5ccdd415f39ed4d7d17c9806c3aba3ef3a6cdda1 100644 (file)
@@ -587,7 +587,11 @@ cat <<EOF
   .exception_ranges ${RELOCATING-0} : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
 
   /* Thread Local Storage sections  */
-  .tdata       ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
+  .tdata       ${RELOCATING-0} :
+   {
+     ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__tdata_start = .);}}
+     *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*})
+   }
   .tbss                ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
 
   ${RELOCATING+${PREINIT_ARRAY}}