[BFD][AARCH64]Add TLSGD relaxation support under large memory model.
authorRenlin Li <renlin.li@arm.com>
Fri, 2 Oct 2015 16:22:36 +0000 (17:22 +0100)
committerRenlin Li <renlin.li@arm.com>
Fri, 2 Oct 2015 16:56:09 +0000 (17:56 +0100)
bfd/

2015-10-02  Renlin Li <renlin.li@arm.com>

* elfnn-aarch64.c(IS_AARCH64_TLS_RELAX_RELOC):
Add relaxation support for TLSGD_MOVW_G0_NC and TLSGD_MOVW_G1.
(aarch64_tls_transition_without_check): Likewise
(elfNN_aarch64_tls_relax): Likwise.

ld/testsuite/

2015-10-02  Renlin Li <renlin.li@arm.com>

* ld-aarch64/aarch64-elf.exp: run new test
* ld-aarch64/tls-relax-large-gd-ie.d: New.
* ld-aarch64/tls-relax-large-gd-ie.s: New.
* ld-aarch64/tls-relax-large-gd-le.d: New.
* ld-aarch64/tls-relax-large-gd-le.s: New.

bfd/ChangeLog
bfd/elfnn-aarch64.c
ld/testsuite/ChangeLog
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s [new file with mode: 0644]

index ecf5d56c70f77b5166adc9197bb0a332f937790d..bad620e0a7efbbc2cea492dbd89a666d5bff6a6a 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-02  Renlin Li  <renlin.li@arm.com>
+
+       * elfnn-aarch64.c(IS_AARCH64_TLS_RELAX_RELOC):
+       Add relaxation support for TLSGD_MOVW_G0_NC and TLSGD_MOVW_G1.
+       (aarch64_tls_transition_without_check): Likewise
+       (elfNN_aarch64_tls_relax): Likwise.
+
 2015-10-02  Renlin Li  <renlin.li@arm.com>
 
        * elfnn-aarch64.c (elfNN_aarch64_check_relocs): Create GOT section
index d71a76f0b01e5f5aa0231c1accd19961de65fee0..cff77cef88e0dbb47a0cf0ad29837a931f0e6c6d 100644 (file)
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21           \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PREL21           \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC          \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC           \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_MOVW_G1              \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21  \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19   \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC        \
@@ -4460,6 +4462,18 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
     case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
       return is_local ? BFD_RELOC_AARCH64_NONE : r_type;
 
+#if ARCH_SIZE == 64
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+      return is_local
+       ? 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
+       ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+       : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
+#endif
+
     default:
       break;
     }
@@ -5692,6 +5706,52 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
          return bfd_reloc_continue;
        }
 
+#if ARCH_SIZE == 64
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
+      BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSGD_MOVW_G0_NC));
+      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)
+       {
+         /* Large GD->LE relaxation:
+            movz x0, #:tlsgd_g1:var    => movz x0, #:tprel_g2:var, lsl #32
+            movk x0, #:tlsgd_g0_nc:var => movk x0, #:tprel_g1_nc:var, lsl #16
+            add x0, gp, x0             => movk x0, #:tprel_g0_nc:var
+            bl __tls_get_addr          => mrs x1, tpidr_el0
+            nop                        => add x0, x0, x1
+          */
+         rel[2].r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+                                       AARCH64_R (TLSLE_MOVW_TPREL_G0_NC));
+         rel[2].r_offset = rel->r_offset + 8;
+
+         bfd_putl32 (0xd2c00000, contents + rel->r_offset + 0);
+         bfd_putl32 (0xf2a00000, contents + rel->r_offset + 4);
+         bfd_putl32 (0xf2800000, contents + rel->r_offset + 8);
+         bfd_putl32 (0xd53bd041, contents + rel->r_offset + 12);
+         bfd_putl32 (0x8b000020, contents + rel->r_offset + 16);
+       }
+      else
+       {
+         /* Large GD->IE relaxation:
+            movz x0, #:tlsgd_g1:var    => movz x0, #:gottprel_g1:var, lsl #16
+            movk x0, #:tlsgd_g0_nc:var => movk x0, #:gottprel_g0_nc:var
+            add x0, gp, x0             => ldr x0, [gp, x0]
+            bl __tls_get_addr          => mrs x1, tpidr_el0
+            nop                        => add x0, x0, x1
+          */
+         rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+         bfd_putl32 (0xd2a80000, contents + rel->r_offset + 0);
+         bfd_putl32 (0x58000000, contents + rel->r_offset + 8);
+         bfd_putl32 (0xd53bd041, contents + rel->r_offset + 12);
+         bfd_putl32 (0x8b000020, contents + rel->r_offset + 16);
+       }
+      return bfd_reloc_continue;
+
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+      return bfd_reloc_continue;
+#endif
+
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
       return bfd_reloc_continue;
 
