]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Adjust TLS relaxation condition
authorMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 5 Aug 2022 16:19:31 +0000 (17:19 +0100)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 5 Aug 2022 16:50:11 +0000 (17:50 +0100)
In aarch64_tls_transition_without_check and elfNN_aarch64_tls_relax we
choose whether to perform a relaxation to an IE access model or an LE
access model based on whether the symbol itself is marked as local (i.e.
`h == NULL`).

This is problematic in two ways.  The first is that sometimes a global
dynamic access can be relaxed to an initial exec access when creating a
shared library, and if that happens on a local symbol then we currently
relax it to a local exec access instead.  This usually does not happen
since we only relax an access if aarch64_can_relax_tls returns true and
aarch64_can_relax_tls does not have the same problem.  However, it can
happen when we have seen both an IE and GD access on the same symbol.
This case is exercised in the newly added testcase tls-relax-gd-ie-2.

The second problem is that deciding based on whether the symbol is local
misses the case when the symbol is global but is still non-interposable
and known to be located in the executable.  This happens on all global
symbols in executables.
This case is exercised in the newly added testcase tls-relax-ie-le-4.

Here we adjust the condition we base our relaxation on so that we relax
to local-exec if we are creating an executable and the relevant symbol
we're accessing is stored inside that executable.

Alongside that general fix, we adjust the existing exclusion parameters
for Morello relaxations.  Patches are in-flight to replace the existing
Morello TLS relocation handling with the more recent TLS ABI.  This
patch simply adjusts the existing handling to use a more robust method
to determine the case when a GD -> LE relaxation can be performed.

-- Updating tests for new relaxation criteria

Many of the tests added to check our relaxation to IE were implemented
by taking advantage of the fact that we did not relax a global symbol
defined in an executable.

Since a global symbol defined in an executable is still not
interposable, we know that a TLS version of such a symbol will be in the
main TLS block.  This means that we can perform a stronger relaxation on
such symbols and relax their accesses to a local-exec access.

Hence we have to update all tests that relied on the older suboptimal
decision making.

The two cases when we still would want to relax a general dynamic access
to an initial exec one are:
1) When in a shared library and accessing a symbol which we have already
   seen accessed with an initial exec access sequence.
2) When in an executable and accessing a symbol defined in a shared
   library.

Both of these require shared library support, which means that these
tests are now only available on targets with that.

I have chosen to switch the existing testcases from a plain executable
to one dynamically linked to a shared object as that doesn't require
changing the testcases quite so much (just requires accessing a
different variable rather than requiring adding another code sequence).

The tls-relax-all testcase was an outlier to the above approach, since
it included a general dynamic access to both a local and global symbol
and inspected for the difference accordingly.

This is the same logical change as
https://sourceware.org/pipermail/binutils/2022-July/121660.html

28 files changed:
bfd/elfnn-aarch64.c
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/relocs-ilp32.ld
ld/testsuite/ld-aarch64/relocs.ld
ld/testsuite/ld-aarch64/tls-relax-all-ilp32.d
ld/testsuite/ld-aarch64/tls-relax-all.d
ld/testsuite/ld-aarch64/tls-relax-gd-ie-2.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-gd-ie-2.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d
ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
ld/testsuite/ld-aarch64/tls-relax-ie-le-4.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-ie-le-4.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-large-desc-ie.d
ld/testsuite/ld-aarch64/tls-relax-large-desc-ie.s
ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d
ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s
ld/testsuite/ld-aarch64/tls-sharedlib.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-tiny-desc-ie-ilp32.d
ld/testsuite/ld-aarch64/tls-tiny-desc-ie.d
ld/testsuite/ld-aarch64/tls-tiny-desc-ie.s
ld/testsuite/ld-aarch64/tls-tiny-gd-ie-ilp32.d
ld/testsuite/ld-aarch64/tls-tiny-gd-ie.d
ld/testsuite/ld-aarch64/tls-tiny-gd-ie.s

