From f5fa6a6eb92939925fc2fec14363ada172e6ed1e Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 10 Jan 2011 08:40:14 +0000 Subject: [PATCH] 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. --- bfd/ChangeLog | 51 ++ bfd/bfd-in2.h | 6 + bfd/elf32-arm.c | 1017 +++++++++++++++++++++++++++--- bfd/libbfd.h | 6 + bfd/reloc.c | 12 + gas/ChangeLog | 16 + gas/config/tc-arm.c | 78 ++- gas/doc/c-arm.texi | 8 + gas/testsuite/ChangeLog | 6 + gas/testsuite/gas/arm/tls.d | 48 +- gas/testsuite/gas/arm/tls.s | 52 +- include/elf/ChangeLog | 7 + include/elf/arm.h | 8 +- ld/testsuite/ChangeLog | 42 ++ ld/testsuite/ld-arm/arm-elf.exp | 48 ++ ld/testsuite/ld-arm/tls-descrelax-be32.d | 108 ++++ ld/testsuite/ld-arm/tls-descrelax-be32.s | 198 ++++++ ld/testsuite/ld-arm/tls-descrelax-be8.d | 108 ++++ ld/testsuite/ld-arm/tls-descrelax-be8.s | 198 ++++++ ld/testsuite/ld-arm/tls-descrelax-v7.d | 108 ++++ ld/testsuite/ld-arm/tls-descrelax-v7.s | 198 ++++++ ld/testsuite/ld-arm/tls-descrelax.d | 108 ++++ ld/testsuite/ld-arm/tls-descrelax.s | 197 ++++++ ld/testsuite/ld-arm/tls-descseq.d | 44 ++ ld/testsuite/ld-arm/tls-descseq.r | 6 + ld/testsuite/ld-arm/tls-descseq.s | 41 ++ ld/testsuite/ld-arm/tls-gdesc-got.d | 30 + ld/testsuite/ld-arm/tls-gdesc-got.s | 45 ++ ld/testsuite/ld-arm/tls-gdesc-nlazy.g | 4 + ld/testsuite/ld-arm/tls-gdesc-nlazy.s | 17 + ld/testsuite/ld-arm/tls-gdesc.d | 42 ++ ld/testsuite/ld-arm/tls-gdesc.r | 7 + ld/testsuite/ld-arm/tls-gdesc.s | 41 ++ ld/testsuite/ld-arm/tls-gdierelax.d | 20 + ld/testsuite/ld-arm/tls-gdierelax.s | 34 + ld/testsuite/ld-arm/tls-gdierelax2.d | 23 + ld/testsuite/ld-arm/tls-gdierelax2.s | 35 + ld/testsuite/ld-arm/tls-gdlerelax.d | 13 + ld/testsuite/ld-arm/tls-gdlerelax.s | 16 + ld/testsuite/ld-arm/tls-lib-loc.d | 33 + ld/testsuite/ld-arm/tls-lib-loc.r | 6 + ld/testsuite/ld-arm/tls-lib-loc.s | 14 + ld/testsuite/ld-arm/tls-longplt-lib.d | 59 ++ ld/testsuite/ld-arm/tls-longplt-lib.s | 51 ++ ld/testsuite/ld-arm/tls-longplt.d | 64 ++ ld/testsuite/ld-arm/tls-longplt.s | 47 ++ ld/testsuite/ld-arm/tls-mixed.r | 10 + ld/testsuite/ld-arm/tls-mixed.s | 25 + ld/testsuite/ld-arm/tls-thumb1.d | 74 +++ ld/testsuite/ld-arm/tls-thumb1.s | 43 ++ 50 files changed, 3354 insertions(+), 118 deletions(-) rewrite gas/testsuite/gas/arm/tls.s (87%) create mode 100644 ld/testsuite/ld-arm/tls-descrelax-be32.d create mode 100644 ld/testsuite/ld-arm/tls-descrelax-be32.s create mode 100644 ld/testsuite/ld-arm/tls-descrelax-be8.d create mode 100644 ld/testsuite/ld-arm/tls-descrelax-be8.s create mode 100644 ld/testsuite/ld-arm/tls-descrelax-v7.d create mode 100644 ld/testsuite/ld-arm/tls-descrelax-v7.s create mode 100644 ld/testsuite/ld-arm/tls-descrelax.d create mode 100644 ld/testsuite/ld-arm/tls-descrelax.s create mode 100644 ld/testsuite/ld-arm/tls-descseq.d create mode 100644 ld/testsuite/ld-arm/tls-descseq.r create mode 100644 ld/testsuite/ld-arm/tls-descseq.s create mode 100644 ld/testsuite/ld-arm/tls-gdesc-got.d create mode 100644 ld/testsuite/ld-arm/tls-gdesc-got.s create mode 100644 ld/testsuite/ld-arm/tls-gdesc-nlazy.g create mode 100644 ld/testsuite/ld-arm/tls-gdesc-nlazy.s create mode 100644 ld/testsuite/ld-arm/tls-gdesc.d create mode 100644 ld/testsuite/ld-arm/tls-gdesc.r create mode 100644 ld/testsuite/ld-arm/tls-gdesc.s create mode 100644 ld/testsuite/ld-arm/tls-gdierelax.d create mode 100644 ld/testsuite/ld-arm/tls-gdierelax.s create mode 100644 ld/testsuite/ld-arm/tls-gdierelax2.d create mode 100644 ld/testsuite/ld-arm/tls-gdierelax2.s create mode 100644 ld/testsuite/ld-arm/tls-gdlerelax.d create mode 100644 ld/testsuite/ld-arm/tls-gdlerelax.s create mode 100644 ld/testsuite/ld-arm/tls-lib-loc.d create mode 100644 ld/testsuite/ld-arm/tls-lib-loc.r create mode 100644 ld/testsuite/ld-arm/tls-lib-loc.s create mode 100644 ld/testsuite/ld-arm/tls-longplt-lib.d create mode 100644 ld/testsuite/ld-arm/tls-longplt-lib.s create mode 100644 ld/testsuite/ld-arm/tls-longplt.d create mode 100644 ld/testsuite/ld-arm/tls-longplt.s create mode 100644 ld/testsuite/ld-arm/tls-mixed.r create mode 100644 ld/testsuite/ld-arm/tls-mixed.s create mode 100644 ld/testsuite/ld-arm/tls-thumb1.d create mode 100644 ld/testsuite/ld-arm/tls-thumb1.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c2c015708..42b07c6d2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,54 @@ +2011-01-10 Nathan Sidwell + Glauber de Oliveira Costa + + * 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 * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Optimized. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8531f8de5..84fc75d2e 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 7c8eb68a7..ea1e485bc 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 1cf63ceec..8c5b3b50f 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 30919f266..719eb00df 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 9d3d46e9f..63d2301ad 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2011-01-10 Nathan Sidwell + Glauber de Oliveira Costa + + * 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 * 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 f4ebdc4e2..ae389f5d8 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 d3cccf4a4..e14cc2e0e 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 67eee86d7..d28da8dfe 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-01-10 Nathan Sidwell + Glauber de Oliveira Costa + + * gas/arm/tls.s: Add tlsdesc tests. + * gas/arm/tls.d: Adjust. + 2011-01-07 H.J. Lu * 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 6401f29f5..727f8e4e0 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
: - 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 : + 0: e1a00000 nop ; .* + 0: R_ARM_TLS_DESCSEQ af + 4: e59f0014 ldr r0, \[pc, #20\] ; 20 .* + 8: fa000000 blx 8 + 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 : + 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 + 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 dissimilarity index 87% index 48722a42b..96a25f56f 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: - nop -.L2: - nop - mov pc, lr - -.Lpool: - .word a(tlsgd) + (. - .L2 - 8) - .word b(tlsldm) + (. - .L2 - 8) - .word c(gottpoff) + (. - .L2 - 8) - .word d(tpoff) + .text + .arm + .globl arm_fn + .type arm_fn, %function +arm_fn: +1: +.tlsdescseq af + nop + ldr r0, 1f +2: blx ae(tlscall) + nop + +.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 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 47a884e21..d178b641b 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,10 @@ +2011-01-10 Nathan Sidwell + Glauber de Oliveira Costa + + * 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 * mips.h (E_MIPS_MACH_LS3A): Defined. diff --git a/include/elf/arm.h b/include/elf/arm.h index 0a5c87d58..18aa5592e 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 0eb510647..0910af2b2 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,45 @@ +2011-01-10 Nathan Sidwell + Glauber de Oliveira Costa + + * 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 * 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 80f521ec4..9ba7b5609 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 000000000..150e331ae --- /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 : + 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c + 8004: e79f0000 ldr r0, \[pc, r0\] + 8008: e1a00000 nop ; .* + 800c: 00008138 .word 0x00008138 + 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c + 8014: e79f0000 ldr r0, \[pc, r0\] + 8018: e1a00000 nop ; .* + 801c: 00008128 .word 0x00008128 + 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c + 8024: e1a00000 nop ; .* + 8028: e1a00000 nop ; .* + 802c: 0000000c .word 0x0000000c + 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c + 8034: e1a00000 nop ; .* + 8038: e1a00000 nop ; .* + 803c: 0000000c .word 0x0000000c + 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 + 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 + 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 + 8074: e1a00000 nop ; .* + 8078: e1a00000 nop ; .* + 807c: e1a00000 nop ; .* + 8080: e1a00000 nop ; .* + 8084: 0000000c .word 0x0000000c + 8088: e59f000c ldr r0, \[pc, #12\] ; 809c + 808c: e1a00000 nop ; .* + 8090: e1a00000 nop ; .* + 8094: e1a00000 nop ; .* + 8098: e1a00000 nop ; .* + 809c: 0000000c .word 0x0000000c + +000080a0 : + 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 \) + 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 \) + 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 \) + 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 \) + 80c6: 46c0 nop ; .* + 80c8: 46c0 nop ; .* + 80ca: 46c0 nop ; .* + 80cc: 0000000c .word 0x0000000c + 80d0: 4801 ldr r0, \[pc, #4\] ; \(80d8 \) + 80d2: bf00 nop + 80d4: bf00 nop + 80d6: 46c0 nop ; .* + 80d8: 0000000c .word 0x0000000c + 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 \) + 80de: bf00 nop + 80e0: bf00 nop + 80e2: 46c0 nop ; .* + 80e4: 00000014 .word 0x00000014 + 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 \) + 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 \) + 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 \) + 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 \) + 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 000000000..dae54585b --- /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 000000000..1b2159c37 --- /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 : + 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c + 8004: e79f0000 ldr r0, \[pc, r0\] + 8008: e320f000 nop \{0\} + 800c: 00008138 .word 0x00008138 + 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c + 8014: e79f0000 ldr r0, \[pc, r0\] + 8018: e320f000 nop \{0\} + 801c: 00008128 .word 0x00008128 + 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c + 8024: e320f000 nop \{0\} + 8028: e320f000 nop \{0\} + 802c: 0000000c .word 0x0000000c + 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c + 8034: e1a00000 nop ; .* + 8038: e320f000 nop \{0\} + 803c: 0000000c .word 0x0000000c + 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 + 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 + 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 + 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 + 808c: e1a00000 nop ; .* + 8090: e1a00000 nop ; .* + 8094: e1a00000 nop ; .* + 8098: e320f000 nop \{0\} + 809c: 0000000c .word 0x0000000c + +000080a0 : + 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 \) + 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 \) + 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 \) + 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 \) + 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 \) + 80d2: (f3af 8000)|(bf00 ) nop(.w)? +#... + 80d6: 46c0 nop ; \(mov r8, r8\) + 80d8: 0000000c .word 0x0000000c + 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 \) + 80de: (f3af 8000)|(bf00 ) nop(.w)? +#... + 80e2: 46c0 nop ; \(mov r8, r8\) + 80e4: 00000014 .word 0x00000014 + 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 \) + 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 \) + 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 \) + 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 \) + 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 000000000..a8c028b52 --- /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 000000000..1b2159c37 --- /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 : + 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c + 8004: e79f0000 ldr r0, \[pc, r0\] + 8008: e320f000 nop \{0\} + 800c: 00008138 .word 0x00008138 + 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c + 8014: e79f0000 ldr r0, \[pc, r0\] + 8018: e320f000 nop \{0\} + 801c: 00008128 .word 0x00008128 + 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c + 8024: e320f000 nop \{0\} + 8028: e320f000 nop \{0\} + 802c: 0000000c .word 0x0000000c + 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c + 8034: e1a00000 nop ; .* + 8038: e320f000 nop \{0\} + 803c: 0000000c .word 0x0000000c + 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 + 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 + 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 + 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 + 808c: e1a00000 nop ; .* + 8090: e1a00000 nop ; .* + 8094: e1a00000 nop ; .* + 8098: e320f000 nop \{0\} + 809c: 0000000c .word 0x0000000c + +000080a0 : + 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 \) + 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 \) + 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 \) + 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 \) + 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 \) + 80d2: (f3af 8000)|(bf00 ) nop(.w)? +#... + 80d6: 46c0 nop ; \(mov r8, r8\) + 80d8: 0000000c .word 0x0000000c + 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 \) + 80de: (f3af 8000)|(bf00 ) nop(.w)? +#... + 80e2: 46c0 nop ; \(mov r8, r8\) + 80e4: 00000014 .word 0x00000014 + 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 \) + 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 \) + 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 \) + 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 \) + 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 000000000..a8c028b52 --- /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 000000000..9b06d6ae9 --- /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 : + 8000: e59f0004 ldr r0, \[pc, #4\] ; 800c + 8004: e79f0000 ldr r0, \[pc, r0\] + 8008: e1a00000 nop ; \(mov r0, r0\) + 800c: 00008138 .word 0x00008138 + 8010: e59f0004 ldr r0, \[pc, #4\] ; 801c + 8014: e79f0000 ldr r0, \[pc, r0\] + 8018: e1a00000 nop ; \(mov r0, r0\) + 801c: 00008128 .word 0x00008128 + 8020: e59f0004 ldr r0, \[pc, #4\] ; 802c + 8024: e1a00000 nop ; \(mov r0, r0\) + 8028: e1a00000 nop ; \(mov r0, r0\) + 802c: 0000000c .word 0x0000000c + 8030: e59f0004 ldr r0, \[pc, #4\] ; 803c + 8034: e1a00000 nop ; \(mov r0, r0\) + 8038: e1a00000 nop ; \(mov r0, r0\) + 803c: 0000000c .word 0x0000000c + 8040: e59f000c ldr r0, \[pc, #12\] ; 8054 + 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 + 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 + 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 + 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 : + 80a0: 4801 ldr r0, \[pc, #4\] ; \(80a8 \) + 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 \) + 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 \) + 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 \) + 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 \) + 80d2: bf00 nop + 80d4: bf00 nop + 80d6: 46c0 nop ; \(mov r8, r8\) + 80d8: 0000000c .word 0x0000000c + 80dc: 4801 ldr r0, \[pc, #4\] ; \(80e4 \) + 80de: bf00 nop + 80e0: bf00 nop + 80e2: 46c0 nop ; \(mov r8, r8\) + 80e4: 00000014 .word 0x00000014 + 80e8: 4802 ldr r0, \[pc, #8\] ; \(80f4 \) + 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 \) + 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 \) + 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 \) + 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 000000000..826f1695a --- /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 000000000..1a04bb07e --- /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]+ : + [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]+ : + [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 000000000..23d463716 --- /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 000000000..9b2628d15 --- /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 000000000..3b4a83b18 --- /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 000000000..8128ff764 --- /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 000000000..4b53a9819 --- /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 000000000..2cd810904 --- /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 000000000..ce18eaced --- /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]+ : + [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]+ : + [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 000000000..3de3ae8dd --- /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 000000000..482ee2966 --- /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 000000000..8d965fc64 --- /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]+ : + [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]+ : + [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 000000000..db620084e --- /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 000000000..055aad8c2 --- /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]+ : + [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]+ : + [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 000000000..2f4edadfd --- /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 000000000..896aed781 --- /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]+ : + [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 000000000..39528371a --- /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 000000000..2235dcb5c --- /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]+ : + [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 000000000..ba54f61f5 --- /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 000000000..a0e4dc78e --- /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 000000000..9032c6193 --- /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 : + 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 : + 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 000000000..e0650cb0e --- /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 000000000..8729e7420 --- /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 : + 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 : + 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 000000000..42eea19c3 --- /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 000000000..79ccdebc8 --- /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 000000000..af2377db5 --- /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 000000000..26b65bb52 --- /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 : + 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 : + 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 000000000..634511e3e --- /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 -- 2.11.4.GIT