index e486bbaf10631b4726701dac8bcce581e6a85028..a95de8c4201aad01a2c6931f8d577767bfd4432c 100644 (file)
@@ -1,3 +1,11 @@
+2015-10-02  Renlin Li  <renlin.li@arm.com>
+
+       * ld-aarch64/aarch64-elf.exp: run new test
+       * ld-aarch64/tls-relax-large-gd-ie.d: New.
+       * ld-aarch64/tls-relax-large-gd-ie.s: New.
+       * ld-aarch64/tls-relax-large-gd-le.d: New.
+       * ld-aarch64/tls-relax-large-gd-le.s: New.
+
 2015-10-02  Renlin Li  <renlin.li@arm.com>
 
        * ld-aarch64/tls-large-ie.d: New.
index d0da92f46f0182e8ab4e53d8f44d6e465acfbad2..f51de9c2068889d1a78521c746f136a46c16d185 100644 (file)
@@ -181,6 +181,8 @@ run_dump_test "tls-relax-all"
 run_dump_test "tls-relax-gd-le"
 run_dump_test "tls-relax-gdesc-le"
 run_dump_test "tls-relax-gd-ie"
+run_dump_test "tls-relax-large-gd-ie"
+run_dump_test "tls-relax-large-gd-le"
 run_dump_test "tls-relax-gdesc-ie"
 run_dump_test "tls-relax-ie-le"
 run_dump_test "tls-relax-ld-le-small"
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d b/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d
new file mode 100644 (file)
index 0000000..f3407ef
--- /dev/null
@@ -0,0 +1,16 @@
+#source: tls-relax-large-gd-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+0000000000010000 <test>:
+ +10000:       58000121        ldr     x1, 10024 <test\+0x24>
+ +10004:       10000102        adr     x2, 10024 <test\+0x24>
+ +10008:       8b010041        add     x1, x2, x1
+ +1000c:       d2a00000        movz    x0, #0x0, lsl #16
+ +10010:       f2800100        movk    x0, #0x8
+ +10014:       58000000        ldr     x0, 10014 <test\+0x14>
+ +10018:       d53bd041        mrs     x1, tpidr_el0
+ +1001c:       8b000020        add     x0, x1, x0
+ +10020:       b9400000        ldr     w0, \[x0\]
+ +10024:       0000ffdc        .word   0x0000ffdc
+ +10028:       00000000        .word   0x00000000
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s b/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s
new file mode 100644 (file)
index 0000000..8e0310d
--- /dev/null
@@ -0,0 +1,20 @@
+       .global var
+       .section        .tdata,"awT",%progbits
+var:
+       .word   2
+
+       .text
+test:
+       ldr     x1, .Lgot
+       adr     x2, .Lgot
+       add     x1, x2, x1
+
+       movz    x0, #:tlsgd_g1:var
+       movk    x0, #:tlsgd_g0_nc:var
+       add     x0, x1, x0
+       bl      __tls_get_addr
+       nop
+       ldr     w0, [x0]
+
+.Lgot:
+       .dword _GLOBAL_OFFSET_TABLE_ - .
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d b/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d
new file mode 100644 (file)
index 0000000..acaea58
--- /dev/null
@@ -0,0 +1,16 @@
+#source: tls-relax-large-gd-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+0000000000010000 <test>:
+ +10000:       58000121        ldr     x1, 10024 <test\+0x24>
+ +10004:       10000102        adr     x2, 10024 <test\+0x24>
+ +10008:       8b010041        add     x1, x2, x1
+ +1000c:       d2c00000        movz    x0, #0x0, lsl #32
+ +10010:       f2a00000        movk    x0, #0x0, lsl #16
+ +10014:       f2800200        movk    x0, #0x10
+ +10018:       d53bd041        mrs     x1, tpidr_el0
+ +1001c:       8b000020        add     x0, x1, x0
+ +10020:       b9400000        ldr     w0, \[x0\]
+ +10024:       0000ffdc        .word   0x0000ffdc
+ +10028:       00000000        .word   0x00000000
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s b/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s
new file mode 100644 (file)
index 0000000..781f6cc
--- /dev/null
@@ -0,0 +1,19 @@
+       .section        .tdata
+var:
+       .word   2
+
+       .text
+test:
+       ldr     x1, .Lgot
+       adr     x2, .Lgot
+       add     x1, x2, x1
+
+       movz    x0, #:tlsgd_g1:var
+       movk    x0, #:tlsgd_g0_nc:var
+       add     x0, x1, x0
+       bl      __tls_get_addr
+       nop
+       ldr     w0, [x0]
+
+.Lgot:
+       .dword _GLOBAL_OFFSET_TABLE_ - .