index a0898f9e7b9e44ae609bbc0a6eae5eaa830771e2..2d3083f540469365a5a8df1448bf5da2df1762e8 100644 (file)
@@ -5814,76 +5814,77 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
                                      struct elf_link_hash_entry *h,
                                      bfd_boolean morello_reloc)
 {
-  bfd_boolean is_local = h == NULL;
+  bfd_boolean local_exec = (bfd_link_executable (info)
+                           && SYMBOL_REFERENCES_LOCAL (info, h));
 
   switch (r_type)
     {
     case BFD_RELOC_MORELLO_TLSDESC_ADR_PAGE20:
-      return (is_local || !bfd_link_pic (info)
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
              : r_type);
 
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
              : BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21);
 
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
              : r_type);
 
     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
              : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19);
 
     case BFD_RELOC_AARCH64_TLSDESC_LDR:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
              : BFD_RELOC_AARCH64_NONE);
 
     case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC
              : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC);
 
     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
              : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1);
 
     case BFD_RELOC_MORELLO_TLSDESC_LD128_LO12:
-      return ((is_local || !bfd_link_pie (info)
-              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type));
+      return (local_exec
+             ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type);
 
     case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC:
     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
              : BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC);
 
     case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
-      return is_local ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 : r_type;
+      return local_exec ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 : r_type;
 
     case BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC:
-      return is_local ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type;
+      return local_exec ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type;
 
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
       return r_type;
 
     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
