aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2011-01-10 08:40:19 +0000
committerNathan Sidwell <nathan@codesourcery.com>2011-01-10 08:40:19 +0000
commit0855e32bf582698d8995b7e85e144ef105d71c82 (patch)
tree75e1748ec86d1c55cb57d5d4efb62d8d696ec6d0
parent9a153e0b6fc93873721787f23edceb272ac87994 (diff)
downloadfsf-binutils-gdb-0855e32bf582698d8995b7e85e144ef105d71c82.zip
fsf-binutils-gdb-0855e32bf582698d8995b7e85e144ef105d71c82.tar.gz
fsf-binutils-gdb-0855e32bf582698d8995b7e85e144ef105d71c82.tar.bz2
bfd/
* reloc.c (BFD_RELOC_ARM_TLS_GOTDESC, BFD_RELOC_ARM_TLS_CALL, BFD_RELOC_ARM_THM_TLS_CALL, BFD_RELOC_ARM_TLS_DESCSEQ, BFD_RELOC_ARM_THM_TLS_DESCSEQ, BFD_RELOC_ARM_TLS_DESC): New relocations. * libbfd.h: Rebuilt. * bfd-in2.h: Rebuilt. * elf32-arm.c (elf32_arm_howto_table_1): Add new relocations. (elf32_arm_reloc_map): Likewise. (tls_trampoline, dl_tlsdesc_lazy_trampoline): New PLT templates. (elf32_arm_stub_long_branch_any_tls_pic, elf32_arm_stub_long_branch_v4t_thumb_tls_pic): New stub templates. (DEF_STUBS): Add new stubs. (struct_elf_arm_obj_data): Add local_tlsdesc_gotent field. (elf32_arm_local_tlsdesc_gotent): New. (GOT_TLS_GDESC): New mask. (GOT_TLS_GD_ANY): Define. (struct elf32_arm_link_hash_entry): Add tlsdesc_got field. (elf32_arm_compute_jump_table_size): New. (struct elf32_arm_link_hash_table): Add next_tls_desc_index, num_tls_desc, dt_tlsdesc_plt, dt_tlsdesc_got, tls_trampoline, sgotplt_jump_table_size fields. (elf32_arm_link_hash_newfunc): Initialize tlsdesc_got field. (elf32_arm_link_hash_table_create): Initialize new fields. (arm_type_of_stub): Check TLS desc relocs too. (elf32_arm_stub_name): TLS desc relocs can be shared. (elf32_arm_tls_transition): Determine relaxation. (arm_stub_required_alignment): Add tls stubs. (elf32_arm_size_stubs): Likewise. (elf32_arm_tls_relax): Perform TLS relaxing. (elf32_arm_final_link_relocate): Process TLS DESC relocations. (IS_ARM_TLS_GNU_RELOC): New. (IS_ARM_TLS_RELOC): Use it. (elf32_arm_relocate_section): Perform TLS relaxing. (elf32_arm_check_relocs): Anticipate TLS relaxing, process tls desc relocations. (allocate_dynrelocs): Allocate tls desc relcoations. (elf32_arm_output_arch_local_syms): Emit tls trampoline mapping symbols. (elf32_arm_size_dynamic_sections): Allocate tls trampolines and got slots. (elf32_arm_always_size_sections): New. Create _TLS_MODULE_BASE symbol. (elf32_arm_finish_dynamic_symbol): Adjust. (arm_put_trampoline): New. (elf32_arm_finish_dynamic_sections): Emit new dynamic tags and tls trampolines. (elf_backend_always_size_sections): Define. include/elf/ * arm.h (R_ARM_TLS_DESC, R_ARM_TLS_GOTDESC, R_ARM_TLS_CALL, R_ARM_TLS_DESCSEQ, T_ARM_THM_TLS_CALL, R_ARM_THM_TLS_DESCSEQ): New relocations. gas/ * doc/c-arm.texi: Document TLSDESC and TLSCALL relocations, and .tlsdescseq directive. * config/tc-arm.c (arm_typed_reg_parse): Check for potential reloc following a symbol. (s_arm_tls_descseq): New directive. (md_pseudo_table): Add it. (encode_branch): Allow TLS_CALL relocs too. (do_t_blx, do_t_branch23): Use encode_branch. (reloc_names): Add tlsdesc and tlscall. (md_apply_fix): Process tls desc relocations. (tc_gen_reloc): Likewise. (arm_fix_adjustable): Likewise. gas/testsuite/ * gas/arm/tls.s: Add tlsdesc tests. * gas/arm/tls.d: Adjust. ld/testsuite/ * ld-arm/arm-elf.exp: Added tests for new TLS handling relocations. * ld-arm/tls-descrelax-be32.d: New. * ld-arm/tls-descrelax-be32.s: New. * ld-arm/tls-descrelax-be8.d: New. * ld-arm/tls-descrelax-be8.s: New. * ld-arm/tls-descrelax-v7.d: New. * ld-arm/tls-descrelax-v7.s: New. * ld-arm/tls-descrelax.d: New. * ld-arm/tls-descrelax.s: New. * ld-arm/tls-descseq.d: New. * ld-arm/tls-descseq.r: New. * ld-arm/tls-descseq.s: New. * ld-arm/tls-gdesc-got.d: New. * ld-arm/tls-gdesc-got.s: New. * ld-arm/tls-gdesc-nlazy.g: New. * ld-arm/tls-gdesc-nlazy.s: New. * ld-arm/tls-gdesc.d: New. * ld-arm/tls-gdesc.r: New. * ld-arm/tls-gdesc.s: New. * ld-arm/tls-gdierelax.d: New. * ld-arm/tls-gdierelax.s: New. * ld-arm/tls-gdierelax2.d: New. * ld-arm/tls-gdierelax2.s: New. * ld-arm/tls-gdlerelax.d: New. * ld-arm/tls-gdlerelax.s: New. * ld-arm/tls-lib-loc.d: New. * ld-arm/tls-lib-loc.r: New. * ld-arm/tls-lib-loc.s: New. * ld-arm/tls-longplt-lib.d: New. * ld-arm/tls-longplt-lib.s: New. * ld-arm/tls-longplt.d: New. * ld-arm/tls-longplt.s: New. * ld-arm/tls-mixed.r: New. * ld-arm/tls-mixed.s: New. * ld-arm/tls-thumb1.d: New. * ld-arm/tls-thumb1.s: New. * ld-arm/arm-elf.exp: New.
-rw-r--r--bfd/ChangeLog51
-rw-r--r--bfd/bfd-in2.h6
-rw-r--r--bfd/elf32-arm.c1017
-rw-r--r--bfd/libbfd.h6
-rw-r--r--bfd/reloc.c12
-rw-r--r--gas/ChangeLog16
-rw-r--r--gas/config/tc-arm.c78
-rw-r--r--gas/doc/c-arm.texi8
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/arm/tls.d48
-rw-r--r--gas/testsuite/gas/arm/tls.s42
-rw-r--r--include/elf/ChangeLog7
-rw-r--r--include/elf/arm.h8
-rw-r--r--ld/testsuite/ChangeLog42
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp48
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax-be32.d108
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax-be32.s198
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax-be8.d108
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax-be8.s198
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax-v7.d108
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax-v7.s198
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax.d108
-rw-r--r--ld/testsuite/ld-arm/tls-descrelax.s197
-rw-r--r--ld/testsuite/ld-arm/tls-descseq.d44
-rw-r--r--ld/testsuite/ld-arm/tls-descseq.r6
-rw-r--r--ld/testsuite/ld-arm/tls-descseq.s41
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc-got.d30
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc-got.s45
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc-nlazy.g4
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc-nlazy.s17
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc.d42
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc.r7
-rw-r--r--ld/testsuite/ld-arm/tls-gdesc.s41
-rw-r--r--ld/testsuite/ld-arm/tls-gdierelax.d20
-rw-r--r--ld/testsuite/ld-arm/tls-gdierelax.s34
-rw-r--r--ld/testsuite/ld-arm/tls-gdierelax2.d23
-rw-r--r--ld/testsuite/ld-arm/tls-gdierelax2.s35
-rw-r--r--ld/testsuite/ld-arm/tls-gdlerelax.d13
-rw-r--r--ld/testsuite/ld-arm/tls-gdlerelax.s16
-rw-r--r--ld/testsuite/ld-arm/tls-lib-loc.d33
-rw-r--r--ld/testsuite/ld-arm/tls-lib-loc.r6
-rw-r--r--ld/testsuite/ld-arm/tls-lib-loc.s14
-rw-r--r--ld/testsuite/ld-arm/tls-longplt-lib.d59
-rw-r--r--ld/testsuite/ld-arm/tls-longplt-lib.s51
-rw-r--r--ld/testsuite/ld-arm/tls-longplt.d64
-rw-r--r--ld/testsuite/ld-arm/tls-longplt.s47
-rw-r--r--ld/testsuite/ld-arm/tls-mixed.r10
-rw-r--r--ld/testsuite/ld-arm/tls-mixed.s25
-rw-r--r--ld/testsuite/ld-arm/tls-thumb1.d74
-rw-r--r--ld/testsuite/ld-arm/tls-thumb1.s43
50 files changed, 3349 insertions, 113 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c2c0157..42b07c6 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,54 @@
+2011-01-10 Nathan Sidwell <nathan@codesourcery.com>
+ Glauber de Oliveira Costa <glommer@gmail.com>
+
+ * reloc.c (BFD_RELOC_ARM_TLS_GOTDESC, BFD_RELOC_ARM_TLS_CALL,
+ BFD_RELOC_ARM_THM_TLS_CALL, BFD_RELOC_ARM_TLS_DESCSEQ,
+ BFD_RELOC_ARM_THM_TLS_DESCSEQ, BFD_RELOC_ARM_TLS_DESC): New
+ relocations.
+ * libbfd.h: Rebuilt.
+ * bfd-in2.h: Rebuilt.
+ * elf32-arm.c (elf32_arm_howto_table_1): Add new relocations.
+ (elf32_arm_reloc_map): Likewise.
+ (tls_trampoline, dl_tlsdesc_lazy_trampoline): New PLT templates.
+ (elf32_arm_stub_long_branch_any_tls_pic,
+ elf32_arm_stub_long_branch_v4t_thumb_tls_pic): New stub templates.
+ (DEF_STUBS): Add new stubs.
+ (struct_elf_arm_obj_data): Add local_tlsdesc_gotent field.
+ (elf32_arm_local_tlsdesc_gotent): New.
+ (GOT_TLS_GDESC): New mask.
+ (GOT_TLS_GD_ANY): Define.
+ (struct elf32_arm_link_hash_entry): Add tlsdesc_got field.
+ (elf32_arm_compute_jump_table_size): New.
+ (struct elf32_arm_link_hash_table): Add next_tls_desc_index,
+ num_tls_desc, dt_tlsdesc_plt, dt_tlsdesc_got, tls_trampoline,
+ sgotplt_jump_table_size fields.
+ (elf32_arm_link_hash_newfunc): Initialize tlsdesc_got field.
+ (elf32_arm_link_hash_table_create): Initialize new fields.
+ (arm_type_of_stub): Check TLS desc relocs too.
+ (elf32_arm_stub_name): TLS desc relocs can be shared.
+ (elf32_arm_tls_transition): Determine relaxation.
+ (arm_stub_required_alignment): Add tls stubs.
+ (elf32_arm_size_stubs): Likewise.
+ (elf32_arm_tls_relax): Perform TLS relaxing.
+ (elf32_arm_final_link_relocate): Process TLS DESC relocations.
+ (IS_ARM_TLS_GNU_RELOC): New.
+ (IS_ARM_TLS_RELOC): Use it.
+ (elf32_arm_relocate_section): Perform TLS relaxing.
+ (elf32_arm_check_relocs): Anticipate TLS relaxing, process tls
+ desc relocations.
+ (allocate_dynrelocs): Allocate tls desc relcoations.
+ (elf32_arm_output_arch_local_syms): Emit tls trampoline mapping
+ symbols.
+ (elf32_arm_size_dynamic_sections): Allocate tls trampolines and
+ got slots.
+ (elf32_arm_always_size_sections): New. Create _TLS_MODULE_BASE
+ symbol.
+ (elf32_arm_finish_dynamic_symbol): Adjust.
+ (arm_put_trampoline): New.
+ (elf32_arm_finish_dynamic_sections): Emit new dynamic tags and tls
+ trampolines.
+ (elf_backend_always_size_sections): Define.
+
2011-01-06 H.J. Lu <hongjiu.lu@intel.com>
* elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Optimized.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8531f8d..84fc75d 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3146,6 +3146,12 @@ pc-relative or some form of GOT-indirect relocation. */
BFD_RELOC_ARM_TLS_TPOFF32,
BFD_RELOC_ARM_TLS_IE32,
BFD_RELOC_ARM_TLS_LE32,
+ BFD_RELOC_ARM_TLS_GOTDESC,
+ BFD_RELOC_ARM_TLS_CALL,
+ BFD_RELOC_ARM_THM_TLS_CALL,
+ BFD_RELOC_ARM_TLS_DESCSEQ,
+ BFD_RELOC_ARM_THM_TLS_DESCSEQ,
+ BFD_RELOC_ARM_TLS_DESC,
/* ARM group relocations. */
BFD_RELOC_ARM_ALU_PC_G0_NC,
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 7c8eb68..ea1e485 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -261,18 +261,18 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
- HOWTO (R_ARM_SWI24, /* type */
+ HOWTO (R_ARM_TLS_DESC, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 0, /* bitsize */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_signed,/* complain_on_overflow */
+ complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
- "R_ARM_SWI24", /* name */
+ "R_ARM_TLS_DESC", /* name */
FALSE, /* partial_inplace */
- 0x00000000, /* src_mask */
- 0x00000000, /* dst_mask */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_SWI8, /* type */
@@ -1352,10 +1352,61 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
0x040f70ff, /* dst_mask */
FALSE), /* pcrel_offset */
- EMPTY_HOWTO (90), /* Unallocated. */
- EMPTY_HOWTO (91),
- EMPTY_HOWTO (92),
- EMPTY_HOWTO (93),
+ HOWTO (R_ARM_TLS_GOTDESC, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield,/* complain_on_overflow */
+ NULL, /* special_function */
+ "R_ARM_TLS_GOTDESC", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_ARM_TLS_CALL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_TLS_CALL", /* name */
+ FALSE, /* partial_inplace */
+ 0x00ffffff, /* src_mask */
+ 0x00ffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_ARM_TLS_DESCSEQ, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_TLS_DESCSEQ", /* name */
+ FALSE, /* partial_inplace */
+ 0x00000000, /* src_mask */
+ 0x00000000, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_ARM_THM_TLS_CALL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_THM_TLS_CALL", /* name */
+ FALSE, /* partial_inplace */
+ 0x07ff07ff, /* src_mask */
+ 0x07ff07ff, /* dst_mask */
+ FALSE), /* pcrel_offset */
HOWTO (R_ARM_PLT32_ABS, /* type */
0, /* rightshift */
@@ -1599,6 +1650,38 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (112),
+ EMPTY_HOWTO (113),
+ EMPTY_HOWTO (114),
+ EMPTY_HOWTO (115),
+ EMPTY_HOWTO (116),
+ EMPTY_HOWTO (117),
+ EMPTY_HOWTO (118),
+ EMPTY_HOWTO (119),
+ EMPTY_HOWTO (120),
+ EMPTY_HOWTO (121),
+ EMPTY_HOWTO (122),
+ EMPTY_HOWTO (123),
+ EMPTY_HOWTO (124),
+ EMPTY_HOWTO (125),
+ EMPTY_HOWTO (126),
+ EMPTY_HOWTO (127),
+ EMPTY_HOWTO (128),
+
+ HOWTO (R_ARM_THM_TLS_DESCSEQ, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_THM_TLS_DESCSEQ",/* name */
+ FALSE, /* partial_inplace */
+ 0x00000000, /* src_mask */
+ 0x00000000, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* 112-127 private relocations
@@ -1730,6 +1813,12 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{BFD_RELOC_ARM_PREL31, R_ARM_PREL31},
{BFD_RELOC_ARM_TARGET2, R_ARM_TARGET2},
{BFD_RELOC_ARM_PLT32, R_ARM_PLT32},
+ {BFD_RELOC_ARM_TLS_GOTDESC, R_ARM_TLS_GOTDESC},
+ {BFD_RELOC_ARM_TLS_CALL, R_ARM_TLS_CALL},
+ {BFD_RELOC_ARM_THM_TLS_CALL, R_ARM_THM_TLS_CALL},
+ {BFD_RELOC_ARM_TLS_DESCSEQ, R_ARM_TLS_DESCSEQ},
+ {BFD_RELOC_ARM_THM_TLS_DESCSEQ, R_ARM_THM_TLS_DESCSEQ},
+ {BFD_RELOC_ARM_TLS_DESC, R_ARM_TLS_DESC},
{BFD_RELOC_ARM_TLS_GD32, R_ARM_TLS_GD32},
{BFD_RELOC_ARM_TLS_LDO32, R_ARM_TLS_LDO32},
{BFD_RELOC_ARM_TLS_LDM32, R_ARM_TLS_LDM32},
@@ -1912,6 +2001,26 @@ typedef unsigned short int insn16;
section. */
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
+static const unsigned long tls_trampoline [] =
+ {
+ 0xe08e0000, /* add r0, lr, r0 */
+ 0xe5901004, /* ldr r1, [r0,#4] */
+ 0xe12fff11, /* bx r1 */
+ };
+
+static const unsigned long dl_tlsdesc_lazy_trampoline [] =
+ {
+ 0xe52d2004, /* push {r2} */
+ 0xe59f200c, /* ldr r2, [pc, #3f - . - 8] */
+ 0xe59f100c, /* ldr r1, [pc, #4f - . - 8] */
+ 0xe79f2002, /* 1: ldr r2, [pc, r2] */
+ 0xe081100f, /* 2: add r1, pc */
+ 0xe12fff12, /* bx r2 */
+ 0x00000014, /* 3: .word _GLOBAL_OFFSET_TABLE_ - 1b - 8
+ + dl_tlsdesc_lazy_resolver(GOT) */
+ 0x00000018, /* 4: .word _GLOBAL_OFFSET_TABLE_ - 2b - 8 */
+ };
+
#ifdef FOUR_WORD_PLT
/* The first entry in a procedure linkage table looks like
@@ -2167,6 +2276,26 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
DATA_WORD(0, R_ARM_REL32, 0), /* dcd R_ARM_REL32(X) */
};
+/* Thumb2/ARM -> TLS trampoline. Lowest common denominator, which is a
+ long PIC stub. We can use r1 as a scratch -- and cannot use ip. */
+static const insn_sequence elf32_arm_stub_long_branch_any_tls_pic[] =
+{
+ ARM_INSN(0xe59f1000), /* ldr r1, [pc] */
+ ARM_INSN(0xe08ff001), /* add pc, pc, r1 */
+ DATA_WORD(0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X-4) */
+};
+
+/* V4T Thumb -> TLS trampoline. lowest common denominator, which is a
+ long PIC stub. We can use r1 as a scratch -- and cannot use ip. */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] =
+{
+ THUMB16_INSN(0x4778), /* bx pc */
+ THUMB16_INSN(0x46c0), /* nop */
+ ARM_INSN(0xe59f1000), /* ldr r1, [pc, #0] */
+ ARM_INSN(0xe081f00f), /* add pc, r1, pc */
+ DATA_WORD(0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X) */
+};
+
/* Cortex-A8 erratum-workaround stubs. */
/* Stub used for conditional branches (which may be beyond +/-1MB away, so we
@@ -2218,6 +2347,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
DEF_STUB(long_branch_v4t_arm_thumb_pic) \
DEF_STUB(long_branch_v4t_thumb_arm_pic) \
DEF_STUB(long_branch_thumb_only_pic) \
+ DEF_STUB(long_branch_any_tls_pic) \
+ DEF_STUB(long_branch_v4t_thumb_tls_pic) \
DEF_STUB(a8_veneer_b_cond) \
DEF_STUB(a8_veneer_b) \
DEF_STUB(a8_veneer_bl) \
@@ -2426,6 +2557,9 @@ struct elf_arm_obj_tdata
/* tls_type for each local got entry. */
char *local_got_tls_type;
+ /* GOTPLT entries for TLS descriptors. */
+ bfd_vma *local_tlsdesc_gotent;
+
/* Zero to warn when linking objects with incompatible enum sizes. */
int no_enum_size_warning;
@@ -2439,6 +2573,9 @@ struct elf_arm_obj_tdata
#define elf32_arm_local_got_tls_type(bfd) \
(elf_arm_tdata (bfd)->local_got_tls_type)
+#define elf32_arm_local_tlsdesc_gotent(bfd) \
+ (elf_arm_tdata (bfd)->local_tlsdesc_gotent)
+
#define is_arm_elf(bfd) \
(bfd_get_flavour (bfd) == bfd_target_elf_flavour \
&& elf_tdata (bfd) != NULL \
@@ -2478,8 +2615,14 @@ struct elf32_arm_link_hash_entry
#define GOT_NORMAL 1
#define GOT_TLS_GD 2
#define GOT_TLS_IE 4
+#define GOT_TLS_GDESC 8
+#define GOT_TLS_GD_ANY_P(type) ((type & GOT_TLS_GD) || (type & GOT_TLS_GDESC))
unsigned char tls_type;
+ /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+ starting at the end of the jump table. */
+ bfd_vma tlsdesc_got;
+
/* The symbol marking the real symbol location for exported thumb
symbols with Arm stubs. */
struct elf_link_hash_entry *export_glue;
@@ -2516,6 +2659,9 @@ struct map_stub
asection *stub_sec;
};
+#define elf32_arm_compute_jump_table_size(htab) \
+ ((htab)->next_tls_desc_index * 4)
+
/* ARM ELF linker hash table. */
struct elf32_arm_link_hash_table
{
@@ -2594,6 +2740,12 @@ struct elf32_arm_link_hash_table
/* True if the target uses REL relocations. */
int use_rel;
+ /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt. */
+ bfd_vma next_tls_desc_index;
+
+ /* How many R_ARM_TLS_DESC relocations were generated so far. */
+ bfd_vma num_tls_desc;
+
/* Short-cuts to get to dynamic linker sections. */
asection *sdynbss;
asection *srelbss;
@@ -2601,6 +2753,19 @@ struct elf32_arm_link_hash_table
/* The (unloaded but important) VxWorks .rela.plt.unloaded section. */
asection *srelplt2;
+ /* The offset into splt of the PLT entry for the TLS descriptor
+ resolver. Special values are 0, if not necessary (or not found
+ to be necessary yet), and -1 if needed but not determined
+ yet. */
+ bfd_vma dt_tlsdesc_plt;
+
+ /* The offset into sgot of the GOT entry used by the PLT entry
+ above. */
+ bfd_vma dt_tlsdesc_got;
+
+ /* Offset in .plt section of tls_arm_trampoline. */
+ bfd_vma tls_trampoline;
+
/* Data for R_ARM_TLS_LDM32 relocations. */
union
{
@@ -2614,6 +2779,10 @@ struct elf32_arm_link_hash_table
/* For convenience in allocate_dynrelocs. */
bfd * obfd;
+ /* The amount of space used by the reserved portion of the sgotplt
+ section, plus whatever space is used by the jump slots. */
+ bfd_vma sgotplt_jump_table_size;
+
/* The stub hash table. */
struct bfd_hash_table stub_hash_table;
@@ -2663,6 +2832,7 @@ elf32_arm_link_hash_newfunc (struct bfd_hash_entry * entry,
{
ret->dyn_relocs = NULL;
ret->tls_type = GOT_UNKNOWN;
+ ret->tlsdesc_got = (bfd_vma) -1;
ret->plt_thumb_refcount = 0;
ret->plt_maybe_thumb_refcount = 0;
ret->plt_got_offset = -1;
@@ -2877,6 +3047,11 @@ elf32_arm_link_hash_table_create (bfd *abfd)
ret->sdynbss = NULL;
ret->srelbss = NULL;
ret->srelplt2 = NULL;
+ ret->dt_tlsdesc_plt = 0;
+ ret->dt_tlsdesc_got = 0;
+ ret->tls_trampoline = 0;
+ ret->next_tls_desc_index = 0;
+ ret->num_tls_desc = 0;
ret->thumb_glue_size = 0;
ret->arm_glue_size = 0;
ret->bx_glue_size = 0;
@@ -3075,7 +3250,8 @@ arm_type_of_stub (struct bfd_link_info *info,
branch_offset = (bfd_signed_vma)(destination - location);
- if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
+ if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
+ || r_type == R_ARM_THM_TLS_CALL)
{
/* Handle cases where:
- this call goes too far (different Thumb/Thumb2 max
@@ -3092,7 +3268,8 @@ arm_type_of_stub (struct bfd_link_info *info,
&& (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
|| ((st_type != STT_ARM_TFUNC)
- && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
+ && (((r_type == R_ARM_THM_CALL
+ || r_type == R_ARM_THM_TLS_CALL) && !globals->use_blx)
|| (r_type == R_ARM_THM_JUMP24))
&& !use_plt))
{
@@ -3143,18 +3320,21 @@ arm_type_of_stub (struct bfd_link_info *info,
sym_sec->owner, input_bfd, name);
}
- stub_type = (info->shared | globals->pic_veneer)
+ stub_type =
+ (info->shared | globals->pic_veneer)
/* PIC stubs. */
- ? ((globals->use_blx
- && (r_type ==R_ARM_THM_CALL))
- /* V5T and above. */
- ? arm_stub_long_branch_any_arm_pic
- /* V4T PIC stub. */
- : arm_stub_long_branch_v4t_thumb_arm_pic)
+ ? (r_type == R_ARM_THM_TLS_CALL
+ /* TLS PIC stubs */
+ ? (globals->use_blx ? arm_stub_long_branch_any_tls_pic
+ : arm_stub_long_branch_v4t_thumb_tls_pic)
+ : ((globals->use_blx && r_type == R_ARM_THM_CALL)
+ /* V5T PIC and above. */
+ ? arm_stub_long_branch_any_arm_pic
+ /* V4T PIC stub. */
+ : arm_stub_long_branch_v4t_thumb_arm_pic))
/* non-PIC stubs. */
- : ((globals->use_blx
- && (r_type ==R_ARM_THM_CALL))
+ : ((globals->use_blx && r_type == R_ARM_THM_CALL)
/* V5T and above. */
? arm_stub_long_branch_any_any
/* V4T. */
@@ -3170,7 +3350,8 @@ arm_type_of_stub (struct bfd_link_info *info,
}
else if (r_type == R_ARM_CALL
|| r_type == R_ARM_JUMP24
- || r_type == R_ARM_PLT32)
+ || r_type == R_ARM_PLT32
+ || r_type == R_ARM_TLS_CALL)
{
if (st_type == STT_ARM_TFUNC)
{
@@ -3190,7 +3371,7 @@ arm_type_of_stub (struct bfd_link_info *info,
the mode change (bit 24 (H) of BLX encoding). */
if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
|| (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)
- || ((r_type == R_ARM_CALL) && !globals->use_blx)
+ || (r_type == R_ARM_CALL && !globals->use_blx)
|| (r_type == R_ARM_JUMP24)
|| (r_type == R_ARM_PLT32))
{
@@ -3216,9 +3397,13 @@ arm_type_of_stub (struct bfd_link_info *info,
if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET))
{
- stub_type = (info->shared | globals->pic_veneer)
+ stub_type =
+ (info->shared | globals->pic_veneer)
/* PIC stubs. */
- ? arm_stub_long_branch_any_arm_pic
+ ? (r_type == R_ARM_TLS_CALL
+ /* TLS PIC Stub */
+ ? arm_stub_long_branch_any_tls_pic
+ : arm_stub_long_branch_any_arm_pic)
/* non-PIC stubs. */
: arm_stub_long_branch_any_any;
}
@@ -3263,7 +3448,9 @@ elf32_arm_stub_name (const asection *input_section,
sprintf (stub_name, "%08x_%x:%x+%x_%d",
input_section->id & 0xffffffff,
sym_sec->id & 0xffffffff,
- (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
+ ELF32_R_TYPE (rel->r_info) == R_ARM_TLS_CALL
+ || ELF32_R_TYPE (rel->r_info) == R_ARM_THM_TLS_CALL
+ ? 0 : (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
(int) rel->r_addend & 0xffffffff,
(int) stub_type);
}
@@ -3426,6 +3613,32 @@ put_thumb_insn (struct elf32_arm_link_hash_table * htab,
bfd_putb16 (val, ptr);
}
+/* If it's possible to change R_TYPE to a more efficient access
+ model, return the new reloc type. */
+
+static unsigned
+elf32_arm_tls_transition (struct bfd_link_info *info, int r_type,
+ struct elf_link_hash_entry *h)
+{
+ int is_local = (h == NULL);
+
+ if (info->shared || (h && h->root.type == bfd_link_hash_undefweak))
+ return r_type;
+
+ /* We do not support relaxations for Old TLS models. */
+ switch (r_type)
+ {
+ case R_ARM_TLS_GOTDESC:
+ case R_ARM_TLS_CALL:
+ case R_ARM_THM_TLS_CALL:
+ case R_ARM_TLS_DESCSEQ:
+ case R_ARM_THM_TLS_DESCSEQ:
+ return is_local ? R_ARM_TLS_LE32 : R_ARM_TLS_IE32;
+ }
+
+ return r_type;
+}
+
static bfd_reloc_status_type elf32_arm_final_link_relocate
(reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, bfd_vma, struct bfd_link_info *, asection *,
@@ -3453,6 +3666,8 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
case arm_stub_long_branch_v4t_arm_thumb_pic:
case arm_stub_long_branch_v4t_thumb_arm_pic:
case arm_stub_long_branch_thumb_only_pic:
+ case arm_stub_long_branch_any_tls_pic:
+ case arm_stub_long_branch_v4t_thumb_tls_pic:
case arm_stub_a8_veneer_blx:
return 4;
@@ -4419,15 +4634,30 @@ elf32_arm_size_stubs (bfd *output_bfd,
free (internal_relocs);
goto error_ret_free_local;
}
-
- /* Only look for stubs on branch instructions. */
+
+ hash = NULL;
+ if (r_indx >= symtab_hdr->sh_info)
+ hash = elf32_arm_hash_entry
+ (elf_sym_hashes (input_bfd)
+ [r_indx - symtab_hdr->sh_info]);
+
+ /* Only look for stubs on branch instructions, or
+ non-relaxed TLSCALL */
if ((r_type != (unsigned int) R_ARM_CALL)
&& (r_type != (unsigned int) R_ARM_THM_CALL)
&& (r_type != (unsigned int) R_ARM_JUMP24)
&& (r_type != (unsigned int) R_ARM_THM_JUMP19)
&& (r_type != (unsigned int) R_ARM_THM_XPC22)
&& (r_type != (unsigned int) R_ARM_THM_JUMP24)
- && (r_type != (unsigned int) R_ARM_PLT32))
+ && (r_type != (unsigned int) R_ARM_PLT32)
+ && !((r_type == (unsigned int) R_ARM_TLS_CALL
+ || r_type == (unsigned int) R_ARM_THM_TLS_CALL)
+ && r_type == elf32_arm_tls_transition
+ (info, r_type, &hash->root)
+ && ((hash ? hash->tls_type
+ : (elf32_arm_local_got_tls_type
+ (input_bfd)[r_indx]))
+ & GOT_TLS_GDESC) != 0))
continue;
/* Now determine the call target, its name, value,
@@ -4435,9 +4665,21 @@ elf32_arm_size_stubs (bfd *output_bfd,
sym_sec = NULL;
sym_value = 0;
destination = 0;
- hash = NULL;
sym_name = NULL;
- if (r_indx < symtab_hdr->sh_info)
+
+ if (r_type == (unsigned int) R_ARM_TLS_CALL
+ || r_type == (unsigned int) R_ARM_THM_TLS_CALL)
+ {
+ /* A non-relaxed TLS call. The target is the
+ plt-resident trampoline and nothing to do
+ with the symbol. */
+ BFD_ASSERT (htab->tls_trampoline > 0);
+ sym_sec = htab->root.splt;
+ sym_value = htab->tls_trampoline;
+ hash = 0;
+ st_type = STT_FUNC;
+ }
+ else if (!hash)
{
/* It's a local symbol. */
Elf_Internal_Sym *sym;
@@ -4485,12 +4727,6 @@ elf32_arm_size_stubs (bfd *output_bfd,
else
{
/* It's an external symbol. */
- int e_indx;
-
- e_indx = r_indx - symtab_hdr->sh_info;
- hash = ((struct elf32_arm_link_hash_entry *)
- elf_sym_hashes (input_bfd)[e_indx]);
-
while (hash->root.root.type == bfd_link_hash_indirect
|| hash->root.root.type == bfd_link_hash_warning)
hash = ((struct elf32_arm_link_hash_entry *)
@@ -6743,6 +6979,148 @@ elf32_arm_abs12_reloc (bfd *abfd, void *data, bfd_vma value)
return bfd_reloc_ok;
}
+/* Handle TLS relaxations. Relaxing is possible for symbols that use
+ R_ARM_GOTDESC, R_ARM_{,THM_}TLS_CALL or
+ R_ARM_{,THM_}TLS_DESCSEQ relocations, during a static link.
+
+ Return bfd_reloc_ok if we're done, bfd_reloc_continue if the caller
+ is to then call final_link_relocate. Return other values in the
+ case of error. */
+
+
+static bfd_reloc_status_type
+elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals,
+ bfd *input_bfd, asection *input_sec, bfd_byte *contents,
+ Elf_Internal_Rela *rel, unsigned long is_local)
+{
+ unsigned long insn;
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ default:
+ return bfd_reloc_notsupported;
+
+ case R_ARM_TLS_GOTDESC:
+ if (is_local)
+ insn = 0;
+ else
+ {
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ if (insn & 1)
+ insn -= 5; /* THUMB */
+ else
+ insn -= 8; /* ARM */
+ }
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+ return bfd_reloc_continue;
+
+ case R_ARM_THM_TLS_DESCSEQ:
+ /* Thumb insn. */
+ insn = bfd_get_16 (input_bfd, contents + rel->r_offset);
+ if ((insn & 0xff78) == 0x4478) /* add rx, pc */
+ {
+ if (is_local)
+ /* nop */
+ bfd_put_16 (input_bfd, 0x46c0, contents + rel->r_offset);
+ }
+ else if ((insn & 0xffc0) == 0x6840) /* ldr rx,[ry,#4] */
+ {
+ if (is_local)
+ /* nop */
+ bfd_put_16 (input_bfd, 0x46c0, contents + rel->r_offset);
+ else
+ /* ldr rx,[ry] */
+ bfd_put_16 (input_bfd, insn & 0xf83f, contents + rel->r_offset);
+ }
+ else if ((insn & 0xff87) == 0x4780) /* blx rx */
+ {
+ if (is_local)
+ /* nop */
+ bfd_put_16 (input_bfd, 0x46c0, contents + rel->r_offset);
+ else
+ /* mov r0, rx */
+ bfd_put_16 (input_bfd, 0x4600 | (insn & 0x78),
+ contents + rel->r_offset);
+ }
+ else
+ {
+ if ((insn & 0xf000) == 0xf000 || (insn & 0xf800) == 0xe800)
+ /* It's a 32 bit instruction, fetch the rest of it for
+ error generation. */
+ insn = (insn << 16)
+ | bfd_get_16 (input_bfd, contents + rel->r_offset + 2);
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx):unexpected Thumb instruction '0x%x' in TLS trampoline"),
+ input_bfd, input_sec, (unsigned long)rel->r_offset, insn);
+ return bfd_reloc_notsupported;
+ }
+ break;
+
+ case R_ARM_TLS_DESCSEQ:
+ /* arm insn. */
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ if ((insn & 0xffff0ff0) == 0xe08f0000) /* add rx,pc,ry */
+ {
+ if (is_local)
+ /* mov rx, ry */
+ bfd_put_32 (input_bfd, 0xe1a00000 | (insn & 0xffff),
+ contents + rel->r_offset);
+ }
+ else if ((insn & 0xfff00fff) == 0xe5900004) /* ldr rx,[ry,#4]*/
+ {
+ if (is_local)
+ /* nop */
+ bfd_put_32 (input_bfd, 0xe1a00000, contents + rel->r_offset);
+ else
+ /* ldr rx,[ry] */
+ bfd_put_32 (input_bfd, insn & 0xfffff000,
+ contents + rel->r_offset);
+ }
+ else if ((insn & 0xfffffff0) == 0xe12fff30) /* blx rx */
+ {
+ if (is_local)
+ /* nop */
+ bfd_put_32 (input_bfd, 0xe1a00000, contents + rel->r_offset);
+ else
+ /* mov r0, rx */
+ bfd_put_32 (input_bfd, 0xe1a00000 | (insn & 0xf),
+ contents + rel->r_offset);
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx):unexpected ARM instruction '0x%x' in TLS trampoline"),
+ input_bfd, input_sec, (unsigned long)rel->r_offset, insn);
+ return bfd_reloc_notsupported;
+ }
+ break;
+
+ case R_ARM_TLS_CALL:
+ /* GD->IE relaxation, turn the instruction into 'nop' or
+ 'ldr r0, [pc,r0]' */
+ insn = is_local ? 0xe1a00000 : 0xe79f0000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+ break;
+
+ case R_ARM_THM_TLS_CALL:
+ /* GD->IE relaxation */
+ if (!is_local)
+ /* add r0,pc; ldr r0, [r0] */
+ insn = 0x44786800;
+ else if (arch_has_thumb2_nop (globals))
+ /* nop.w */
+ insn = 0xf3af8000;
+ else
+ /* nop; nop */
+ insn = 0xbf00bf00;
+
+ bfd_put_16 (input_bfd, insn >> 16, contents + rel->r_offset);
+ bfd_put_16 (input_bfd, insn & 0xffff, contents + rel->r_offset + 2);
+ break;
+ }
+ return bfd_reloc_ok;
+}
+
/* For a given value of n, calculate the value of G_n as required to
deal with group relocations. We return it in the form of an
encoded constant-and-rotation, together with the final residual. If n is
@@ -6834,6 +7212,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
unsigned long r_symndx;
bfd_byte * hit_data = contents + rel->r_offset;
bfd_vma * local_got_offsets;
+ bfd_vma * local_tlsdesc_gotents;
asection * sgot = NULL;
asection * splt = NULL;
asection * sreloc = NULL;
@@ -6851,6 +7230,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
/* Some relocation types map to different relocations depending on the
target. We pick the right one here. */
r_type = arm_real_reloc_type (globals, r_type);
+
+ /* It is possible to have linker relaxations on some TLS access
+ models. Update our information here. */
+ r_type = elf32_arm_tls_transition (info, r_type, h);
+
if (r_type != howto->type)
howto = elf32_arm_howto_from_type (r_type);
@@ -6870,6 +7254,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
splt = globals->root.splt;
srelgot = globals->root.srelgot;
local_got_offsets = elf_local_got_offsets (input_bfd);
+ local_tlsdesc_gotents = elf32_arm_local_tlsdesc_gotent (input_bfd);
+
r_symndx = ELF32_R_SYM (rel->r_info);
if (globals->use_rel)
@@ -8010,17 +8396,20 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
rel->r_addend);
}
+ case R_ARM_TLS_CALL:
+ case R_ARM_THM_TLS_CALL:
case R_ARM_TLS_GD32:
case R_ARM_TLS_IE32:
+ case R_ARM_TLS_GOTDESC:
+ case R_ARM_TLS_DESCSEQ:
+ case R_ARM_THM_TLS_DESCSEQ:
{
- bfd_vma off;
- int indx;
+ bfd_vma off, offplt;
+ int indx = 0;
char tls_type;
- if (sgot == NULL)
- abort ();
+ BFD_ASSERT (sgot != NULL);
- indx = 0;
if (h != NULL)
{
bfd_boolean dyn;
@@ -8033,18 +8422,23 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
indx = h->dynindx;
}
off = h->got.offset;
+ offplt = elf32_arm_hash_entry (h)->tlsdesc_got;
tls_type = ((struct elf32_arm_link_hash_entry *) h)->tls_type;
}
else
{
- if (local_got_offsets == NULL)
- abort ();
+ BFD_ASSERT (local_got_offsets != NULL);
off = local_got_offsets[r_symndx];
+ offplt = local_tlsdesc_gotents[r_symndx];
tls_type = elf32_arm_local_got_tls_type (input_bfd)[r_symndx];
}
- if (tls_type == GOT_UNKNOWN)
- abort ();
+ /* Linker relaxations happens from one of the
+ R_ARM_{GOTDESC,CALL,DESCSEQ} relocations to IE or LE. */
+ if (ELF32_R_TYPE(rel->r_info) != r_type)
+ tls_type = GOT_TLS_IE;
+
+ BFD_ASSERT (tls_type != GOT_UNKNOWN);
if ((off & 1) != 0)
off &= ~1;
@@ -8065,12 +8459,49 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
|| h->root.type != bfd_link_hash_undefweak))
{
need_relocs = TRUE;
- if (srelgot == NULL)
- abort ();
- loc = srelgot->contents;
- loc += srelgot->reloc_count * RELOC_SIZE (globals);
+ BFD_ASSERT (srelgot != NULL);
}
+ if (tls_type & GOT_TLS_GDESC)
+ {
+ /* We should have relaxed, unless this is an undefined
+ weak symbol. */
+ BFD_ASSERT ((h && (h->root.type == bfd_link_hash_undefweak))
+ || info->shared);
+ BFD_ASSERT (globals->sgotplt_jump_table_size + offplt + 8
+ <= globals->root.sgotplt->size);
+
+ outrel.r_addend = 0;
+ outrel.r_offset = (globals->root.sgotplt->output_section->vma
+ + globals->root.sgotplt->output_offset
+ + offplt
+ + globals->sgotplt_jump_table_size);
+
+ outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_DESC);
+ sreloc = globals->root.srelplt;
+ loc = sreloc->contents;
+ loc += globals->next_tls_desc_index++ * RELOC_SIZE (globals);
+ BFD_ASSERT (loc + RELOC_SIZE (globals)
+ <= sreloc->contents + sreloc->size);
+
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
+
+ /* For globals, the first word in the relocation gets
+ the relocation index and the top bit set, or zero,
+ if we're binding now. For locals, it gets the
+ symbol's offset in the tls section. */
+ bfd_put_32 (output_bfd,
+ !h ? value - elf_hash_table (info)->tls_sec->vma
+ : info->flags & DF_BIND_NOW ? 0
+ : 0x80000000 | ELF32_R_SYM (outrel.r_info),
+ globals->root.sgotplt->contents + offplt +
+ globals->sgotplt_jump_table_size);
+
+ /* Second word in the relocation is always zero. */
+ bfd_put_32 (output_bfd, 0,
+ globals->root.sgotplt->contents + offplt +
+ globals->sgotplt_jump_table_size + 4);
+ }
if (tls_type & GOT_TLS_GD)
{
if (need_relocs)
@@ -8084,10 +8515,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (globals->use_rel)
bfd_put_32 (output_bfd, outrel.r_addend,
sgot->contents + cur_off);
+ loc = srelgot->contents;
+ loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
- srelgot->reloc_count++;
- loc += RELOC_SIZE (globals);
if (indx == 0)
bfd_put_32 (output_bfd, value - dtpoff_base (info),
@@ -8103,10 +8534,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
bfd_put_32 (output_bfd, outrel.r_addend,
sgot->contents + cur_off + 4);
+ loc = srelgot->contents;
+ loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
- srelgot->reloc_count++;
- loc += RELOC_SIZE (globals);
}
}
else
@@ -8142,9 +8573,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
bfd_put_32 (output_bfd, outrel.r_addend,
sgot->contents + cur_off);
+ loc = srelgot->contents;
+ loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
+
SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
- srelgot->reloc_count++;
- loc += RELOC_SIZE (globals);
}
else
bfd_put_32 (output_bfd, tpoff (info, value),
@@ -8160,8 +8592,142 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32)
off += 8;
- value = sgot->output_section->vma + sgot->output_offset + off
- - (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
+ else if (tls_type & GOT_TLS_GDESC)
+ off = offplt;
+
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_TLS_CALL
+ || ELF32_R_TYPE(rel->r_info) == R_ARM_THM_TLS_CALL)
+ {
+ bfd_signed_vma offset;
+ enum elf32_arm_stub_type stub_type
+ = arm_type_of_stub (info, input_section, rel, &sym_flags,
+ (struct elf32_arm_link_hash_entry *)h,
+ globals->tls_trampoline, globals->root.splt,
+ input_bfd, sym_name);
+
+ if (stub_type != arm_stub_none)
+ {
+ struct elf32_arm_stub_hash_entry *stub_entry
+ = elf32_arm_get_stub_entry
+ (input_section, globals->root.splt, 0, rel,
+ globals, stub_type);
+ offset = (stub_entry->stub_offset
+ + stub_entry->stub_sec->output_offset
+ + stub_entry->stub_sec->output_section->vma);
+ }
+ else
+ offset = (globals->root.splt->output_section->vma
+ + globals->root.splt->output_offset
+ + globals->tls_trampoline);
+
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_TLS_CALL)
+ {
+ unsigned long inst;
+
+ offset -= (input_section->output_section->vma +
+ input_section->output_offset + rel->r_offset + 8);
+
+ inst = offset >> 2;
+ inst &= 0x00ffffff;
+ value = inst | (globals->use_blx ? 0xfa000000 : 0xeb000000);
+ }
+ else
+ {
+ /* Thumb blx encodes the offset in a complicated
+ fashion. */
+ unsigned upper_insn, lower_insn;
+ unsigned neg;
+
+ offset -= (input_section->output_section->vma +
+ input_section->output_offset
+ + rel->r_offset + 4);
+
+ /* Round up the offset to a word boundary */
+ offset = (offset + 2) & ~2;
+ neg = offset < 0;
+ upper_insn = (0xf000
+ | ((offset >> 12) & 0x3ff)
+ | (neg << 10));
+ lower_insn = (0xc000
+ | (((!((offset >> 23) & 1)) ^ neg) << 13)
+ | (((!((offset >> 22) & 1)) ^ neg) << 11)
+ | ((offset >> 1) & 0x7ff));
+ bfd_put_16 (input_bfd, upper_insn, hit_data);
+ bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+ return bfd_reloc_ok;
+ }
+ }
+ /* These relocations needs special care, as besides the fact
+ they point somewhere in .gotplt, the addend must be
+ adjusted accordingly depending on the type of instruction
+ we refer to */
+ else if ((r_type == R_ARM_TLS_GOTDESC) && (tls_type & GOT_TLS_GDESC))
+ {
+ unsigned long data, insn;
+ unsigned thumb;
+
+ data = bfd_get_32 (input_bfd, hit_data);
+ thumb = data & 1;
+ data &= ~1u;
+
+ if (thumb)
+ {
+ insn = bfd_get_16 (input_bfd, contents + rel->r_offset - data);
+ if ((insn & 0xf000) == 0xf000 || (insn & 0xf800) == 0xe800)
+ insn = (insn << 16)
+ | bfd_get_16 (input_bfd,
+ contents + rel->r_offset - data + 2);
+ if ((insn & 0xf800c000) == 0xf000c000)
+ /* bl/blx */
+ value = -6;
+ else if ((insn & 0xffffff00) == 0x4400)
+ /* add */
+ value = -5;
+ else
+ {
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx):unexpected Thumb instruction '0x%x' referenced by TLS_GOTDESC"),
+ input_bfd, input_section,
+ (unsigned long)rel->r_offset, insn);
+ return bfd_reloc_notsupported;
+ }
+ }
+ else
+ {
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset - data);
+
+ switch (insn >> 24)
+ {
+ case 0xeb: /* bl */
+ case 0xfa: /* blx */
+ value = -4;
+ break;
+
+ case 0xe0: /* add */
+ value = -8;
+ break;
+
+ default:
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx):unexpected ARM instruction '0x%x' referenced by TLS_GOTDESC"),
+ input_bfd, input_section,
+ (unsigned long)rel->r_offset, insn);
+ return bfd_reloc_notsupported;
+ }
+ }
+
+ value += ((globals->root.sgotplt->output_section->vma
+ + globals->root.sgotplt->output_offset + off)
+ - (input_section->output_section->vma
+ + input_section->output_offset
+ + rel->r_offset)
+ + globals->sgotplt_jump_table_size);
+ }
+ else
+ value = ((globals->root.sgot->output_section->vma
+ + globals->root.sgot->output_offset + off)
+ - (input_section->output_section->vma
+ + input_section->output_offset + rel->r_offset));
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
@@ -8789,7 +9355,16 @@ arm_add_to_rel (bfd * abfd,
|| (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 \
+ || IS_ARM_TLS_GNU_RELOC (R_TYPE))
+
+/* Specific set of relocations for the gnu tls dialect. */
+#define IS_ARM_TLS_GNU_RELOC(R_TYPE) \
+ ((R_TYPE) == R_ARM_TLS_GOTDESC \
+ || (R_TYPE) == R_ARM_TLS_CALL \
+ || (R_TYPE) == R_ARM_THM_TLS_CALL \
+ || (R_TYPE) == R_ARM_TLS_DESCSEQ \
+ || (R_TYPE) == R_ARM_THM_TLS_DESCSEQ)
/* Relocate an ARM ELF section. */
@@ -9032,12 +9607,33 @@ elf32_arm_relocate_section (bfd * output_bfd,
name);
}
- r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
- input_section, contents, rel,
- relocation, info, sec, name,
- (h ? ELF_ST_TYPE (h->type) :
- ELF_ST_TYPE (sym->st_info)), h,
- &unresolved_reloc, &error_message);
+ /* We call elf32_arm_final_link_relocate unless we're completely
+ done, i.e., the relaxation produced the final output we want,
+ and we won't let anybody mess with it. Also, we have to do
+ addend adjustments in case of a R_ARM_TLS_GOTDESC relocation
+ both in relaxed and non-relaxed cases */
+ if ((elf32_arm_tls_transition (info, r_type, h) != (unsigned)r_type)
+ || (IS_ARM_TLS_GNU_RELOC (r_type)
+ && !((h ? elf32_arm_hash_entry (h)->tls_type :
+ elf32_arm_local_got_tls_type (input_bfd)[r_symndx])
+ & GOT_TLS_GDESC)))
+ {
+ r = elf32_arm_tls_relax (globals, input_bfd, input_section,
+ contents, rel, h == NULL);
+ /* This may have been marked unresolved because it came from
+ a shared library. But we've just dealt with that. */
+ unresolved_reloc = 0;
+ }
+ else
+ r = bfd_reloc_continue;
+
+ if (r == bfd_reloc_continue)
+ r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
+ input_section, contents, rel,
+ relocation, info, sec, name,
+ (h ? ELF_ST_TYPE (h->type) :
+ ELF_ST_TYPE (sym->st_info)), h,
+ &unresolved_reloc, &error_message);
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
because such sections are not SEC_ALLOC and thus ld.so will
@@ -10780,12 +11376,19 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
eh = (struct elf32_arm_link_hash_entry *) h;
+ /* Could be done earlier, if h were already available. */
+ r_type = elf32_arm_tls_transition (info, r_type, h);
switch (r_type)
{
case R_ARM_GOT32:
case R_ARM_GOT_PREL:
case R_ARM_TLS_GD32:
case R_ARM_TLS_IE32:
+ case R_ARM_TLS_GOTDESC:
+ case R_ARM_TLS_DESCSEQ:
+ case R_ARM_THM_TLS_DESCSEQ:
+ case R_ARM_TLS_CALL:
+ case R_ARM_THM_TLS_CALL:
/* This symbol requires a global offset table entry. */
{
int tls_type, old_tls_type;
@@ -10793,7 +11396,14 @@ 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_IE32: tls_type = GOT_TLS_IE; break;
+
+ case R_ARM_TLS_GOTDESC:
+ case R_ARM_TLS_CALL: case R_ARM_THM_TLS_CALL:
+ case R_ARM_TLS_DESCSEQ: case R_ARM_THM_TLS_DESCSEQ:
+ tls_type = GOT_TLS_GDESC; break;
+
default: tls_type = GOT_NORMAL; break;
}
@@ -10813,27 +11423,44 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
bfd_size_type size;
size = symtab_hdr->sh_info;
- size *= (sizeof (bfd_signed_vma) + sizeof (char));
+ size *= (sizeof (bfd_signed_vma)
+ + sizeof (bfd_vma) + sizeof (char));
local_got_refcounts = (bfd_signed_vma *)
bfd_zalloc (abfd, size);
if (local_got_refcounts == NULL)
return FALSE;
elf_local_got_refcounts (abfd) = local_got_refcounts;
+ elf32_arm_local_tlsdesc_gotent (abfd)
+ = (bfd_vma *) (local_got_refcounts
+ + symtab_hdr->sh_info);
elf32_arm_local_got_tls_type (abfd)
- = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+ = (char *) (elf32_arm_local_tlsdesc_gotent (abfd)
+ + symtab_hdr->sh_info);
}
local_got_refcounts[r_symndx] += 1;
old_tls_type = elf32_arm_local_got_tls_type (abfd) [r_symndx];
}
- /* We will already have issued an error message if there is a
- TLS / non-TLS mismatch, based on the symbol type. We don't
- support any linker relaxations. So just combine any TLS
- types needed. */
+ /* If a variable is accessed with both tls methods, two
+ slots may be created. */
+ if (GOT_TLS_GD_ANY_P (old_tls_type)
+ && GOT_TLS_GD_ANY_P (tls_type))
+ tls_type |= old_tls_type;
+
+ /* We will already have issued an error message if there
+ is a TLS/non-TLS mismatch, based on the symbol
+ type. So just combine any TLS types needed. */
if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL
&& tls_type != GOT_NORMAL)
tls_type |= old_tls_type;
+ /* If the symbol is accessed in both IE and GDESC
+ method, we're able to relax. Turn off the GDESC flag,
+ without messing up with any other kind of tls types
+ that may be involved */
+ if ((tls_type & GOT_TLS_IE) && (tls_type & GOT_TLS_GDESC))
+ tls_type &= ~GOT_TLS_GDESC;
+
if (old_tls_type != tls_type)
{
if (h != NULL)
@@ -11454,12 +12081,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
{
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
- eh->plt_got_offset = htab->root.sgotplt->size;
+ eh->plt_got_offset = (htab->root.sgotplt->size
+ - 8 * htab->num_tls_desc);
htab->root.sgotplt->size += 4;
}
/* We also need to make an entry in the .rel(a).plt section. */
htab->root.srelplt->size += RELOC_SIZE (htab);
+ htab->next_tls_desc_index++;
/* VxWorks executables have a second set of relocations for
each PLT entry. They go in a separate relocation section,
@@ -11489,6 +12118,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
h->needs_plt = 0;
}
+ eh = (struct elf32_arm_link_hash_entry *) h;
+ eh->tlsdesc_got = (bfd_vma) -1;
+
if (h->got.refcount > 0)
{
asection *s;
@@ -11518,9 +12150,28 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
s->size += 4;
else
{
+ if (tls_type & GOT_TLS_GDESC)
+ {
+ /* R_ARM_TLS_DESC needs 2 GOT slots. */
+ eh->tlsdesc_got
+ = (htab->root.sgotplt->size
+ - elf32_arm_compute_jump_table_size (htab));
+ htab->root.sgotplt->size += 8;
+ h->got.offset = (bfd_vma) -2;
+ /* plt_got_offset needs to know there's a TLS_DESC
+ reloc in the middle of .got.plt. */
+ htab->num_tls_desc++;
+ }
+
if (tls_type & GOT_TLS_GD)
- /* R_ARM_TLS_GD32 needs 2 consecutive GOT slots. */
- s->size += 8;
+ {
+ /* R_ARM_TLS_GD32 needs 2 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. */
s->size += 4;
@@ -11545,8 +12196,17 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
if (tls_type & GOT_TLS_GD)
htab->root.srelgot->size += RELOC_SIZE (htab);
- if ((tls_type & GOT_TLS_GD) && indx != 0)
- htab->root.srelgot->size += RELOC_SIZE (htab);
+ if (tls_type & GOT_TLS_GDESC)
+ {
+ htab->root.srelplt->size += RELOC_SIZE (htab);
+ /* GDESC needs a trampoline to jump to. */
+ htab->tls_trampoline = -1;
+ }
+
+ /* Only GD needs it. GDESC just emits one relocation per
+ 2 entries. */
+ if ((tls_type & GOT_TLS_GD) && indx != 0)
+ htab->root.srelgot->size += RELOC_SIZE (htab);
}
else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
@@ -11788,6 +12448,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
char *local_tls_type;
+ bfd_vma *local_tlsdesc_gotent;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
asection *srel;
@@ -11836,23 +12497,49 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
local_tls_type = elf32_arm_local_got_tls_type (ibfd);
+ local_tlsdesc_gotent = elf32_arm_local_tlsdesc_gotent (ibfd);
s = htab->root.sgot;
srel = htab->root.srelgot;
- for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+ for (; local_got < end_local_got;
+ ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
{
+ *local_tlsdesc_gotent = (bfd_vma) -1;
if (*local_got > 0)
{
*local_got = s->size;
if (*local_tls_type & GOT_TLS_GD)
/* TLS_GD relocs need an 8-byte structure in the GOT. */
s->size += 8;
+ if (*local_tls_type & GOT_TLS_GDESC)
+ {
+ *local_tlsdesc_gotent = htab->root.sgotplt->size
+ - elf32_arm_compute_jump_table_size (htab);
+ htab->root.sgotplt->size += 8;
+ *local_got = (bfd_vma) -2;
+ /* plt_got_offset needs to know there's a TLS_DESC
+ reloc in the middle of .got.plt. */
+ htab->num_tls_desc++;
+ }
if (*local_tls_type & GOT_TLS_IE)
s->size += 4;
- if (*local_tls_type == GOT_NORMAL)
- s->size += 4;
- if (info->shared || *local_tls_type == GOT_TLS_GD)
+ if (*local_tls_type & GOT_NORMAL)
+ {
+ /* If the symbol is both GD and GDESC, *local_got
+ may have been overwritten. */
+ *local_got = s->size;
+ s->size += 4;
+ }
+
+ if ((info->shared && !(*local_tls_type & GOT_TLS_GDESC))
+ || *local_tls_type & GOT_TLS_GD)
srel->size += RELOC_SIZE (htab);
+
+ if (info->shared && *local_tls_type & GOT_TLS_GDESC)
+ {
+ htab->root.srelplt->size += RELOC_SIZE (htab);
+ htab->tls_trampoline = -1;
+ }
}
else
*local_got = (bfd_vma) -1;
@@ -11894,6 +12581,34 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
/* Allocate space for the glue sections now that we've sized them. */
bfd_elf32_arm_allocate_interworking_sections (info);
+ /* For every jump slot reserved in the sgotplt, reloc_count is
+ incremented. However, when we reserve space for TLS descriptors,
+ it's not incremented, so in order to compute the space reserved
+ for them, it suffices to multiply the reloc count by the jump
+ slot size. */
+ if (htab->root.srelplt)
+ htab->sgotplt_jump_table_size = elf32_arm_compute_jump_table_size(htab);
+
+ if (htab->tls_trampoline)
+ {
+ if (htab->root.splt->size == 0)
+ htab->root.splt->size += htab->plt_header_size;
+
+ htab->tls_trampoline = htab->root.splt->size;
+ htab->root.splt->size += htab->plt_entry_size;
+
+ /* If we're not using lazy TLS relocations, don't generate the
+ PLT and GOT entries they require. */
+ if (!(info->flags & DF_BIND_NOW))
+ {
+ htab->dt_tlsdesc_got = htab->root.sgot->size;
+ htab->root.sgot->size += 4;
+
+ htab->dt_tlsdesc_plt = htab->root.splt->size;
+ htab->root.splt->size += 4 * ARRAY_SIZE (dl_tlsdesc_lazy_trampoline);
+ }
+ }
+
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
@@ -11984,6 +12699,11 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
htab->use_rel ? DT_REL : DT_RELA)
|| !add_dynamic_entry (DT_JMPREL, 0))
return FALSE;
+
+ if (htab->dt_tlsdesc_plt &&
+ (!add_dynamic_entry (DT_TLSDESC_PLT,0)
+ || !add_dynamic_entry (DT_TLSDESC_GOT,0)))
+ return FALSE;
}
if (relocs)
@@ -12024,6 +12744,49 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
return TRUE;
}
+/* Size sections even though they're not dynamic. We use it to setup
+ _TLS_MODULE_BASE_, if needed. */
+
+static bfd_boolean
+elf32_arm_always_size_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ asection *tls_sec;
+
+ if (info->relocatable)
+ return TRUE;
+
+ tls_sec = elf_hash_table (info)->tls_sec;
+
+ if (tls_sec)
+ {
+ struct elf_link_hash_entry *tlsbase;
+
+ tlsbase = elf_link_hash_lookup
+ (elf_hash_table (info), "_TLS_MODULE_BASE_", TRUE, TRUE, FALSE);
+
+ if (tlsbase)
+ {
+ struct bfd_link_hash_entry *bh = NULL;
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (output_bfd);
+
+ if (!(_bfd_generic_link_add_one_symbol
+ (info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+ tls_sec, 0, NULL, FALSE,
+ bed->collect, &bh)))
+ return FALSE;
+
+ tlsbase->type = STT_TLS;
+ tlsbase = (struct elf_link_hash_entry *)bh;
+ tlsbase->def_regular = 1;
+ tlsbase->other = STV_HIDDEN;
+ (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+ }
+ }
+ return TRUE;
+}
+
/* Finish up dynamic symbol handling. We set the contents of various
dynamic sections here. */
@@ -12240,7 +13003,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
}
if (h->got.offset != (bfd_vma) -1
- && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_GD) == 0
+ && (! GOT_TLS_GD_ANY_P (elf32_arm_hash_entry (h)->tls_type))
&& (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0)
{
asection * sgot;
@@ -12321,6 +13084,24 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
return TRUE;
}
+static void
+arm_put_trampoline (struct elf32_arm_link_hash_table *htab, bfd *output_bfd,
+ void *contents,
+ const unsigned long *template, unsigned count)
+{
+ unsigned ix;
+
+ for (ix = 0; ix != count; ix++)
+ {
+ unsigned long insn = template[ix];
+
+ /* Emit mov pc,rx if bx is not permitted. */
+ if (htab->fix_v4bx == 1 && (insn & 0x0ffffff0) == 0x012fff10)
+ insn = (insn & 0xf000000f) | 0x01a0f000;
+ put_arm_insn (htab, output_bfd, insn, (char *)contents + ix*4);
+ }
+}
+
/* Finish up the dynamic sections. */
static bfd_boolean
@@ -12474,6 +13255,20 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
}
break;
+ case DT_TLSDESC_PLT:
+ s = htab->root.splt;
+ dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
+ + htab->dt_tlsdesc_plt);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_TLSDESC_GOT:
+ s = htab->root.sgot;
+ dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
+ + htab->dt_tlsdesc_got);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
/* Set the bottom bit of DT_INIT/FINI if the
corresponding function is Thumb. */
case DT_INIT:
@@ -12563,6 +13358,41 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
if (splt->output_section->owner == output_bfd)
elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+ if (htab->dt_tlsdesc_plt)
+ {
+ bfd_vma got_address
+ = sgot->output_section->vma + sgot->output_offset;
+ bfd_vma gotplt_address = (htab->root.sgot->output_section->vma
+ + htab->root.sgot->output_offset);
+ bfd_vma plt_address
+ = splt->output_section->vma + splt->output_offset;
+
+ arm_put_trampoline (htab, output_bfd,
+ splt->contents + htab->dt_tlsdesc_plt,
+ dl_tlsdesc_lazy_trampoline, 6);
+
+ bfd_put_32 (output_bfd,
+ gotplt_address + htab->dt_tlsdesc_got
+ - (plt_address + htab->dt_tlsdesc_plt)
+ - dl_tlsdesc_lazy_trampoline[6],
+ splt->contents + htab->dt_tlsdesc_plt + 24);
+ bfd_put_32 (output_bfd,
+ got_address - (plt_address + htab->dt_tlsdesc_plt)
+ - dl_tlsdesc_lazy_trampoline[7],
+ splt->contents + htab->dt_tlsdesc_plt + 24 + 4);
+ }
+
+ if (htab->tls_trampoline)
+ {
+ arm_put_trampoline (htab, output_bfd,
+ splt->contents + htab->tls_trampoline,
+ tls_trampoline, 3);
+#ifdef FOUR_WORD_PLT
+ bfd_put_32 (output_bfd, 0x00000000,
+ splt->contents + htab->tls_trampoline + 12);
+#endif
+ }
+
if (htab->vxworks_p && !info->shared && htab->root.splt->size > 0)
{
/* Correct the .rel(a).plt.unloaded relocations. They will have
@@ -13137,6 +13967,28 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
#endif
}
+ if (htab->dt_tlsdesc_plt != 0)
+ {
+ /* Mapping symbols for the lazy tls trampoline. */
+ if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, htab->dt_tlsdesc_plt))
+ return FALSE;
+
+ if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
+ htab->dt_tlsdesc_plt + 24))
+ return FALSE;
+ }
+ if (htab->tls_trampoline != 0)
+ {
+ /* Mapping symbols for the tls trampoline. */
+ if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, htab->tls_trampoline))
+ return FALSE;
+#ifdef FOUR_WORD_PLT
+ if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
+ htab->tls_trampoline + 12))
+ return FALSE;
+#endif
+ }
+
elf_link_hash_traverse (&htab->root, elf32_arm_output_plt_map, (void *) &osi);
return TRUE;
}
@@ -13795,6 +14647,7 @@ const struct elf_size_info elf32_arm_size_info =
#define elf_backend_finish_dynamic_symbol elf32_arm_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections
#define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections
+#define elf_backend_always_size_sections elf32_arm_always_size_sections
#define elf_backend_init_index_section _bfd_elf_init_2_index_sections
#define elf_backend_post_process_headers elf32_arm_post_process_headers
#define elf_backend_reloc_type_class elf32_arm_reloc_type_class
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 1cf63ce..8c5b3b5 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1377,6 +1377,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_ARM_TLS_TPOFF32",
"BFD_RELOC_ARM_TLS_IE32",
"BFD_RELOC_ARM_TLS_LE32",
+ "BFD_RELOC_ARM_TLS_GOTDESC",
+ "BFD_RELOC_ARM_TLS_CALL",
+ "BFD_RELOC_ARM_THM_TLS_CALL",
+ "BFD_RELOC_ARM_TLS_DESCSEQ",
+ "BFD_RELOC_ARM_THM_TLS_DESCSEQ",
+ "BFD_RELOC_ARM_TLS_DESC",
"BFD_RELOC_ARM_ALU_PC_G0_NC",
"BFD_RELOC_ARM_ALU_PC_G0",
"BFD_RELOC_ARM_ALU_PC_G1_NC",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 30919f2..719eb00 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2962,6 +2962,18 @@ ENUMX
BFD_RELOC_ARM_TLS_IE32
ENUMX
BFD_RELOC_ARM_TLS_LE32
+ENUMX
+ BFD_RELOC_ARM_TLS_GOTDESC
+ENUMX
+ BFD_RELOC_ARM_TLS_CALL
+ENUMX
+ BFD_RELOC_ARM_THM_TLS_CALL
+ENUMX
+ BFD_RELOC_ARM_TLS_DESCSEQ
+ENUMX
+ BFD_RELOC_ARM_THM_TLS_DESCSEQ
+ENUMX
+ BFD_RELOC_ARM_TLS_DESC
ENUMDOC
ARM thread-local storage relocations.
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9d3d46e..63d2301 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,19 @@
+2011-01-10 Nathan Sidwell <nathan@codesourcery.com>
+ Glauber de Oliveira Costa <glommer@gmail.com>
+
+ * doc/c-arm.texi: Document TLSDESC and TLSCALL relocations, and
+ .tlsdescseq directive.
+ * config/tc-arm.c (arm_typed_reg_parse): Check for potential reloc
+ following a symbol.
+ (s_arm_tls_descseq): New directive.
+ (md_pseudo_table): Add it.
+ (encode_branch): Allow TLS_CALL relocs too.
+ (do_t_blx, do_t_branch23): Use encode_branch.
+ (reloc_names): Add tlsdesc and tlscall.
+ (md_apply_fix): Process tls desc relocations.
+ (tc_gen_reloc): Likewise.
+ (arm_fix_adjustable): Likewise.
+
2011-01-07 Quentin Neill <quentin.neill@amd.com>
* config/tc-i386.c (cpu_arch): Add CPU_BMI_FLAGS.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index f4ebdc4..ae389f5 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1472,6 +1472,10 @@ arm_typed_reg_parse (char **ccp, enum arm_reg_type type,
if (reg == FAIL)
return FAIL;
+ /* Do not allow regname(... to parse as a register. */
+ if (*str == '(')
+ return FAIL;
+
/* Do not allow a scalar (reg+index) to parse as a register. */
if ((atype.defined & NTA_HASINDEX) != 0)
{
@@ -4273,6 +4277,30 @@ s_arm_eabi_attribute (int ignored ATTRIBUTE_UNUSED)
}
#endif /* OBJ_ELF */
+/* Emit a tls fix for the symbol. */
+
+static void
+s_arm_tls_descseq (int ignored ATTRIBUTE_UNUSED)
+{
+ char *p;
+ expressionS exp;
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+#ifdef md_cons_align
+ md_cons_align (4);
+#endif
+
+ /* Since we're just labelling the code, there's no need to define a
+ mapping symbol. */
+ expression (&exp);
+ p = obstack_next_free (&frchain_now->frch_obstack);
+ fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
+ thumb_mode ? BFD_RELOC_ARM_THM_TLS_DESCSEQ
+ : BFD_RELOC_ARM_TLS_DESCSEQ);
+}
+
static void s_arm_arch (int);
static void s_arm_object_arch (int);
static void s_arm_cpu (int);
@@ -4352,6 +4380,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "setfp", s_arm_unwind_setfp, 0 },
{ "unwind_raw", s_arm_unwind_raw, 0 },
{ "eabi_attribute", s_arm_eabi_attribute, 0 },
+ { "tlsdescseq", s_arm_tls_descseq, 0 },
#else
{ "word", cons, 4},
@@ -7281,9 +7310,12 @@ encode_branch (int default_reloc)
{
if (inst.operands[0].hasreloc)
{
- constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32,
- _("the only suffix valid here is '(plt)'"));
- inst.reloc.type = BFD_RELOC_ARM_PLT32;
+ constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32
+ && inst.operands[0].imm != BFD_RELOC_ARM_TLS_CALL,
+ _("the only valid suffixes here are '(plt)' and '(tlscall)'"));
+ inst.reloc.type = inst.operands[0].imm == BFD_RELOC_ARM_PLT32
+ ? BFD_RELOC_ARM_PLT32
+ : thumb_mode ? BFD_RELOC_ARM_THM_TLS_CALL : BFD_RELOC_ARM_TLS_CALL;
}
else
inst.reloc.type = (bfd_reloc_code_real_type) default_reloc;
@@ -9655,8 +9687,7 @@ do_t_blx (void)
{
/* No register. This must be BLX(1). */
inst.instruction = 0xf000e800;
- inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
- inst.reloc.pc_rel = 1;
+ encode_branch (BFD_RELOC_THUMB_PCREL_BLX);
}
}
@@ -9734,8 +9765,15 @@ static void
do_t_branch23 (void)
{
set_it_insn_type_last ();
- inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
- inst.reloc.pc_rel = 1;
+ encode_branch (BFD_RELOC_THUMB_PCREL_BRANCH23);
+
+ /* md_apply_fix blows up with 'bl foo(PLT)' where foo is defined in
+ this file. We used to simply ignore the PLT reloc type here --
+ the branch encoding is now needed to deal with TLSCALL relocs.
+ So if we see a PLT reloc now, put it back to how it used to be to
+ keep the preexisting behaviour. */
+ if (inst.reloc.type == BFD_RELOC_ARM_PLT32)
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
#if defined(OBJ_COFF)
/* If the destination of the branch is a defined symbol which does not have
@@ -16517,7 +16555,13 @@ static struct reloc_entry reloc_names[] =
{ "tlsldo", BFD_RELOC_ARM_TLS_LDO32}, { "TLSLDO", BFD_RELOC_ARM_TLS_LDO32},
{ "gottpoff",BFD_RELOC_ARM_TLS_IE32}, { "GOTTPOFF",BFD_RELOC_ARM_TLS_IE32},
{ "tpoff", BFD_RELOC_ARM_TLS_LE32}, { "TPOFF", BFD_RELOC_ARM_TLS_LE32},
- { "got_prel", BFD_RELOC_ARM_GOT_PREL}, { "GOT_PREL", BFD_RELOC_ARM_GOT_PREL}
+ { "got_prel", BFD_RELOC_ARM_GOT_PREL}, { "GOT_PREL", BFD_RELOC_ARM_GOT_PREL},
+ { "tlsdesc", BFD_RELOC_ARM_TLS_GOTDESC},
+ { "TLSDESC", BFD_RELOC_ARM_TLS_GOTDESC},
+ { "tlscall", BFD_RELOC_ARM_TLS_CALL},
+ { "TLSCALL", BFD_RELOC_ARM_TLS_CALL},
+ { "tlsdescseq", BFD_RELOC_ARM_TLS_DESCSEQ},
+ { "TLSDESCSEQ", BFD_RELOC_ARM_TLS_DESCSEQ}
};
#endif
@@ -20835,6 +20879,14 @@ md_apply_fix (fixS * fixP,
break;
#ifdef OBJ_ELF
+ case BFD_RELOC_ARM_TLS_CALL:
+ case BFD_RELOC_ARM_THM_TLS_CALL:
+ case BFD_RELOC_ARM_TLS_DESCSEQ:
+ case BFD_RELOC_ARM_THM_TLS_DESCSEQ:
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
+
+ case BFD_RELOC_ARM_TLS_GOTDESC:
case BFD_RELOC_ARM_TLS_GD32:
case BFD_RELOC_ARM_TLS_LE32:
case BFD_RELOC_ARM_TLS_IE32:
@@ -21436,6 +21488,10 @@ tc_gen_reloc (asection *section, fixS *fixp)
return NULL;
#ifdef OBJ_ELF
+ case BFD_RELOC_ARM_TLS_CALL:
+ case BFD_RELOC_ARM_THM_TLS_CALL:
+ case BFD_RELOC_ARM_TLS_DESCSEQ:
+ case BFD_RELOC_ARM_THM_TLS_DESCSEQ:
case BFD_RELOC_ARM_GOT32:
case BFD_RELOC_ARM_GOTOFF:
case BFD_RELOC_ARM_GOT_PREL:
@@ -21481,6 +21537,7 @@ tc_gen_reloc (asection *section, fixS *fixp)
code = fixp->fx_r_type;
break;
+ case BFD_RELOC_ARM_TLS_GOTDESC:
case BFD_RELOC_ARM_TLS_GD32:
case BFD_RELOC_ARM_TLS_IE32:
case BFD_RELOC_ARM_TLS_LDM32:
@@ -21742,6 +21799,11 @@ arm_fix_adjustable (fixS * fixP)
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
|| 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
+ || fixP->fx_r_type == BFD_RELOC_ARM_THM_TLS_CALL
+ || fixP->fx_r_type == BFD_RELOC_ARM_TLS_DESCSEQ
+ || fixP->fx_r_type == BFD_RELOC_ARM_THM_TLS_DESCSEQ
|| fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
return FALSE;
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index d3cccf4..e14cc2e 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -478,6 +478,8 @@ The following relocations are supported:
@code{TLSGD},
@code{TLSLDM},
@code{TLSLDO},
+@code{TLSDESC},
+@code{TLSCALL},
@code{GOTTPOFF},
@code{GOT_PREL}
and
@@ -864,6 +866,12 @@ defined). This directive also has the added property in that it marks
the aliased symbol as being a thumb function entry point, in the same
way that the @code{.thumb_func} directive does.
+@cindex @code{.tlsdescseq} directive, ARM
+@item .tlsdescseq @var{tls-variable}
+This directive is used to annotate parts of an inlined TLS descriptor
+trampoline. Normally the trampoline is provided by the linker, and
+this directive is not needed.
+
@c UUUUUUUUUUUUUUUUUUUUUUUUUU
@cindex @code{.unreq} directive, ARM
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 67eee86..d28da8d 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-01-10 Nathan Sidwell <nathan@codesourcery.com>
+ Glauber de Oliveira Costa <glommer@gmail.com>
+
+ * gas/arm/tls.s: Add tlsdesc tests.
+ * gas/arm/tls.d: Adjust.
+
2011-01-07 H.J. Lu <hongjiu.lu@intel.com>
* gas/i386/ilp32/x86-64-arch-2.d: Add bmi flag and BMI instruction
diff --git a/gas/testsuite/gas/arm/tls.d b/gas/testsuite/gas/arm/tls.d
index 6401f29..727f8e4 100644
--- a/gas/testsuite/gas/arm/tls.d
+++ b/gas/testsuite/gas/arm/tls.d
@@ -11,15 +11,39 @@
Disassembly of section .text:
-00+0 <main>:
- 0: e1a00000 nop ; \(mov r0, r0\)
- 4: e1a00000 nop ; \(mov r0, r0\)
- 8: e1a0f00e mov pc, lr
- c: 00000000 .word 0x00000000
- c: R_ARM_TLS_GD32 a
- 10: 00000004 .word 0x00000004
- 10: R_ARM_TLS_LDM32 b
- 14: 00000008 .word 0x00000008
- 14: R_ARM_TLS_IE32 c
- 18: 00000000 .word 0x00000000
- 18: R_ARM_TLS_LE32 d
+0+00 <arm_fn>:
+ 0: e1a00000 nop ; .*
+ 0: R_ARM_TLS_DESCSEQ af
+ 4: e59f0014 ldr r0, \[pc, #20\] ; 20 .*
+ 8: fa000000 blx 8 <ae\+.*>
+ 8: R_ARM_TLS_CALL ae
+ c: e1a00000 nop ; .*
+0+10 <.arm_pool>:
+ 10: 00000008 .word 0x00000008
+ 10: R_ARM_TLS_GD32 aa
+ 14: 0000000c .word 0x0000000c
+ 14: R_ARM_TLS_LDM32 ab
+ 18: 00000010 .word 0x00000010
+ 18: R_ARM_TLS_IE32 ac
+ 1c: 00000000 .word 0x00000000
+ 1c: R_ARM_TLS_LE32 ad
+ 20: 00000018 .word 0x00000018
+ 20: R_ARM_TLS_GOTDESC ae
+0+24 <thumb_fn>:
+ 24: 46c0 nop ; .*
+ 26: 46c0 nop ; .*
+ 26: R_ARM_THM_TLS_DESCSEQ tf
+ 28: 4805 ldr r0, \[pc, #20\] ; \(40 .*\)
+ 2a: f000 e800 blx 4 <te\+0x4>
+ 2a: R_ARM_THM_TLS_CALL te
+ 2e: 46c0 nop ; .*
+ 30: 00000002 .word 0x00000002
+ 30: R_ARM_TLS_GD32 ta
+ 34: 00000006 .word 0x00000006
+ 34: R_ARM_TLS_LDM32 tb
+ 38: 0000000a .word 0x0000000a
+ 38: R_ARM_TLS_IE32 tc
+ 3c: 00000000 .word 0x00000000
+ 3c: R_ARM_TLS_LE32 td
+ 40: 00000017 .word 0x00000017
+ 40: R_ARM_TLS_GOTDESC te
diff --git a/gas/testsuite/gas/arm/tls.s b/gas/testsuite/gas/arm/tls.s
index 48722a4..96a25f5 100644
--- a/gas/testsuite/gas/arm/tls.s
+++ b/gas/testsuite/gas/arm/tls.s
@@ -1,14 +1,38 @@
.text
- .globl main
- .type main, %function
-main:
+ .arm
+ .globl arm_fn
+ .type arm_fn, %function
+arm_fn:
+1:
+.tlsdescseq af
nop
-.L2:
+ ldr r0, 1f
+2: blx ae(tlscall)
nop
- mov pc, lr
+.arm_pool:
+ .word aa(tlsgd) + (. - 1b - 8)
+ .word ab(tlsldm) + (. - 1b- 8)
+ .word ac(gottpoff) + (. - 1b - 8)
+ .word ad(tpoff)
+1: .word ae(tlsdesc) + (. - 2b)
+
+ .thumb
+ .globl thumb_fn
+ .type thumb_fn, %function
+thumb_fn:
+ nop
+1:
+.tlsdescseq tf
+ nop
+ ldr r0, 1f
+2: blx te(tlscall)
+ nop
+
+ .p2align 2
.Lpool:
- .word a(tlsgd) + (. - .L2 - 8)
- .word b(tlsldm) + (. - .L2 - 8)
- .word c(gottpoff) + (. - .L2 - 8)
- .word d(tpoff)
+ .word ta(tlsgd) + (. - 1b - 8)
+ .word tb(tlsldm) + (. - 1b - 8)
+ .word tc(gottpoff) + (. - 1b - 8)
+ .word td(tpoff)
+1: .word te(tlsdesc) + (. - 2b + 1)
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index 47a884e..d178b64 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,10 @@
+2011-01-10 Nathan Sidwell <nathan@codesourcery.com>
+ Glauber de Oliveira Costa <glommer@gmail.com>
+
+ * arm.h (R_ARM_TLS_DESC, R_ARM_TLS_GOTDESC, R_ARM_TLS_CALL,
+ R_ARM_TLS_DESCSEQ, T_ARM_THM_TLS_CALL, R_ARM_THM_TLS_DESCSEQ): New
+ relocations.
+
2010-11-11 Mingming Sun <mingm.sun@gmail.com>
* mips.h (E_MIPS_MACH_LS3A): Defined.
diff --git a/include/elf/arm.h b/include/elf/arm.h
index 0a5c87d..18aa559 100644
--- a/include/elf/arm.h
+++ b/include/elf/arm.h
@@ -123,7 +123,7 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
RELOC_NUMBER (R_ARM_THM_CALL, 10)
RELOC_NUMBER (R_ARM_THM_PC8, 11)
RELOC_NUMBER (R_ARM_BREL_ADJ, 12)
- RELOC_NUMBER (R_ARM_SWI24, 13) /* obsolete */
+ RELOC_NUMBER (R_ARM_TLS_DESC, 13)
RELOC_NUMBER (R_ARM_THM_SWI8, 14) /* obsolete */
RELOC_NUMBER (R_ARM_XPC25, 15) /* obsolete */
RELOC_NUMBER (R_ARM_THM_XPC22, 16) /* obsolete */
@@ -200,7 +200,10 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
RELOC_NUMBER (R_ARM_THM_MOVW_BREL_NC, 87)
RELOC_NUMBER (R_ARM_THM_MOVT_BREL, 88)
RELOC_NUMBER (R_ARM_THM_MOVW_BREL, 89)
- /* 90-93 unallocated */
+ RELOC_NUMBER (R_ARM_TLS_GOTDESC, 90)
+ RELOC_NUMBER (R_ARM_TLS_CALL, 91)
+ RELOC_NUMBER (R_ARM_TLS_DESCSEQ, 92)
+ RELOC_NUMBER (R_ARM_THM_TLS_CALL, 93)
RELOC_NUMBER (R_ARM_PLT32_ABS, 94)
RELOC_NUMBER (R_ARM_GOT_ABS, 95)
RELOC_NUMBER (R_ARM_GOT_PREL, 96)
@@ -221,6 +224,7 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
RELOC_NUMBER (R_ARM_TLS_IE12GP, 111)
/* 112 - 127 private range */
RELOC_NUMBER (R_ARM_ME_TOO, 128) /* obsolete */
+ RELOC_NUMBER (R_ARM_THM_TLS_DESCSEQ ,129)
/* Extensions? R=read-only? */
RELOC_NUMBER (R_ARM_RXPC25, 249)
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 0eb5106..0910af2 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,45 @@
+2011-01-10 Nathan Sidwell <nathan@codesourcery.com>
+ Glauber de Oliveira Costa <glommer@gmail.com>
+
+ * ld-arm/arm-elf.exp: Added tests for new TLS handling
+ relocations.
+ * ld-arm/tls-descrelax-be32.d: New.
+ * ld-arm/tls-descrelax-be32.s: New.
+ * ld-arm/tls-descrelax-be8.d: New.
+ * ld-arm/tls-descrelax-be8.s: New.
+ * ld-arm/tls-descrelax-v7.d: New.
+ * ld-arm/tls-descrelax-v7.s: New.
+ * ld-arm/tls-descrelax.d: New.
+ * ld-arm/tls-descrelax.s: New.
+ * ld-arm/tls-descseq.d: New.
+ * ld-arm/tls-descseq.r: New.
+ * ld-arm/tls-descseq.s: New.
+ * ld-arm/tls-gdesc-got.d: New.
+ * ld-arm/tls-gdesc-got.s: New.
+ * ld-arm/tls-gdesc-nlazy.g: New.
+ * ld-arm/tls-gdesc-nlazy.s: New.
+ * ld-arm/tls-gdesc.d: New.
+ * ld-arm/tls-gdesc.r: New.
+ * ld-arm/tls-gdesc.s: New.
+ * ld-arm/tls-gdierelax.d: New.
+ * ld-arm/tls-gdierelax.s: New.
+ * ld-arm/tls-gdierelax2.d: New.
+ * ld-arm/tls-gdierelax2.s: New.
+ * ld-arm/tls-gdlerelax.d: New.
+ * ld-arm/tls-gdlerelax.s: New.
+ * ld-arm/tls-lib-loc.d: New.
+ * ld-arm/tls-lib-loc.r: New.
+ * ld-arm/tls-lib-loc.s: New.
+ * ld-arm/tls-longplt-lib.d: New.
+ * ld-arm/tls-longplt-lib.s: New.
+ * ld-arm/tls-longplt.d: New.
+ * ld-arm/tls-longplt.s: New.
+ * ld-arm/tls-mixed.r: New.
+ * ld-arm/tls-mixed.s: New.
+ * ld-arm/tls-thumb1.d: New.
+ * ld-arm/tls-thumb1.s: New.
+ * ld-arm/arm-elf.exp: New.
+
2011-01-08 Nick Clifton <nickc@redhat.com>
* ld-misc/defsym1.d: Add a -e linker command line option.
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 80f521e..9ba7b56 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -135,6 +135,39 @@ set armelftests {
{"TLS dynamic application" "-T arm-dyn.ld tmpdir/tls-lib.so" "" {tls-app.s}
{{objdump -fdw tls-app.d} {objdump -Rw tls-app.r}}
"tls-app"}
+ {"TLS gnu shared library got" "-shared -T arm-dyn.ld" "" {tls-gdesc-got.s}
+ {{objdump "-fDR -j .got" tls-gdesc-got.d}}
+ "tls-lib2-got.so"}
+ {"TLS gnu shared library inlined trampoline" "-shared -T arm-dyn.ld" "" {tls-descseq.s}
+ {{objdump -fdw tls-descseq.d} {objdump -Rw tls-descseq.r}}
+ "tls-lib2inline.so"}
+ {"TLS shared library gdesc local" "-shared -T arm-dyn.ld" "" {tls-lib-loc.s}
+ {{objdump -fdw tls-lib-loc.d} {objdump -Rw tls-lib-loc.r}}
+ "tls-lib-loc.so"}
+ {"TLS gnu GD to IE relaxation" "-static -T arm-dyn.ld" "" {tls-gdierelax.s}
+ {{objdump -fdw tls-gdierelax.d}}
+ "tls-app-rel-ie"}
+ {"TLS gnu GD to IE shared relaxation" "-shared -T arm-dyn.ld" "" {tls-gdierelax2.s}
+ {{objdump -fdw tls-gdierelax2.d}}
+ "tls-app-rel-ie2"}
+ {"TLS gnu GD to LE relaxation" "-T arm-dyn.ld" "" {tls-gdlerelax.s}
+ {{objdump -fdw tls-gdlerelax.d}}
+ "tls-app-rel-le"}
+ {"TLS mixed models shared lib" "-shared -T arm-dyn.ld" "" {tls-mixed.s}
+ {{objdump -Rw tls-mixed.r}}
+ "tls-mixed.so"}
+ {"TLS descseq relaxation" "-T arm-dyn.ld" "" {tls-descrelax.s}
+ {{objdump -fdw tls-descrelax.d}}
+ "tls-descrelax"}
+ {"TLS descseq relaxation v7" "-T arm-dyn.ld" "" {tls-descrelax-v7.s}
+ {{objdump -fdw tls-descrelax-v7.d}}
+ "tls-descrelax-v7"}
+ {"TLS descseq relaxation BE8" "-T arm-dyn.ld -EB --be8" "-mbig-endian" {tls-descrelax-be8.s}
+ {{objdump -fdw tls-descrelax-be8.d}}
+ "tls-descrelax-be8"}
+ {"TLS descseq relaxation BE32" "-T arm-dyn.ld -EB" "-mbig-endian" {tls-descrelax-be32.s}
+ {{objdump -fdw tls-descrelax-be32.d}}
+ "tls-descrelax-be32"}
{"Thumb entry point" "-T arm.ld" "" {thumb-entry.s}
{{readelf -h thumb-entry.d}}
"thumb-entry"}
@@ -481,6 +514,21 @@ set armeabitests {
{jump-reloc-veneers.s}
{{objdump -d jump-reloc-veneers-long.d}}
"jump-reloc-veneers-long"}
+ {"TLS gnu shared library" "-shared -T arm-dyn.ld" "" {tls-gdesc.s}
+ {{objdump -fdw tls-gdesc.d} {objdump -Rw tls-gdesc.r}}
+ "tls-lib2.so"}
+ {"TLS gnu shared library non-lazy" "-z now -shared -T arm-dyn.ld" "" {tls-gdesc.s}
+ {{readelf "-x .got" tls-gdesc-nlazy.g}}
+ "tls-lib2-nlazy.so"}
+ {"TLS long plt library" "-shared -T arm-dyn.ld --section-start .foo=0x4001000" "" {tls-longplt-lib.s}
+ {{objdump -fdw tls-longplt-lib.d}}
+ "tls-longplt-lib.so"}
+ {"TLS long plt" "-T arm-dyn.ld --section-start .foo=0x4001000 tmpdir/tls-longplt-lib.so" "" {tls-longplt.s}
+ {{objdump -fdw tls-longplt.d}}
+ "tls-longplt"}
+ {"TLS thumb1" "-shared -T arm-dyn.ld --section-start .foo=0x4001000" "" {tls-thumb1.s}
+ {{objdump -fdw tls-thumb1.d}}
+ "tls-thumb1"}
}
run_ld_link_tests $armeabitests
diff --git a/ld/testsuite/ld-arm/tls-descrelax-be32.d b/ld/testsuite/ld-arm/tls-descrelax-be32.d
new file mode 100644
index 0000000..150e331
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax-be32.d
@@ -0,0 +1,108 @@
+.*: file format elf32-.*
+architecture: arm, flags 0x[0-9a-f]+:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+00008000 <foo>:
+ 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c <foo\+0xc>
+ 8004: e79f0000 ldr r0, \[pc, r0\]
+ 8008: e1a00000 nop ; .*
+ 800c: 00008138 .word 0x00008138
+ 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c <foo\+0x1c>
+ 8014: e79f0000 ldr r0, \[pc, r0\]
+ 8018: e1a00000 nop ; .*
+ 801c: 00008128 .word 0x00008128
+ 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c <foo\+0x2c>
+ 8024: e1a00000 nop ; .*
+ 8028: e1a00000 nop ; .*
+ 802c: 0000000c .word 0x0000000c
+ 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c <foo\+0x3c>
+ 8034: e1a00000 nop ; .*
+ 8038: e1a00000 nop ; .*
+ 803c: 0000000c .word 0x0000000c
+ 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 <foo\+0x54>
+ 8044: e08f0000 add r0, pc, r0
+ 8048: e5901000 ldr r1, \[r0\]
+ 804c: e1a00001 mov r0, r1
+ 8050: e1a00000 nop ; .*
+ 8054: 000080f8 .word 0x000080f8
+ 8058: e59f000c ldr r0, \[pc, #12\] ; 806c <foo\+0x6c>
+ 805c: e08f0000 add r0, pc, r0
+ 8060: e5901000 ldr r1, \[r0\]
+ 8064: e1a00001 mov r0, r1
+ 8068: e1a00000 nop ; .*
+ 806c: 000080e0 .word 0x000080e0
+ 8070: e59f000c ldr r0, \[pc, #12\] ; 8084 <foo\+0x84>
+ 8074: e1a00000 nop ; .*
+ 8078: e1a00000 nop ; .*
+ 807c: e1a00000 nop ; .*
+ 8080: e1a00000 nop ; .*
+ 8084: 0000000c .word 0x0000000c
+ 8088: e59f000c ldr r0, \[pc, #12\] ; 809c <foo\+0x9c>
+ 808c: e1a00000 nop ; .*
+ 8090: e1a00000 nop ; .*
+ 8094: e1a00000 nop ; .*
+ 8098: e1a00000 nop ; .*
+ 809c: 0000000c .word 0x0000000c
+
+000080a0 <bar>:
+ 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 <bar\+0x8>\)
+ 80a2: 4478 add r0, pc
+ 80a4: 6800 ldr r0, \[r0, #0\]
+ 80a6: 46c0 nop ; .*
+ 80a8: 0000809e .word 0x0000809e
+ 80ac: 4801 ldr r0, \[pc, #4\] ; \(80b4 <bar\+0x14>\)
+ 80ae: 4478 add r0, pc
+ 80b0: 6800 ldr r0, \[r0, #0\]
+ 80b2: 46c0 nop ; .*
+ 80b4: 00008092 .word 0x00008092
+ 80b8: 4801 ldr r0, \[pc, #4\] ; \(80c0 <bar\+0x20>\)
+ 80ba: 4478 add r0, pc
+ 80bc: 6800 ldr r0, \[r0, #0\]
+ 80be: 46c0 nop ; .*
+ 80c0: 0000808a .word 0x0000808a
+ 80c4: 4801 ldr r0, \[pc, #4\] ; \(80cc <bar\+0x2c>\)
+ 80c6: 46c0 nop ; .*
+ 80c8: 46c0 nop ; .*
+ 80ca: 46c0 nop ; .*
+ 80cc: 0000000c .word 0x0000000c
+ 80d0: 4801 ldr r0, \[pc, #4\] ; \(80d8 <bar\+0x38>\)
+ 80d2: bf00 nop
+ 80d4: bf00 nop
+ 80d6: 46c0 nop ; .*
+ 80d8: 0000000c .word 0x0000000c
+ 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 <bar\+0x44>\)
+ 80de: bf00 nop
+ 80e0: bf00 nop
+ 80e2: 46c0 nop ; .*
+ 80e4: 00000014 .word 0x00000014
+ 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 <bar\+0x54>\)
+ 80ea: 4478 add r0, pc
+ 80ec: 6801 ldr r1, \[r0, #0\]
+ 80ee: 1c08 adds r0, r1, #0
+ 80f0: 46c0 nop ; .*
+ 80f2: 46c0 nop ; .*
+ 80f4: 00008056 .word 0x00008056
+ 80f8: 4802 ldr r0, \[pc, #8\] ; \(8104 <bar\+0x64>\)
+ 80fa: 4478 add r0, pc
+ 80fc: 6801 ldr r1, \[r0, #0\]
+ 80fe: 4608 mov r0, r1
+ 8100: 46c0 nop ; .*
+ 8102: 46c0 nop ; .*
+ 8104: 00008046 .word 0x00008046
+ 8108: 4802 ldr r0, \[pc, #8\] ; \(8114 <bar\+0x74>\)
+ 810a: 46c0 nop ; .*
+ 810c: 46c0 nop ; .*
+ 810e: 46c0 nop ; .*
+ 8110: 46c0 nop ; .*
+ 8112: 46c0 nop ; .*
+ 8114: 0000000c .word 0x0000000c
+ 8118: 4802 ldr r0, \[pc, #8\] ; \(8124 <bar\+0x84>\)
+ 811a: 46c0 nop ; .*
+ 811c: 46c0 nop ; .*
+ 811e: 46c0 nop ; .*
+ 8120: 46c0 nop ; .*
+ 8122: 46c0 nop ; .*
+ 8124: 0000000c .word 0x0000000c
diff --git a/ld/testsuite/ld-arm/tls-descrelax-be32.s b/ld/testsuite/ld-arm/tls-descrelax-be32.s
new file mode 100644
index 0000000..dae5458
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax-be32.s
@@ -0,0 +1,198 @@
+@ we can relax local and non-weak globals for non-shared links
+
+ .arch armv5te
+ .text
+ .arm
+
+ .p2align 2
+foo:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: ldr r0, [pc, r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc, r0
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc, r0
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc, r0
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+
+ .thumb
+ .p2align 1
+bar:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: add r0, pc, r0
+ ldr r0, [r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx r1(tlscall)
+ nop
+ .p2align 2
+1: .word r1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx r0(tlscall)
+ nop
+ .p2align 2
+1: .word r0(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .global gd1
+gd1: .space 4
+ld1: .space 4
+ .globl r1
+r1: .space 4
+r0: .space 4
diff --git a/ld/testsuite/ld-arm/tls-descrelax-be8.d b/ld/testsuite/ld-arm/tls-descrelax-be8.d
new file mode 100644
index 0000000..1b2159c
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax-be8.d
@@ -0,0 +1,108 @@
+.*: file format elf32-.*
+architecture: arm, flags 0x[0-9a-f]+:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+00008000 <foo>:
+ 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c <foo\+0xc>
+ 8004: e79f0000 ldr r0, \[pc, r0\]
+ 8008: e320f000 nop \{0\}
+ 800c: 00008138 .word 0x00008138
+ 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c <foo\+0x1c>
+ 8014: e79f0000 ldr r0, \[pc, r0\]
+ 8018: e320f000 nop \{0\}
+ 801c: 00008128 .word 0x00008128
+ 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c <foo\+0x2c>
+ 8024: e320f000 nop \{0\}
+ 8028: e320f000 nop \{0\}
+ 802c: 0000000c .word 0x0000000c
+ 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c <foo\+0x3c>
+ 8034: e1a00000 nop ; .*
+ 8038: e320f000 nop \{0\}
+ 803c: 0000000c .word 0x0000000c
+ 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 <foo\+0x54>
+ 8044: e08f0000 add r0, pc, r0
+ 8048: e5901000 ldr r1, \[r0\]
+ 804c: e1a00001 mov r0, r1
+ 8050: e320f000 nop \{0\}
+ 8054: 000080f8 .word 0x000080f8
+ 8058: e59f000c ldr r0, \[pc, #12\] ; 806c <foo\+0x6c>
+ 805c: e08f0000 add r0, pc, r0
+ 8060: e5901000 ldr r1, \[r0\]
+ 8064: e1a00001 mov r0, r1
+ 8068: e320f000 nop \{0\}
+ 806c: 000080e0 .word 0x000080e0
+ 8070: e59f000c ldr r0, \[pc, #12\] ; 8084 <foo\+0x84>
+ 8074: e320f000 nop \{0\}
+ 8078: e320f000 nop \{0\}
+ 807c: e320f000 nop \{0\}
+ 8080: e320f000 nop \{0\}
+ 8084: 0000000c .word 0x0000000c
+ 8088: e59f000c ldr r0, \[pc, #12\] ; 809c <foo\+0x9c>
+ 808c: e1a00000 nop ; .*
+ 8090: e1a00000 nop ; .*
+ 8094: e1a00000 nop ; .*
+ 8098: e320f000 nop \{0\}
+ 809c: 0000000c .word 0x0000000c
+
+000080a0 <bar>:
+ 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 <bar\+0x8>\)
+ 80a2: 4478 add r0, pc
+ 80a4: 6800 ldr r0, \[r0, #0\]
+ 80a6: 46c0 nop ; .*
+ 80a8: 0000809e .word 0x0000809e
+ 80ac: 4801 ldr r0, \[pc, #4\] ; \(80b4 <bar\+0x14>\)
+ 80ae: 4478 add r0, pc
+ 80b0: 6800 ldr r0, \[r0, #0\]
+ 80b2: 46c0 nop ; \(mov r8, r8\)
+ 80b4: 00008092 .word 0x00008092
+ 80b8: 4801 ldr r0, \[pc, #4\] ; \(80c0 <bar\+0x20>\)
+ 80ba: 4478 add r0, pc
+ 80bc: 6800 ldr r0, \[r0, #0\]
+ 80be: 46c0 nop ; \(mov r8, r8\)
+ 80c0: 0000808a .word 0x0000808a
+ 80c4: 4801 ldr r0, \[pc, #4\] ; \(80cc <bar\+0x2c>\)
+ 80c6: 46c0 nop ; \(mov r8, r8\)
+ 80c8: 46c0 nop ; \(mov r8, r8\)
+ 80ca: bf00 nop
+ 80cc: 0000000c .word 0x0000000c
+ 80d0: 4801 ldr r0, \[pc, #4\] ; \(80d8 <bar\+0x38>\)
+ 80d2: (f3af 8000)|(bf00 ) nop(.w)?
+#...
+ 80d6: 46c0 nop ; \(mov r8, r8\)
+ 80d8: 0000000c .word 0x0000000c
+ 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 <bar\+0x44>\)
+ 80de: (f3af 8000)|(bf00 ) nop(.w)?
+#...
+ 80e2: 46c0 nop ; \(mov r8, r8\)
+ 80e4: 00000014 .word 0x00000014
+ 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 <bar\+0x54>\)
+ 80ea: 4478 add r0, pc
+ 80ec: 6801 ldr r1, \[r0, #0\]
+ 80ee: 1c08 adds r0, r1, #0
+ 80f0: 46c0 nop ; \(mov r8, r8\)
+ 80f2: bf00 nop
+ 80f4: 00008056 .word 0x00008056
+ 80f8: 4802 ldr r0, \[pc, #8\] ; \(8104 <bar\+0x64>\)
+ 80fa: 4478 add r0, pc
+ 80fc: 6801 ldr r1, \[r0, #0\]
+ 80fe: 4608 mov r0, r1
+ 8100: 46c0 nop ; \(mov r8, r8\)
+ 8102: bf00 nop
+ 8104: 00008046 .word 0x00008046
+ 8108: 4802 ldr r0, \[pc, #8\] ; \(8114 <bar\+0x74>\)
+ 810a: 46c0 nop ; \(mov r8, r8\)
+ 810c: 46c0 nop ; \(mov r8, r8\)
+ 810e: 46c0 nop ; \(mov r8, r8\)
+ 8110: 46c0 nop ; \(mov r8, r8\)
+ 8112: bf00 nop
+ 8114: 0000000c .word 0x0000000c
+ 8118: 4802 ldr r0, \[pc, #8\] ; \(8124 <bar\+0x84>\)
+ 811a: 46c0 nop ; \(mov r8, r8\)
+ 811c: 46c0 nop ; \(mov r8, r8\)
+ 811e: 46c0 nop ; \(mov r8, r8\)
+ 8120: 46c0 nop ; \(mov r8, r8\)
+ 8122: bf00 nop
+ 8124: 0000000c .word 0x0000000c
diff --git a/ld/testsuite/ld-arm/tls-descrelax-be8.s b/ld/testsuite/ld-arm/tls-descrelax-be8.s
new file mode 100644
index 0000000..a8c028b
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax-be8.s
@@ -0,0 +1,198 @@
+@ we can relax local and non-weak globals for non-shared links
+
+ .arch armv7-a
+ .text
+ .arm
+
+ .p2align 2
+foo:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: ldr r0, [pc, r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc, r0
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc, r0
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc, r0
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+
+ .thumb
+ .p2align 1
+bar:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: add r0, pc, r0
+ ldr r0, [r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx r1(tlscall)
+ nop
+ .p2align 2
+1: .word r1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx r0(tlscall)
+ nop
+ .p2align 2
+1: .word r0(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .global gd1
+gd1: .space 4
+ld1: .space 4
+ .globl r1
+r1: .space 4
+r0: .space 4
diff --git a/ld/testsuite/ld-arm/tls-descrelax-v7.d b/ld/testsuite/ld-arm/tls-descrelax-v7.d
new file mode 100644
index 0000000..1b2159c
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax-v7.d
@@ -0,0 +1,108 @@
+.*: file format elf32-.*
+architecture: arm, flags 0x[0-9a-f]+:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+00008000 <foo>:
+ 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c <foo\+0xc>
+ 8004: e79f0000 ldr r0, \[pc, r0\]
+ 8008: e320f000 nop \{0\}
+ 800c: 00008138 .word 0x00008138
+ 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c <foo\+0x1c>
+ 8014: e79f0000 ldr r0, \[pc, r0\]
+ 8018: e320f000 nop \{0\}
+ 801c: 00008128 .word 0x00008128
+ 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c <foo\+0x2c>
+ 8024: e320f000 nop \{0\}
+ 8028: e320f000 nop \{0\}
+ 802c: 0000000c .word 0x0000000c
+ 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c <foo\+0x3c>
+ 8034: e1a00000 nop ; .*
+ 8038: e320f000 nop \{0\}
+ 803c: 0000000c .word 0x0000000c
+ 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 <foo\+0x54>
+ 8044: e08f0000 add r0, pc, r0
+ 8048: e5901000 ldr r1, \[r0\]
+ 804c: e1a00001 mov r0, r1
+ 8050: e320f000 nop \{0\}
+ 8054: 000080f8 .word 0x000080f8
+ 8058: e59f000c ldr r0, \[pc, #12\] ; 806c <foo\+0x6c>
+ 805c: e08f0000 add r0, pc, r0
+ 8060: e5901000 ldr r1, \[r0\]
+ 8064: e1a00001 mov r0, r1
+ 8068: e320f000 nop \{0\}
+ 806c: 000080e0 .word 0x000080e0
+ 8070: e59f000c ldr r0, \[pc, #12\] ; 8084 <foo\+0x84>
+ 8074: e320f000 nop \{0\}
+ 8078: e320f000 nop \{0\}
+ 807c: e320f000 nop \{0\}
+ 8080: e320f000 nop \{0\}
+ 8084: 0000000c .word 0x0000000c
+ 8088: e59f000c ldr r0, \[pc, #12\] ; 809c <foo\+0x9c>
+ 808c: e1a00000 nop ; .*
+ 8090: e1a00000 nop ; .*
+ 8094: e1a00000 nop ; .*
+ 8098: e320f000 nop \{0\}
+ 809c: 0000000c .word 0x0000000c
+
+000080a0 <bar>:
+ 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 <bar\+0x8>\)
+ 80a2: 4478 add r0, pc
+ 80a4: 6800 ldr r0, \[r0, #0\]
+ 80a6: 46c0 nop ; .*
+ 80a8: 0000809e .word 0x0000809e
+ 80ac: 4801 ldr r0, \[pc, #4\] ; \(80b4 <bar\+0x14>\)
+ 80ae: 4478 add r0, pc
+ 80b0: 6800 ldr r0, \[r0, #0\]
+ 80b2: 46c0 nop ; \(mov r8, r8\)
+ 80b4: 00008092 .word 0x00008092
+ 80b8: 4801 ldr r0, \[pc, #4\] ; \(80c0 <bar\+0x20>\)
+ 80ba: 4478 add r0, pc
+ 80bc: 6800 ldr r0, \[r0, #0\]
+ 80be: 46c0 nop ; \(mov r8, r8\)
+ 80c0: 0000808a .word 0x0000808a
+ 80c4: 4801 ldr r0, \[pc, #4\] ; \(80cc <bar\+0x2c>\)
+ 80c6: 46c0 nop ; \(mov r8, r8\)
+ 80c8: 46c0 nop ; \(mov r8, r8\)
+ 80ca: bf00 nop
+ 80cc: 0000000c .word 0x0000000c
+ 80d0: 4801 ldr r0, \[pc, #4\] ; \(80d8 <bar\+0x38>\)
+ 80d2: (f3af 8000)|(bf00 ) nop(.w)?
+#...
+ 80d6: 46c0 nop ; \(mov r8, r8\)
+ 80d8: 0000000c .word 0x0000000c
+ 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 <bar\+0x44>\)
+ 80de: (f3af 8000)|(bf00 ) nop(.w)?
+#...
+ 80e2: 46c0 nop ; \(mov r8, r8\)
+ 80e4: 00000014 .word 0x00000014
+ 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 <bar\+0x54>\)
+ 80ea: 4478 add r0, pc
+ 80ec: 6801 ldr r1, \[r0, #0\]
+ 80ee: 1c08 adds r0, r1, #0
+ 80f0: 46c0 nop ; \(mov r8, r8\)
+ 80f2: bf00 nop
+ 80f4: 00008056 .word 0x00008056
+ 80f8: 4802 ldr r0, \[pc, #8\] ; \(8104 <bar\+0x64>\)
+ 80fa: 4478 add r0, pc
+ 80fc: 6801 ldr r1, \[r0, #0\]
+ 80fe: 4608 mov r0, r1
+ 8100: 46c0 nop ; \(mov r8, r8\)
+ 8102: bf00 nop
+ 8104: 00008046 .word 0x00008046
+ 8108: 4802 ldr r0, \[pc, #8\] ; \(8114 <bar\+0x74>\)
+ 810a: 46c0 nop ; \(mov r8, r8\)
+ 810c: 46c0 nop ; \(mov r8, r8\)
+ 810e: 46c0 nop ; \(mov r8, r8\)
+ 8110: 46c0 nop ; \(mov r8, r8\)
+ 8112: bf00 nop
+ 8114: 0000000c .word 0x0000000c
+ 8118: 4802 ldr r0, \[pc, #8\] ; \(8124 <bar\+0x84>\)
+ 811a: 46c0 nop ; \(mov r8, r8\)
+ 811c: 46c0 nop ; \(mov r8, r8\)
+ 811e: 46c0 nop ; \(mov r8, r8\)
+ 8120: 46c0 nop ; \(mov r8, r8\)
+ 8122: bf00 nop
+ 8124: 0000000c .word 0x0000000c
diff --git a/ld/testsuite/ld-arm/tls-descrelax-v7.s b/ld/testsuite/ld-arm/tls-descrelax-v7.s
new file mode 100644
index 0000000..a8c028b
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax-v7.s
@@ -0,0 +1,198 @@
+@ we can relax local and non-weak globals for non-shared links
+
+ .arch armv7-a
+ .text
+ .arm
+
+ .p2align 2
+foo:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: ldr r0, [pc, r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc, r0
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc, r0
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc, r0
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+
+ .thumb
+ .p2align 1
+bar:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: add r0, pc, r0
+ ldr r0, [r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx r1(tlscall)
+ nop
+ .p2align 2
+1: .word r1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx r0(tlscall)
+ nop
+ .p2align 2
+1: .word r0(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .global gd1
+gd1: .space 4
+ld1: .space 4
+ .globl r1
+r1: .space 4
+r0: .space 4
diff --git a/ld/testsuite/ld-arm/tls-descrelax.d b/ld/testsuite/ld-arm/tls-descrelax.d
new file mode 100644
index 0000000..9b06d6a
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax.d
@@ -0,0 +1,108 @@
+.*: file format elf32-.*
+architecture: arm, flags 0x[0-9a-f]+:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+00008000 <foo>:
+ 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c <foo\+0xc>
+ 8004: e79f0000 ldr r0, \[pc, r0\]
+ 8008: e1a00000 nop ; \(mov r0, r0\)
+ 800c: 00008138 .word 0x00008138
+ 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c <foo\+0x1c>
+ 8014: e79f0000 ldr r0, \[pc, r0\]
+ 8018: e1a00000 nop ; \(mov r0, r0\)
+ 801c: 00008128 .word 0x00008128
+ 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c <foo\+0x2c>
+ 8024: e1a00000 nop ; \(mov r0, r0\)
+ 8028: e1a00000 nop ; \(mov r0, r0\)
+ 802c: 0000000c .word 0x0000000c
+ 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c <foo\+0x3c>
+ 8034: e1a00000 nop ; \(mov r0, r0\)
+ 8038: e1a00000 nop ; \(mov r0, r0\)
+ 803c: 0000000c .word 0x0000000c
+ 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 <foo\+0x54>
+ 8044: e08f0000 add r0, pc, r0
+ 8048: e5901000 ldr r1, \[r0\]
+ 804c: e1a00001 mov r0, r1
+ 8050: e1a00000 nop ; \(mov r0, r0\)
+ 8054: 000080f8 .word 0x000080f8
+ 8058: e59f000c ldr r0, \[pc, #12\] ; 806c <foo\+0x6c>
+ 805c: e08f0000 add r0, pc, r0
+ 8060: e5901000 ldr r1, \[r0\]
+ 8064: e1a00001 mov r0, r1
+ 8068: e1a00000 nop ; \(mov r0, r0\)
+ 806c: 000080e0 .word 0x000080e0
+ 8070: e59f000c ldr r0, \[pc, #12\] ; 8084 <foo\+0x84>
+ 8074: e1a00000 nop ; \(mov r0, r0\)
+ 8078: e1a00000 nop ; \(mov r0, r0\)
+ 807c: e1a00000 nop ; \(mov r0, r0\)
+ 8080: e1a00000 nop ; \(mov r0, r0\)
+ 8084: 0000000c .word 0x0000000c
+ 8088: e59f000c ldr r0, \[pc, #12\] ; 809c <foo\+0x9c>
+ 808c: e1a00000 nop ; \(mov r0, r0\)
+ 8090: e1a00000 nop ; \(mov r0, r0\)
+ 8094: e1a00000 nop ; \(mov r0, r0\)
+ 8098: e1a00000 nop ; \(mov r0, r0\)
+ 809c: 0000000c .word 0x0000000c
+
+000080a0 <bar>:
+ 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 <bar\+0x8>\)
+ 80a2: 4478 add r0, pc
+ 80a4: 6800 ldr r0, \[r0, #0\]
+ 80a6: 46c0 nop ; \(mov r8, r8\)
+ 80a8: 0000809e .word 0x0000809e
+ 80ac: 4801 ldr r0, \[pc, #4\] ; \(80b4 <bar\+0x14>\)
+ 80ae: 4478 add r0, pc
+ 80b0: 6800 ldr r0, \[r0, #0\]
+ 80b2: 46c0 nop ; \(mov r8, r8\)
+ 80b4: 00008092 .word 0x00008092
+ 80b8: 4801 ldr r0, \[pc, #4\] ; \(80c0 <bar\+0x20>\)
+ 80ba: 4478 add r0, pc
+ 80bc: 6800 ldr r0, \[r0, #0\]
+ 80be: 46c0 nop ; \(mov r8, r8\)
+ 80c0: 0000808a .word 0x0000808a
+ 80c4: 4801 ldr r0, \[pc, #4\] ; \(80cc <bar\+0x2c>\)
+ 80c6: 46c0 nop ; \(mov r8, r8\)
+ 80c8: 46c0 nop ; \(mov r8, r8\)
+ 80ca: 46c0 nop ; \(mov r8, r8\)
+ 80cc: 0000000c .word 0x0000000c
+ 80d0: 4801 ldr r0, \[pc, #4\] ; \(80d8 <bar\+0x38>\)
+ 80d2: bf00 nop
+ 80d4: bf00 nop
+ 80d6: 46c0 nop ; \(mov r8, r8\)
+ 80d8: 0000000c .word 0x0000000c
+ 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 <bar\+0x44>\)
+ 80de: bf00 nop
+ 80e0: bf00 nop
+ 80e2: 46c0 nop ; \(mov r8, r8\)
+ 80e4: 00000014 .word 0x00000014
+ 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 <bar\+0x54>\)
+ 80ea: 4478 add r0, pc
+ 80ec: 6801 ldr r1, \[r0, #0\]
+ 80ee: 1c08 adds r0, r1, #0
+ 80f0: 46c0 nop ; \(mov r8, r8\)
+ 80f2: 46c0 nop ; \(mov r8, r8\)
+ 80f4: 00008056 .word 0x00008056
+ 80f8: 4802 ldr r0, \[pc, #8\] ; \(8104 <bar\+0x64>\)
+ 80fa: 4478 add r0, pc
+ 80fc: 6801 ldr r1, \[r0, #0\]
+ 80fe: 4608 mov r0, r1
+ 8100: 46c0 nop ; \(mov r8, r8\)
+ 8102: 46c0 nop ; \(mov r8, r8\)
+ 8104: 00008046 .word 0x00008046
+ 8108: 4802 ldr r0, \[pc, #8\] ; \(8114 <bar\+0x74>\)
+ 810a: 46c0 nop ; \(mov r8, r8\)
+ 810c: 46c0 nop ; \(mov r8, r8\)
+ 810e: 46c0 nop ; \(mov r8, r8\)
+ 8110: 46c0 nop ; \(mov r8, r8\)
+ 8112: 46c0 nop ; \(mov r8, r8\)
+ 8114: 0000000c .word 0x0000000c
+ 8118: 4802 ldr r0, \[pc, #8\] ; \(8124 <bar\+0x84>\)
+ 811a: 46c0 nop ; \(mov r8, r8\)
+ 811c: 46c0 nop ; \(mov r8, r8\)
+ 811e: 46c0 nop ; \(mov r8, r8\)
+ 8120: 46c0 nop ; \(mov r8, r8\)
+ 8122: 46c0 nop ; \(mov r8, r8\)
+ 8124: 0000000c .word 0x0000000c
diff --git a/ld/testsuite/ld-arm/tls-descrelax.s b/ld/testsuite/ld-arm/tls-descrelax.s
new file mode 100644
index 0000000..826f169
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descrelax.s
@@ -0,0 +1,197 @@
+@ we can relax local and non-weak globals for non-shared links
+
+ .text
+ .arm
+
+ .p2align 2
+foo:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: ldr r0, [pc, r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc, r0
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 8)
+
+ .p2align 2
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc, r0
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b)
+
+ .p2align 2
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 2
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc, r0
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b)
+
+
+ .thumb
+ .p2align 1
+bar:
+@tlscall global, manually relaxed to IE
+ ldr r0, 1f
+2: add r0, pc, r0
+ ldr r0, [r0]
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx gd1(tlscall)
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall global, should relax to IE
+ ldr r0, 1f
+2: blx r1(tlscall)
+ nop
+ .p2align 2
+1: .word r1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, manually relaxed to LE
+ ldr r0, 1f
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx ld1(tlscall)
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@tlscall local, should relax to LE
+ ldr r0, 1f
+2: blx r0(tlscall)
+ nop
+ .p2align 2
+1: .word r0(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded global, manually relaxed to IE
+ ldr r0, 1f
+2:
+ add r0, pc
+ ldr r1, [r0]
+ mov r0, r1
+ nop
+ .p2align 2
+1: .word gd1(gottpoff) + (. - 2b - 4)
+
+ .p2align 1
+@open coded global, should relax to IE
+ ldr r0, 1f
+2:
+.tlsdescseq gd1
+ add r0, pc
+.tlsdescseq gd1
+ ldr r1, [r0,#4]
+.tlsdescseq gd1
+ blx r1
+ nop
+ .p2align 2
+1: .word gd1(tlsdesc) + (. - 2b + 1)
+
+ .p2align 1
+@open coded local, manually relaxed to LE
+ ldr r0, 1f
+2:
+ nop
+ nop
+ nop
+ nop
+ .p2align 2
+1: .word ld1(tpoff)
+
+ .p2align 1
+@open coded local, should relax to LE
+ ldr r0, 1f
+2:
+.tlsdescseq ld1
+ add r0, pc
+.tlsdescseq ld1
+ ldr r1, [r0,#4]
+.tlsdescseq ld1
+ blx r1
+ nop
+ .p2align 2
+1: .word ld1(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .global gd1
+gd1: .space 4
+ld1: .space 4
+ .globl r1
+r1: .space 4
+r0: .space 4
diff --git a/ld/testsuite/ld-arm/tls-descseq.d b/ld/testsuite/ld-arm/tls-descseq.d
new file mode 100644
index 0000000..1a04bb0
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descseq.d
@@ -0,0 +1,44 @@
+
+tmpdir/tls-lib2inline.so: file format elf32-.*arm
+architecture: arm, flags 0x[0-9a-f]+:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .plt:
+
+[0-9a-f]+ <.plt>:
+ [0-9a-f]+: e52de004 push {lr} ; .*
+ [0-9a-f]+: e59fe004 ldr lr, \[pc, #4\] ; .*
+ [0-9a-f]+: e08fe00e add lr, pc, lr
+ [0-9a-f]+: e5bef008 ldr pc, \[lr, #8\]!
+ [0-9a-f]+: 000080e4 .word 0x000080e4
+ [0-9a-f]+: e08e0000 add r0, lr, r0
+ [0-9a-f]+: e5901004 ldr r1, \[r0, #4\]
+ [0-9a-f]+: e12fff11 bx r1
+ [0-9a-f]+: e52d2004 push {r2} ; .*
+ [0-9a-f]+: e59f200c ldr r2, \[pc, #12\] ; .*
+ [0-9a-f]+: e59f100c ldr r1, \[pc, #12\] ; .*
+ [0-9a-f]+: e79f2002 ldr r2, \[pc, r2\]
+ [0-9a-f]+: e081100f add r1, r1, pc
+ [0-9a-f]+: e12fff12 bx r2
+ [0-9a-f]+: 000080d4 .word 0x000080d4
+ [0-9a-f]+: 000080bc .word 0x000080bc
+
+Disassembly of section .text:
+
+[0-9a-f]+ <foo>:
+ [0-9a-f]+: e59f000c ldr r0, \[pc, #12\] ; .*
+ [0-9a-f]+: e08f0000 add r0, pc, r0
+ [0-9a-f]+: e5901004 ldr r1, \[r0, #4\]
+ [0-9a-f]+: e12fff31 blx r1
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: 000080b4 .word 0x000080b4
+
+[0-9a-f]+ <bar>:
+ [0-9a-f]+: 4802 ldr r0, \[pc, #8\] ; .*
+ [0-9a-f]+: 4478 add r0, pc
+ [0-9a-f]+: 6841 ldr r1, \[r0, #4\]
+ [0-9a-f]+: 4788 blx r1
+ [0-9a-f]+: 46c0 nop ; .*
+ [0-9a-f]+: 46c0 nop ; .*
+ [0-9a-f]+: 000080a2 .word 0x000080a2
diff --git a/ld/testsuite/ld-arm/tls-descseq.r b/ld/testsuite/ld-arm/tls-descseq.r
new file mode 100644
index 0000000..23d4637
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descseq.r
@@ -0,0 +1,6 @@
+
+.*: file format elf32-.*arm
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+[0-9a-f]+ R_ARM_TLS_DESC lib_gd2
diff --git a/ld/testsuite/ld-arm/tls-descseq.s b/ld/testsuite/ld-arm/tls-descseq.s
new file mode 100644
index 0000000..9b2628d
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-descseq.s
@@ -0,0 +1,41 @@
+ .text
+ .arm
+ .globl foo
+ .type foo, %function
+foo:
+ ldr r0, 1f
+2:
+.tlsdescseq lib_gd2
+ add r0, pc, r0
+.tlsdescseq lib_gd2
+ ldr r1, [r0,#4]
+.tlsdescseq lib_gd2
+ blx r1
+ nop
+
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b)
+
+ .thumb
+ .globl bar
+ .type bar, %function
+bar:
+ ldr r0, 1f
+2:
+.tlsdescseq lib_gd2
+ add r0, pc
+.tlsdescseq lib_gd2
+ ldr r1, [r0,#4]
+.tlsdescseq lib_gd2
+ blx r1
+ nop
+
+ .p2align 2
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .global lib_gd2
+lib_gd2:
+ .space 4
+
diff --git a/ld/testsuite/ld-arm/tls-gdesc-got.d b/ld/testsuite/ld-arm/tls-gdesc-got.d
new file mode 100644
index 0000000..3b4a83b
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc-got.d
@@ -0,0 +1,30 @@
+
+.*/tls-lib2-got.so: file format elf32-.*arm
+architecture: arm, flags 0x00000150:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x00008210
+
+
+Disassembly of section .got:
+
+00010310 <.*>:
+ 10310: 00010288 .*
+ ...
+ 1031c: 00000008 .*
+ 1031c: R_ARM_TLS_DESC \*ABS\*
+ 10320: 00000000 .*
+ 10324: 0000000c .*
+ 10324: R_ARM_TLS_DESC \*ABS\*
+ 10328: 00000000 .*
+ 1032c: 80000004 .*
+ 1032c: R_ARM_TLS_DESC glob1
+ 10330: 00000000 .*
+ 10334: 80000006 .*
+ 10334: R_ARM_TLS_DESC ext2
+ 10338: 00000000 .*
+ 1033c: 80000007 .*
+ 1033c: R_ARM_TLS_DESC ext1
+ 10340: 00000000 .*
+ 10344: 80000009 .*
+ 10344: R_ARM_TLS_DESC glob2
+ ...
diff --git a/ld/testsuite/ld-arm/tls-gdesc-got.s b/ld/testsuite/ld-arm/tls-gdesc-got.s
new file mode 100644
index 0000000..8128ff7
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc-got.s
@@ -0,0 +1,45 @@
+
+ .arm
+foo:
+ ldr r0,1f
+2: bl loc1(tlscall)
+ nop
+1: .word loc1(tlsdesc) + (. - 2b)
+
+ ldr r0,1f
+2: bl loc2(tlscall)
+ nop
+1: .word loc2(tlsdesc) + (. - 2b)
+
+ ldr r0,1f
+2: bl glob1(tlscall)
+ nop
+1: .word glob1(tlsdesc) + (. - 2b)
+
+ ldr r0,1f
+2: bl glob2(tlscall)
+ nop
+1: .word glob2(tlsdesc) + (. - 2b)
+
+ ldr r0,1f
+2: bl ext1(tlscall)
+ nop
+1: .word ext1(tlsdesc) + (. - 2b)
+
+ ldr r0,1f
+2: bl ext2(tlscall)
+ nop
+1: .word ext2(tlsdesc) + (. - 2b)
+
+ .section .tdata,"awT",%progbits
+ .space 8
+ .type loc1, %object
+loc1: .space 4
+ .type loc2, %object
+loc2: .space 4
+ .globl glob1
+ .type glob1, %object
+glob1: .space 4
+ .globl glob2
+ .type glob2, %object
+glob2: .space 4
diff --git a/ld/testsuite/ld-arm/tls-gdesc-nlazy.g b/ld/testsuite/ld-arm/tls-gdesc-nlazy.g
new file mode 100644
index 0000000..4b53a98
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc-nlazy.g
@@ -0,0 +1,4 @@
+
+Hex dump of section '.got':
+ 0x[0-9a-f]+ [0-9a-f]+ 00000000 00000000 00000000 ................
+ 0x[0-9a-f]+ 00000000 00000000 00000000 ............
diff --git a/ld/testsuite/ld-arm/tls-gdesc-nlazy.s b/ld/testsuite/ld-arm/tls-gdesc-nlazy.s
new file mode 100644
index 0000000..2cd8109
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc-nlazy.s
@@ -0,0 +1,17 @@
+ .text
+ .globl foo
+ .type foo, %function
+foo:
+ nop
+.L2:
+ blx lib_gd2(tlscall)
+ mov pc, lr
+
+.Lpool:
+ .word lib_gd2(tlsdesc) + (. - .L2)
+
+ .section .tdata,"awT"
+ .global lib_gd2
+lib_gd2:
+ .space 4
+
diff --git a/ld/testsuite/ld-arm/tls-gdesc.d b/ld/testsuite/ld-arm/tls-gdesc.d
new file mode 100644
index 0000000..ce18eac
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc.d
@@ -0,0 +1,42 @@
+
+tmpdir/tls-lib2.so: file format elf32-.*arm
+architecture: arm, flags 0x[0-9a-f]+:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .plt:
+
+[0-9a-f]+ <.plt>:
+ [0-9a-f]+: e52de004 push {lr} ; .*
+ [0-9a-f]+: e59fe004 ldr lr, \[pc, #4\] ; .*
+ [0-9a-f]+: e08fe00e add lr, pc, lr
+ [0-9a-f]+: e5bef008 ldr pc, \[lr, #8\]!
+ [0-9a-f]+: 000080e8 .word 0x000080e8
+ [0-9a-f]+: e08e0000 add r0, lr, r0
+ [0-9a-f]+: e5901004 ldr r1, \[r0, #4\]
+ [0-9a-f]+: e12fff11 bx r1
+ [0-9a-f]+: e52d2004 push {r2} ; .*
+ [0-9a-f]+: e59f200c ldr r2, \[pc, #12\] ; .*
+ [0-9a-f]+: e59f100c ldr r1, \[pc, #12\] ; .*
+ [0-9a-f]+: e79f2002 ldr r2, \[pc, r2\]
+ [0-9a-f]+: e081100f add r1, r1, pc
+ [0-9a-f]+: e12fff12 bx r2
+ [0-9a-f]+: 000080e0 .word 0x000080e0
+ [0-9a-f]+: 000080c0 .word 0x000080c0
+Disassembly of section .text:
+
+[0-9a-f]+ <foo>:
+ [0-9a-f]+: e59f0004 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: fafffff2 blx [0-9a-f]+ .*
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: 000080c4 .word 0x000080c4
+
+[0-9a-f]+ <bar>:
+ [0-9a-f]+: 4801 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: f7ff efe0 blx [0-9a-f]+ .*
+ [0-9a-f]+: 46c0 nop ; .*
+ [0-9a-f]+: 000080b5 .word 0x000080b5
+ [0-9a-f]+: 4801 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: f7ff efda blx [0-9a-f]+ .*
+ [0-9a-f]+: 46c0 nop ; .*
+ [0-9a-f]+: 000080a1 .word 0x000080a1
diff --git a/ld/testsuite/ld-arm/tls-gdesc.r b/ld/testsuite/ld-arm/tls-gdesc.r
new file mode 100644
index 0000000..3de3ae8
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc.r
@@ -0,0 +1,7 @@
+
+.*: file format elf32-.*arm
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+[0-9a-f]+ R_ARM_TLS_DESC lib_gd2
+[0-9a-f]+ R_ARM_TLS_DESC r0
diff --git a/ld/testsuite/ld-arm/tls-gdesc.s b/ld/testsuite/ld-arm/tls-gdesc.s
new file mode 100644
index 0000000..482ee29
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdesc.s
@@ -0,0 +1,41 @@
+ .text
+ .arm
+ .globl foo
+ .type foo, %function
+foo:
+ ldr r0,1f
+2:
+ blx lib_gd2(tlscall)
+ nop
+
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b)
+
+ .thumb
+ .globl bar
+ .type bar, %function
+bar:
+ ldr r0,1f
+2:
+ blx lib_gd2(tlscall)
+ nop
+
+ .p2align 2
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b + 1)
+
+ ldr r0,1f
+2:
+ blx r0(tlscall)
+ nop
+
+ .p2align 2
+1:
+ .word r0(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .global lib_gd2
+lib_gd2:
+ .space 4
+ .globl r0
+r0: .space 4
diff --git a/ld/testsuite/ld-arm/tls-gdierelax.d b/ld/testsuite/ld-arm/tls-gdierelax.d
new file mode 100644
index 0000000..8d965fc
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdierelax.d
@@ -0,0 +1,20 @@
+
+tmpdir/tls-app-rel-ie: file format elf32-.*arm
+architecture: arm, flags 0x[0-9a-f]+:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <foo>:
+ [0-9a-f]+: e59f0004 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: e79f0000 ldr r0, \[pc, r0\]
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: 00008020 .word 0x00008020
+
+[0-9a-f]+ <bar>:
+ [0-9a-f]+: 4801 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: 4478 add r0, pc
+ [0-9a-f]+: 6800 ldr r0, \[r0, #0\]
+ [0-9a-f]+: 46c0 nop ; .*
+ [0-9a-f]+: 00008016 .word 0x00008016
diff --git a/ld/testsuite/ld-arm/tls-gdierelax.s b/ld/testsuite/ld-arm/tls-gdierelax.s
new file mode 100644
index 0000000..db62008
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdierelax.s
@@ -0,0 +1,34 @@
+ .text
+ .arm
+ .globl foo
+ .type foo, %function
+foo:
+ ldr r0, 1f
+2:
+ blx lib_gd2(tlscall)
+ nop
+
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b)
+
+ .thumb
+ .globl bar
+ .type bar, %function
+bar:
+ ldr r0,1f
+2:
+ blx lib_gd2(tlscall)
+ nop
+
+ .p2align 2
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b + 1)
+
+ .globl _start
+_start:
+
+ .section .tdata,"awT"
+ .global lib_gd2
+lib_gd2:
+ .space 4
+
diff --git a/ld/testsuite/ld-arm/tls-gdierelax2.d b/ld/testsuite/ld-arm/tls-gdierelax2.d
new file mode 100644
index 0000000..055aad8
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdierelax2.d
@@ -0,0 +1,23 @@
+
+tmpdir/tls-app-rel-ie2: file format elf32-.*arm
+architecture: arm, flags 0x[0-9a-f]+:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <foo>:
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: e59f0004 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: e79f0000 ldr r0, \[pc, r0\]
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: 00008098 .word 0x00008098
+ [0-9a-f]+: 0000809c .word 0x0000809c
+
+[0-9a-f]+ <bar>:
+ [0-9a-f]+: 4801 ldr r0, \[pc, #4\] ; .*
+ [0-9a-f]+: 4478 add r0, pc
+ [0-9a-f]+: 6800 ldr r0, \[r0, #0\]
+ [0-9a-f]+: 46c0 nop ; .*
+ [0-9a-f]+: 0000808a .word 0x0000808a
+ [0-9a-f]+: 0000808c .word 0x0000808c
diff --git a/ld/testsuite/ld-arm/tls-gdierelax2.s b/ld/testsuite/ld-arm/tls-gdierelax2.s
new file mode 100644
index 0000000..2f4edad
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdierelax2.s
@@ -0,0 +1,35 @@
+ .text
+ .arm
+ .globl foo
+ .type foo, %function
+foo:
+ nop
+3: ldr r0,1f
+2: bl lib_gd2(tlscall)
+ nop
+
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b)
+ .word lib_gd2(gottpoff) + (. - 3b - 8)
+
+ .thumb
+ .globl bar
+ .type bar, %function
+bar:
+3: ldr r0,1f
+2: blx lib_gd2(tlscall)
+ nop
+
+ .p2align 2
+1:
+ .word lib_gd2(tlsdesc) + (. - 2b + 1)
+ .word lib_gd2(gottpoff) + (. - 3b - 4)
+
+ .globl _start
+_start:
+
+ .section .tdata,"awT"
+ .global lib_gd2
+lib_gd2:
+ .space 4
+
diff --git a/ld/testsuite/ld-arm/tls-gdlerelax.d b/ld/testsuite/ld-arm/tls-gdlerelax.d
new file mode 100644
index 0000000..896aed7
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdlerelax.d
@@ -0,0 +1,13 @@
+
+tmpdir/tls-app-rel-le: file format elf32-.*arm
+architecture: arm, flags 0x[0-9a-f]+:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x[0-9a-f]+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <foo>:
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: e1a00000 nop ; .*
+ [0-9a-f]+: e1a0f00e mov pc, lr
+ [0-9a-f]+: 00000008 .word 0x00000008
diff --git a/ld/testsuite/ld-arm/tls-gdlerelax.s b/ld/testsuite/ld-arm/tls-gdlerelax.s
new file mode 100644
index 0000000..3952837
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-gdlerelax.s
@@ -0,0 +1,16 @@
+ .text
+ .globl foo
+ .type foo, %function
+foo:
+ nop
+.L2:
+ blx lib_gd2(tlscall)
+ mov pc, lr
+
+.Lpool:
+ .word lib_gd2(tlsdesc) + (. - .L2)
+
+ .section .tdata,"awT"
+lib_gd2:
+ .space 4
+
diff --git a/ld/testsuite/ld-arm/tls-lib-loc.d b/ld/testsuite/ld-arm/tls-lib-loc.d
new file mode 100644
index 0000000..2235dcb
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-lib-loc.d
@@ -0,0 +1,33 @@
+
+.*: file format elf32-.*arm
+architecture: arm, flags 0x00000150:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x.*
+
+Disassembly of section .plt:
+
+[0-9a-f]+ <.plt>:
+ [0-9a-f]+: e52de004 push {lr} ; .*
+ [0-9a-f]+: e59fe004 ldr lr, \[pc, #4\] ; 8150 .*
+ [0-9a-f]+: e08fe00e add lr, pc, lr
+ [0-9a-f]+: e5bef008 ldr pc, \[lr, #8\]!
+ 8150: 000080cc .word 0x000080cc
+ 8154: e08e0000 add r0, lr, r0
+ [0-9a-f]+: e5901004 ldr r1, \[r0, #4\]
+ [0-9a-f]+: e12fff11 bx r1
+ [0-9a-f]+: e52d2004 push {r2} ; .*
+ 8164: e59f200c ldr r2, \[pc, #12\] ; 8178 .*
+ [0-9a-f]+: e59f100c ldr r1, \[pc, #12\] ; 817c .*
+ [0-9a-f]+: e79f2002 ldr r2, \[pc, r2\]
+ [0-9a-f]+: e081100f add r1, r1, pc
+ [0-9a-f]+: e12fff12 bx r2
+ 8178: 000080bc .word 0x000080bc
+ 817c: 000080a4 .word 0x000080a4
+
+Disassembly of section .text:
+
+[0-9a-f]+ <foo>:
+ [0-9a-f]+: e59f0004 ldr r0, \[pc, #4\] ; 818c .*
+ [0-9a-f]+: fafffff2 blx 8154 <.*\+0x8154>
+ [0-9a-f]+: e1a00000 nop ; .*
+ 818c: 000080a0 .word 0x000080a0
diff --git a/ld/testsuite/ld-arm/tls-lib-loc.r b/ld/testsuite/ld-arm/tls-lib-loc.r
new file mode 100644
index 0000000..ba54f61
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-lib-loc.r
@@ -0,0 +1,6 @@
+
+.*: file format elf32-.*arm
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+.* R_ARM_TLS_DESC \*ABS\*
diff --git a/ld/testsuite/ld-arm/tls-lib-loc.s b/ld/testsuite/ld-arm/tls-lib-loc.s
new file mode 100644
index 0000000..a0e4dc7
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-lib-loc.s
@@ -0,0 +1,14 @@
+ .text
+ .arm
+
+foo:
+ ldr r0,1f
+2: blx loc(tlscall)
+ nop
+
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b)
+
+ .section .tdata,"awT"
+loc:
+ .space 4
diff --git a/ld/testsuite/ld-arm/tls-longplt-lib.d b/ld/testsuite/ld-arm/tls-longplt-lib.d
new file mode 100644
index 0000000..9032c61
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-longplt-lib.d
@@ -0,0 +1,59 @@
+.*: file format elf32-.*arm
+architecture: arm, flags 0x00000150:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x.*
+
+Disassembly of section .plt:
+
+00008198 <.plt>:
+ 8198: e52de004 push {lr} ; .*
+ 819c: e59fe004 ldr lr, \[pc, #4\] ; .*
+ 81a0: e08fe00e add lr, pc, lr
+ 81a4: e5bef008 ldr pc, \[lr, #8\]!
+ 81a8: 000080e0 .word 0x000080e0
+ 81ac: e08e0000 add r0, lr, r0
+ 81b0: e5901004 ldr r1, \[r0, #4\]
+ 81b4: e12fff11 bx r1
+ 81b8: e52d2004 push {r2} ; .*
+ 81bc: e59f200c ldr r2, \[pc, #12\] ; .*
+ 81c0: e59f100c ldr r1, \[pc, #12\] ; .*
+ 81c4: e79f2002 ldr r2, \[pc, r2\]
+ 81c8: e081100f add r1, r1, pc
+ 81cc: e12fff12 bx r2
+ 81d0: 000080d8 .word 0x000080d8
+ 81d4: 000080b8 .word 0x000080b8
+
+Disassembly of section .text:
+
+000081d8 <text>:
+ 81d8: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 81dc: fafffff2 blx 81ac .*
+ 81e0: e1a00000 nop ; .*
+ 81e4: 000080b4 .word 0x000080b4
+ 81e8: 4801 ldr r0, \[pc, #4\] ; .*
+ 81ea: f7ff efe0 blx 81ac <.*>
+ 81ee: 46c0 nop ; .*
+ 81f0: 000080a5 .word 0x000080a5
+
+Disassembly of section .foo:
+
+04001000 <foo>:
+ 4001000: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 4001004: fa000009 blx 4001030 .*
+ 4001008: e1a00000 nop ; .*
+ 400100c: fc00f28c .word 0xfc00f28c
+ 4001010: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 4001014: fa000005 blx 4001030 .*
+ 4001018: e1a00000 nop ; .*
+ 400101c: fc00f284 .word 0xfc00f284
+ 4001020: 4801 ldr r0, \[pc, #4\] ; .*
+ 4001022: f000 e806 blx 4001030 .*
+ 4001026: 46c0 nop ; .*
+ 4001028: fc00f26d .word 0xfc00f26d
+ 400102c: 00000000 .word 0x00000000
+
+04001030 <__unnamed_veneer>:
+ 4001030: e59f1000 ldr r1, \[pc, #0\] ; .*
+ 4001034: e08ff001 add pc, pc, r1
+ 4001038: fc007170 .word 0xfc007170
+ 400103c: 00000000 .word 0x00000000
diff --git a/ld/testsuite/ld-arm/tls-longplt-lib.s b/ld/testsuite/ld-arm/tls-longplt-lib.s
new file mode 100644
index 0000000..e0650cb
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-longplt-lib.s
@@ -0,0 +1,51 @@
+ .syntax unified
+ .text
+text:
+ .arm
+ ldr r0,1f
+2: blx loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b)
+
+ .thumb
+ ldr r0,1f
+2: blx loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b + 1)
+
+ .section ".foo","ax"
+foo:
+ .arm
+ ldr r0,1f
+2: blx loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b)
+
+ .arm
+ ldr r0,1f
+2: blx glob(tlscall)
+ nop
+ .p2align 2
+1: .word glob(tlsdesc) + (. - 2b)
+
+ .thumb
+ ldr r0,1f
+2: blx loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ .type loc, %object
+loc: .space 4
+
+ @ glob1 and glob2 used by tls-longplt
+ .type glob1, %object
+ .globl glob1
+glob1: .space 4
+ .type glob2, %object
+ .globl glob2
+glob2: .space 4
diff --git a/ld/testsuite/ld-arm/tls-longplt.d b/ld/testsuite/ld-arm/tls-longplt.d
new file mode 100644
index 0000000..8729e74
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-longplt.d
@@ -0,0 +1,64 @@
+.*: file format elf32-.*arm
+architecture: arm, flags 0x00000112:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x.*
+
+Disassembly of section .plt:
+
+0000819c <.plt>:
+ 819c: e52de004 push {lr} ; .*
+ 81a0: e59fe004 ldr lr, \[pc, #4\] ; .*
+ 81a4: e08fe00e add lr, pc, lr
+ 81a8: e5bef008 ldr pc, \[lr, #8\]!
+ 81ac: 00008100 .word 0x00008100
+ 81b0: e08e0000 add r0, lr, r0
+ 81b4: e5901004 ldr r1, \[r0, #4]
+ 81b8: e12fff11 bx r1
+ 81bc: e52d2004 push {r2} ; .*
+ 81c0: e59f200c ldr r2, \[pc, #12\] ; .*
+ 81c4: e59f100c ldr r1, \[pc, #12\] ; .*
+ 81c8: e79f2002 ldr r2, \[pc, r2\]
+ 81cc: e081100f add r1, r1, pc
+ 81d0: e12fff12 bx r2
+ 81d4: 000080f4 .word 0x000080f4
+ 81d8: 000080d8 .word 0x000080d8
+
+Disassembly of section .text:
+
+000081dc <text>:
+ 81dc: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 81e0: fafffff2 blx 81b0 .*
+ 81e4: e1a00000 nop ; .*
+ 81e8: 000080d4 .word 0x000080d4
+ 81ec: 4801 ldr r0, \[pc, #4\] ; .*
+ 81ee: f7ff efe0 blx 81b0 .*
+ 81f2: 46c0 nop ; .*
+ 81f4: 000080c5 .word 0x000080c5
+
+Disassembly of section .foo:
+
+04001000 <foo>:
+ 4001000: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 4001004: e79f0000 ldr r0, \[pc, r0\]
+ 4001008: e1a00000 nop ; .*
+ 400100c: fc00f2b4 .word 0xfc00f2b4
+ 4001010: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 4001014: fa000005 blx 4001030 .*
+ 4001018: e1a00000 nop ; .*
+ 400101c: fc00f2a0 .word 0xfc00f2a0
+ 4001020: 4801 ldr r0, \[pc, #4\] ; .*
+ 4001022: f000 e80a blx 4001038 .*
+ 4001026: 46c0 nop ; .*
+ 4001028: fc00f291 .word 0xfc00f291
+ 400102c: 00000000 .word 0x00000000
+
+04001030 <__unnamed_veneer>:
+ 4001030: e51ff004 ldr pc, \[pc, #-4\] ; .*
+ 4001034: 000081b0 .word 0x000081b0
+
+04001038 <__unnamed_veneer>:
+ 4001038: 4778 bx pc
+ 400103a: 46c0 nop ; .*
+ 400103c: e51ff004 ldr pc, \[pc, #-4\] ; .*
+ 4001040: 000081b0 .word 0x000081b0
+ 4001044: 00000000 .word 0x00000000
diff --git a/ld/testsuite/ld-arm/tls-longplt.s b/ld/testsuite/ld-arm/tls-longplt.s
new file mode 100644
index 0000000..42eea19
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-longplt.s
@@ -0,0 +1,47 @@
+ .syntax unified
+ .text
+text:
+ .arm
+ ldr r0,1f
+2: blx udefw(tlscall)
+ nop
+ .p2align 2
+1: .word udefw(tlsdesc) + (. - 2b)
+
+ .thumb
+ ldr r0,1f
+2: blx udefw(tlscall)
+ nop
+ .p2align 2
+1: .word udefw(tlsdesc) + (. - 2b + 1)
+
+ .section ".foo","ax"
+foo:
+ .arm
+ ldr r0,1f
+2: blx glob1(tlscall)
+ nop
+ .p2align 2
+1: .word glob1(tlsdesc) + (. - 2b)
+
+ .arm
+ ldr r0,1f
+2: blx udefw(tlscall)
+ nop
+ .p2align 2
+1: .word udefw(tlsdesc) + (. - 2b)
+
+ .thumb
+ ldr r0,1f
+2: blx udefw(tlscall)
+ nop
+ .p2align 2
+1: .word udefw(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+ @ glob used by tls-longplt-lib
+ .type glob, %object
+ .globl glob
+glob: .space 4
+ .globl udefw
+ .weak udefw
diff --git a/ld/testsuite/ld-arm/tls-mixed.r b/ld/testsuite/ld-arm/tls-mixed.r
new file mode 100644
index 0000000..79ccdeb
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-mixed.r
@@ -0,0 +1,10 @@
+
+.*: file format elf32-.*arm
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+[0-9a-f]+ R_ARM_TLS_DTPMOD32 lib_gd2
+[0-9a-f]+ R_ARM_TLS_DTPOFF32 lib_gd2
+[0-9a-f]+ R_ARM_TLS_DTPMOD32 lib_gd
+[0-9a-f]+ R_ARM_TLS_DTPOFF32 lib_gd
+[0-9a-f]+ R_ARM_TLS_DESC lib_gd2
diff --git a/ld/testsuite/ld-arm/tls-mixed.s b/ld/testsuite/ld-arm/tls-mixed.s
new file mode 100644
index 0000000..af2377d
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-mixed.s
@@ -0,0 +1,25 @@
+ .text
+ .globl foo
+ .type foo, %function
+foo:
+ nop
+.L1:
+ nop
+.L2:
+ bl lib_gd2(tlscall)
+ mov pc, lr
+
+.Lpool:
+ .word lib_gd(tlsgd) + (. - .L1 - 8)
+.Lpool2:
+ .word lib_gd2(tlsdesc) + (. - .L2)
+ .word lib_gd2(tlsgd) + (. - .L2 - 8)
+
+ .section .tdata,"awT"
+ .global lib_gd
+lib_gd:
+ .space 4
+ .global lib_gd2
+lib_gd2:
+ .space 4
+
diff --git a/ld/testsuite/ld-arm/tls-thumb1.d b/ld/testsuite/ld-arm/tls-thumb1.d
new file mode 100644
index 0000000..26b65bb
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-thumb1.d
@@ -0,0 +1,74 @@
+.*: file format elf32-.*arm
+architecture: arm, flags 0x00000150:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x.*
+
+Disassembly of section .plt:
+
+00008164 <.plt>:
+ 8164: e52de004 push {lr} ; .*
+ 8168: e59fe004 ldr lr, \[pc, #4\] ; .*
+ 816c: e08fe00e add lr, pc, lr
+ 8170: e5bef008 ldr pc, \[lr, #8\]!
+ 8174: 000080f0 .word 0x000080f0
+ 8178: e08e0000 add r0, lr, r0
+ 817c: e5901004 ldr r1, \[r0, #4\]
+ 8180: e12fff11 bx r1
+ 8184: e52d2004 push {r2} ; .*
+ 8188: e59f200c ldr r2, \[pc, #12\] ; .*
+ 818c: e59f100c ldr r1, \[pc, #12\] ; .*
+ 8190: e79f2002 ldr r2, \[pc, r2\]
+ 8194: e081100f add r1, r1, pc
+ 8198: e12fff12 bx r2
+ 819c: 000080e8 .word 0x000080e8
+ 81a0: 000080c8 .word 0x000080c8
+
+Disassembly of section .text:
+
+000081a8 <text>:
+ 81a8: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 81ac: ebfffff1 bl 8178 .*
+ 81b0: e1a00000 nop ; .*
+ 81b4: 000080c0 .word 0x000080c0
+ 81b8: 4801 ldr r0, \[pc, #4\] ; .*
+ 81ba: f000 e806 blx 81c8 .*
+ 81be: 46c0 nop ; .*
+ 81c0: 000080b1 .word 0x000080b1
+ 81c4: 00000000 .word 0x00000000
+
+000081c8 <__unnamed_veneer>:
+ 81c8: 4778 bx pc
+ 81ca: 46c0 nop ; .*
+ 81cc: e59f1000 ldr r1, \[pc, #0\] ; .*
+ 81d0: e081f00f add pc, r1, pc
+ 81d4: ffffffa0 .word 0xffffffa0
+
+Disassembly of section .foo:
+
+04001000 <foo>:
+ 4001000: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 4001004: eb000009 bl 4001030 .*
+ 4001008: e1a00000 nop ; .*
+ 400100c: fc00f268 .word 0xfc00f268
+ 4001010: e59f0004 ldr r0, \[pc, #4\] ; .*
+ 4001014: eb000005 bl 4001030 .*
+ 4001018: e1a00000 nop ; .*
+ 400101c: fc00f260 .word 0xfc00f260
+ 4001020: 4801 ldr r0, \[pc, #4\] ; .*
+ 4001022: f000 e80c blx 400103c .*
+ 4001026: 46c0 nop ; .*
+ 4001028: fc00f249 .word 0xfc00f249
+ 400102c: 00000000 .word 0x00000000
+
+04001030 <__unnamed_veneer>:
+ 4001030: e59f1000 ldr r1, \[pc, #0\] ; .*
+ 4001034: e08ff001 add pc, pc, r1
+ 4001038: fc00713c .word 0xfc00713c
+
+0400103c <__unnamed_veneer>:
+ 400103c: 4778 bx pc
+ 400103e: 46c0 nop ; .*
+ 4001040: e59f1000 ldr r1, \[pc, #0\] ; .*
+ 4001044: e081f00f add pc, r1, pc
+ 4001048: fc00712c .word 0xfc00712c
+ 400104c: 00000000 .word 0x00000000
diff --git a/ld/testsuite/ld-arm/tls-thumb1.s b/ld/testsuite/ld-arm/tls-thumb1.s
new file mode 100644
index 0000000..634511e
--- /dev/null
+++ b/ld/testsuite/ld-arm/tls-thumb1.s
@@ -0,0 +1,43 @@
+ .arch armv4t
+ .syntax unified
+ .text
+text:
+ .arm
+ ldr r0,1f
+2: bl +loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b)
+
+ .thumb
+ ldr r0,1f
+2: bl +loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b + 1)
+
+ .section ".foo","ax"
+foo:
+ .arm
+ ldr r0,1f
+2: bl +loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b)
+
+ .arm
+ ldr r0,1f
+2: bl +glob(tlscall)
+ nop
+ .p2align 2
+1: .word glob(tlsdesc) + (. - 2b)
+
+ .thumb
+ ldr r0,1f
+2: bl +loc(tlscall)
+ nop
+ .p2align 2
+1: .word loc(tlsdesc) + (. - 2b + 1)
+
+ .section .tdata,"awT"
+loc: .space 4