[LD][AARCH64]Add TLSIE relaxation support under large memory model.
authorRenlin Li <renlin.li@arm.com>
Fri, 2 Oct 2015 16:48:31 +0000 (17:48 +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
TLSIE_MOVW_GOTTPREL_G1.
(aarch64_tls_transition_without_check): Add
TLSIE_MOVW_GOTTPREL_G1 to TLSLE_MOVW_TPREL_G2
transition for local symbol.
(elfNN_aarch64_tls_relax): Add a argument to pass tp offset.
Add TLSIE_MOVW_GOTTPREL_G1 relaxation.
(elfNN_aarch64_relocate_section): Call elfNN_aarch64_tls_relax
with new argument.

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

* ld-aarch64/aarch64-elf.exp (tls-relax-large-le-ie): Run new test.
* ld-aarch64/tls-relax-large-ie-le.d: New.
* ld-aarch64/tls-relax-large-ie-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-ie-le.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s [new file with mode: 0644]

index aef8fe3..162c801 100644 (file)
@@ -1,5 +1,17 @@
 2015-10-02  Renlin Li  <renlin.li@arm.com>
 
+       * elfnn-aarch64.c (IS_AARCH64_TLS_RELAX_RELOC): Add
+       TLSIE_MOVW_GOTTPREL_G1.
+       (aarch64_tls_transition_without_check): Add
+       TLSIE_MOVW_GOTTPREL_G1 to TLSLE_MOVW_TPREL_G2
+       transition for local symbol.
+       (elfNN_aarch64_tls_relax): Add a argument to pass tp offset.
+       Add TLSIE_MOVW_GOTTPREL_G1 relaxation.
+       (elfNN_aarch64_relocate_section): Call elfNN_aarch64_tls_relax
+       with new argument.
+
+2015-10-02  Renlin Li  <renlin.li@arm.com>
+
        * elfnn-aarch64.c (aarch64_tls_transition_without_check):  Add
        relax transitions for TLSDESC_ADD, TLSDESC_LDR, TLSDESC_OFF_G0_NC,
        TLSDESC_OFF_G1.
index aa22c3e..f3489d5 100644 (file)
    || (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        \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1     \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC          \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21           \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21)
@@ -4493,6 +4494,11 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
       return is_local
        ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
        : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
+
+    case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
+      return is_local
+       ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+       : r_type;
 #endif
 
     default:
@@ -5627,7 +5633,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 static bfd_reloc_status_type
 elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
                         bfd *input_bfd, bfd_byte *contents,
-                        Elf_Internal_Rela *rel, struct elf_link_hash_entry *h)
+                        Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
+                        bfd_vma relocation ATTRIBUTE_UNUSED)
 {
   bfd_boolean is_local = h == NULL;
   unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
@@ -5793,6 +5800,47 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 
     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
       return bfd_reloc_continue;
+
+    case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
+      if (is_local)
+       {
+         /* Large IE->LE relaxation:
+            mrs tp, tpidr_el0
+            movz tx, #:gottprel_g1:var    => movz tx, #:tprel_g2:var, lsl #32
+            movk tx, #:gottprel_g0_nc:var => movk tx, #:tprel_g1_nc:var, lsl #16
+            ldr tx, [gp, tx]              => movk tx, #:tprel_g0_nc:var
+            add tx, tx, tp
+          */
+         uint32_t value;
+         BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info)
+                     == AARCH64_R (TLSIE_MOVW_GOTTPREL_G0_NC));
+         BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+
+         value = (relocation & ~(bfd_vma) 0xffffffff) >>  32;
+         insn = bfd_getl32 (contents + rel->r_offset);
+         insn &= 0xff80001f;
+         insn |= (0x400000 + (value << 5));
+         bfd_putl32 (insn, contents + rel->r_offset + 0);
+
+         value = (relocation & (bfd_vma) 0xffff0000) >> 16;
+         insn = bfd_getl32 (contents + rel->r_offset + 4);
+         insn &= 0xff80001f;
+         insn |= (0x200000 + (value << 5));
+         bfd_putl32 (insn, contents + rel->r_offset + 4);
+
+         value = relocation & (bfd_vma) 0xffff;
+         insn = bfd_getl32 (contents + rel->r_offset + 4);
+         insn &= 0xff80001f;
+         insn |= (value << 5);
+         bfd_putl32 (insn, contents + rel->r_offset + 8);
+
+         /* Relocations are already resolved here.  */
+         rel->r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+         rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+         return bfd_reloc_ok;
+       }
+
+      return bfd_reloc_continue;
 #endif
 
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
@@ -6151,7 +6199,8 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
          howto = elfNN_aarch64_howto_from_bfd_reloc (bfd_r_type);
          BFD_ASSERT (howto != NULL);
          r_type = howto->type;
-         r = elfNN_aarch64_tls_relax (globals, input_bfd, contents, rel, h);
+         r = elfNN_aarch64_tls_relax (globals, input_bfd, contents, rel, h,
+                                      relocation - tpoff_base (info));
          unresolved_reloc = 0;
        }
       else
index 43b688f..b078d3a 100644 (file)
@@ -1,5 +1,11 @@
 2015-10-02  Renlin Li  <renlin.li@arm.com>
 
+       * ld-aarch64/aarch64-elf.exp (tls-relax-large-le-ie): Run new test.
+       * ld-aarch64/tls-relax-large-ie-le.d: New.
+       * ld-aarch64/tls-relax-large-ie-le.s: New.
+
+2015-10-02  Renlin Li  <renlin.li@arm.com>
+
        * ld-aarch64/aarch64-elf.exp: Run new test.
        * ld-aarch64/tls-large-desc.d: New.
        * ld-aarch64/tls-large-desc.s: New.
index 5c55dc7..5d42710 100644 (file)
@@ -185,6 +185,7 @@ run_dump_test "tls-relax-large-gd-ie"
 run_dump_test "tls-relax-large-gd-le"
 run_dump_test "tls-relax-large-desc-ie"
 run_dump_test "tls-relax-large-desc-le"
+run_dump_test "tls-relax-large-ie-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-ie-le.d b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.d
new file mode 100644 (file)
index 0000000..6bf211b
--- /dev/null
@@ -0,0 +1,14 @@
+#source: tls-relax-large-ie-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+0000000000010000 <test>:
+  +10000:      d53bd041        mrs     x1, tpidr_el0
+  +10004:      d2c00006        movz    x6, #0x0, lsl #32
+  +10008:      f2a00006        movk    x6, #0x0, lsl #16
+  +1000c:      f2800206        movk    x6, #0x10
+  +10010:      8b0100c6        add     x6, x6, x1
+  +10014:      d2c00007        movz    x7, #0x0, lsl #32
+  +10018:      f2a00007        movk    x7, #0x0, lsl #16
+  +1001c:      f2800287        movk    x7, #0x14
+  +10020:      8b0100e7        add     x7, x7, x1
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s
new file mode 100644 (file)
index 0000000..c5c12a1
--- /dev/null
@@ -0,0 +1,19 @@
+       .section        .tdata,"awT"
+x:
+       .word   2
+y:
+       .word   4
+
+       .text
+test:
+       mrs     x1, tpidr_el0
+
+       movz    x6, #:gottprel_g1:x
+       movk    x6, #:gottprel_g0_nc:x
+       ldr     x6, [x2, x6]
+       add     x6, x6, x1
+
+       movz    x7, #:gottprel_g1:y
+       movk    x7, #:gottprel_g0_nc:y
+       ldr     x7, [x2, x7]
+       add     x7, x7, x1