-      return (is_local
+      return (local_exec
              ? BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12
              : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19);
 
     case BFD_RELOC_MORELLO_TLSDESC_CALL:
-      return ((is_local || !bfd_link_pie (info))
+      return (local_exec
              ? BFD_RELOC_AARCH64_NONE : r_type);
 
     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
-      if (morello_reloc && !is_local && bfd_link_pie (info))
+      if (morello_reloc && !local_exec)
        return r_type;
       /* Fall through.  */
     case BFD_RELOC_AARCH64_TLSDESC_ADD:
@@ -5896,16 +5897,16 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
     case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
-      return is_local ? BFD_RELOC_AARCH64_NONE : r_type;
+      return local_exec ? BFD_RELOC_AARCH64_NONE : r_type;
 
 #if ARCH_SIZE == 64
     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
-      return is_local
+      return local_exec
        ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC
        : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
 
     case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
-      return is_local
+      return local_exec
        ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
        : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
 #endif
@@ -6032,12 +6033,6 @@ aarch64_tls_transition (bfd *input_bfd,
                               && (ELFNN_R_TYPE (rel[1].r_info)
                                   == MORELLO_R (TLSDESC_CALL)));
 
-  /* GD -> IE is not supported for Morello TLSDESC yet.  We do however allow
-     lowering of GD -> LE for static non-pie executables.  XXX It ought to be
-     safe to do this for A64 as well but it is not implemented yet.  */
-  if (h != NULL && morello_reloc && bfd_link_pie (info))
-    return bfd_r_type;
-
   return aarch64_tls_transition_without_check (bfd_r_type, info, h,
                                               morello_reloc);
 }
@@ -7833,8 +7828,8 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
                         bfd_byte *contents, Elf_Internal_Rela *rel,
                         struct elf_link_hash_entry *h, unsigned long r_symndx)
 {
-  bfd_boolean is_local = h == NULL;
-
+  bfd_boolean local_exec = (bfd_link_executable (info)
+                           && SYMBOL_REFERENCES_LOCAL (info, h));
   unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
   unsigned long insn;
   bfd_vma sym_size = 0;
@@ -7842,7 +7837,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
 
   BFD_ASSERT (globals && input_bfd && contents && rel);
 
-  if (is_local || !bfd_link_pic (info))
+  if (local_exec)
     {
       if (h != NULL)
        sym_size = h->size;
@@ -7860,7 +7855,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
   switch (elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type))
     {
     case BFD_RELOC_MORELLO_TLSDESC_ADR_PAGE20:
-      if (is_local || !bfd_link_pic (info))
+      if (local_exec)
        {
          /* GD->LE relaxation:
             nop                     =>   movz x1, objsize_hi16
@@ -7880,7 +7875,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
        }
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
-      if (is_local)
+      if (local_exec)
        {
          /* GD->LE relaxation:
             adrp x0, :tlsgd:var     =>   movz R0, :tprel_g1:var
@@ -7909,7 +7904,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
       break;
 
     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
-      if (is_local)
+      if (local_exec)
        {
          /* Tiny TLSDESC->LE relaxation:
             ldr   x1, :tlsdesc:var      =>  movz  R0, #:tprel_g1:var
@@ -7951,7 +7946,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
        }
 
     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
-      if (is_local)
+      if (local_exec)
        {
          /* Tiny GD->LE relaxation:
             adr x0, :tlsgd:var      =>   mrs  x1, tpidr_el0
@@ -8003,7 +7998,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
       BFD_ASSERT (rel->r_offset + 12 == rel[2].r_offset);
       BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (CALL26));
 
-      if (is_local)
+      if (local_exec)
        {
          /* Large GD->LE relaxation:
             movz x0, #:tlsgd_g1:var    => movz x0, #:tprel_g2:var, lsl #32
@@ -8047,7 +8042,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
       return bfd_reloc_continue;
 
     case BFD_RELOC_MORELLO_TLSDESC_LD128_LO12:
-      if (is_local || !bfd_link_pic (info))
+      if (local_exec)
        {
          /* GD->LE relaxation:
             ldr xd, [x0, #:tlsdesc_lo12:var] => movk x0, :tprel_g0_nc:var  */
@@ -8060,7 +8055,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
          return bfd_reloc_continue;
        }
     case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC:
-      if (is_local)
+      if (local_exec)
        {
          /* GD->LE relaxation:
             ldr xd, [x0, #:tlsdesc_lo12:var]   =>   movk x0, :tprel_g0_nc:var
@@ -8081,7 +8076,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
        }
 
     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
-      if (is_local)
+      if (local_exec)
        {
          /* GD->LE relaxation
             add  x0, #:tlsgd_lo12:var  => movk R0, :tprel_g0_nc:var
@@ -8126,7 +8121,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
     case BFD_RELOC_MORELLO_TLSDESC_CALL:
       /* GD->LE relaxation:
         blr cd                           =>   add c0, c2, x0  */
-      if (is_local || !bfd_link_pic (info))
+      if (local_exec)
        {
          bfd_putl32 (0xc2a06040, contents + rel->r_offset);
          return bfd_reloc_ok;
@@ -8137,7 +8132,7 @@ elfNN_aarch64_tls_relax (bfd *input_bfd, struct bfd_link_info *info,
     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
       /* GD->LE relaxation:
         ldr cd, [c0, #:tlsdesc_lo12:var] => movk x1, objsize_lo16  */
-      if ((is_local || !bfd_link_pic (info))
+      if (local_exec
          && ELFNN_R_TYPE (rel[1].r_info) == MORELLO_R (TLSDESC_CALL))
        {
          bfd_putl32 (BUILD_MOVK(1, sym_size), contents + rel->r_offset);
@@ -8156,7 +8151,7 @@ set_nop:
       return bfd_reloc_ok;
 
     case BFD_RELOC_AARCH64_TLSDESC_LDR:
-      if (is_local)
+      if (local_exec)
        {
          /* GD->LE relaxation:
             ldr xd, [gp, xn]   =>   movk R0, #:tprel_g0_nc:var
@@ -8183,12 +8178,12 @@ set_nop:
         movk xd, #:tlsdesc_off_g0_nc:var => movk Rd, #:gottprel_g0_nc:var
 
         Where R is x for lp64 mode, and w for ILP32 mode.  */
-      if (is_local)
+      if (local_exec)
        bfd_putl32 (ldr_hw_R0, contents + rel->r_offset);
       return bfd_reloc_continue;
 
     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
-      if (is_local)
+      if (local_exec)
        {
          /* GD->LE relaxation:
             movz xd, #:tlsdesc_off_g1:var => movz R0, #:tprel_g2:var, lsl #32
@@ -8213,7 +8208,7 @@ set_nop:
         adrp xd, :gottprel:var   =>   movz Rd, :tprel_g1:var
 
         Where R is x for lp64 mode, and w for ILP32 mode.  */
-      if (is_local)
+      if (local_exec)
        {
          insn = bfd_getl32 (contents + rel->r_offset);
          bfd_putl32 (movz_R0 | (insn & 0x1f), contents + rel->r_offset);
@@ -8228,7 +8223,7 @@ set_nop:
         ldr  xd, [xm, #:gottprel_lo12:var]   =>   movk Rd, :tprel_g0_nc:var
 
         Where R is x for lp64 mode, and w for ILP32 mode.  */
-      if (is_local)
+      if (local_exec)
        {
          insn = bfd_getl32 (contents + rel->r_offset);
          bfd_putl32 (movk_R0 | (insn & 0x1f), contents + rel->r_offset);
@@ -8241,7 +8236,7 @@ set_nop:
         bl   __tls_get_addr => add R0, R0, TCB_SIZE
 
         Where R is x for lp64 mode, and w for ilp32 mode.  */
-      if (is_local)
+      if (local_exec)
        {
          BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
          BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
@@ -8258,7 +8253,7 @@ set_nop:
       /* LD->LE relaxation (small):
         adrp  x0, :tlsldm:x       => mrs x0, tpidr_el0
        */
-      if (is_local)
+      if (local_exec)
        {
          bfd_putl32 (0xd53bd040, contents + rel->r_offset);
          return bfd_reloc_ok;
@@ -8271,7 +8266,7 @@ set_nop:
         bl   __tls_get_addr       => nop
 
         Where R is x for lp64 mode, and w for ilp32 mode.  */
-      if (is_local)
+      if (local_exec)
        {
          BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
          BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
index 5af3bbfa84151cbfca25dd5580407def9387fba0..38ee991e20d048a0359bf01f403e8329003c0aea 100644 (file)
@@ -375,17 +375,8 @@ run_dump_test "tls-relax-gd-le-ilp32"
 run_dump_test "tls-relax-gdesc-le"
 run_dump_test "tls-relax-gdesc-le-now"
 run_dump_test "tls-relax-gdesc-le-ilp32"
-run_dump_test "tls-relax-gd-ie"
-run_dump_test "tls-relax-gd-ie-ilp32"
-run_dump_test_lp64 "tls-relax-large-gd-ie"
-run_dump_test_lp64 "tls-relax-large-gd-ie-be"
 run_dump_test_lp64 "tls-relax-large-gd-le"
 run_dump_test_lp64 "tls-relax-large-gd-le-be"
-run_dump_test_lp64 "tls-relax-large-desc-ie"
-run_dump_test_lp64 "tls-relax-large-desc-ie-be"
-run_dump_test_lp64 "tls-relax-large-desc-le"
-run_dump_test_lp64 "tls-relax-large-desc-le-be"
-run_dump_test "tls-relax-gdesc-ie"
 run_dump_test "tls-relax-ie-le"
 run_dump_test "tls-relax-ie-le-ilp32"
 run_dump_test "tls-relax-ld-le-small"
@@ -394,7 +385,6 @@ run_dump_test "tls-relax-ld-le-tiny"
 run_dump_test "tls-relax-ld-le-tiny-ilp32"
 run_dump_test "tls-desc-ie"
 run_dump_test "tls-desc-ie-ilp32"
-run_dump_test "tls-relax-gdesc-ie-2"
 run_dump_test "tls-relax-gdesc-le-2"
 run_dump_test "tls-relax-gdesc-le-2-ilp32"
 run_dump_test "tls-relax-ie-le-2"
@@ -402,13 +392,9 @@ run_dump_test "tls-relax-ie-le-2-ilp32"
 run_dump_test "tls-relax-ie-le-3"
 run_dump_test "tls-relax-ie-le-3-ilp32"
 run_dump_test "tls-tiny-gd"
-run_dump_test "tls-tiny-gd-ie"
-run_dump_test "tls-tiny-gd-ie-ilp32"
 run_dump_test "tls-tiny-gd-le"
 run_dump_test "tls-tiny-gd-le-ilp32"
 run_dump_test "tls-tiny-desc"
-run_dump_test "tls-tiny-desc-ie"
-run_dump_test "tls-tiny-desc-ie-ilp32"
 run_dump_test "tls-tiny-desc-le"
 run_dump_test "tls-tiny-desc-le-ilp32"
 run_dump_test "tls-tiny-ie"
@@ -433,6 +419,31 @@ run_dump_test "protected-data"
 run_dump_test_lp64 "pr22764"
 run_dump_test_lp64 "pr20402"
 
+if {[check_shared_lib_support]
+    && [ld_assemble $as $srcdir/$subdir/tls-sharedlib.s tmpdir/tls-sharedlib.o]
+    && [ld_link $ld tmpdir/tls-sharedlib.so "-shared tmpdir/tls-sharedlib.o"] } {
+      run_dump_test "tls-relax-gd-ie"
+      run_dump_test_lp64 "tls-relax-large-gd-ie"
+      run_dump_test_lp64 "tls-relax-large-gd-ie-be"
+      run_dump_test_lp64 "tls-relax-large-desc-ie"
+      run_dump_test_lp64 "tls-relax-large-desc-ie-be"
+      run_dump_test_lp64 "tls-relax-large-desc-le"
+      run_dump_test_lp64 "tls-relax-large-desc-le-be"
+      run_dump_test "tls-relax-gdesc-ie"
+      run_dump_test "tls-relax-gdesc-ie-2"
+      run_dump_test "tls-tiny-gd-ie"
+      run_dump_test "tls-tiny-desc-ie"
+}
+if {[check_shared_lib_support]
+    && [ld_assemble_flags $as -mabi=ilp32 $srcdir/$subdir/tls-sharedlib.s tmpdir/tls-sharedlib.o]
+    && [ld_link $ld tmpdir/tls-sharedlib-ilp32.so "-shared tmpdir/tls-sharedlib.o -m [aarch64_choose_ilp32_emul]"] } {
+      run_dump_test "tls-relax-gd-ie-ilp32"
+      run_dump_test "tls-tiny-gd-ie-ilp32"
+      run_dump_test "tls-tiny-desc-ie-ilp32"
+}
+run_dump_test "tls-relax-gd-ie-2"
+run_dump_test "tls-relax-ie-le-4"
+
 # ifunc tests
 run_dump_test "ifunc-1"
 run_dump_test "ifunc-1-local"
index 7174aff236f189a1ae5caa94ecaf27c7ddb171b5..4ddba9141209a48c1342c4ffaf65b327d91873a8 100644 (file)
@@ -16,4 +16,8 @@ SECTIONS
   . = 0x12340000;
   .far : { *(.far) }
   .ARM.attributes 0 : { *(.ARM.atttributes) }
+  /* Providing a .data section triggers a non-executable segment to be
+     generated, which gives somewhere else for the linker to put the TLS
+     segment without creating a RWX permissioned one. */
+  .data : { *(.data) }
 }
index f42176e64d30daa9949c0679ff3b0a931de46dfd..77adac8b46e01b488e68405b1291335a2dfa29fc 100644 (file)
@@ -16,4 +16,8 @@ SECTIONS
   . = 0x12340000;
   .far : { *(.far) }
   .ARM.attributes 0 : { *(.ARM.atttributes) }
+  /* Providing a .data section triggers a non-executable segment to be
+     generated, which gives somewhere else for the linker to put the TLS
+     segment without creating a RWX permissioned one. */
+  .data : { *(.data) }
 }
index 1cb4ef4261307c13139707ad27b8e85bbe11b0a9..62faed4b73aac484119ed18dbc7f588f6ec8c794 100644 (file)
@@ -5,8 +5,8 @@
 #...
  +10000:       a9bf7bfd        stp     x29, x30, \[sp, #-16\]!
  +10004:       910003fd        mov     x29, sp
- +10008:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
- +1000c:       b9400400        ldr     w0, \[x0, #4\]
+ +10008:       52a00000        movz    w0, #0x0, lsl #16
+ +1000c:       72800100        movk    w0, #0x8
  +10010:       d503201f        nop
  +10014:       d503201f        nop
  +10018:       d53bd041        mrs     x1, tpidr_el0
@@ -20,8 +20,8 @@
  +10038:       8b000040        add     x0, x2, x0
  +1003c:       b9400000        ldr     w0, \[x0\]
  +10040:       0b000021        add     w1, w1, w0
- +10044:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
- +10048:       b9400800        ldr     w0, \[x0, #8\]
+ +10044:       52a00000        movz    w0, #0x0, lsl #16
+ +10048:       72800200        movk    w0, #0x10
  +1004c:       d53bd041        mrs     x1, tpidr_el0
  +10050:       0b000020        add     w0, w1, w0
  +10054:       b9400000        ldr     w0, \[x0\]
index 59421864f9558050bf1d2ae1cab794bf54ac30df..1262a99a6a0debb22256903a25e9075f1666543b 100644 (file)
@@ -4,8 +4,8 @@
 #...
  +10000:       a9bf7bfd        stp     x29, x30, \[sp, #-16\]!
  +10004:       910003fd        mov     x29, sp
- +10008:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
- +1000c:       f9400400        ldr     x0, \[x0, #8\]
+ +10008:       d2a00000        movz    x0, #0x0, lsl #16
+ +1000c:       f2800200        movk    x0, #0x10
  +10010:       d503201f        nop
  +10014:       d503201f        nop
  +10018:       d53bd041        mrs     x1, tpidr_el0
@@ -19,8 +19,8 @@
  +10038:       8b000040        add     x0, x2, x0
  +1003c:       b9400000        ldr     w0, \[x0\]
  +10040:       0b000021        add     w1, w1, w0
- +10044:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
- +10048:       f9400800        ldr     x0, \[x0, #16\]
+ +10044:       d2a00000        movz    x0, #0x0, lsl #16
+ +10048:       f2800300        movk    x0, #0x18
  +1004c:       d53bd041        mrs     x1, tpidr_el0
  +10050:       8b000020        add     x0, x1, x0
  +10054:       b9400000        ldr     w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie-2.d b/ld/testsuite/ld-aarch64/tls-relax-gd-ie-2.d
new file mode 100644 (file)
index 0000000..bb5713e
--- /dev/null
@@ -0,0 +1,26 @@
+# The linker recognises that if we have one IE access to a TLS symbol then all
+# accesses to that symbol could be IE.  Here we are also interested to check
+# the linker does not also decide that a second access to that symbol could be
+# LE.
+#ld: -shared
+#objdump: -dr
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo>:
+ +[0-9a-f]+:   d2800000        mov     x0, #0x0                        // #0
+ +[0-9a-f]+:   d53bd041        mrs     x1, tpidr_el0
+ +[0-9a-f]+:   .*      adrp    x0, .*
+ +[0-9a-f]+:   .*      ldr     x0, \[x0, #.*\]
+ +[0-9a-f]+:   b8606820        ldr     w0, \[x1, x0\]
+ +[0-9a-f]+:   d53bd041        mrs     x1, tpidr_el0
+ +[0-9a-f]+:   910003fd        mov     x29, sp
+ +[0-9a-f]+:   .*      adrp    x0, .*
+ +[0-9a-f]+:   .*      ldr     x0, \[x0, #.*\]
+ +[0-9a-f]+:   d503201f        nop
+ +[0-9a-f]+:   d503201f        nop
+ +[0-9a-f]+:   b8606820        ldr     w0, \[x1, x0\]
+ +[0-9a-f]+:   d65f03c0        ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie-2.s b/ld/testsuite/ld-aarch64/tls-relax-gd-ie-2.s
new file mode 100644 (file)
index 0000000..79bdc84
--- /dev/null
@@ -0,0 +1,35 @@
+       # N.b. a local symbol `g`.
+        .section        .tbss,"awT",@nobits
+        .align  2
+        .type   y, %object
+        .size   y, 4
+y:
+        .zero   4
+
+
+
+
+        .text
+        .global foo
+        .type foo, @function
+foo:
+       # Access the local symbol with an IE access.
+        mov     x0, 0
+        mrs     x1, tpidr_el0
+        adrp    x0, :gottprel:y
+        ldr     x0, [x0, #:gottprel_lo12:y]
+        ldr     w0, [x1, x0]
+
+       # Also access the same symbol with a General Dynamic access.
+       # The linker should be able to recognise that if we're already
+       # accessing this symbol with an Initial Exec access then this General
+       # Dynamic access could be relaxed to an Initial Exec one too.
+        mrs     x1, tpidr_el0
+        mov     x29, sp
+        adrp    x0, :tlsdesc:y
+        ldr     x2, [x0, #:tlsdesc_lo12:y]
+        add     x0, x0, :tlsdesc_lo12:y
+        .tlsdesccall    y
+        blr     x2
+        ldr     w0, [x1, x0]
+        ret
index ab08c6161b9330110a9ffbb33eb6d44b0a8e8ac7..340206a9e2bbd37534eb3a1fed79e6386480aed3 100644 (file)
@@ -1,6 +1,6 @@
 #source: tls-relax-gd-ie.s
 #as: -mabi=ilp32
-#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0
+#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0 tmpdir/tls-sharedlib-ilp32.so
 #objdump: -dr
 #...
  +10000:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
index f80bb9077705d83e793fcdd6b45169ac82a24aa9..0c03290e0a9cca61baab061e0b24475f9a8f00ab 100644 (file)
@@ -1,5 +1,5 @@
 #source: tls-relax-gd-ie.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #objdump: -dr
 #...
  +10000:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
index 88c7eec73e43afb680a6c1c9051bf5485491fa1e..afe076c8c8203ee547e84ccab544b67e388279d3 100644 (file)
@@ -1,7 +1,3 @@
-       .global var
-       .section        .tdata,"awT",%progbits
-var:
-       .word   2
        .text
        adrp    x0, :tlsgd:var
        add     x0, x0, :tlsgd_lo12:var
index 2b8e346fc66c79c3d992714da7a876dc83c0b5ee..f13263f201ff781b0c8c41f468c069ee71c4fd61 100644 (file)
@@ -1,5 +1,5 @@
 #source: tls-relax-gdesc-ie-2.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #objdump: -dr
 #...
  +10000:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
index 790b6c6eb8bb4b9c2efa0688f46a5413d8231f78..f7be57c320716d6c56559d2ebfa181a2944bdb88 100644 (file)
@@ -1,9 +1,5 @@
 // Test TLS Desc to TLS IE relaxation when instructions are not consecutive.
 
-       .global var
-       .section        .tdata
-var:
-       .word   2
        .text
        adrp    x0, :tlsdesc:var
        nop
@@ -20,5 +16,4 @@ var:
        mrs     x1, tpidr_el0
        add     x0, x1, x0
        ldr     w0, [x0]
-       .global var
        .section        .tdata
index 86277f82565c401aa6d2b4b365e2c9c8bc8ccfe6..1ace84858a32e1ef0336cf24f7017a55ccbb611e 100644 (file)
@@ -1,5 +1,5 @@
 #source: tls-relax-gdesc-ie.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #objdump: -dr
 #...
  +10000:       90000080        adrp    x0, 20000 <_GLOBAL_OFFSET_TABLE_>
index 38b372132f49c926be8d6527bce9d203b794a4b5..089d36c9cc8a9f4dd9f6cfe71996bdbdd9b68502 100644 (file)
@@ -1,7 +1,3 @@
-       .global var
-       .section        .tdata
-var:
-       .word   2
        .text
        adrp    x0, :tlsdesc:var
        ldr     x17, [x0, #:tlsdesc_lo12:var]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-4.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-4.d
new file mode 100644 (file)
index 0000000..e2bc5f1
--- /dev/null
@@ -0,0 +1,20 @@
+# We already test that we relax an access to a local symbol, this testcase
+# checks that we relax an access to a global-binding symbol if the static linker
+# knows that the symbol will resolve to the executable local value.
+#
+# The access should be relaxed to a LE access.
+#ld:
+#objdump: -d
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <_start>:
+ +[0-9a-f]+:   d2800000        mov     x0, #0x0                        // #0
+ +[0-9a-f]+:   d53bd041        mrs     x1, tpidr_el0
+ +[0-9a-f]+:   d2a00000        movz    x0, #0x0, lsl #16
+ +[0-9a-f]+:   f2800200        movk    x0, #0x10
+ +[0-9a-f]+:   b8606820        ldr     w0, \[x1, x0\]
+ +[0-9a-f]+:   d65f03c0        ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-4.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-4.s
new file mode 100644 (file)
index 0000000..e151cd4
--- /dev/null
@@ -0,0 +1,22 @@
+# Test TLS IE to TLS LE relaxation for global symbols.
+        .section        .tbss,"awT",@nobits
+        .global x
+        .align  2
+        .type   x, %object
+        .size   x, 4
+x:
+        .zero   4
+
+
+
+        .text
+        .global _start
+        .type _start, @function
+_start:
+        mov     x0, 0
+        mrs     x1, tpidr_el0
+        adrp    x0, :gottprel:x
+        ldr     x0, [x0, #:gottprel_lo12:x]
+        ldr     w0, [x1, x0]
+        ret
+
index 21ad5e5a18c265e5e095b2053752a578d689d411..cb546ad74e6da35e7d3cd4f56ba62af52afebc22 100644 (file)
@@ -1,5 +1,5 @@
 #source: tls-relax-large-desc-ie.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #notarget: aarch64_be-*-*
 #objdump: -dr
 #...
index a4d1e00086ad3ed3818eb73b4aba606cb0de6cf7..98dc2a571d5836b60f05cb9daf47b385456a3ee2 100644 (file)
@@ -1,8 +1,3 @@
-       .global var
-       .section        .tdata,"awT",%progbits
-var:
-       .word 2
-
        .text
 test:
        ldr x1, .Lgot
index 2b398dbb9c6ce48f48f258e3ed337dcd383af82c..740178d46105483fa4176b1a4c77ebac459ef846 100644 (file)
@@ -1,5 +1,5 @@
 #source: tls-relax-large-gd-ie.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #notarget: aarch64_be-*-*
 #objdump: -dr
 #...
index 8e0310d6b3f8caecdbfc2bdd3f310b6ee3942d80..d35aace776ee0bc327cfa1cf258c8ce687865d7a 100644 (file)
@@ -1,8 +1,3 @@
-       .global var
-       .section        .tdata,"awT",%progbits
-var:
-       .word   2
-
        .text
 test:
        ldr     x1, .Lgot
diff --git a/ld/testsuite/ld-aarch64/tls-sharedlib.s b/ld/testsuite/ld-aarch64/tls-sharedlib.s
new file mode 100644 (file)
index 0000000..8838b9f
--- /dev/null
@@ -0,0 +1,4 @@
+    .global var
+    .section  .tdata,"awT",@progbits
+var:
+    .word 2
index ebbaf854baa9548503d0eeac351ab3ee6e330183..3dffa1b85e6376fd72970ba79ecf8d42640173ae 100644 (file)
@@ -1,12 +1,12 @@
 #source: tls-tiny-desc-ie.s
 #as: -mabi=ilp32
-#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0
+#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0 tmpdir/tls-sharedlib-ilp32.so
 #objdump: -dr
 #...
 
 Disassembly of section .text:
 
 00010000 \<test\>:
- +10000:       18080020        ldr     w0, 20004 \<_GLOBAL_OFFSET_TABLE_\+0x4\>
+ +10000:       18080020        ldr     w0, 20004 \<var\>
  +10004:       d503201f        nop
  +10008:       d503201f        nop
index 0088539d6bfae0bdfc70c86afeaf7f1d16305d12..e759ae94576ccca484a9690d1334032f97df6fd6 100644 (file)
@@ -1,11 +1,11 @@
 #source: tls-tiny-desc-ie.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #objdump: -dr
 #...
 
 Disassembly of section .text:
 
 0000000000010000 \<test\>:
- +10000:       58080040        ldr     x0, 20008 \<_GLOBAL_OFFSET_TABLE_\+0x8\>
+ +10000:       58080040        ldr     x0, 20008 \<var\>
  +10004:       d503201f        nop
  +10008:       d503201f        nop
index 520cd4e85b29f8c3acc912d2d31b902b91ee337e..fcc970f6d8f46b7c57724b55c857dcee77bc0722 100644 (file)
@@ -1,12 +1,3 @@
-        .global var
-
-        .section .tbss,"awT",%nobits
-        .align  2
-        .type   var, %object
-        .size   var, 4
-var:
-       .zero   4
-
        .text
 test:
         ldr    x1, :tlsdesc:var
index 1ea61103b47ba1a23703be914da5f5f1008a9cb1..6317152eb1ecc8830d8a0b736276c4ef19301d58 100644 (file)
@@ -1,12 +1,12 @@
 #source: tls-tiny-gd-ie.s
 #as: -mabi=ilp32
-#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0
+#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0 tmpdir/tls-sharedlib-ilp32.so
 #objdump: -dr
 #...
 
 Disassembly of section .text:
 
 00010000 \<test\>:
- +10000:       18080020        ldr     w0, 20004 \<_GLOBAL_OFFSET_TABLE_\+0x4\>
+ +10000:       18080020        ldr     w0, 20004 \<var\>
  +10004:       d53bd041        mrs     x1, tpidr_el0
  +10008:       0b000020        add     w0, w1, w0
index 629d90c942d34845e700b935ef2701d06235b7dd..66b996e6f4abc279d96be510956eff0c606ab240 100644 (file)
@@ -1,11 +1,11 @@
 #source: tls-tiny-gd-ie.s
-#ld: -T relocs.ld -e0
+#ld: -T relocs.ld -e0 tmpdir/tls-sharedlib.so
 #objdump: -dr
 #...
 
 Disassembly of section .text:
 
 0000000000010000 \<test\>:
- +10000:       58080040        ldr     x0, 20008 \<_GLOBAL_OFFSET_TABLE_\+0x8\>
+ +10000:       58080040        ldr     x0, 20008 \<var\>
  +10004:       d53bd041        mrs     x1, tpidr_el0
  +10008:       8b000020        add     x0, x1, x0
index 4dc7e66bbdb7d7c01754aebcdaf4b1328667e143..3ae4a0cc9fe1329140c60ed9424b80e8b4669da3 100644 (file)
@@ -1,12 +1,3 @@
-        .global var
-
-        .section .tbss,"awT",%nobits
-        .align  2
-        .type   var, %object
-        .size   var, 4
-var:
-       .zero   4
-
        .text
 test:
         adr x0, :tlsgd:var