From: Alexandre Oliva Date: Wed, 18 Jan 2006 21:07:51 +0000 (+0000) Subject: include/elf/ChangeLog: X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=67a4f2b710581acc83afecff55424af285ecbc28;p=binutils-gdb.git include/elf/ChangeLog: Introduce TLS descriptors for i386 and x86_64. * common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New. * i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC_CALL, R_386_TLS_DESC): New. * x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC): New. bfd/ChangeLog: Introduce TLS descriptors for i386 and x86_64. * reloc.c (BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC, BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL): New. * libbfd.h, bfd-in2.h: Rebuilt. * elf32-i386.c (elf_howto_table): New relocations. (R_386_tls): Adjust. (elf_i386_reloc_type_lookup): Map new relocations. (GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros. (GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros. (struct elf_i386_link_hash_entry): Add tlsdesc_got field. (struct elf_i386_obj_tdata): Add local_tlsdesc_gotent field. (elf_i386_local_tlsdesc_gotent): New macro. (struct elf_i386_link_hash_table): Add sgotplt_jump_table_size. (elf_i386_compute_jump_table_size): New macro. (link_hash_newfunc): Initialize tlsdesc_got. (elf_i386_link_hash_table_create): Set sgotplt_jump_table_size. (elf_i386_tls_transition): Handle R_386_TLS_GOTDESC and R_386_TLS_DESC_CALL. (elf_i386_check_relocs): Likewise. Allocate space for local_tlsdesc_gotent. (elf_i386_gc_sweep_hook): Handle R_386_TLS_GOTDESC and R_386_TLS_DESC_CALL. (allocate_dynrelocs): Count function PLT relocations. Reserve space for TLS descriptors and relocations. (elf_i386_size_dynamic_sections): Reserve space for TLS descriptors and relocations. Set up sgotplt_jump_table_size. Don't zero reloc_count in srelplt. (elf_i386_always_size_sections): New. Set up _TLS_MODULE_BASE_. (elf_i386_relocate_section): Handle R_386_TLS_GOTDESC and R_386_TLS_DESC_CALL. (elf_i386_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P. (elf_backend_always_size_sections): Define. * elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC, R_X86_64_TLSDESC_CALL. (R_X86_64_standard): Adjust. (x86_64_reloc_map): Map new relocs. (elf64_x86_64_rtype_to_howto): New, split out of... (elf64_x86_64_info_to_howto): ... this function, and... (elf64_x86_64_reloc_type_lookup): ... use it to map elf_reloc_val. (GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros. (GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros. (struct elf64_x86_64_link_hash_entry): Add tlsdesc_got field. (struct elf64_x86_64_obj_tdata): Add local_tlsdesc_gotent field. (elf64_x86_64_local_tlsdesc_gotent): New macro. (struct elf64_x86_64_link_hash_table): Add tlsdesc_plt, tlsdesc_got and sgotplt_jump_table_size fields. (elf64_x86_64_compute_jump_table_size): New macro. (link_hash_newfunc): Initialize tlsdesc_got. (elf64_x86_64_link_hash_table_create): Initialize new fields. (elf64_x86_64_tls_transition): Handle R_X86_64_GOTPC32_TLSDESC and R_X86_64_TLSDESC_CALL. (elf64_x86_64_check_relocs): Likewise. Allocate space for local_tlsdesc_gotent. (elf64_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPC32_TLSDESC and R_X86_64_TLSDESC_CALL. (allocate_dynrelocs): Count function PLT relocations. Reserve space for TLS descriptors and relocations. (elf64_x86_64_size_dynamic_sections): Reserve space for TLS descriptors and relocations. Set up sgotplt_jump_table_size, tlsdesc_plt and tlsdesc_got. Make room for them. Don't zero reloc_count in srelplt. Add dynamic entries for DT_TLSDESC_PLT and DT_TLSDESC_GOT. (elf64_x86_64_always_size_sections): New. Set up _TLS_MODULE_BASE_. (elf64_x86_64_relocate_section): Handle R_386_TLS_GOTDESC and R_386_TLS_DESC_CALL. (elf64_x86_64_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P. (elf64_x86_64_finish_dynamic_sections): Set DT_TLSDESC_PLT and DT_TLSDESC_GOT. Set up TLS descriptor lazy resolver PLT entry. (elf_backend_always_size_sections): Define. binutils/ChangeLog: Introduce TLS descriptors for i386 and x86_64. * readelf.c (get_dynamic_type): Handle DT_TLSDESC_GOT and DT_TLSDESC_PLT. gas/ChangeLog: Introduce TLS descriptors for i386 and x86_64. * config/tc-i386.c (tc_i386_fix_adjustable): Handle BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL. (optimize_disp): Emit fix up for BFD_RELOC_386_TLS_DESC_CALL and BFD_RELOC_X86_64_TLSDESC_CALL immediately, and clear the displacement bits. (build_modrm_byte): Set up zero modrm for TLS desc calls. (lex_got): Handle @tlsdesc and @tlscall. (md_apply_fix, tc_gen_reloc): Handle the new relocations. ld/testsuite/ChangeLog: Introduce TLS descriptors for i386 and x86_64. * ld-i386/i386.exp: Run on x86_64-*-linux* and amd64-*-linux*. Add new tests. * ld-i386/pcrel16.d: Add -melf_i386. * ld-i386/pcrel8.d: Likewise. * ld-i386/tlsbindesc.dd: New. * ld-i386/tlsbindesc.rd: New. * ld-i386/tlsbindesc.s: New. * ld-i386/tlsbindesc.sd: New. * ld-i386/tlsbindesc.td: New. * ld-i386/tlsdesc.dd: New. * ld-i386/tlsdesc.rd: New. * ld-i386/tlsdesc.s: New. * ld-i386/tlsdesc.sd: New. * ld-i386/tlsdesc.td: New. * ld-i386/tlsgdesc.dd: New. * ld-i386/tlsgdesc.rd: New. * ld-i386/tlsgdesc.s: New. * ld-x86-64/x86-64.exp: Run new tests. * ld-x86-64/tlsbindesc.dd: New. * ld-x86-64/tlsbindesc.rd: New. * ld-x86-64/tlsbindesc.s: New. * ld-x86-64/tlsbindesc.sd: New. * ld-x86-64/tlsbindesc.td: New. * ld-x86-64/tlsdesc.dd: New. * ld-x86-64/tlsdesc.pd: New. * ld-x86-64/tlsdesc.rd: New. * ld-x86-64/tlsdesc.s: New. * ld-x86-64/tlsdesc.sd: New. * ld-x86-64/tlsdesc.td: New. * ld-x86-64/tlsgdesc.dd: New. * ld-x86-64/tlsgdesc.rd: New. * ld-x86-64/tlsgdesc.s: New. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3012ba7c2f8..fade6a7f4e3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,77 @@ +2006-01-18 Alexandre Oliva + + Introduce TLS descriptors for i386 and x86_64. + * reloc.c (BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC, + BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC, + BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL): New. + * libbfd.h, bfd-in2.h: Rebuilt. + * elf32-i386.c (elf_howto_table): New relocations. + (R_386_tls): Adjust. + (elf_i386_reloc_type_lookup): Map new relocations. + (GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros. + (GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros. + (struct elf_i386_link_hash_entry): Add tlsdesc_got field. + (struct elf_i386_obj_tdata): Add local_tlsdesc_gotent field. + (elf_i386_local_tlsdesc_gotent): New macro. + (struct elf_i386_link_hash_table): Add sgotplt_jump_table_size. + (elf_i386_compute_jump_table_size): New macro. + (link_hash_newfunc): Initialize tlsdesc_got. + (elf_i386_link_hash_table_create): Set sgotplt_jump_table_size. + (elf_i386_tls_transition): Handle R_386_TLS_GOTDESC and + R_386_TLS_DESC_CALL. + (elf_i386_check_relocs): Likewise. Allocate space for + local_tlsdesc_gotent. + (elf_i386_gc_sweep_hook): Handle R_386_TLS_GOTDESC and + R_386_TLS_DESC_CALL. + (allocate_dynrelocs): Count function PLT relocations. Reserve + space for TLS descriptors and relocations. + (elf_i386_size_dynamic_sections): Reserve space for TLS + descriptors and relocations. Set up sgotplt_jump_table_size. + Don't zero reloc_count in srelplt. + (elf_i386_always_size_sections): New. Set up _TLS_MODULE_BASE_. + (elf_i386_relocate_section): Handle R_386_TLS_GOTDESC and + R_386_TLS_DESC_CALL. + (elf_i386_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P. + (elf_backend_always_size_sections): Define. + * elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_GOTPC32_TLSDESC, + R_X86_64_TLSDESC, R_X86_64_TLSDESC_CALL. + (R_X86_64_standard): Adjust. + (x86_64_reloc_map): Map new relocs. + (elf64_x86_64_rtype_to_howto): New, split out of... + (elf64_x86_64_info_to_howto): ... this function, and... + (elf64_x86_64_reloc_type_lookup): ... use it to map elf_reloc_val. + (GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros. + (GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros. + (struct elf64_x86_64_link_hash_entry): Add tlsdesc_got field. + (struct elf64_x86_64_obj_tdata): Add local_tlsdesc_gotent field. + (elf64_x86_64_local_tlsdesc_gotent): New macro. + (struct elf64_x86_64_link_hash_table): Add tlsdesc_plt, + tlsdesc_got and sgotplt_jump_table_size fields. + (elf64_x86_64_compute_jump_table_size): New macro. + (link_hash_newfunc): Initialize tlsdesc_got. + (elf64_x86_64_link_hash_table_create): Initialize new fields. + (elf64_x86_64_tls_transition): Handle R_X86_64_GOTPC32_TLSDESC and + R_X86_64_TLSDESC_CALL. + (elf64_x86_64_check_relocs): Likewise. Allocate space for + local_tlsdesc_gotent. + (elf64_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPC32_TLSDESC and + R_X86_64_TLSDESC_CALL. + (allocate_dynrelocs): Count function PLT relocations. Reserve + space for TLS descriptors and relocations. + (elf64_x86_64_size_dynamic_sections): Reserve space for TLS + descriptors and relocations. Set up sgotplt_jump_table_size, + tlsdesc_plt and tlsdesc_got. Make room for them. Don't zero + reloc_count in srelplt. Add dynamic entries for DT_TLSDESC_PLT + and DT_TLSDESC_GOT. + (elf64_x86_64_always_size_sections): New. Set up + _TLS_MODULE_BASE_. + (elf64_x86_64_relocate_section): Handle R_386_TLS_GOTDESC and + R_386_TLS_DESC_CALL. + (elf64_x86_64_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P. + (elf64_x86_64_finish_dynamic_sections): Set DT_TLSDESC_PLT and + DT_TLSDESC_GOT. Set up TLS descriptor lazy resolver PLT entry. + (elf_backend_always_size_sections): Define. + 2006-01-17 H.J. Lu PR binutils/2096 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 3cf72f3c8b0..cae4ede6e9d 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -8,7 +8,8 @@ /* Main header file for the bfd library -- portable access to object files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -2661,6 +2662,9 @@ in the instruction. */ BFD_RELOC_386_TLS_DTPMOD32, BFD_RELOC_386_TLS_DTPOFF32, BFD_RELOC_386_TLS_TPOFF32, + BFD_RELOC_386_TLS_GOTDESC, + BFD_RELOC_386_TLS_DESC_CALL, + BFD_RELOC_386_TLS_DESC, /* x86-64/elf relocations */ BFD_RELOC_X86_64_GOT32, @@ -2681,6 +2685,9 @@ in the instruction. */ BFD_RELOC_X86_64_TPOFF32, BFD_RELOC_X86_64_GOTOFF64, BFD_RELOC_X86_64_GOTPC32, + BFD_RELOC_X86_64_GOTPC32_TLSDESC, + BFD_RELOC_X86_64_TLSDESC_CALL, + BFD_RELOC_X86_64_TLSDESC, /* ns32k relocations */ BFD_RELOC_NS32K_IMM_8, diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 061a9cb32d8..b8e87909282 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,6 +1,6 @@ /* Intel 80386/80486-specific support for 32-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -126,9 +126,19 @@ static reloc_howto_type elf_howto_table[]= HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_TLS_TPOFF32", TRUE, 0xffffffff, 0xffffffff, FALSE), + EMPTY_HOWTO (38), + HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_386_TLS_GOTDESC", + TRUE, 0xffffffff, 0xffffffff, FALSE), + HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL", + FALSE, 0, 0, FALSE), + HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_386_TLS_DESC", + TRUE, 0xffffffff, 0xffffffff, FALSE), /* Another gap. */ -#define R_386_tls (R_386_TLS_TPOFF32 + 1 - R_386_tls_offset) +#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset) #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls) /* GNU extension to record C++ vtable hierarchy. */ @@ -292,6 +302,18 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, TRACE ("BFD_RELOC_386_TLS_TPOFF32"); return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset]; + case BFD_RELOC_386_TLS_GOTDESC: + TRACE ("BFD_RELOC_386_TLS_GOTDESC"); + return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset]; + + case BFD_RELOC_386_TLS_DESC_CALL: + TRACE ("BFD_RELOC_386_TLS_DESC_CALL"); + return &elf_howto_table[R_386_TLS_DESC_CALL - R_386_tls_offset]; + + case BFD_RELOC_386_TLS_DESC: + TRACE ("BFD_RELOC_386_TLS_DESC"); + return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset]; + case BFD_RELOC_VTABLE_INHERIT: TRACE ("BFD_RELOC_VTABLE_INHERIT"); return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset]; @@ -559,7 +581,20 @@ struct elf_i386_link_hash_entry #define GOT_TLS_IE_POS 5 #define GOT_TLS_IE_NEG 6 #define GOT_TLS_IE_BOTH 7 +#define GOT_TLS_GDESC 8 +#define GOT_TLS_GD_BOTH_P(type) \ + ((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) +#define GOT_TLS_GD_P(type) \ + ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type)) +#define GOT_TLS_GDESC_P(type) \ + ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type)) +#define GOT_TLS_GD_ANY_P(type) \ + (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type)) 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; }; #define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent)) @@ -570,6 +605,9 @@ struct elf_i386_obj_tdata /* tls_type for each local got entry. */ char *local_got_tls_type; + + /* GOTPLT entries for TLS descriptors. */ + bfd_vma *local_tlsdesc_gotent; }; #define elf_i386_tdata(abfd) \ @@ -578,6 +616,9 @@ struct elf_i386_obj_tdata #define elf_i386_local_got_tls_type(abfd) \ (elf_i386_tdata (abfd)->local_got_tls_type) +#define elf_i386_local_tlsdesc_gotent(abfd) \ + (elf_i386_tdata (abfd)->local_tlsdesc_gotent) + static bfd_boolean elf_i386_mkobject (bfd *abfd) { @@ -620,6 +661,10 @@ struct elf_i386_link_hash_table bfd_vma offset; } tls_ldm_got; + /* 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; + /* Small local sym to section mapping cache. */ struct sym_sec_cache sym_sec; }; @@ -629,6 +674,9 @@ struct elf_i386_link_hash_table #define elf_i386_hash_table(p) \ ((struct elf_i386_link_hash_table *) ((p)->hash)) +#define elf_i386_compute_jump_table_size(htab) \ + ((htab)->srelplt->reloc_count * 4) + /* Create an entry in an i386 ELF linker hash table. */ static struct bfd_hash_entry * @@ -655,6 +703,7 @@ link_hash_newfunc (struct bfd_hash_entry *entry, eh = (struct elf_i386_link_hash_entry *) entry; eh->dyn_relocs = NULL; eh->tls_type = GOT_UNKNOWN; + eh->tlsdesc_got = (bfd_vma) -1; } return entry; @@ -686,6 +735,7 @@ elf_i386_link_hash_table_create (bfd *abfd) ret->sdynbss = NULL; ret->srelbss = NULL; ret->tls_ldm_got.refcount = 0; + ret->sgotplt_jump_table_size = 0; ret->sym_sec.abfd = NULL; ret->is_vxworks = 0; ret->srelplt2 = NULL; @@ -845,6 +895,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, int r_type, int is_local) switch (r_type) { case R_386_TLS_GD: + case R_386_TLS_GOTDESC: + case R_386_TLS_DESC_CALL: case R_386_TLS_IE_32: if (is_local) return R_386_TLS_LE_32; @@ -949,6 +1001,8 @@ elf_i386_check_relocs (bfd *abfd, case R_386_GOT32: case R_386_TLS_GD: + case R_386_TLS_GOTDESC: + case R_386_TLS_DESC_CALL: /* This symbol requires a global offset table entry. */ { int tls_type, old_tls_type; @@ -958,6 +1012,9 @@ elf_i386_check_relocs (bfd *abfd, default: case R_386_GOT32: tls_type = GOT_NORMAL; break; case R_386_TLS_GD: tls_type = GOT_TLS_GD; break; + case R_386_TLS_GOTDESC: + case R_386_TLS_DESC_CALL: + tls_type = GOT_TLS_GDESC; break; case R_386_TLS_IE_32: if (ELF32_R_TYPE (rel->r_info) == r_type) tls_type = GOT_TLS_IE_NEG; @@ -987,13 +1044,16 @@ elf_i386_check_relocs (bfd *abfd, 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_zalloc (abfd, size); if (local_got_refcounts == NULL) return FALSE; elf_local_got_refcounts (abfd) = local_got_refcounts; + elf_i386_local_tlsdesc_gotent (abfd) + = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info); elf_i386_local_got_tls_type (abfd) - = (char *) (local_got_refcounts + symtab_hdr->sh_info); + = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info); } local_got_refcounts[r_symndx] += 1; old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx]; @@ -1004,11 +1064,14 @@ elf_i386_check_relocs (bfd *abfd, /* If a TLS symbol is accessed using IE at least once, there is no point to use dynamic model for it. */ else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN - && (old_tls_type != GOT_TLS_GD + && (! GOT_TLS_GD_ANY_P (old_tls_type) || (tls_type & GOT_TLS_IE) == 0)) { - if ((old_tls_type & GOT_TLS_IE) && tls_type == GOT_TLS_GD) + if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type)) tls_type = old_tls_type; + else if (GOT_TLS_GD_ANY_P (old_tls_type) + && GOT_TLS_GD_ANY_P (tls_type)) + tls_type |= old_tls_type; else { (*_bfd_error_handler) @@ -1316,6 +1379,8 @@ elf_i386_gc_sweep_hook (bfd *abfd, break; case R_386_TLS_GD: + case R_386_TLS_GOTDESC: + case R_386_TLS_DESC_CALL: case R_386_TLS_IE_32: case R_386_TLS_IE: case R_386_TLS_GOTIE: @@ -1579,6 +1644,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* We also need to make an entry in the .rel.plt section. */ htab->srelplt->size += sizeof (Elf32_External_Rel); + htab->srelplt->reloc_count++; if (htab->is_vxworks && !info->shared) { @@ -1612,6 +1678,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->needs_plt = 0; } + eh = (struct elf_i386_link_hash_entry *) h; + eh->tlsdesc_got = (bfd_vma) -1; + /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary, make it a R_386_TLS_LE_32 requiring no TLS entry. */ if (h->got.refcount > 0 @@ -1635,11 +1704,22 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } s = htab->sgot; - h->got.offset = s->size; - s->size += 4; - /* R_386_TLS_GD needs 2 consecutive GOT slots. */ - if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE_BOTH) - s->size += 4; + if (GOT_TLS_GDESC_P (tls_type)) + { + eh->tlsdesc_got = htab->sgotplt->size + - elf_i386_compute_jump_table_size (htab); + htab->sgotplt->size += 8; + h->got.offset = (bfd_vma) -2; + } + if (! GOT_TLS_GDESC_P (tls_type) + || GOT_TLS_GD_P (tls_type)) + { + h->got.offset = s->size; + s->size += 4; + /* R_386_TLS_GD needs 2 consecutive GOT slots. */ + if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH) + s->size += 4; + } dyn = htab->elf.dynamic_sections_created; /* R_386_TLS_IE_32 needs one dynamic relocation, R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation, @@ -1648,21 +1728,23 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) global. */ if (tls_type == GOT_TLS_IE_BOTH) htab->srelgot->size += 2 * sizeof (Elf32_External_Rel); - else if ((tls_type == GOT_TLS_GD && h->dynindx == -1) + else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) || (tls_type & GOT_TLS_IE)) htab->srelgot->size += sizeof (Elf32_External_Rel); - else if (tls_type == GOT_TLS_GD) + else if (GOT_TLS_GD_P (tls_type)) htab->srelgot->size += 2 * sizeof (Elf32_External_Rel); - else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || h->root.type != bfd_link_hash_undefweak) + else if (! GOT_TLS_GDESC_P (tls_type) + && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) && (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) htab->srelgot->size += sizeof (Elf32_External_Rel); + if (GOT_TLS_GDESC_P (tls_type)) + htab->srelplt->size += sizeof (Elf32_External_Rel); } else h->got.offset = (bfd_vma) -1; - eh = (struct elf_i386_link_hash_entry *) h; if (eh->dyn_relocs == NULL) return TRUE; @@ -1810,6 +1892,7 @@ elf_i386_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; @@ -1852,25 +1935,42 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, locsymcount = symtab_hdr->sh_info; end_local_got = local_got + locsymcount; local_tls_type = elf_i386_local_got_tls_type (ibfd); + local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd); s = htab->sgot; srel = htab->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; - s->size += 4; - if (*local_tls_type == GOT_TLS_GD - || *local_tls_type == GOT_TLS_IE_BOTH) - s->size += 4; + if (GOT_TLS_GDESC_P (*local_tls_type)) + { + *local_tlsdesc_gotent = htab->sgotplt->size + - elf_i386_compute_jump_table_size (htab); + htab->sgotplt->size += 8; + *local_got = (bfd_vma) -2; + } + if (! GOT_TLS_GDESC_P (*local_tls_type) + || GOT_TLS_GD_P (*local_tls_type)) + { + *local_got = s->size; + s->size += 4; + if (GOT_TLS_GD_P (*local_tls_type) + || *local_tls_type == GOT_TLS_IE_BOTH) + s->size += 4; + } if (info->shared - || *local_tls_type == GOT_TLS_GD + || GOT_TLS_GD_ANY_P (*local_tls_type) || (*local_tls_type & GOT_TLS_IE)) { if (*local_tls_type == GOT_TLS_IE_BOTH) srel->size += 2 * sizeof (Elf32_External_Rel); - else + else if (GOT_TLS_GD_P (*local_tls_type) + || ! GOT_TLS_GDESC_P (*local_tls_type)) srel->size += sizeof (Elf32_External_Rel); + if (GOT_TLS_GDESC_P (*local_tls_type)) + htab->srelplt->size += sizeof (Elf32_External_Rel); } } else @@ -1914,6 +2014,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, sym dynamic relocs. */ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) 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->srelplt) + htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4; + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -1945,7 +2053,8 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ - s->reloc_count = 0; + if (s != htab->srelplt) + s->reloc_count = 0; } else { @@ -2032,6 +2141,41 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return TRUE; } +static bfd_boolean +elf_i386_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + asection *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_", + FALSE, FALSE, FALSE); + + if (tlsbase && tlsbase->type == STT_TLS) + { + 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 = (struct elf_link_hash_entry *)bh; + tlsbase->def_regular = 1; + tlsbase->other = STV_HIDDEN; + (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE); + } + } + + return TRUE; +} + /* Set the correct type for an x86 ELF section. We do this by the section name, which is a hack, but ought to work. */ @@ -2109,6 +2253,7 @@ elf_i386_relocate_section (bfd *output_bfd, Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; + bfd_vma *local_tlsdesc_gotents; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; @@ -2116,6 +2261,7 @@ elf_i386_relocate_section (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); + local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd); rel = relocs; relend = relocs + input_section->reloc_count; @@ -2127,7 +2273,7 @@ elf_i386_relocate_section (bfd *output_bfd, struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; - bfd_vma off; + bfd_vma off, offplt; bfd_vma relocation; bfd_boolean unresolved_reloc; bfd_reloc_status_type r; @@ -2549,6 +2695,8 @@ elf_i386_relocate_section (bfd *output_bfd, /* Fall through */ case R_386_TLS_GD: + case R_386_TLS_GOTDESC: + case R_386_TLS_DESC_CALL: case R_386_TLS_IE_32: case R_386_TLS_GOTIE: r_type = elf_i386_tls_transition (info, r_type, h == NULL); @@ -2563,7 +2711,9 @@ elf_i386_relocate_section (bfd *output_bfd, } if (tls_type == GOT_TLS_IE) tls_type = GOT_TLS_IE_NEG; - if (r_type == R_386_TLS_GD) + if (r_type == R_386_TLS_GD + || r_type == R_386_TLS_GOTDESC + || r_type == R_386_TLS_DESC_CALL) { if (tls_type == GOT_TLS_IE_POS) r_type = R_386_TLS_GOTIE; @@ -2637,6 +2787,63 @@ elf_i386_relocate_section (bfd *output_bfd, rel++; continue; } + else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) + { + /* GDesc -> LE transition. + It's originally something like: + leal x@tlsdesc(%ebx), %eax + + leal x@ntpoff, %eax + + Registers other than %eax may be set up here. */ + + unsigned int val, type; + bfd_vma roff; + + /* First, make sure it's a leal adding ebx to a + 32-bit offset into any register, although it's + probably almost always going to be eax. */ + roff = rel->r_offset; + BFD_ASSERT (roff >= 2); + type = bfd_get_8 (input_bfd, contents + roff - 2); + BFD_ASSERT (type == 0x8d); + val = bfd_get_8 (input_bfd, contents + roff - 1); + BFD_ASSERT ((val & 0xc7) == 0x83); + BFD_ASSERT (roff + 4 <= input_section->size); + + /* Now modify the instruction as appropriate. */ + /* aoliva FIXME: remove the above and xor the byte + below with 0x86. */ + bfd_put_8 (output_bfd, val ^ 0x86, + contents + roff - 1); + bfd_put_32 (output_bfd, -tpoff (info, relocation), + contents + roff); + continue; + } + else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) + { + /* GDesc -> LE transition. + It's originally: + call *(%eax) + Turn it into: + nop; nop */ + + unsigned int val, type; + bfd_vma roff; + + /* First, make sure it's a call *(%eax). */ + roff = rel->r_offset; + BFD_ASSERT (roff + 2 <= input_section->size); + type = bfd_get_8 (input_bfd, contents + roff); + BFD_ASSERT (type == 0xff); + val = bfd_get_8 (input_bfd, contents + roff + 1); + BFD_ASSERT (val == 0x10); + + /* Now modify the instruction as appropriate. */ + bfd_put_8 (output_bfd, 0x90, contents + roff); + bfd_put_8 (output_bfd, 0x90, contents + roff + 1); + continue; + } else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE) { unsigned int val, type; @@ -2751,13 +2958,17 @@ elf_i386_relocate_section (bfd *output_bfd, abort (); if (h != NULL) - off = h->got.offset; + { + off = h->got.offset; + offplt = elf_i386_hash_entry (h)->tlsdesc_got; + } else { if (local_got_offsets == NULL) abort (); off = local_got_offsets[r_symndx]; + offplt = local_tlsdesc_gotents[r_symndx]; } if ((off & 1) != 0) @@ -2767,35 +2978,77 @@ elf_i386_relocate_section (bfd *output_bfd, Elf_Internal_Rela outrel; bfd_byte *loc; int dr_type, indx; + asection *sreloc; if (htab->srelgot == NULL) abort (); + indx = h && h->dynindx != -1 ? h->dynindx : 0; + + if (GOT_TLS_GDESC_P (tls_type)) + { + outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC); + BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8 + <= htab->sgotplt->size); + outrel.r_offset = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + offplt + + htab->sgotplt_jump_table_size); + sreloc = htab->srelplt; + loc = sreloc->contents; + loc += sreloc->reloc_count++ + * sizeof (Elf32_External_Rel); + BFD_ASSERT (loc + sizeof (Elf32_External_Rel) + <= sreloc->contents + sreloc->size); + bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); + if (indx == 0) + { + BFD_ASSERT (! unresolved_reloc); + bfd_put_32 (output_bfd, + relocation - dtpoff_base (info), + htab->sgotplt->contents + offplt + + htab->sgotplt_jump_table_size + 4); + } + else + { + bfd_put_32 (output_bfd, 0, + htab->sgotplt->contents + offplt + + htab->sgotplt_jump_table_size + 4); + } + } + + sreloc = htab->srelgot; + outrel.r_offset = (htab->sgot->output_section->vma + htab->sgot->output_offset + off); - indx = h && h->dynindx != -1 ? h->dynindx : 0; - if (r_type == R_386_TLS_GD) + if (GOT_TLS_GD_P (tls_type)) dr_type = R_386_TLS_DTPMOD32; + else if (GOT_TLS_GDESC_P (tls_type)) + goto dr_done; else if (tls_type == GOT_TLS_IE_POS) dr_type = R_386_TLS_TPOFF; else dr_type = R_386_TLS_TPOFF32; + if (dr_type == R_386_TLS_TPOFF && indx == 0) bfd_put_32 (output_bfd, relocation - dtpoff_base (info), htab->sgot->contents + off); else if (dr_type == R_386_TLS_TPOFF32 && indx == 0) bfd_put_32 (output_bfd, dtpoff_base (info) - relocation, htab->sgot->contents + off); - else + else if (dr_type != R_386_TLS_DESC) bfd_put_32 (output_bfd, 0, htab->sgot->contents + off); outrel.r_info = ELF32_R_INFO (indx, dr_type); - loc = htab->srelgot->contents; - loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel); + + loc = sreloc->contents; + loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); + BFD_ASSERT (loc + sizeof (Elf32_External_Rel) + <= sreloc->contents + sreloc->size); bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); - if (r_type == R_386_TLS_GD) + if (GOT_TLS_GD_P (tls_type)) { if (indx == 0) { @@ -2811,8 +3064,10 @@ elf_i386_relocate_section (bfd *output_bfd, outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DTPOFF32); outrel.r_offset += 4; - htab->srelgot->reloc_count++; + sreloc->reloc_count++; loc += sizeof (Elf32_External_Rel); + BFD_ASSERT (loc + sizeof (Elf32_External_Rel) + <= sreloc->contents + sreloc->size); bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); } } @@ -2823,25 +3078,33 @@ elf_i386_relocate_section (bfd *output_bfd, htab->sgot->contents + off + 4); outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); outrel.r_offset += 4; - htab->srelgot->reloc_count++; + sreloc->reloc_count++; loc += sizeof (Elf32_External_Rel); bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); } + dr_done: if (h != NULL) h->got.offset |= 1; else local_got_offsets[r_symndx] |= 1; } - if (off >= (bfd_vma) -2) + if (off >= (bfd_vma) -2 + && ! GOT_TLS_GDESC_P (tls_type)) abort (); - if (r_type == ELF32_R_TYPE (rel->r_info)) + if (r_type == R_386_TLS_GOTDESC + || r_type == R_386_TLS_DESC_CALL) + { + relocation = htab->sgotplt_jump_table_size + offplt; + unresolved_reloc = FALSE; + } + else if (r_type == ELF32_R_TYPE (rel->r_info)) { bfd_vma g_o_t = htab->sgotplt->output_section->vma + htab->sgotplt->output_offset; relocation = htab->sgot->output_section->vma - + htab->sgot->output_offset + off - g_o_t; + + htab->sgot->output_offset + off - g_o_t; if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE) && tls_type == GOT_TLS_IE_BOTH) relocation += 4; @@ -2849,7 +3112,7 @@ elf_i386_relocate_section (bfd *output_bfd, relocation += g_o_t; unresolved_reloc = FALSE; } - else + else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) { unsigned int val, type; bfd_vma roff; @@ -2913,6 +3176,94 @@ elf_i386_relocate_section (bfd *output_bfd, rel++; continue; } + else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) + { + /* GDesc -> IE transition. + It's originally something like: + leal x@tlsdesc(%ebx), %eax + + Change it to: + movl x@gotntpoff(%ebx), %eax # before nop; nop + or: + movl x@gottpoff(%ebx), %eax # before negl %eax + + Registers other than %eax may be set up here. */ + + unsigned int val, type; + bfd_vma roff; + + /* First, make sure it's a leal adding ebx to a 32-bit + offset into any register, although it's probably + almost always going to be eax. */ + roff = rel->r_offset; + BFD_ASSERT (roff >= 2); + type = bfd_get_8 (input_bfd, contents + roff - 2); + BFD_ASSERT (type == 0x8d); + val = bfd_get_8 (input_bfd, contents + roff - 1); + BFD_ASSERT ((val & 0xc7) == 0x83); + BFD_ASSERT (roff + 4 <= input_section->size); + + /* Now modify the instruction as appropriate. */ + /* To turn a leal into a movl in the form we use it, it + suffices to change the first byte from 0x8d to 0x8b. + aoliva FIXME: should we decide to keep the leal, all + we have to do is remove the statement below, and + adjust the relaxation of R_386_TLS_DESC_CALL. */ + bfd_put_8 (output_bfd, 0x8b, contents + roff - 2); + + if (tls_type == GOT_TLS_IE_BOTH) + off += 4; + + bfd_put_32 (output_bfd, + htab->sgot->output_section->vma + + htab->sgot->output_offset + off + - htab->sgotplt->output_section->vma + - htab->sgotplt->output_offset, + contents + roff); + continue; + } + else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) + { + /* GDesc -> IE transition. + It's originally: + call *(%eax) + + Change it to: + nop; nop + or + negl %eax + depending on how we transformed the TLS_GOTDESC above. + */ + + unsigned int val, type; + bfd_vma roff; + + /* First, make sure it's a call *(%eax). */ + roff = rel->r_offset; + BFD_ASSERT (roff + 2 <= input_section->size); + type = bfd_get_8 (input_bfd, contents + roff); + BFD_ASSERT (type == 0xff); + val = bfd_get_8 (input_bfd, contents + roff + 1); + BFD_ASSERT (val == 0x10); + + /* Now modify the instruction as appropriate. */ + if (tls_type != GOT_TLS_IE_NEG) + { + /* nop; nop */ + bfd_put_8 (output_bfd, 0x90, contents + roff); + bfd_put_8 (output_bfd, 0x90, contents + roff + 1); + } + else + { + /* negl %eax */ + bfd_put_8 (output_bfd, 0xf7, contents + roff); + bfd_put_8 (output_bfd, 0xd8, contents + roff + 1); + } + + continue; + } + else + BFD_ASSERT (FALSE); break; case R_386_TLS_LDM: @@ -3220,7 +3571,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, } if (h->got.offset != (bfd_vma) -1 - && elf_i386_hash_entry(h)->tls_type != GOT_TLS_GD + && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type) && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0) { Elf_Internal_Rela rel; @@ -3555,6 +3906,7 @@ elf_i386_plt_sym_val (bfd_vma i, const asection *plt, #define elf_backend_reloc_type_class elf_i386_reloc_type_class #define elf_backend_relocate_section elf_i386_relocate_section #define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections +#define elf_backend_always_size_sections elf_i386_always_size_sections #define elf_backend_plt_sym_val elf_i386_plt_sym_val #include "elf32-target.h" diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 54914ba2d3d..5433771c13f 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1,5 +1,5 @@ /* X86-64 specific support for 64-bit ELF - Copyright 2000, 2001, 2002, 2003, 2004, 2005 + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Jan Hubicka . @@ -112,12 +112,31 @@ static reloc_howto_type x86_64_elf_howto_table[] = HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_X86_64_GOTPC32", FALSE, 0xffffffff, 0xffffffff, TRUE), + EMPTY_HOWTO (27), + EMPTY_HOWTO (28), + EMPTY_HOWTO (29), + EMPTY_HOWTO (30), + EMPTY_HOWTO (31), + EMPTY_HOWTO (32), + EMPTY_HOWTO (33), + HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0, + complain_overflow_bitfield, bfd_elf_generic_reloc, + "R_X86_64_GOTPC32_TLSDESC", + FALSE, 0xffffffff, 0xffffffff, TRUE), + HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, FALSE, 0, + complain_overflow_dont, bfd_elf_generic_reloc, + "R_X86_64_TLSDESC_CALL", + FALSE, 0, 0, FALSE), + HOWTO(R_X86_64_TLSDESC, 0, 4, 64, FALSE, 0, + complain_overflow_bitfield, bfd_elf_generic_reloc, + "R_X86_64_TLSDESC", + FALSE, MINUS_ONE, MINUS_ONE, FALSE), /* We have a gap in the reloc numbers here. R_X86_64_standard counts the number up to this point, and R_X86_64_vt_offset is the value to subtract from a reloc type of R_X86_64_GNU_VT* to form an index into this table. */ -#define R_X86_64_standard (R_X86_64_GOTPC32 + 1) +#define R_X86_64_standard (R_X86_64_TLSDESC + 1) #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) /* GNU extension to record C++ vtable hierarchy. */ @@ -166,14 +185,38 @@ static const struct elf_reloc_map x86_64_reloc_map[] = { BFD_RELOC_64_PCREL, R_X86_64_PC64, }, { BFD_RELOC_X86_64_GOTOFF64, R_X86_64_GOTOFF64, }, { BFD_RELOC_X86_64_GOTPC32, R_X86_64_GOTPC32, }, + { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, }, + { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, }, + { BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, }, { BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, { BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, }; +static reloc_howto_type * +elf64_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type) +{ + unsigned i; + + if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT + || r_type >= (unsigned int) R_X86_64_max) + { + if (r_type >= (unsigned int) R_X86_64_standard) + { + (*_bfd_error_handler) (_("%B: invalid relocation type %d"), + abfd, (int) r_type); + r_type = R_X86_64_NONE; + } + i = r_type; + } + else + i = r_type - (unsigned int) R_X86_64_vt_offset; + BFD_ASSERT (x86_64_elf_howto_table[i].type == r_type); + return &x86_64_elf_howto_table[i]; +} /* Given a BFD reloc type, return a HOWTO structure. */ static reloc_howto_type * -elf64_x86_64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, +elf64_x86_64_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) { unsigned int i; @@ -182,7 +225,8 @@ elf64_x86_64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, i++) { if (x86_64_reloc_map[i].bfd_reloc_val == code) - return &x86_64_elf_howto_table[i]; + return elf64_x86_64_rtype_to_howto (abfd, + x86_64_reloc_map[i].elf_reloc_val); } return 0; } @@ -193,23 +237,10 @@ static void elf64_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst) { - unsigned r_type, i; + unsigned r_type; r_type = ELF64_R_TYPE (dst->r_info); - if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT - || r_type >= (unsigned int) R_X86_64_max) - { - if (r_type >= (unsigned int) R_X86_64_standard) - { - (*_bfd_error_handler) (_("%B: invalid relocation type %d"), - abfd, (int) r_type); - r_type = R_X86_64_NONE; - } - i = r_type; - } - else - i = r_type - (unsigned int) R_X86_64_vt_offset; - cache_ptr->howto = &x86_64_elf_howto_table[i]; + cache_ptr->howto = elf64_x86_64_rtype_to_howto (abfd, r_type); BFD_ASSERT (r_type == cache_ptr->howto->type); } @@ -353,7 +384,20 @@ struct elf64_x86_64_link_hash_entry #define GOT_NORMAL 1 #define GOT_TLS_GD 2 #define GOT_TLS_IE 3 +#define GOT_TLS_GDESC 4 +#define GOT_TLS_GD_BOTH_P(type) \ + ((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) +#define GOT_TLS_GD_P(type) \ + ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type)) +#define GOT_TLS_GDESC_P(type) \ + ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type)) +#define GOT_TLS_GD_ANY_P(type) \ + (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type)) 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; }; #define elf64_x86_64_hash_entry(ent) \ @@ -365,6 +409,9 @@ struct elf64_x86_64_obj_tdata /* tls_type for each local got entry. */ char *local_got_tls_type; + + /* GOTPLT entries for TLS descriptors. */ + bfd_vma *local_tlsdesc_gotent; }; #define elf64_x86_64_tdata(abfd) \ @@ -373,6 +420,8 @@ struct elf64_x86_64_obj_tdata #define elf64_x86_64_local_got_tls_type(abfd) \ (elf64_x86_64_tdata (abfd)->local_got_tls_type) +#define elf64_x86_64_local_tlsdesc_gotent(abfd) \ + (elf64_x86_64_tdata (abfd)->local_tlsdesc_gotent) /* x86-64 ELF linker hash table. */ @@ -389,11 +438,23 @@ struct elf64_x86_64_link_hash_table asection *sdynbss; asection *srelbss; + /* 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 tlsdesc_plt; + /* The offset into sgot of the GOT entry used by the PLT entry + above. */ + bfd_vma tlsdesc_got; + union { bfd_signed_vma refcount; bfd_vma offset; } tls_ld_got; + /* The amount of space used by the jump slots in the GOT. */ + bfd_vma sgotplt_jump_table_size; + /* Small local sym to section mapping cache. */ struct sym_sec_cache sym_sec; }; @@ -403,6 +464,9 @@ struct elf64_x86_64_link_hash_table #define elf64_x86_64_hash_table(p) \ ((struct elf64_x86_64_link_hash_table *) ((p)->hash)) +#define elf64_x86_64_compute_jump_table_size(htab) \ + ((htab)->srelplt->reloc_count * GOT_ENTRY_SIZE) + /* Create an entry in an x86-64 ELF linker hash table. */ static struct bfd_hash_entry * @@ -428,6 +492,7 @@ link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, eh = (struct elf64_x86_64_link_hash_entry *) entry; eh->dyn_relocs = NULL; eh->tls_type = GOT_UNKNOWN; + eh->tlsdesc_got = (bfd_vma) -1; } return entry; @@ -459,7 +524,10 @@ elf64_x86_64_link_hash_table_create (bfd *abfd) ret->sdynbss = NULL; ret->srelbss = NULL; ret->sym_sec.abfd = NULL; + ret->tlsdesc_plt = 0; + ret->tlsdesc_got = 0; ret->tls_ld_got.refcount = 0; + ret->sgotplt_jump_table_size = 0; return &ret->elf.root; } @@ -616,6 +684,8 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, int r_type, int is_loca switch (r_type) { case R_X86_64_TLSGD: + case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: if (is_local) return R_X86_64_TPOFF32; @@ -706,6 +776,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, case R_X86_64_GOT32: case R_X86_64_GOTPCREL: case R_X86_64_TLSGD: + case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_TLSDESC_CALL: /* This symbol requires a global offset table entry. */ { int tls_type, old_tls_type; @@ -715,6 +787,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, default: tls_type = GOT_NORMAL; break; case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break; case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break; + case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_TLSDESC_CALL: + tls_type = GOT_TLS_GDESC; break; } if (h != NULL) @@ -733,14 +808,17 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, 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; + elf64_x86_64_local_tlsdesc_gotent (abfd) + = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info); elf64_x86_64_local_got_tls_type (abfd) - = (char *) (local_got_refcounts + symtab_hdr->sh_info); + = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info); } local_got_refcounts[r_symndx] += 1; old_tls_type @@ -750,10 +828,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, /* If a TLS symbol is accessed using IE at least once, there is no point to use dynamic model for it. */ if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN - && (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE)) + && (! GOT_TLS_GD_ANY_P (old_tls_type) + || tls_type != GOT_TLS_IE)) { - if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD) + if (old_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (tls_type)) tls_type = old_tls_type; + else if (GOT_TLS_GD_ANY_P (old_tls_type) + && GOT_TLS_GD_ANY_P (tls_type)) + tls_type |= old_tls_type; else { (*_bfd_error_handler) @@ -1101,6 +1183,8 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, break; case R_X86_64_TLSGD: + case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: case R_X86_64_GOT32: case R_X86_64_GOTPCREL: @@ -1368,6 +1452,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* We also need to make an entry in the .rela.plt section. */ htab->srelplt->size += sizeof (Elf64_External_Rela); + htab->srelplt->reloc_count++; } else { @@ -1381,6 +1466,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) h->needs_plt = 0; } + eh = (struct elf64_x86_64_link_hash_entry *) h; + eh->tlsdesc_got = (bfd_vma) -1; + /* If R_X86_64_GOTTPOFF symbol is now local to the binary, make it a R_X86_64_TPOFF32 requiring no GOT entry. */ if (h->got.refcount > 0 @@ -1403,31 +1491,46 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) return FALSE; } - s = htab->sgot; - h->got.offset = s->size; - s->size += GOT_ENTRY_SIZE; - /* R_X86_64_TLSGD needs 2 consecutive GOT slots. */ - if (tls_type == GOT_TLS_GD) - s->size += GOT_ENTRY_SIZE; + if (GOT_TLS_GDESC_P (tls_type)) + { + eh->tlsdesc_got = htab->sgotplt->size + - elf64_x86_64_compute_jump_table_size (htab); + htab->sgotplt->size += 2 * GOT_ENTRY_SIZE; + h->got.offset = (bfd_vma) -2; + } + if (! GOT_TLS_GDESC_P (tls_type) + || GOT_TLS_GD_P (tls_type)) + { + s = htab->sgot; + h->got.offset = s->size; + s->size += GOT_ENTRY_SIZE; + if (GOT_TLS_GD_P (tls_type)) + s->size += GOT_ENTRY_SIZE; + } dyn = htab->elf.dynamic_sections_created; /* R_X86_64_TLSGD needs one dynamic relocation if local symbol and two if global. R_X86_64_GOTTPOFF needs one dynamic relocation. */ - if ((tls_type == GOT_TLS_GD && h->dynindx == -1) + if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) || tls_type == GOT_TLS_IE) htab->srelgot->size += sizeof (Elf64_External_Rela); - else if (tls_type == GOT_TLS_GD) + else if (GOT_TLS_GD_P (tls_type)) htab->srelgot->size += 2 * sizeof (Elf64_External_Rela); - else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || h->root.type != bfd_link_hash_undefweak) + else if (! GOT_TLS_GDESC_P (tls_type) + && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) && (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) htab->srelgot->size += sizeof (Elf64_External_Rela); + if (GOT_TLS_GDESC_P (tls_type)) + { + htab->srelplt->size += sizeof (Elf64_External_Rela); + htab->tlsdesc_plt = (bfd_vma) -1; + } } else h->got.offset = (bfd_vma) -1; - eh = (struct elf64_x86_64_link_hash_entry *) h; if (eh->dyn_relocs == NULL) return TRUE; @@ -1575,6 +1678,7 @@ elf64_x86_64_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; @@ -1618,20 +1722,43 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, locsymcount = symtab_hdr->sh_info; end_local_got = local_got + locsymcount; local_tls_type = elf64_x86_64_local_got_tls_type (ibfd); + local_tlsdesc_gotent = elf64_x86_64_local_tlsdesc_gotent (ibfd); s = htab->sgot; srel = htab->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; - s->size += GOT_ENTRY_SIZE; - if (*local_tls_type == GOT_TLS_GD) - s->size += GOT_ENTRY_SIZE; + if (GOT_TLS_GDESC_P (*local_tls_type)) + { + *local_tlsdesc_gotent = htab->sgotplt->size + - elf64_x86_64_compute_jump_table_size (htab); + htab->sgotplt->size += 2 * GOT_ENTRY_SIZE; + *local_got = (bfd_vma) -2; + } + if (! GOT_TLS_GDESC_P (*local_tls_type) + || GOT_TLS_GD_P (*local_tls_type)) + { + *local_got = s->size; + s->size += GOT_ENTRY_SIZE; + if (GOT_TLS_GD_P (*local_tls_type)) + s->size += GOT_ENTRY_SIZE; + } if (info->shared - || *local_tls_type == GOT_TLS_GD + || GOT_TLS_GD_ANY_P (*local_tls_type) || *local_tls_type == GOT_TLS_IE) - srel->size += sizeof (Elf64_External_Rela); + { + if (GOT_TLS_GDESC_P (*local_tls_type)) + { + htab->srelplt->size += sizeof (Elf64_External_Rela); + htab->tlsdesc_plt = (bfd_vma) -1; + } + if (! GOT_TLS_GDESC_P (*local_tls_type) + || GOT_TLS_GD_P (*local_tls_type)) + srel->size += sizeof (Elf64_External_Rela); + } } else *local_got = (bfd_vma) -1; @@ -1653,6 +1780,34 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, sym dynamic relocs. */ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) 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->srelplt) + htab->sgotplt_jump_table_size + = elf64_x86_64_compute_jump_table_size (htab); + + if (htab->tlsdesc_plt) + { + /* 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->tlsdesc_plt = 0; + else + { + htab->tlsdesc_got = htab->sgot->size; + htab->sgot->size += GOT_ENTRY_SIZE; + /* Reserve room for the initial entry. + FIXME: we could probably do away with it in this case. */ + if (htab->splt->size == 0) + htab->splt->size += PLT_ENTRY_SIZE; + htab->tlsdesc_plt = htab->splt->size; + htab->splt->size += PLT_ENTRY_SIZE; + } + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -1676,7 +1831,8 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ - s->reloc_count = 0; + if (s != htab->srelplt) + s->reloc_count = 0; } else { @@ -1736,6 +1892,11 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, || !add_dynamic_entry (DT_PLTREL, DT_RELA) || !add_dynamic_entry (DT_JMPREL, 0)) return FALSE; + + if (htab->tlsdesc_plt + && (!add_dynamic_entry (DT_TLSDESC_PLT, 0) + || !add_dynamic_entry (DT_TLSDESC_GOT, 0))) + return FALSE; } if (relocs) @@ -1763,6 +1924,41 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return TRUE; } +static bfd_boolean +elf64_x86_64_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + asection *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_", + FALSE, FALSE, FALSE); + + if (tlsbase && tlsbase->type == STT_TLS) + { + 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 = (struct elf_link_hash_entry *)bh; + tlsbase->def_regular = 1; + tlsbase->other = STV_HIDDEN; + (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE); + } + } + + return TRUE; +} + /* Return the base VMA address which should be subtracted from real addresses when resolving @dtpoff relocation. This is PT_TLS segment p_vaddr. */ @@ -1821,6 +2017,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; + bfd_vma *local_tlsdesc_gotents; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; @@ -1831,6 +2028,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); + local_tlsdesc_gotents = elf64_x86_64_local_tlsdesc_gotent (input_bfd); rel = relocs; relend = relocs + input_section->reloc_count; @@ -1842,7 +2040,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; - bfd_vma off; + bfd_vma off, offplt; bfd_vma relocation; bfd_boolean unresolved_reloc; bfd_reloc_status_type r; @@ -2201,6 +2399,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, break; case R_X86_64_TLSGD: + case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL); tls_type = GOT_UNKNOWN; @@ -2212,7 +2412,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE) r_type = R_X86_64_TPOFF32; } - if (r_type == R_X86_64_TLSGD) + if (r_type == R_X86_64_TLSGD + || r_type == R_X86_64_GOTPC32_TLSDESC + || r_type == R_X86_64_TLSDESC_CALL) { if (tls_type == GOT_TLS_IE) r_type = R_X86_64_GOTTPOFF; @@ -2254,6 +2456,67 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, rel++; continue; } + else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) + { + /* GDesc -> LE transition. + It's originally something like: + leaq x@tlsdesc(%rip), %rax + + Change it to: + movl $x@tpoff, %rax + + Registers other than %rax may be set up here. */ + + unsigned int val, type, type2; + bfd_vma roff; + + /* First, make sure it's a leaq adding rip to a + 32-bit offset into any register, although it's + probably almost always going to be rax. */ + roff = rel->r_offset; + BFD_ASSERT (roff >= 3); + type = bfd_get_8 (input_bfd, contents + roff - 3); + BFD_ASSERT ((type & 0xfb) == 0x48); + type2 = bfd_get_8 (input_bfd, contents + roff - 2); + BFD_ASSERT (type2 == 0x8d); + val = bfd_get_8 (input_bfd, contents + roff - 1); + BFD_ASSERT ((val & 0xc7) == 0x05); + BFD_ASSERT (roff + 4 <= input_section->size); + + /* Now modify the instruction as appropriate. */ + bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1), + contents + roff - 3); + bfd_put_8 (output_bfd, 0xc7, contents + roff - 2); + bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7), + contents + roff - 1); + bfd_put_32 (output_bfd, tpoff (info, relocation), + contents + roff); + continue; + } + else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) + { + /* GDesc -> LE transition. + It's originally: + call *(%rax) + Turn it into: + nop; nop. */ + + unsigned int val, type; + bfd_vma roff; + + /* First, make sure it's a call *(%rax). */ + roff = rel->r_offset; + BFD_ASSERT (roff + 2 <= input_section->size); + type = bfd_get_8 (input_bfd, contents + roff); + BFD_ASSERT (type == 0xff); + val = bfd_get_8 (input_bfd, contents + roff + 1); + BFD_ASSERT (val == 0x10); + + /* Now modify the instruction as appropriate. */ + bfd_put_8 (output_bfd, 0x90, contents + roff); + bfd_put_8 (output_bfd, 0x90, contents + roff + 1); + continue; + } else { unsigned int val, type, reg; @@ -2319,13 +2582,17 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, abort (); if (h != NULL) - off = h->got.offset; + { + off = h->got.offset; + offplt = elf64_x86_64_hash_entry (h)->tlsdesc_got; + } else { if (local_got_offsets == NULL) abort (); off = local_got_offsets[r_symndx]; + offplt = local_tlsdesc_gotents[r_symndx]; } if ((off & 1) != 0) @@ -2335,30 +2602,61 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, Elf_Internal_Rela outrel; bfd_byte *loc; int dr_type, indx; + asection *sreloc; if (htab->srelgot == NULL) abort (); + indx = h && h->dynindx != -1 ? h->dynindx : 0; + + if (GOT_TLS_GDESC_P (tls_type)) + { + outrel.r_info = ELF64_R_INFO (indx, R_X86_64_TLSDESC); + BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + + 2 * GOT_ENTRY_SIZE <= htab->sgotplt->size); + outrel.r_offset = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + offplt + + htab->sgotplt_jump_table_size); + sreloc = htab->srelplt; + loc = sreloc->contents; + loc += sreloc->reloc_count++ + * sizeof (Elf64_External_Rela); + BFD_ASSERT (loc + sizeof (Elf64_External_Rela) + <= sreloc->contents + sreloc->size); + if (indx == 0) + outrel.r_addend = relocation - dtpoff_base (info); + else + outrel.r_addend = 0; + bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); + } + + sreloc = htab->srelgot; + outrel.r_offset = (htab->sgot->output_section->vma + htab->sgot->output_offset + off); - indx = h && h->dynindx != -1 ? h->dynindx : 0; - if (r_type == R_X86_64_TLSGD) + if (GOT_TLS_GD_P (tls_type)) dr_type = R_X86_64_DTPMOD64; + else if (GOT_TLS_GDESC_P (tls_type)) + goto dr_done; else dr_type = R_X86_64_TPOFF64; bfd_put_64 (output_bfd, 0, htab->sgot->contents + off); outrel.r_addend = 0; - if (dr_type == R_X86_64_TPOFF64 && indx == 0) + if ((dr_type == R_X86_64_TPOFF64 + || dr_type == R_X86_64_TLSDESC) && indx == 0) outrel.r_addend = relocation - dtpoff_base (info); outrel.r_info = ELF64_R_INFO (indx, dr_type); - loc = htab->srelgot->contents; - loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); + loc = sreloc->contents; + loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); + BFD_ASSERT (loc + sizeof (Elf64_External_Rela) + <= sreloc->contents + sreloc->size); bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); - if (r_type == R_X86_64_TLSGD) + if (GOT_TLS_GD_P (tls_type)) { if (indx == 0) { @@ -2374,27 +2672,37 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, outrel.r_info = ELF64_R_INFO (indx, R_X86_64_DTPOFF64); outrel.r_offset += GOT_ENTRY_SIZE; - htab->srelgot->reloc_count++; + sreloc->reloc_count++; loc += sizeof (Elf64_External_Rela); + BFD_ASSERT (loc + sizeof (Elf64_External_Rela) + <= sreloc->contents + sreloc->size); bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); } } + dr_done: if (h != NULL) h->got.offset |= 1; else local_got_offsets[r_symndx] |= 1; } - if (off >= (bfd_vma) -2) + if (off >= (bfd_vma) -2 + && ! GOT_TLS_GDESC_P (tls_type)) abort (); if (r_type == ELF64_R_TYPE (rel->r_info)) { - relocation = htab->sgot->output_section->vma - + htab->sgot->output_offset + off; + if (r_type == R_X86_64_GOTPC32_TLSDESC + || r_type == R_X86_64_TLSDESC_CALL) + relocation = htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + offplt + htab->sgotplt_jump_table_size; + else + relocation = htab->sgot->output_section->vma + + htab->sgot->output_offset + off; unresolved_reloc = FALSE; } - else + else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD) { unsigned int i; static unsigned char tlsgd[8] @@ -2434,6 +2742,77 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, rel++; continue; } + else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) + { + /* GDesc -> IE transition. + It's originally something like: + leaq x@tlsdesc(%rip), %rax + + Change it to: + movq x@gottpoff(%rip), %rax # before nop; nop + + Registers other than %rax may be set up here. */ + + unsigned int val, type, type2; + bfd_vma roff; + + /* First, make sure it's a leaq adding rip to a 32-bit + offset into any register, although it's probably + almost always going to be rax. */ + roff = rel->r_offset; + BFD_ASSERT (roff >= 3); + type = bfd_get_8 (input_bfd, contents + roff - 3); + BFD_ASSERT ((type & 0xfb) == 0x48); + type2 = bfd_get_8 (input_bfd, contents + roff - 2); + BFD_ASSERT (type2 == 0x8d); + val = bfd_get_8 (input_bfd, contents + roff - 1); + BFD_ASSERT ((val & 0xc7) == 0x05); + BFD_ASSERT (roff + 4 <= input_section->size); + + /* Now modify the instruction as appropriate. */ + /* To turn a leaq into a movq in the form we use it, it + suffices to change the second byte from 0x8d to + 0x8b. */ + bfd_put_8 (output_bfd, 0x8b, contents + roff - 2); + + bfd_put_32 (output_bfd, + htab->sgot->output_section->vma + + htab->sgot->output_offset + off + - rel->r_offset + - input_section->output_section->vma + - input_section->output_offset + - 4, + contents + roff); + continue; + } + else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) + { + /* GDesc -> IE transition. + It's originally: + call *(%rax) + + Change it to: + nop; nop. */ + + unsigned int val, type; + bfd_vma roff; + + /* First, make sure it's a call *(%eax). */ + roff = rel->r_offset; + BFD_ASSERT (roff + 2 <= input_section->size); + type = bfd_get_8 (input_bfd, contents + roff); + BFD_ASSERT (type == 0xff); + val = bfd_get_8 (input_bfd, contents + roff + 1); + BFD_ASSERT (val == 0x10); + + /* Now modify the instruction as appropriate. */ + bfd_put_8 (output_bfd, 0x90, contents + roff); + bfd_put_8 (output_bfd, 0x90, contents + roff + 1); + + continue; + } + else + BFD_ASSERT (FALSE); break; case R_X86_64_TLSLD: @@ -2672,7 +3051,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, } if (h->got.offset != (bfd_vma) -1 - && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD + && ! GOT_TLS_GD_ANY_P (elf64_x86_64_hash_entry (h)->tls_type) && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE) { Elf_Internal_Rela rela; @@ -2827,6 +3206,18 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf dyn.d_un.d_val -= s->size; } break; + + case DT_TLSDESC_PLT: + s = htab->splt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset + + htab->tlsdesc_plt; + break; + + case DT_TLSDESC_GOT: + s = htab->sgot; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset + + htab->tlsdesc_got; + break; } bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); @@ -2861,6 +3252,40 @@ elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; + + if (htab->tlsdesc_plt) + { + bfd_put_64 (output_bfd, (bfd_vma) 0, + htab->sgot->contents + htab->tlsdesc_got); + + memcpy (htab->splt->contents + htab->tlsdesc_plt, + elf64_x86_64_plt0_entry, + PLT_ENTRY_SIZE); + + /* Add offset for pushq GOT+8(%rip), since the + instruction uses 6 bytes subtract this value. */ + bfd_put_32 (output_bfd, + (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + 8 + - htab->splt->output_section->vma + - htab->splt->output_offset + - htab->tlsdesc_plt + - 6), + htab->splt->contents + htab->tlsdesc_plt + 2); + /* Add offset for jmp *GOT+TDG(%rip), where TGD stands for + htab->tlsdesc_got. The 12 is the offset to the end of + the instruction. */ + bfd_put_32 (output_bfd, + (htab->sgot->output_section->vma + + htab->sgot->output_offset + + htab->tlsdesc_got + - htab->splt->output_section->vma + - htab->splt->output_offset + - htab->tlsdesc_plt + - 12), + htab->splt->contents + htab->tlsdesc_plt + 8); + } } } @@ -3132,6 +3557,7 @@ static const struct bfd_elf_special_section #define elf_backend_reloc_type_class elf64_x86_64_reloc_type_class #define elf_backend_relocate_section elf64_x86_64_relocate_section #define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections +#define elf_backend_always_size_sections elf64_x86_64_always_size_sections #define elf_backend_plt_sym_val elf64_x86_64_plt_sym_val #define elf_backend_object_p elf64_x86_64_elf_object_p #define bfd_elf64_mkobject elf64_x86_64_mkobject diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 5a8c2167b00..984ade3e7dd 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -7,7 +7,7 @@ (This include file is not for users of the library.) Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Written by Cygnus Support. @@ -1034,6 +1034,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_386_TLS_DTPMOD32", "BFD_RELOC_386_TLS_DTPOFF32", "BFD_RELOC_386_TLS_TPOFF32", + "BFD_RELOC_386_TLS_GOTDESC", + "BFD_RELOC_386_TLS_DESC_CALL", + "BFD_RELOC_386_TLS_DESC", "BFD_RELOC_X86_64_GOT32", "BFD_RELOC_X86_64_PLT32", "BFD_RELOC_X86_64_COPY", @@ -1052,6 +1055,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_X86_64_TPOFF32", "BFD_RELOC_X86_64_GOTOFF64", "BFD_RELOC_X86_64_GOTPC32", + "BFD_RELOC_X86_64_GOTPC32_TLSDESC", + "BFD_RELOC_X86_64_TLSDESC_CALL", + "BFD_RELOC_X86_64_TLSDESC", "BFD_RELOC_NS32K_IMM_8", "BFD_RELOC_NS32K_IMM_16", "BFD_RELOC_NS32K_IMM_32", diff --git a/bfd/reloc.c b/bfd/reloc.c index 14c3392fb78..98246c8d381 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -1,6 +1,6 @@ /* BFD support for handling relocation entries. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005 + 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Written by Cygnus Support. @@ -2298,6 +2298,12 @@ ENUMX BFD_RELOC_386_TLS_DTPOFF32 ENUMX BFD_RELOC_386_TLS_TPOFF32 +ENUMX + BFD_RELOC_386_TLS_GOTDESC +ENUMX + BFD_RELOC_386_TLS_DESC_CALL +ENUMX + BFD_RELOC_386_TLS_DESC ENUMDOC i386/elf relocations @@ -2337,6 +2343,12 @@ ENUMX BFD_RELOC_X86_64_GOTOFF64 ENUMX BFD_RELOC_X86_64_GOTPC32 +ENUMX + BFD_RELOC_X86_64_GOTPC32_TLSDESC +ENUMX + BFD_RELOC_X86_64_TLSDESC_CALL +ENUMX + BFD_RELOC_X86_64_TLSDESC ENUMDOC x86-64/elf relocations diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 999ebd82469..bbc0c9a0481 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2006-01-18 Alexandre Oliva + + Introduce TLS descriptors for i386 and x86_64. + * readelf.c (get_dynamic_type): Handle DT_TLSDESC_GOT and + DT_TLSDESC_PLT. + 2006-01-18 Nick Clifton PR binutils/1391 diff --git a/binutils/readelf.c b/binutils/readelf.c index b432b0bc831..f0385d0f9c8 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1480,6 +1480,8 @@ get_dynamic_type (unsigned long type) case DT_VERSYM: return "VERSYM"; + case DT_TLSDESC_GOT: return "TLSDESC_GOT"; + case DT_TLSDESC_PLT: return "TLSDESC_PLT"; case DT_RELACOUNT: return "RELACOUNT"; case DT_RELCOUNT: return "RELCOUNT"; case DT_FLAGS_1: return "FLAGS_1"; diff --git a/gas/ChangeLog b/gas/ChangeLog index 977f5a1d2f0..e93cecec94d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2006-01-18 Alexandre Oliva + + Introduce TLS descriptors for i386 and x86_64. + * config/tc-i386.c (tc_i386_fix_adjustable): Handle + BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL, + BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL. + (optimize_disp): Emit fix up for BFD_RELOC_386_TLS_DESC_CALL and + BFD_RELOC_X86_64_TLSDESC_CALL immediately, and clear the + displacement bits. + (build_modrm_byte): Set up zero modrm for TLS desc calls. + (lex_got): Handle @tlsdesc and @tlscall. + (md_apply_fix, tc_gen_reloc): Handle the new relocations. + 2006-01-11 Nick Clifton Fixes for building on 64-bit hosts: diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index f9804e064ee..337149ee76d 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1,6 +1,6 @@ /* i386.c -- Assemble code for the Intel 80386 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005 + 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -1345,6 +1345,8 @@ tc_i386_fix_adjustable (fixP) || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32 || fixP->fx_r_type == BFD_RELOC_386_TLS_LE + || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTDESC + || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32 || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32 || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL @@ -1356,6 +1358,8 @@ tc_i386_fix_adjustable (fixP) || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32 || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64 || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64 + || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC + || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 0; @@ -2196,7 +2200,14 @@ optimize_disp () && fits_in_signed_byte (disp)) i.types[op] |= Disp8; } - else + else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL + || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL) + { + fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0, + i.op[op].disps, 0, i.reloc[op]); + i.types[op] &= ~Disp; + } + else /* We only support 64bit displacement on constants. */ i.types[op] &= ~Disp64; } @@ -3157,7 +3168,13 @@ build_modrm_byte () if ((i.index_reg->reg_flags & RegRex) != 0) i.rex |= REX_EXTY; } - i.rm.mode = mode_from_disp_size (i.types[op]); + + if (i.disp_operands + && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL + || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)) + i.rm.mode = 0; + else + i.rm.mode = mode_from_disp_size (i.types[op]); } if (fake_zero_displacement) @@ -3856,7 +3873,9 @@ lex_got (enum bfd_reloc_code_real *reloc, { "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 }, { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0 }, 0 }, { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0 }, 0 }, - { "GOT", { BFD_RELOC_386_GOT32, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32 } + { "GOT", { BFD_RELOC_386_GOT32, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32 }, + { "TLSDESC", { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 }, + { "TLSCALL", { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 } }; char *cp; unsigned int j; @@ -5063,9 +5082,11 @@ md_apply_fix (fixP, valP, seg) case BFD_RELOC_386_TLS_IE_32: case BFD_RELOC_386_TLS_IE: case BFD_RELOC_386_TLS_GOTIE: + case BFD_RELOC_386_TLS_GOTDESC: case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_GOTPC32_TLSDESC: value = 0; /* Fully resolved at runtime. No addend. */ /* Fallthrough */ case BFD_RELOC_386_TLS_LE: @@ -5078,6 +5099,13 @@ md_apply_fix (fixP, valP, seg) S_SET_THREAD_LOCAL (fixP->fx_addsy); break; + case BFD_RELOC_386_TLS_DESC_CALL: + case BFD_RELOC_X86_64_TLSDESC_CALL: + value = 0; /* Fully resolved at runtime. No addend. */ + S_SET_THREAD_LOCAL (fixP->fx_addsy); + fixP->fx_done = 0; + return; + case BFD_RELOC_386_GOT32: case BFD_RELOC_X86_64_GOT32: value = 0; /* Fully resolved at runtime. No addend. */ @@ -5655,6 +5683,8 @@ tc_gen_reloc (section, fixp) case BFD_RELOC_386_TLS_GOTIE: case BFD_RELOC_386_TLS_LE_32: case BFD_RELOC_386_TLS_LE: + case BFD_RELOC_386_TLS_GOTDESC: + case BFD_RELOC_386_TLS_DESC_CALL: case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_DTPOFF32: @@ -5664,6 +5694,8 @@ tc_gen_reloc (section, fixp) case BFD_RELOC_X86_64_TPOFF64: case BFD_RELOC_X86_64_GOTOFF64: case BFD_RELOC_X86_64_GOTPC32: + case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_TLSDESC_CALL: case BFD_RELOC_RVA: case BFD_RELOC_VTABLE_ENTRY: case BFD_RELOC_VTABLE_INHERIT: @@ -5760,6 +5792,8 @@ tc_gen_reloc (section, fixp) case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_TLSDESC_CALL: rel->addend = fixp->fx_offset - fixp->fx_size; break; default: diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 372bef5588b..1bac01d0e9f 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,12 @@ +2006-01-18 Alexandre Oliva + + Introduce TLS descriptors for i386 and x86_64. + * common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New. + * i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC_CALL, R_386_TLS_DESC): + New. + * x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL, + R_X86_64_TLSDESC): New. + 2006-01-09 Mike Frysinger : * common.h (EM_ALTERA_NIOS2, EM_NIOS32) Define. diff --git a/include/elf/common.h b/include/elf/common.h index 0108c4f7ad6..350d63b64d8 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -1,6 +1,6 @@ /* ELF support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004 + 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published @@ -576,6 +576,8 @@ #define DT_VALRNGHI 0x6ffffdff #define DT_ADDRRNGLO 0x6ffffe00 +#define DT_TLSDESC_PLT 0x6ffffef6 +#define DT_TLSDESC_GOT 0x6ffffef7 #define DT_GNU_CONFLICT 0x6ffffef8 #define DT_GNU_LIBLIST 0x6ffffef9 #define DT_CONFIG 0x6ffffefa diff --git a/include/elf/i386.h b/include/elf/i386.h index 5a4d3306deb..e167871f34a 100644 --- a/include/elf/i386.h +++ b/include/elf/i386.h @@ -1,5 +1,6 @@ /* ix86 ELF support for BFD. - Copyright 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2002, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -61,6 +62,10 @@ START_RELOC_NUMBERS (elf_i386_reloc_type) RELOC_NUMBER (R_386_TLS_DTPMOD32, 35) RELOC_NUMBER (R_386_TLS_DTPOFF32, 36) RELOC_NUMBER (R_386_TLS_TPOFF32, 37) +/* 38 */ + RELOC_NUMBER (R_386_TLS_GOTDESC, 39) + RELOC_NUMBER (R_386_TLS_DESC_CALL,40) + RELOC_NUMBER (R_386_TLS_DESC, 41) /* Used by Intel. */ RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200) diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h index 309be6bfc03..74655fbcd03 100644 --- a/include/elf/x86-64.h +++ b/include/elf/x86-64.h @@ -1,5 +1,6 @@ /* x86_64 ELF support for BFD. - Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006 + Free Software Foundation, Inc. Contributed by Jan Hubicka This file is part of BFD, the Binary File Descriptor library. @@ -53,6 +54,14 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type) RELOC_NUMBER (R_X86_64_GOTOFF64, 25) /* 64 bit offset to GOT */ RELOC_NUMBER (R_X86_64_GOTPC32, 26) /* 32 bit signed pc relative offset to GOT */ + /* 27 .. 33 */ + RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34) + /* 32 bit signed pc relative + offset to TLS descriptor + in the GOT. */ + RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 35) /* Relaxable call through TLS + descriptor. */ + RELOC_NUMBER (R_X86_64_TLSDESC, 36) /* 2x64-bit TLS descriptor. */ RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */ RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */ END_RELOC_NUMBERS (R_X86_64_max) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 63da63dbd7d..62d63186089 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,39 @@ +2006-01-18 Alexandre Oliva + + Introduce TLS descriptors for i386 and x86_64. + * ld-i386/i386.exp: Run on x86_64-*-linux* and amd64-*-linux*. + Add new tests. + * ld-i386/pcrel16.d: Add -melf_i386. + * ld-i386/pcrel8.d: Likewise. + * ld-i386/tlsbindesc.dd: New. + * ld-i386/tlsbindesc.rd: New. + * ld-i386/tlsbindesc.s: New. + * ld-i386/tlsbindesc.sd: New. + * ld-i386/tlsbindesc.td: New. + * ld-i386/tlsdesc.dd: New. + * ld-i386/tlsdesc.rd: New. + * ld-i386/tlsdesc.s: New. + * ld-i386/tlsdesc.sd: New. + * ld-i386/tlsdesc.td: New. + * ld-i386/tlsgdesc.dd: New. + * ld-i386/tlsgdesc.rd: New. + * ld-i386/tlsgdesc.s: New. + * ld-x86-64/x86-64.exp: Run new tests. + * ld-x86-64/tlsbindesc.dd: New. + * ld-x86-64/tlsbindesc.rd: New. + * ld-x86-64/tlsbindesc.s: New. + * ld-x86-64/tlsbindesc.sd: New. + * ld-x86-64/tlsbindesc.td: New. + * ld-x86-64/tlsdesc.dd: New. + * ld-x86-64/tlsdesc.pd: New. + * ld-x86-64/tlsdesc.rd: New. + * ld-x86-64/tlsdesc.s: New. + * ld-x86-64/tlsdesc.sd: New. + * ld-x86-64/tlsdesc.td: New. + * ld-x86-64/tlsgdesc.dd: New. + * ld-x86-64/tlsgdesc.rd: New. + * ld-x86-64/tlsgdesc.s: New. + 2006-01-03 Hans-Peter Nilsson * ld-mmix/sec-1.d: Adjust for section order changes. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 05343f0297e..4a170cdd10e 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -1,5 +1,5 @@ # Expect script for ld-i386 tests -# Copyright (C) 2002 Free Software Foundation +# Copyright (C) 2002, 2005, 2006 Free Software Foundation # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -22,7 +22,9 @@ if { !([istarget "i?86-*-elf*"] || ([istarget "i?86-*-linux*"] && ![istarget "*-*-*aout*"] - && ![istarget "*-*-*oldld*"])) } { + && ![istarget "*-*-*oldld*"]) + || [istarget "x86_64-*-linux*"] + || [istarget "amd64-*-linux*"]) } { return } @@ -41,6 +43,11 @@ set i386tests { {{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd} {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}} "libtlspic.so"} + {"TLS descriptor -fpic -shared transitions" "-shared -melf_i386" + "--32" {tlsdesc.s tlspic2.s} + {{readelf -Ssrl tlsdesc.rd} {objdump -drj.text tlsdesc.dd} + {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}} + "libtlsdesc.so"} {"Helper shared library" "-shared -melf_i386" "--32" {tlslib.s} {} "libtlslib.so"} {"TLS -fpic and -fno-pic exec transitions" @@ -48,10 +55,19 @@ set i386tests { {{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd} {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}} "tlsbin"} + {"TLS descriptor -fpic and -fno-pic exec transitions" + "-melf_i386 tmpdir/libtlslib.so" "--32" {tlsbindesc.s tlsbin.s} + {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd} + {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}} + "tlsbindesc"} {"TLS -fno-pic -shared" "-shared -melf_i386" "--32" {tlsnopic1.s tlsnopic2.s} {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd} {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"} + {"TLS with global dynamic and descriptors" + "-shared -melf_i386" "--32" {tlsgdesc.s} + {{readelf -Ssrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}} + "libtlsgdesc.so"} {"TLS in debug sections" "-melf_i386" "--32" {tlsg.s} {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"} diff --git a/ld/testsuite/ld-i386/pcrel16.d b/ld/testsuite/ld-i386/pcrel16.d index 0c438a95f58..3d45afeb42b 100644 --- a/ld/testsuite/ld-i386/pcrel16.d +++ b/ld/testsuite/ld-i386/pcrel16.d @@ -1,5 +1,6 @@ #name: PCREL16 overflow -#ld: -Ttext 0x0 +#as: --32 +#ld: -melf_i386 -Ttext 0x0 #objdump: -drj.text -m i8086 .*: +file format elf32-i386 diff --git a/ld/testsuite/ld-i386/pcrel8.d b/ld/testsuite/ld-i386/pcrel8.d index ed939a32fd5..208c64e4fad 100644 --- a/ld/testsuite/ld-i386/pcrel8.d +++ b/ld/testsuite/ld-i386/pcrel8.d @@ -1,3 +1,4 @@ #name: PCREL8 overflow -#ld: +#as: --32 +#ld: -melf_i386 #error: .*relocation truncated to fit: R_386_PC8 .* diff --git a/ld/testsuite/ld-i386/tlsbindesc.dd b/ld/testsuite/ld-i386/tlsbindesc.dd new file mode 100644 index 00000000000..071a5b32042 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsbindesc.dd @@ -0,0 +1,463 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --32 +#ld: -melf_i386 tmpdir/libtlslib.so +#objdump: -drj.text +#target: i?86-*-* + +# PT_TLS layout is: +# Offset from Offset from Name +# TCB base TCB end +# 0x00 -0xa0 sg1..sg8 +# 0x20 -0x80 sl1..sl8 +# 0x40 -0x60 sh1..sh8 +# 0x60 -0x40 bg1..bg8 +# 0x80 -0x20 bl1..bl8 + +.*: +file format elf32-i386 + +Disassembly of section .text: + +[0-9a-f]+ : + [0-9a-f]+: 55[ ]+push %ebp + [0-9a-f]+: 89 e5[ ]+mov %esp,%ebp + [0-9a-f]+: 53[ ]+push %ebx + [0-9a-f]+: 50[ ]+push %eax + [0-9a-f]+: e8 00 00 00 00[ ]+call [0-9a-f]+ + [0-9a-f]+: 5b[ ]+pop %ebx + [0-9a-f]+: 81 c3 fa 10 00 00[ ]+add \$0x10fa,%ebx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is not defined in executable + [0-9a-f]+: 8b 83 f8 ff ff ff[ ]+mov 0xfffffff8\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG1 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is not defined in executable where +# the variable is referenced through @gottpoff too + [0-9a-f]+: 8b 83 e8 ff ff ff[ ]+mov 0xffffffe8\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG2 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is not defined in executable where +# the variable is referenced through @gotntpoff too + [0-9a-f]+: 8b 83 dc ff ff ff[ ]+mov 0xffffffdc\(%ebx\),%eax +# ->R_386_TLS_TPOFF sG3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is not defined in executable where +# the variable is referenced through @gottpoff and @gotntpoff too + [0-9a-f]+: 8b 83 f0 ff ff ff[ ]+mov 0xfffffff0\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> LE with global variable defined in executable + [0-9a-f]+: 8d 05 00 f0 ff ff[ ]+lea 0xfffff000,%eax +# sg1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> LE with local variable defined in executable + [0-9a-f]+: 8d 05 20 f0 ff ff[ ]+lea 0xfffff020,%eax +# sl1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> LE with hidden variable defined in executable + [0-9a-f]+: 8d 05 40 f0 ff ff[ ]+lea 0xfffff040,%eax +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD -> LE + [0-9a-f]+: 8d 05 00 f0 ff ff[ ]+lea 0xfffff000,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 90 20 f0 ff ff[ ]+lea 0xfffff020\(%eax\),%edx +# sl1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 88 24 f0 ff ff[ ]+lea 0xfffff024\(%eax\),%ecx +# sl2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD -> LE against hidden variables + [0-9a-f]+: 8d 05 00 f0 ff ff[ ]+lea 0xfffff000,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 90 40 f0 ff ff[ ]+lea 0xfffff040\(%eax\),%edx +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 88 44 f0 ff ff[ ]+lea 0xfffff044\(%eax\),%ecx +# sh2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b e8 ff ff ff[ ]+sub 0xffffffe8\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 sG2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 83 ec ff ff ff[ ]+sub 0xffffffec\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b dc ff ff ff[ ]+add 0xffffffdc\(%ebx\),%ecx +# ->R_386_TLS_TPOFF sG3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against global var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 83 f0 ff ff ff[ ]+add 0xfffffff0\(%ebx\),%eax +# ->R_386_TLS_TPOFF sG4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE -> LE against global var defined in exec + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 e9 00 10 00 00[ ]+sub \$0x1000,%ecx +# sg1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE -> LE against local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 c0 20 f0 ff ff[ ]+add \$0xfffff020,%eax +# sl1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE -> LE against hidden var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 e9 c0 0f 00 00[ ]+sub \$0xfc0,%ecx +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# Direct access through %gs +# @gotntpoff IE against global var + [0-9a-f]+: 8b 8b e0 ff ff ff[ ]+mov 0xffffffe0\(%ebx\),%ecx +# ->R_386_TLS_TPOFF sG5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 11[ ]+mov %gs:\(%ecx\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE->LE against local var + [0-9a-f]+: c7 c0 30 f0 ff ff[ ]+mov \$0xfffff030,%eax +# sl5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 10[ ]+mov %gs:\(%eax\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE->LE against hidden var + [0-9a-f]+: c7 c2 50 f0 ff ff[ ]+mov \$0xfffff050,%edx +# sh5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 12[ ]+mov %gs:\(%edx\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8b 5d fc[ ]+mov 0xfffffffc\(%ebp\),%ebx + [0-9a-f]+: c9[ ]+leave * + [0-9a-f]+: c3[ ]+ret * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+ <_start>: + [0-9a-f]+: 55[ ]+push %ebp + [0-9a-f]+: 89 e5[ ]+mov %esp,%ebp + [0-9a-f]+: e8 00 00 00 00[ ]+call [0-9a-f]+ <_start\+0x8> + [0-9a-f]+: 59[ ]+pop %ecx + [0-9a-f]+: 81 c1 a4 0f 00 00[ ]+add \$0xfa4,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 91 f4 ff ff ff[ ]+sub 0xfffffff4\(%ecx\),%edx +# ->R_386_TLS_TPOFF32 sG6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff IE against global var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 05 e8 a0 04 08[ ]+add 0x804a0e8,%eax +# ->R_386_TLS_TPOFF sG7 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff direct %gs access IE against global var + [0-9a-f]+: 8b 15 00 a1 04 08[ ]+mov 0x804a100,%edx +# ->R_386_TLS_TPOFF sG8 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 02[ ]+mov %gs:\(%edx\),%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE -> LE against global var defined in exec + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 ea 8c 0f 00 00[ ]+sub \$0xf8c,%edx +# bg6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff IE -> LE against global var defined in exec + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 c0 78 f0 ff ff[ ]+add \$0xfffff078,%eax +# bg7 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff direct %gs access IE -> LE against global var defined +# in exec + [0-9a-f]+: c7 c2 7c f0 ff ff[ ]+mov \$0xfffff07c,%edx +# bg8 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 02[ ]+mov %gs:\(%edx\),%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE -> LE against local var + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 ea 6c 0f 00 00[ ]+sub \$0xf6c,%edx +# bl6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff IE -> LE against local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 c0 98 f0 ff ff[ ]+add \$0xfffff098,%eax +# bl7 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff direct %gs access IE -> LE against local var + [0-9a-f]+: c7 c2 9c f0 ff ff[ ]+mov \$0xfffff09c,%edx +# bl8 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 02[ ]+mov %gs:\(%edx\),%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE -> LE against hidden but not local var + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 ea ac 0f 00 00[ ]+sub \$0xfac,%edx +# sh6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff IE -> LE against hidden but not local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 c0 58 f0 ff ff[ ]+add \$0xfffff058,%eax +# sh7 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @indntpoff direct %gs access IE -> LE against hidden but not +# local var + [0-9a-f]+: c7 c2 5c f0 ff ff[ ]+mov \$0xfffff05c,%edx +# sh8 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 02[ ]+mov %gs:\(%edx\),%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @tpoff, global var defined in exec + [0-9a-f]+: ba 00 10 00 00[ ]+mov \$0x1000,%edx +# sg1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 29 d0[ ]+sub %edx,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @tpoff, local var + [0-9a-f]+: b8 7f 0f 00 00[ ]+mov \$0xf7f,%eax +# bl1+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 29 c2[ ]+sub %eax,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @tpoff, hidden var defined in exec + [0-9a-f]+: b8 bd 0f 00 00[ ]+mov \$0xfbd,%eax +# sh1+3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 29 c2[ ]+sub %eax,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @ntpoff, global var defined in exec + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 90 04 f0 ff ff[ ]+lea 0xfffff004\(%eax\),%edx +# sg2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @ntpoff, local var, non-canonical sequence + [0-9a-f]+: b8 86 f0 ff ff[ ]+mov \$0xfffff086,%eax +# bl2+2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 01 c2[ ]+add %eax,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @ntpoff, hidden var defined in exec, non-canonical sequence + [0-9a-f]+: 65 8b 15 00 00 00 00[ ]+mov %gs:0x0,%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 81 c2 45 f0 ff ff[ ]+add \$0xfffff045,%edx +# sh2+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @ntpoff, global var defined in exec + [0-9a-f]+: 65 a1 08 f0 ff ff[ ]+mov %gs:0xfffff008,%eax +# sg3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @ntpoff, local var + [0-9a-f]+: 65 8b 15 8b f0 ff ff[ ]+mov %gs:0xfffff08b,%edx +# bl3+3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE @ntpoff, hidden var defined in exec + [0-9a-f]+: 65 8b 15 49 f0 ff ff[ ]+mov %gs:0xfffff049,%edx +# sh3+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8b 5d fc[ ]+mov 0xfffffffc\(%ebp\),%ebx + [0-9a-f]+: c9[ ]+leave * + [0-9a-f]+: c3[ ]+ret * diff --git a/ld/testsuite/ld-i386/tlsbindesc.rd b/ld/testsuite/ld-i386/tlsbindesc.rd new file mode 100644 index 00000000000..27d0670c993 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsbindesc.rd @@ -0,0 +1,154 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --32 +#ld: -melf_i386 tmpdir/libtlslib.so +#readelf: -Ssrl +#target: i?86-*-* + +There are 15 section headers, starting at offset 0x[0-9a-f]+: + +Section Headers: + \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al + \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0 + \[ 1\] \.interp +.* + \[ 2\] \.hash +.* + \[ 3\] \.dynsym +.* + \[ 4\] \.dynstr +.* + \[ 5\] \.rel.dyn +.* + \[ 6\] \.text +PROGBITS +0+8049000 .* + \[ 7\] \.tdata +PROGBITS +0+804a000 [0-9a-f]+ 000060 00 WAT 0 0 4096 + \[ 8\] \.tbss +NOBITS +[0-9a-f]+ [0-9a-f]+ 000040 00 WAT 0 0 1 + \[ 9\] \.dynamic +DYNAMIC +0+804a060 .* + \[10\] \.got +PROGBITS +0+804a0e0 .* + \[11\] \.got\.plt +PROGBITS +0+804a104 .* + \[12\] \.shstrtab +.* + \[13\] \.symtab +.* + \[14\] \.strtab +.* +Key to Flags: +.* +.* +.* + +Elf file type is EXEC \(Executable file\) +Entry point 0x8049158 +There are 6 program headers, starting at offset [0-9]+ + +Program Headers: + Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align + PHDR.* + INTERP.* +.*Requesting program interpreter.* + LOAD.* + LOAD.* + DYNAMIC.* + TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+a0 R +0x1000 + + Section to Segment mapping: + Segment Sections... + 00 + + 01 +.interp * + 02 +.interp .hash .dynsym .dynstr .rel.dyn .text * + 03 +.tdata .dynamic .got .got.plt * + 04 +.dynamic * + 05 +.tdata .tbss * + +Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 9 entries: + Offset +Info +Type +Sym.Value +Sym. Name +0+804a0e0 0000010e R_386_TLS_TPOFF +0+ +sG3 +0+804a0e4 0000020e R_386_TLS_TPOFF +0+ +sG5 +0+804a0e8 0000030e R_386_TLS_TPOFF +0+ +sG7 +0+804a0ec 00000425 R_386_TLS_TPOFF32 0+ +sG2 +0+804a0f0 00000525 R_386_TLS_TPOFF32 0+ +sG4 +0+804a0f4 0000050e R_386_TLS_TPOFF +0+ +sG4 +0+804a0f8 00000725 R_386_TLS_TPOFF32 0+ +sG6 +0+804a0fc 00000825 R_386_TLS_TPOFF32 0+ +sG1 +0+804a100 00000b0e R_386_TLS_TPOFF +0+ +sG8 + +Symbol table '.dynsym' contains 12 entries: + +Num: +Value Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG7 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG4 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG8 + +Symbol table '.symtab' contains 71 entries: + +Num: +Value Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +1 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +2 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +3 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +4 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +5 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +10 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +11 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +12 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +13 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +14 * + +[0-9]+: 00000020 +0 TLS +LOCAL DEFAULT +7 sl1 + +[0-9]+: 00000024 +0 TLS +LOCAL DEFAULT +7 sl2 + +[0-9]+: 00000028 +0 TLS +LOCAL DEFAULT +7 sl3 + +[0-9]+: 0000002c +0 TLS +LOCAL DEFAULT +7 sl4 + +[0-9]+: 00000030 +0 TLS +LOCAL DEFAULT +7 sl5 + +[0-9]+: 00000034 +0 TLS +LOCAL DEFAULT +7 sl6 + +[0-9]+: 00000038 +0 TLS +LOCAL DEFAULT +7 sl7 + +[0-9]+: 0000003c +0 TLS +LOCAL DEFAULT +7 sl8 + +[0-9]+: 00000080 +0 TLS +LOCAL DEFAULT +8 bl1 + +[0-9]+: 00000084 +0 TLS +LOCAL DEFAULT +8 bl2 + +[0-9]+: 00000088 +0 TLS +LOCAL DEFAULT +8 bl3 + +[0-9]+: 0000008c +0 TLS +LOCAL DEFAULT +8 bl4 + +[0-9]+: 00000090 +0 TLS +LOCAL DEFAULT +8 bl5 + +[0-9]+: 00000094 +0 TLS +LOCAL DEFAULT +8 bl6 + +[0-9]+: 00000098 +0 TLS +LOCAL DEFAULT +8 bl7 + +[0-9]+: 0000009c +0 TLS +LOCAL DEFAULT +8 bl8 + +[0-9]+: 00000000 +0 TLS +LOCAL HIDDEN +7 _TLS_MODULE_BASE_ + +[0-9]+: 0+804a060 +0 OBJECT LOCAL HIDDEN 9 _DYNAMIC + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN 11 _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG3 + +[0-9]+: 0000001c +0 TLS +GLOBAL DEFAULT +7 sg8 + +[0-9]+: 0000007c +0 TLS +GLOBAL DEFAULT +8 bg8 + +[0-9]+: 00000074 +0 TLS +GLOBAL DEFAULT +8 bg6 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 00000068 +0 TLS +GLOBAL DEFAULT +8 bg3 + +[0-9]+: 00000008 +0 TLS +GLOBAL DEFAULT +7 sg3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG7 + +[0-9]+: 00000048 +0 TLS +GLOBAL HIDDEN +7 sh3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0000000c +0 TLS +GLOBAL DEFAULT +7 sg4 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG4 + +[0-9]+: 00000010 +0 TLS +GLOBAL DEFAULT +7 sg5 + +[0-9]+: 00000070 +0 TLS +GLOBAL DEFAULT +8 bg5 + +[0-9]+: 00000058 +0 TLS +GLOBAL HIDDEN +7 sh7 + +[0-9]+: 0000005c +0 TLS +GLOBAL HIDDEN +7 sh8 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1 + +[0-9]+: 0+8049158 +0 FUNC +GLOBAL DEFAULT +6 _start + +[0-9]+: 0000004c +0 TLS +GLOBAL HIDDEN +7 sh4 + +[0-9]+: 00000078 +0 TLS +GLOBAL DEFAULT +8 bg7 + +[0-9]+: 00000050 +0 TLS +GLOBAL HIDDEN +7 sh5 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: 0+8049000 +0 FUNC +GLOBAL DEFAULT +6 fn2 + +[0-9]+: 00000004 +0 TLS +GLOBAL DEFAULT +7 sg2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: 00000040 +0 TLS +GLOBAL HIDDEN +7 sh1 + +[0-9]+: 00000014 +0 TLS +GLOBAL DEFAULT +7 sg6 + +[0-9]+: 00000018 +0 TLS +GLOBAL DEFAULT +7 sg7 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +[0-9]+: 00000044 +0 TLS +GLOBAL HIDDEN +7 sh2 + +[0-9]+: 00000054 +0 TLS +GLOBAL HIDDEN +7 sh6 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG8 + +[0-9]+: 00000064 +0 TLS +GLOBAL DEFAULT +8 bg2 + +[0-9]+: 00000060 +0 TLS +GLOBAL DEFAULT +8 bg1 + +[0-9]+: 0000006c +0 TLS +GLOBAL DEFAULT +8 bg4 diff --git a/ld/testsuite/ld-i386/tlsbindesc.s b/ld/testsuite/ld-i386/tlsbindesc.s new file mode 100644 index 00000000000..9094d083e8f --- /dev/null +++ b/ld/testsuite/ld-i386/tlsbindesc.s @@ -0,0 +1,167 @@ + /* Force .got aligned to 4K, so it very likely gets at 0x804a100 + (0x60 bytes .tdata and 0xa0 bytes .dynamic) */ + .section ".tdata", "awT", @progbits + .balign 4096 + .globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8 + .globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 + .hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 +sg1: .long 17 +sg2: .long 18 +sg3: .long 19 +sg4: .long 20 +sg5: .long 21 +sg6: .long 22 +sg7: .long 23 +sg8: .long 24 +sl1: .long 65 +sl2: .long 66 +sl3: .long 67 +sl4: .long 68 +sl5: .long 69 +sl6: .long 70 +sl7: .long 71 +sl8: .long 72 +sh1: .long 257 +sh2: .long 258 +sh3: .long 259 +sh4: .long 260 +sh5: .long 261 +sh6: .long 262 +sh7: .long 263 +sh8: .long 264 + /* Force .text aligned to 4K, so it very likely gets at 0x8049000. */ + .text + .balign 4096 + .globl fn2 + .type fn2,@function +fn2: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %eax + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + nop;nop;nop;nop + + /* GD -> IE because variable is not defined in executable */ + leal sG1@tlsdesc(%ebx), %eax + call *sG1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE because variable is not defined in executable where + the variable is referenced through @gottpoff too */ + leal sG2@tlsdesc(%ebx), %eax + call *sG2@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE because variable is not defined in executable where + the variable is referenced through @gotntpoff too */ + leal sG3@tlsdesc(%ebx), %eax + call *sG3@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE because variable is not defined in executable where + the variable is referenced through @gottpoff and @gotntpoff too */ + leal sG4@tlsdesc(%ebx), %eax + call *sG4@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> LE with global variable defined in executable */ + leal sg1@tlsdesc(%ebx), %eax + call *sg1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> LE with local variable defined in executable */ + leal sl1@tlsdesc(%ebx), %eax + call *sl1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> LE with hidden variable defined in executable */ + leal sh1@tlsdesc(%ebx), %eax + call *sh1@tlscall(%eax) + nop;nop;nop;nop + + /* LD -> LE */ + leal _TLS_MODULE_BASE_@tlsdesc(%ebx), %eax + call *_TLS_MODULE_BASE_@tlscall(%eax) + nop;nop + leal sl1@dtpoff(%eax), %edx + nop;nop + leal sl2@dtpoff(%eax), %ecx + nop;nop;nop;nop + + /* LD -> LE against hidden variables */ + leal _TLS_MODULE_BASE_@tlsdesc(%ebx), %eax + call *_TLS_MODULE_BASE_@tlscall(%eax) + nop;nop + leal sh1@dtpoff(%eax), %edx + nop;nop + leal sh2@dtpoff(%eax), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + subl sG2@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against global var */ + movl %gs:0, %eax + nop;nop + subl sG4@gottpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gotntpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + addl sG3@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE against global var */ + movl %gs:0, %eax + nop;nop + addl sG4@gotntpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gottpoff IE -> LE against global var defined in exec */ + movl %gs:0, %ecx + nop;nop + subl sg1@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE -> LE against local var */ + movl %gs:0, %ecx + nop;nop + addl sl1@gotntpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gottpoff IE -> LE against hidden var */ + movl %gs:0, %ecx + nop;nop + subl sh1@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* Direct access through %gs */ + + /* @gotntpoff IE against global var */ + movl sG5@gotntpoff(%ebx), %ecx + nop;nop + movl %gs:(%ecx), %edx + nop;nop;nop;nop + + /* @gotntpoff IE->LE against local var */ + movl sl5@gotntpoff(%ebx), %eax + nop;nop + movl %gs:(%eax), %edx + nop;nop;nop;nop + + /* @gotntpoff IE->LE against hidden var */ + movl sh5@gotntpoff(%ebx), %edx + nop;nop + movl %gs:(%edx), %edx + nop;nop;nop;nop + + movl -4(%ebp), %ebx + leave + ret diff --git a/ld/testsuite/ld-i386/tlsbindesc.sd b/ld/testsuite/ld-i386/tlsbindesc.sd new file mode 100644 index 00000000000..a87f5da402e --- /dev/null +++ b/ld/testsuite/ld-i386/tlsbindesc.sd @@ -0,0 +1,13 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --32 +#ld: -melf_i386 tmpdir/libtlslib.so +#objdump: -sj.got +#target: i?86-*-* + +.*: file format elf32-i386 + +Contents of section \.got: + 804a0e0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+ .* + 804a0f0 00000000 00000000 00000000 00000000 .* + 804a100 00000000 +.* diff --git a/ld/testsuite/ld-i386/tlsbindesc.td b/ld/testsuite/ld-i386/tlsbindesc.td new file mode 100644 index 00000000000..726df3edbe3 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsbindesc.td @@ -0,0 +1,16 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --32 +#ld: -melf_i386 tmpdir/libtlslib.so +#objdump: -sj.tdata +#target: i?86-*-* + +.*: file format elf32-i386 + +Contents of section \.tdata: + 804a000 11000000 12000000 13000000 14000000 .* + 804a010 15000000 16000000 17000000 18000000 .* + 804a020 41000000 42000000 43000000 44000000 .* + 804a030 45000000 46000000 47000000 48000000 .* + 804a040 01010000 02010000 03010000 04010000 .* + 804a050 05010000 06010000 07010000 08010000 .* diff --git a/ld/testsuite/ld-i386/tlsdesc.dd b/ld/testsuite/ld-i386/tlsdesc.dd new file mode 100644 index 00000000000..666f790cc23 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsdesc.dd @@ -0,0 +1,399 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --32 +#ld: -shared -melf_i386 +#objdump: -drj.text +#target: i?86-*-* + +.*: +file format elf32-i386 + +Disassembly of section .text: + +[0-9a-f]+ : + [0-9a-f]+: 55[ ]+push %ebp + [0-9a-f]+: 89 e5[ ]+mov %esp,%ebp + [0-9a-f]+: 53[ ]+push %ebx + [0-9a-f]+: 50[ ]+push %eax + [0-9a-f]+: e8 00 00 00 00[ ]+call [0-9a-f]+ + [0-9a-f]+: 5b[ ]+pop %ebx + [0-9a-f]+: 81 c3 9a 13 00 00[ ]+add \$0x[0-9a-f]+,%ebx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GDesc + [0-9a-f]+: 8d 83 24 00 00 00[ ]+lea 0x24\(%ebx\),%eax +# ->R_386_TLS_DESC sg1 + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gottpoff too + [0-9a-f]+: 8b 83 f8 ff ff ff[ ]+mov 0xfffffff8\(%ebx\),%eax +# ->R_386_TLS_TPOFF sg2 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gotntpoff too + [0-9a-f]+: 8b 83 c4 ff ff ff[ ]+mov 0xffffffc4\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sg3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gottpoff and + [0-9a-f]+: 8b 83 d4 ff ff ff[ ]+mov 0xffffffd4\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sg4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD against local variable + [0-9a-f]+: 8d 83 0c 00 00 00[ ]+lea 0xc\(%ebx\),%eax +# ->R_386_TLS_DESC sl1 + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against local variable referenced through @gottpoff too + [0-9a-f]+: 8b 83 b0 ff ff ff[ ]+mov 0xffffffb0\(%ebx\),%eax +# ->R_386_TLS_TPOFF sl2 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against local variable referenced through @gotntpoff + [0-9a-f]+: 8b 83 b4 ff ff ff[ ]+mov 0xffffffb4\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sl3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against local variable referenced through @gottpoff and + [0-9a-f]+: 8b 83 bc ff ff ff[ ]+mov 0xffffffbc\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sl4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD against hidden and local variable + [0-9a-f]+: 8d 83 2c 00 00 00[ ]+lea 0x2c\(%ebx\),%eax +# ->R_386_TLS_DESC sh1 + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden and local variable referenced through @gottpoff too + [0-9a-f]+: 8b 83 fc ff ff ff[ ]+mov 0xfffffffc\(%ebx\),%eax +# ->R_386_TLS_TPOFF sh2 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden and local variable referenced through @gotntpoff too + [0-9a-f]+: 8b 83 c8 ff ff ff[ ]+mov 0xffffffc8\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sh3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden and local variable referenced through @gottpoff and @gotntpoff too + [0-9a-f]+: 8b 83 e8 ff ff ff[ ]+mov 0xffffffe8\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sh4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD against hidden but not local variable + [0-9a-f]+: 8d 83 14 00 00 00[ ]+lea 0x14\(%ebx\),%eax +# ->R_386_TLS_DESC sH1 + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden but not local variable referenced through + [0-9a-f]+: 8b 83 cc ff ff ff[ ]+mov 0xffffffcc\(%ebx\),%eax +# ->R_386_TLS_TPOFF sH2 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden but not local variable referenced through + [0-9a-f]+: 8b 83 ec ff ff ff[ ]+mov 0xffffffec\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sH3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden but not local variable referenced through + [0-9a-f]+: 8b 83 e0 ff ff ff[ ]+mov 0xffffffe0\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sH4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD + [0-9a-f]+: 8d 83 1c 00 00 00[ ]+lea 0x1c\(%ebx\),%eax +# ->R_386_TLS_DESC _TLS_MODULE_BASE_ + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 90 20 00 00 00[ ]+lea 0x20\(%eax\),%edx +# sl1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 88 26 00 00 00[ ]+lea 0x26\(%eax\),%ecx +# sl2+2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD against hidden and local variables + [0-9a-f]+: 8d 90 40 00 00 00[ ]+lea 0x40\(%eax\),%edx +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 88 47 00 00 00[ ]+lea 0x47\(%eax\),%ecx +# sh2+3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD against hidden but not local variables + [0-9a-f]+: 8d 90 60 00 00 00[ ]+lea 0x60\(%eax\),%edx +# sH1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 88 65 00 00 00[ ]+lea 0x65\(%eax\),%ecx +# sH2+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b f8 ff ff ff[ ]+sub 0xfffffff8\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 sg2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 83 d0 ff ff ff[ ]+sub 0xffffffd0\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sg4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b c4 ff ff ff[ ]+add 0xffffffc4\(%ebx\),%ecx +# ->R_386_TLS_TPOFF sg3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against global var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 83 d4 ff ff ff[ ]+add 0xffffffd4\(%ebx\),%eax +# ->R_386_TLS_TPOFF sg4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b b0 ff ff ff[ ]+sub 0xffffffb0\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 [0xdcffffff] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 83 b8 ff ff ff[ ]+sub 0xffffffb8\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 [0xd4ffffff] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b b4 ff ff ff[ ]+add 0xffffffb4\(%ebx\),%ecx +# ->R_386_TLS_TPOFF [0x28000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 83 bc ff ff ff[ ]+add 0xffffffbc\(%ebx\),%eax +# ->R_386_TLS_TPOFF [0x2c000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against hidden and local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b fc ff ff ff[ ]+sub 0xfffffffc\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 [0xbcffffff] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against hidden and local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 83 e4 ff ff ff[ ]+sub 0xffffffe4\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 [0xb4ffffff] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against hidden and local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b c8 ff ff ff[ ]+add 0xffffffc8\(%ebx\),%ecx +# ->R_386_TLS_TPOFF [0x48000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against hidden and local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 83 e8 ff ff ff[ ]+add 0xffffffe8\(%ebx\),%eax +# ->R_386_TLS_TPOFF [0x4c000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against hidden but not local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b cc ff ff ff[ ]+sub 0xffffffcc\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 [0x9cffffff] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against hidden but not local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 83 dc ff ff ff[ ]+sub 0xffffffdc\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 [0x94ffffff] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against hidden but not local var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b ec ff ff ff[ ]+add 0xffffffec\(%ebx\),%ecx +# ->R_386_TLS_TPOFF [0x68000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against hidden but not local var + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 83 e0 ff ff ff[ ]+add 0xffffffe0\(%ebx\),%eax +# ->R_386_TLS_TPOFF [0x6c000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# Direct access through %gs +# @gotntpoff IE against global var + [0-9a-f]+: 8b 8b d8 ff ff ff[ ]+mov 0xffffffd8\(%ebx\),%ecx +# ->R_386_TLS_TPOFF sg5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 11[ ]+mov %gs:\(%ecx\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against local var + [0-9a-f]+: 8b 83 c0 ff ff ff[ ]+mov 0xffffffc0\(%ebx\),%eax +# ->R_386_TLS_TPOFF [0x30000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 10[ ]+mov %gs:\(%eax\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against hidden and local var + [0-9a-f]+: 8b 93 f0 ff ff ff[ ]+mov 0xfffffff0\(%ebx\),%edx +# ->R_386_TLS_TPOFF [0x50000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 12[ ]+mov %gs:\(%edx\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against hidden but not local var + [0-9a-f]+: 8b 8b f4 ff ff ff[ ]+mov 0xfffffff4\(%ebx\),%ecx +# ->R_386_TLS_TPOFF [0x70000000] + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 8b 11[ ]+mov %gs:\(%ecx\),%edx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8b 5d fc[ ]+mov 0xfffffffc\(%ebp\),%ebx + [0-9a-f]+: c9[ ]+leave * + [0-9a-f]+: c3[ ]+ret * diff --git a/ld/testsuite/ld-i386/tlsdesc.rd b/ld/testsuite/ld-i386/tlsdesc.rd new file mode 100644 index 00000000000..12fd5d4236b --- /dev/null +++ b/ld/testsuite/ld-i386/tlsdesc.rd @@ -0,0 +1,155 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --32 +#ld: -shared -melf_i386 +#readelf: -Ssrl +#target: i?86-*-* + +There are [0-9]+ section headers, starting at offset 0x.*: + +Section Headers: + \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al + \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0 + \[ 1\] \.hash +.* + \[ 2\] \.dynsym +.* + \[ 3\] \.dynstr +.* + \[ 4\] \.rel.dyn +.* + \[ 5\] \.rel.plt +.* + \[ 6\] \.text +.* + \[ 7\] \.tdata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 000060 00 WAT 0 0 1 + \[ 8\] \.tbss +NOBITS +[0-9aa-f]+ [0-9a-f]+ 000020 00 WAT 0 0 1 + \[ 9\] \.dynamic +.* + \[10\] \.got +.* + \[11\] \.got.plt +.* + \[12\] \.shstrtab +.* + \[13\] \.symtab +.* + \[14\] \.strtab +.* +Key to Flags: +.* +.* +.* + +Elf file type is DYN \(Shared object file\) +Entry point 0x[0-9a-f]+ +There are [0-9]+ program headers, starting at offset [0-9]+ + +Program Headers: + Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align + LOAD.* + LOAD.* + DYNAMIC.* + TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+80 R +0x1 + + Section to Segment mapping: + Segment Sections... + 00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .text * + 01 +.tdata .dynamic .got .got.plt * + 02 +.dynamic * + 03 +.tdata .tbss * + +Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 20 entries: + Offset +Info +Type +Sym.Value +Sym. Name +[0-9a-f]+ +0+25 R_386_TLS_TPOFF32 +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+25 R_386_TLS_TPOFF32 +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+25 R_386_TLS_TPOFF32 +[0-9a-f]+ +0+25 R_386_TLS_TPOFF32 +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+25 R_386_TLS_TPOFF32 +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+0e R_386_TLS_TPOFF * +[0-9a-f]+ +0+25 R_386_TLS_TPOFF32 +[0-9a-f]+ +0+50e R_386_TLS_TPOFF 0+8 sg3 +[0-9a-f]+ +0+625 R_386_TLS_TPOFF32 0+c sg4 +[0-9a-f]+ +0+60e R_386_TLS_TPOFF 0+c sg4 +[0-9a-f]+ +0+70e R_386_TLS_TPOFF 0+10 sg5 +[0-9a-f]+ +0+b25 R_386_TLS_TPOFF32 0+4 sg2 + +Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 5 entries: + Offset Info Type Sym.Value Sym. Name +[0-9a-f]+ +0+829 R_386_TLS_DESC * 0+ sg1 +[0-9a-f]+ +0+29 R_386_TLS_DESC * +[0-9a-f]+ +0+29 R_386_TLS_DESC * +[0-9a-f]+ +0+29 R_386_TLS_DESC * +[0-9a-f]+ +0+29 R_386_TLS_DESC * + +Symbol table '.dynsym' contains 16 entries: + +Num: + Value Size Type + Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8 + +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3 + +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4 + +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1 + +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2 + +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6 + +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +Symbol table '.symtab' contains 54 entries: + +Num: +Value Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +1 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +2 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +3 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +4 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +5 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +10 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +11 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +12 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +13 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +14 * + +[0-9]+: 0+20 +0 TLS +LOCAL DEFAULT +7 sl1 + +[0-9]+: 0+24 +0 TLS +LOCAL DEFAULT +7 sl2 + +[0-9]+: 0+28 +0 TLS +LOCAL DEFAULT +7 sl3 + +[0-9]+: 0+2c +0 TLS +LOCAL DEFAULT +7 sl4 + +[0-9]+: 0+30 +0 TLS +LOCAL DEFAULT +7 sl5 + +[0-9]+: 0+34 +0 TLS +LOCAL DEFAULT +7 sl6 + +[0-9]+: 0+38 +0 TLS +LOCAL DEFAULT +7 sl7 + +[0-9]+: 0+3c +0 TLS +LOCAL DEFAULT +7 sl8 + +[0-9]+: 0+60 +0 TLS +LOCAL HIDDEN +8 sH1 + +[0-9]+: 0+ +0 TLS +LOCAL HIDDEN +7 _TLS_MODULE_BASE_ + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN ABS _DYNAMIC + +[0-9]+: 0+48 +0 TLS +LOCAL HIDDEN +7 sh3 + +[0-9]+: 0+64 +0 TLS +LOCAL HIDDEN +8 sH2 + +[0-9]+: 0+78 +0 TLS +LOCAL HIDDEN +8 sH7 + +[0-9]+: 0+58 +0 TLS +LOCAL HIDDEN +7 sh7 + +[0-9]+: 0+5c +0 TLS +LOCAL HIDDEN +7 sh8 + +[0-9]+: 0+6c +0 TLS +LOCAL HIDDEN +8 sH4 + +[0-9]+: 0+4c +0 TLS +LOCAL HIDDEN +7 sh4 + +[0-9]+: 0+68 +0 TLS +LOCAL HIDDEN +8 sH3 + +[0-9]+: 0+50 +0 TLS +LOCAL HIDDEN +7 sh5 + +[0-9]+: 0+70 +0 TLS +LOCAL HIDDEN +8 sH5 + +[0-9]+: 0+74 +0 TLS +LOCAL HIDDEN +8 sH6 + +[0-9]+: 0+7c +0 TLS +LOCAL HIDDEN +8 sH8 + +[0-9]+: 0+40 +0 TLS +LOCAL HIDDEN +7 sh1 + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN ABS _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+44 +0 TLS +LOCAL HIDDEN +7 sh2 + +[0-9]+: 0+54 +0 TLS +LOCAL HIDDEN +7 sh6 + +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8 + +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3 + +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4 + +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1 + +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2 + +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6 + +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end diff --git a/ld/testsuite/ld-i386/tlsdesc.s b/ld/testsuite/ld-i386/tlsdesc.s new file mode 100644 index 00000000000..8377f649aa5 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsdesc.s @@ -0,0 +1,276 @@ + .section ".tdata", "awT", @progbits + .globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8 + .globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 + .hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 +sg1: .long 17 +sg2: .long 18 +sg3: .long 19 +sg4: .long 20 +sg5: .long 21 +sg6: .long 22 +sg7: .long 23 +sg8: .long 24 +sl1: .long 65 +sl2: .long 66 +sl3: .long 67 +sl4: .long 68 +sl5: .long 69 +sl6: .long 70 +sl7: .long 71 +sl8: .long 72 +sh1: .long 257 +sh2: .long 258 +sh3: .long 259 +sh4: .long 260 +sh5: .long 261 +sh6: .long 262 +sh7: .long 263 +sh8: .long 264 + .text + .globl fn1 + .type fn1,@function +fn1: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %eax + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + nop;nop;nop;nop + + /* GD */ + leal sg1@tlsdesc(%ebx), %eax + call *sg1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE because variable is referenced through @gottpoff too */ + leal sg2@tlsdesc(%ebx), %eax + call *sg2@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE because variable is referenced through @gotntpoff too */ + leal sg3@tlsdesc(%ebx), %eax + call *sg3@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE because variable is referenced through @gottpoff and + @gotntpoff too */ + leal sg4@tlsdesc(%ebx), %eax + call *sg4@tlscall(%eax) + nop;nop;nop;nop + + /* GD against local variable */ + leal sl1@tlsdesc(%ebx), %eax + call *sl1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against local variable referenced through @gottpoff too */ + leal sl2@tlsdesc(%ebx), %eax + call *sl2@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against local variable referenced through @gotntpoff + too */ + leal sl3@tlsdesc(%ebx), %eax + call *sl3@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against local variable referenced through @gottpoff and + @gotntpoff too */ + leal sl4@tlsdesc(%ebx), %eax + call *sl4@tlscall(%eax) + nop;nop;nop;nop + + /* GD against hidden and local variable */ + leal sh1@tlsdesc(%ebx), %eax + call *sh1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against hidden and local variable referenced through + @gottpoff too */ + leal sh2@tlsdesc(%ebx), %eax + call *sh2@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against hidden and local variable referenced through + @gotntpoff too */ + leal sh3@tlsdesc(%ebx), %eax + call *sh3@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against hidden and local variable referenced through + @gottpoff and @gotntpoff too */ + leal sh4@tlsdesc(%ebx), %eax + call *sh4@tlscall(%eax) + nop;nop;nop;nop + + /* GD against hidden but not local variable */ + leal sH1@tlsdesc(%ebx), %eax + call *sH1@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against hidden but not local variable referenced through + @gottpoff too */ + leal sH2@tlsdesc(%ebx), %eax + call *sH2@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against hidden but not local variable referenced through + @gotntpoff too */ + leal sH3@tlsdesc(%ebx), %eax + call *sH3@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE against hidden but not local variable referenced through + @gottpoff and @gotntpoff too */ + leal sH4@tlsdesc(%ebx), %eax + call *sH4@tlscall(%eax) + nop;nop;nop;nop + + /* LD */ + leal _TLS_MODULE_BASE_@tlsdesc(%ebx), %eax + call *_TLS_MODULE_BASE_@tlscall(%eax) + nop;nop + leal sl1@dtpoff(%eax), %edx + nop;nop + leal 2+sl2@dtpoff(%eax), %ecx + nop;nop;nop;nop + + /* LD against hidden and local variables */ + leal sh1@dtpoff(%eax), %edx + nop;nop + leal sh2@dtpoff+3(%eax), %ecx + nop;nop;nop;nop + + /* LD against hidden but not local variables */ + leal sH1@dtpoff(%eax), %edx + nop;nop + leal sH2@dtpoff+1(%eax), %ecx + nop;nop + + /* @gottpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + subl sg2@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against global var */ + movl %gs:0, %eax + nop;nop + subl sg4@gottpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gotntpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + addl sg3@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE against global var */ + movl %gs:0, %eax + nop;nop + addl sg4@gotntpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gottpoff IE against local var */ + movl %gs:0, %ecx + nop;nop + subl sl2@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against local var */ + movl %gs:0, %eax + nop;nop + subl sl4@gottpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gotntpoff IE against local var */ + movl %gs:0, %ecx + nop;nop + addl sl3@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE against local var */ + movl %gs:0, %eax + nop;nop + addl sl4@gotntpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gottpoff IE against hidden and local var */ + movl %gs:0, %ecx + nop;nop + subl sh2@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against hidden and local var */ + movl %gs:0, %eax + nop;nop + subl sh4@gottpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gotntpoff IE against hidden and local var */ + movl %gs:0, %ecx + nop;nop + addl sh3@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE against hidden and local var */ + movl %gs:0, %eax + nop;nop + addl sh4@gotntpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gottpoff IE against hidden but not local var */ + movl %gs:0, %ecx + nop;nop + subl sH2@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against hidden but not local var */ + movl %gs:0, %eax + nop;nop + subl sH4@gottpoff(%ebx), %eax + nop;nop;nop;nop + + /* @gotntpoff IE against hidden but not local var */ + movl %gs:0, %ecx + nop;nop + addl sH3@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE against hidden but not local var */ + movl %gs:0, %eax + nop;nop + addl sH4@gotntpoff(%ebx), %eax + nop;nop;nop;nop + + /* Direct access through %gs */ + + /* @gotntpoff IE against global var */ + movl sg5@gotntpoff(%ebx), %ecx + nop;nop + movl %gs:(%ecx), %edx + nop;nop;nop;nop + + /* @gotntpoff IE against local var */ + movl sl5@gotntpoff(%ebx), %eax + nop;nop + movl %gs:(%eax), %edx + nop;nop;nop;nop + + /* @gotntpoff IE against hidden and local var */ + movl sh5@gotntpoff(%ebx), %edx + nop;nop + movl %gs:(%edx), %edx + nop;nop;nop;nop + + /* @gotntpoff IE against hidden but not local var */ + movl sH5@gotntpoff(%ebx), %ecx + nop;nop + movl %gs:(%ecx), %edx + nop;nop;nop;nop + + movl -4(%ebp), %ebx + leave + ret diff --git a/ld/testsuite/ld-i386/tlsdesc.sd b/ld/testsuite/ld-i386/tlsdesc.sd new file mode 100644 index 00000000000..2af8c2d3df1 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsdesc.sd @@ -0,0 +1,20 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --32 +#ld: -shared -melf_i386 +#objdump: -s -j.got -j.got.plt +#target: i?86-*-* + +.*: file format elf32-i386 + +Contents of section \.got: + [0-9a-f]+ dcffffff 28000000 d4ffffff 2c000000 .* + [0-9a-f]+ 30000000 00000000 48000000 9cffffff .* + [0-9a-f]+ 00000000 00000000 00000000 94ffffff .* + [0-9a-f]+ 6c000000 b4ffffff 4c000000 68000000 .* + [0-9a-f]+ 50000000 70000000 00000000 bcffffff .* +Contents of section \.got\.plt: + [0-9a-f]+ ec150000 00000000 00000000 00000000 .* + [0-9a-f]+ 20000000 00000000 60000000 00000000 .* + [0-9a-f]+ 00000000 00000000 00000000 00000000 .* + [0-9a-f]+ 40000000 +.* diff --git a/ld/testsuite/ld-i386/tlsdesc.td b/ld/testsuite/ld-i386/tlsdesc.td new file mode 100644 index 00000000000..f3612b32a79 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsdesc.td @@ -0,0 +1,16 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --32 +#ld: -shared -melf_i386 +#objdump: -sj.tdata +#target: i?86-*-* + +.*: file format elf32-i386 + +Contents of section \.tdata: + [0-9a-f]+ 11000000 12000000 13000000 14000000 .* + [0-9a-f]+ 15000000 16000000 17000000 18000000 .* + [0-9a-f]+ 41000000 42000000 43000000 44000000 .* + [0-9a-f]+ 45000000 46000000 47000000 48000000 .* + [0-9a-f]+ 01010000 02010000 03010000 04010000 .* + [0-9a-f]+ 05010000 06010000 07010000 08010000 .* diff --git a/ld/testsuite/ld-i386/tlsgdesc.dd b/ld/testsuite/ld-i386/tlsgdesc.dd new file mode 100644 index 00000000000..ca4092ea843 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsgdesc.dd @@ -0,0 +1,158 @@ +#source: tlsgdesc.s +#as: --32 +#ld: -shared -melf_i386 +#objdump: -drj.text +#target: i?86-*-* + +.*: +file format elf32-i386 + +Disassembly of section .text: + +[0-9a-f]+ : + [0-9a-f]+: 55[ ]+push %ebp + [0-9a-f]+: 89 e5[ ]+mov %esp,%ebp + [0-9a-f]+: 53[ ]+push %ebx + [0-9a-f]+: 50[ ]+push %eax + [0-9a-f]+: e8 00 00 00 00[ ]+call [0-9a-f]+ <.*> + [0-9a-f]+: 5b[ ]+pop %ebx + [0-9a-f]+: 81 c3 be 11 00 00[ ]+add \$0x[0-9a-f]+,%ebx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b e0 ff ff ff[ ]+sub 0xffffffe0\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 sG3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b f0 ff ff ff[ ]+add 0xfffffff0\(%ebx\),%ecx +# ->R_386_TLS_TPOFF sG4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD + [0-9a-f]+: 8d 04 1d f8 ff ff ff[ ]+lea 0xfffffff8\(,%ebx,1\),%eax +# ->R_386_TLS_DTPMOD32 sG1 + [0-9a-f]+: e8 a9 ff ff ff[ ]+call [0-9a-f]+ <___tls_get_addr@plt> +# ->R_386_JUMP_SLOT ___tls_get_addr + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 83 18 00 00 00[ ]+lea 0x18\(%ebx\),%eax +# ->R_386_TLS_DESC sG1 + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 83 10 00 00 00[ ]+lea 0x10\(%ebx\),%eax +# ->R_386_TLS_DESC sG2 + [0-9a-f]+: ff 10[ ]+call \*\(%eax\) + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8d 04 1d e8 ff ff ff[ ]+lea 0xffffffe8\(,%ebx,1\),%eax +# ->R_386_TLS_DTPMOD32 sG2 + [0-9a-f]+: e8 81 ff ff ff[ ]+call [0-9a-f]+ <___tls_get_addr@plt> +# ->R_386_JUMP_SLOT ___tls_get_addr + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gottpoff too + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 2b 83 e0 ff ff ff[ ]+sub 0xffffffe0\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8b 83 e0 ff ff ff[ ]+mov 0xffffffe0\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG3 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gotntpoff too + [0-9a-f]+: 8b 83 f0 ff ff ff[ ]+mov 0xfffffff0\(%ebx\),%eax +# ->R_386_TLS_TPOFF sG4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 03 83 f0 ff ff ff[ ]+add 0xfffffff0\(%ebx\),%eax +# ->R_386_TLS_TPOFF sG4 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gotntpoff too + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 03 83 e4 ff ff ff[ ]+add 0xffffffe4\(%ebx\),%eax +# ->R_386_TLS_TPOFF sG5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8b 83 e4 ff ff ff[ ]+mov 0xffffffe4\(%ebx\),%eax +# ->R_386_TLS_TPOFF sG5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through @gottpoff too + [0-9a-f]+: 8b 83 f4 ff ff ff[ ]+mov 0xfffffff4\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG6 + [0-9a-f]+: f7 d8[ ]+neg %eax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 65 a1 00 00 00 00[ ]+mov %gs:0x0,%eax + [0-9a-f]+: 2b 83 f4 ff ff ff[ ]+sub 0xfffffff4\(%ebx\),%eax +# ->R_386_TLS_TPOFF32 sG6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gotntpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 03 8b e4 ff ff ff[ ]+add 0xffffffe4\(%ebx\),%ecx +# ->R_386_TLS_TPOFF sG5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# @gottpoff IE against global var + [0-9a-f]+: 65 8b 0d 00 00 00 00[ ]+mov %gs:0x0,%ecx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 2b 8b f4 ff ff ff[ ]+sub 0xfffffff4\(%ebx\),%ecx +# ->R_386_TLS_TPOFF32 sG6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 8b 5d fc[ ]+mov 0xfffffffc\(%ebp\),%ebx + [0-9a-f]+: c9[ ]+leave * + [0-9a-f]+: c3[ ]+ret * diff --git a/ld/testsuite/ld-i386/tlsgdesc.rd b/ld/testsuite/ld-i386/tlsgdesc.rd new file mode 100644 index 00000000000..9253d22cef1 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsgdesc.rd @@ -0,0 +1,107 @@ +#source: tlsgdesc.s +#as: --32 +#ld: -shared -melf_i386 +#readelf: -Ssrl +#target: i?86-*-* + +There are [0-9]+ section headers, starting at offset 0x.*: + +Section Headers: + \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al + \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0 + \[ 1\] \.hash +.* + \[ 2\] \.dynsym +.* + \[ 3\] \.dynstr +.* + \[ 4\] \.rel.dyn +.* + \[ 5\] \.rel.plt +.* + \[ 6\] \.plt +.* + \[ 7\] \.text +.* + \[ 8\] \.dynamic +.* + \[ 9\] \.got +.* + \[10\] \.got.plt +.* + \[11\] \.shstrtab +.* + \[12\] \.symtab +.* + \[13\] \.strtab +.* +Key to Flags: +.* +.* +.* + +Elf file type is DYN \(Shared object file\) +Entry point 0x[0-9a-f]+ +There are [0-9]+ program headers, starting at offset [0-9]+ + +Program Headers: + Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align + LOAD.* + LOAD.* + DYNAMIC.* + + Section to Segment mapping: + Segment Sections... + 00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text * + 01 +.dynamic .got .got.plt * + 02 +.dynamic * + +Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 8 entries: + Offset +Info +Type +Sym.Value +Sym. Name +[0-9a-f]+ +0+225 R_386_TLS_TPOFF32 0+ sG3 +[0-9a-f]+ +0+30e R_386_TLS_TPOFF 0+ sG5 +[0-9a-f]+ +0+423 R_386_TLS_DTPMOD3 0+ sG2 +[0-9a-f]+ +0+424 R_386_TLS_DTPOFF3 0+ sG2 +[0-9a-f]+ +0+50e R_386_TLS_TPOFF 0+ sG4 +[0-9a-f]+ +0+725 R_386_TLS_TPOFF32 0+ sG6 +[0-9a-f]+ +0+923 R_386_TLS_DTPMOD3 0+ sG1 +[0-9a-f]+ +0+924 R_386_TLS_DTPOFF3 0+ sG1 + +Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 3 entries: + Offset Info Type Sym.Value Sym. Name +[0-9a-f]+ 0+c07 R_386_JUMP_SLOT 0+ ___tls_get_addr +[0-9a-f]+ 0+929 R_386_TLS_DESC 0+ sG1 +[0-9a-f]+ 0+429 R_386_TLS_DESC 0+ sG2 + +Symbol table '.dynsym' contains 13 entries: + +Num: + Value Size Type + Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG4 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +[0-9]+: 0+ +0 NOTYPE GLOBAL DEFAULT UND ___tls_get_addr + +Symbol table '.symtab' contains 27 entries: + +Num: +Value Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +1 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +2 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +3 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +4 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +5 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +10 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +11 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +12 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +13 * + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN ABS _DYNAMIC + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN ABS _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG4 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +[0-9]+: 0+ +0 NOTYPE GLOBAL DEFAULT UND ___tls_get_addr diff --git a/ld/testsuite/ld-i386/tlsgdesc.s b/ld/testsuite/ld-i386/tlsgdesc.s new file mode 100644 index 00000000000..9502a10d0f7 --- /dev/null +++ b/ld/testsuite/ld-i386/tlsgdesc.s @@ -0,0 +1,100 @@ + .text + .globl fc1 + .type fc1,@function +fc1: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %eax + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + nop;nop;nop;nop + + /* @gottpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + subl sG3@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gotntpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + addl sG4@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* GD */ + leal sG1@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@plt + nop;nop;nop;nop + + /* GD */ + leal sG1@tlsdesc(%ebx), %eax + call *sG1@tlscall(%eax) + nop;nop;nop;nop + + /* GD */ + leal sG2@tlsdesc(%ebx), %eax + call *sG2@tlscall(%eax) + nop;nop;nop;nop + + /* GD */ + leal sG2@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@plt + nop;nop;nop;nop + + /* GD -> IE tpoff */ + leal sG3@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@plt + nop;nop;nop;nop + + /* GD -> IE tpoff */ + leal sG3@tlsdesc(%ebx), %eax + call *sG3@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE ntpoff */ + leal sG4@tlsdesc(%ebx), %eax + call *sG4@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE ntpoff */ + leal sG4@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@plt + nop;nop;nop;nop + + /* GD -> IE ntpoff */ + leal sG5@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@plt + nop;nop;nop;nop + + /* GD -> IE ntpoff */ + leal sG5@tlsdesc(%ebx), %eax + call *sG5@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE tpoff */ + leal sG6@tlsdesc(%ebx), %eax + call *sG6@tlscall(%eax) + nop;nop;nop;nop + + /* GD -> IE tpoff */ + leal sG6@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@plt + nop;nop;nop;nop + + /* @gotntpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + addl sG5@gotntpoff(%ebx), %ecx + nop;nop;nop;nop + + /* @gottpoff IE against global var */ + movl %gs:0, %ecx + nop;nop + subl sG6@gottpoff(%ebx), %ecx + nop;nop;nop;nop + + movl -4(%ebp), %ebx + leave + ret diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.dd b/ld/testsuite/ld-x86-64/tlsbindesc.dd new file mode 100644 index 00000000000..c41efecf293 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsbindesc.dd @@ -0,0 +1,307 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -drj.text +#target: x86_64-*-* + +# PT_TLS layout is: +# Offset from Offset from Name +# TCB base TCB end +# 0x00 -0xa0 sg1..sg8 +# 0x20 -0x80 sl1..sl8 +# 0x40 -0x60 sh1..sh8 +# 0x60 -0x40 bg1..bg8 +# 0x80 -0x20 bl1..bl8 + +.*: +file format elf64-x86-64 + +Disassembly of section .text: + +0+401000 : + [0-9a-f]+: 55[ ]+push %rbp + [0-9a-f]+: 48 89 e5[ ]+mov %rsp,%rbp +# GD -> IE because variable is not defined in executable + [0-9a-f]+: 48 8b 05 65 03 10 00[ ]+mov 1049445\(%rip\),%rax +# 501370 <.*> +# -> R_X86_64_TPOFF64 sG1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is not defined in executable where +# the variable is referenced through IE too + [0-9a-f]+: 48 8b 05 48 03 10 00[ ]+mov 1049416\(%rip\),%rax +# 501360 <.*> +# -> R_X86_64_TPOFF64 sG2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> LE with global variable defined in executable + [0-9a-f]+: 48 c7 c0 60 ff ff ff[ ]+mov \$0xf+60,%rax +# sg1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> LE with local variable defined in executable + [0-9a-f]+: 48 c7 c0 80 ff ff ff[ ]+mov \$0xf+80,%rax +# sl1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# GD -> LE with hidden variable defined in executable + [0-9a-f]+: 48 c7 c0 a0 ff ff ff[ ]+mov \$0xf+a0,%rax +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD -> LE + [0-9a-f]+: 48 c7 c0 60 ff ff ff[ ]+mov \$0xf+60,%rax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 90 81 ff ff ff[ ]+lea 0xf+81\(%rax\),%rdx +# sl1+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 4c 8d 88 86 ff ff ff[ ]+lea 0xf+86\(%rax\),%r9 +# sl2+2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LD -> LE against hidden variables + [0-9a-f]+: 48 8d 90 a0 ff ff ff[ ]+lea 0xf+a0\(%rax\),%rdx +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 88 a7 ff ff ff[ ]+lea 0xf+a7\(%rax\),%rcx +# sh2+3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE against global var + [0-9a-f]+: 64 4c 8b 0c 25 00 00[ ]+mov %fs:0x0,%r9 + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 4c 03 0d d6 02 10 00[ ]+add 1049302\(%rip\),%r9 +# 501360 <.*> +# -> R_X86_64_TPOFF64 sG2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE -> LE against global var defined in exec + [0-9a-f]+: 64 4c 8b 14 25 00 00[ ]+mov %fs:0x0,%r10 + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 4d 8d 92 60 ff ff ff[ ]+lea 0xf+60\(%r10\),%r10 +# sg1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE -> LE against local var + [0-9a-f]+: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 80 80 ff ff ff[ ]+lea 0xf+80\(%rax\),%rax +# sl1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE -> LE against hidden var + [0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 89 a0 ff ff ff[ ]+lea 0xf+a0\(%rcx\),%rcx +# sh1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# Direct access through %fs +# IE against global var + [0-9a-f]+: 48 8b 0d 81 02 10 00[ ]+mov 1049217\(%rip\),%rcx +# 501358 <.*> +# -> R_X86_64_TPOFF64 sG5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 64 48 8b 11[ ]+mov %fs:\(%rcx\),%rdx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE->LE against local var + [0-9a-f]+: 49 c7 c3 90 ff ff ff[ ]+mov \$0xf+90,%r11 +# sl5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 64 4d 8b 23[ ]+mov %fs:\(%r11\),%r12 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE->LE against hidden var + [0-9a-f]+: 48 c7 c2 b0 ff ff ff[ ]+mov \$0xf+b0,%rdx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 64 48 8b 12[ ]+mov %fs:\(%rdx\),%rdx +# sh5 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: c9[ ]+leaveq * + [0-9a-f]+: c3[ ]+retq * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+ <_start>: + [0-9a-f]+: 55[ ]+push %rbp + [0-9a-f]+: 48 89 e5[ ]+mov %rsp,%rbp +# IE against global var + [0-9a-f]+: 64 4c 8b 1c 25 00 00[ ]+mov %fs:0x0,%r11 + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 4c 03 1d 4a 02 10 00[ ]+add 1049162\(%rip\),%r11 +# 501368 <.*> +# -> R_X86_64_TPOFF64 sG6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE -> LE against global var defined in exec + [0-9a-f]+: 64 48 8b 14 25 00 00[ ]+mov %fs:0x0,%rdx + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 92 d4 ff ff ff[ ]+lea 0xf+d4\(%rdx\),%rdx +# bg6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE -> LE against local var + [0-9a-f]+: 64 4c 8b 24 25 00 00[ ]+mov %fs:0x0,%r12 + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 49 81 c4 f4 ff ff ff[ ]+add \$0xf+f4,%r12 +# bl6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# direct %fs access IE -> LE against local var + [0-9a-f]+: 48 c7 c2 fc ff ff ff[ ]+mov \$0xf+fc,%rdx +# bl8 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 64 48 8b 02[ ]+mov %fs:\(%rdx\),%rax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# IE -> LE against hidden but not local var + [0-9a-f]+: 64 48 8b 14 25 00 00[ ]+mov %fs:0x0,%rdx + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 92 b4 ff ff ff[ ]+lea 0xf+b4\(%rdx\),%rdx +# sh6 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# direct %fs access IE -> LE against hidden but not local var + [0-9a-f]+: 48 c7 c2 bc ff ff ff[ ]+mov \$0xf+bc,%rdx +# sh8 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 64 48 8b 02[ ]+mov %fs:\(%rdx\),%rax + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE, global var defined in exec + [0-9a-f]+: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 8d 90 64 ff ff ff[ ]+lea 0xf+64\(%rax\),%rdx +# sg2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE, local var, non-canonical sequence + [0-9a-f]+: 49 c7 c1 e6 ff ff ff[ ]+mov \$0xf+e6,%r9 +# bl2+2 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 64 48 8b 14 25 00 00[ ]+mov %fs:0x0,%rdx + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 4c 01 ca[ ]+add %r9,%rdx + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE, hidden var defined in exec, non-canonical sequence + [0-9a-f]+: 64 48 8b 14 25 00 00[ ]+mov %fs:0x0,%rdx + [0-9a-f]+: 00 00 * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 48 81 c2 a5 ff ff ff[ ]+add \$0xf+a5,%rdx +# sh2+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# Direct %fs access +# LE, global var defined in exec + [0-9a-f]+: 64 48 8b 04 25 68 ff[ ]+mov %fs:0xf+68,%rax + [0-9a-f]+: ff ff * +# sg3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE, local var + [0-9a-f]+: 64 4c 8b 14 25 eb ff[ ]+mov %fs:0xf+eb,%r10 + [0-9a-f]+: ff ff * +# bl3+3 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * +# LE, hidden var defined in exec + [0-9a-f]+: 64 48 8b 14 25 a9 ff[ ]+mov %fs:0xf+a9,%rdx + [0-9a-f]+: ff ff * +# sh3+1 + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: 90[ ]+nop * + [0-9a-f]+: c9[ ]+leaveq * + [0-9a-f]+: c3[ ]+retq * diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.rd b/ld/testsuite/ld-x86-64/tlsbindesc.rd new file mode 100644 index 00000000000..787002d1899 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsbindesc.rd @@ -0,0 +1,141 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --64 +#ld: -shared -melf_x86_64 +#readelf: -WSsrl +#target: x86_64-*-* + +There are 15 section headers, starting at offset 0x[0-9a-f]+: + +Section Headers: + \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al + \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0 + \[ 1\] .interp +.* + \[ 2\] .hash +.* + \[ 3\] .dynsym +.* + \[ 4\] .dynstr +.* + \[ 5\] .rela.dyn +.* + \[ 6\] .text +PROGBITS +0+401000 0+1000 0+1f6 00 +AX +0 +0 +4096 + \[ 7\] .tdata +PROGBITS +0+5011f6 0+11f6 0+60 00 WAT +0 +0 +1 + \[ 8\] .tbss +NOBITS +0+501256 0+1256 0+40 00 WAT +0 +0 +1 + \[ 9\] .dynamic +DYNAMIC +0+501258 0+1258 0+100 10 +WA +4 +0 +8 + \[10\] .got +PROGBITS +0+501358 0+1358 0+20 08 +WA +0 +0 +8 + \[11\] .got.plt +PROGBITS +0+501378 0+1378 0+18 08 +WA +0 +0 +8 + \[12\] .shstrtab +.* + \[13\] .symtab +.* + \[14\] .strtab +.* +Key to Flags: +.* +.* +.* + +Elf file type is EXEC \(Executable file\) +Entry point 0x401108 +There are 6 program headers, starting at offset [0-9]+ + +Program Headers: + Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align + PHDR.* + INTERP.* +.*Requesting program interpreter.* + LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11f6 0x0+11f6 R E 0x100000 + LOAD +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+19a 0x0+19a RW 0x100000 + DYNAMIC +0x0+1258 0x0+501258 0x0+501258 0x0+100 0x0+100 RW 0x8 + TLS +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+60 0x0+a0 R +0x1 + + Section to Segment mapping: + Segment Sections... + 00 * + 01 +.interp * + 02 +.interp .hash .dynsym .dynstr .rela.dyn .text * + 03 +.tdata .dynamic .got .got.plt * + 04 +.dynamic * + 05 +.tdata .tbss * + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries: + +Offset +Info +Type +Symbol's Value Symbol's Name \+ Addend +0+501358 0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0 +0+501360 0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0 +0+501368 0+400000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0 +0+501370 0+500000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0 + +Symbol table '.dynsym' contains 8 entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +Symbol table '.symtab' contains 67 entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +1 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +2 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +3 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +4 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +5 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +10 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +11 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +12 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +13 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +14 * + +[0-9]+: 0+20 +0 TLS +LOCAL DEFAULT +7 sl1 + +[0-9]+: 0+24 +0 TLS +LOCAL DEFAULT +7 sl2 + +[0-9]+: 0+28 +0 TLS +LOCAL DEFAULT +7 sl3 + +[0-9]+: 0+2c +0 TLS +LOCAL DEFAULT +7 sl4 + +[0-9]+: 0+30 +0 TLS +LOCAL DEFAULT +7 sl5 + +[0-9]+: 0+34 +0 TLS +LOCAL DEFAULT +7 sl6 + +[0-9]+: 0+38 +0 TLS +LOCAL DEFAULT +7 sl7 + +[0-9]+: 0+3c +0 TLS +LOCAL DEFAULT +7 sl8 + +[0-9]+: 0+80 +0 TLS +LOCAL DEFAULT +8 bl1 + +[0-9]+: 0+84 +0 TLS +LOCAL DEFAULT +8 bl2 + +[0-9]+: 0+88 +0 TLS +LOCAL DEFAULT +8 bl3 + +[0-9]+: 0+8c +0 TLS +LOCAL DEFAULT +8 bl4 + +[0-9]+: 0+90 +0 TLS +LOCAL DEFAULT +8 bl5 + +[0-9]+: 0+94 +0 TLS +LOCAL DEFAULT +8 bl6 + +[0-9]+: 0+98 +0 TLS +LOCAL DEFAULT +8 bl7 + +[0-9]+: 0+9c +0 TLS +LOCAL DEFAULT +8 bl8 + +[0-9]+: 0+0 +0 TLS +LOCAL HIDDEN +7 _TLS_MODULE_BASE_ + +[0-9]+: 0+501258 +0 OBJECT LOCAL HIDDEN 9 _DYNAMIC + +[0-9]+: 0+501378 +0 OBJECT LOCAL HIDDEN 11 _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8 + +[0-9]+: 0+7c +0 TLS +GLOBAL DEFAULT +8 bg8 + +[0-9]+: 0+74 +0 TLS +GLOBAL DEFAULT +8 bg6 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 bg3 + +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3 + +[0-9]+: 0+48 +0 TLS +GLOBAL HIDDEN +7 sh3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4 + +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5 + +[0-9]+: 0+70 +0 TLS +GLOBAL DEFAULT +8 bg5 + +[0-9]+: 0+58 +0 TLS +GLOBAL HIDDEN +7 sh7 + +[0-9]+: 0+5c +0 TLS +GLOBAL HIDDEN +7 sh8 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1 + +[0-9]+: 0+401108 +0 FUNC +GLOBAL DEFAULT +6 _start + +[0-9]+: 0+4c +0 TLS +GLOBAL HIDDEN +7 sh4 + +[0-9]+: 0+78 +0 TLS +GLOBAL DEFAULT +8 bg7 + +[0-9]+: 0+50 +0 TLS +GLOBAL HIDDEN +7 sh5 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: 0+401000 +0 FUNC +GLOBAL DEFAULT +6 fn2 + +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: 0+40 +0 TLS +GLOBAL HIDDEN +7 sh1 + +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6 + +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +[0-9]+: 0+44 +0 TLS +GLOBAL HIDDEN +7 sh2 + +[0-9]+: 0+54 +0 TLS +GLOBAL HIDDEN +7 sh6 + +[0-9]+: 0+64 +0 TLS +GLOBAL DEFAULT +8 bg2 + +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 bg1 + +[0-9]+: 0+6c +0 TLS +GLOBAL DEFAULT +8 bg4 diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.s b/ld/testsuite/ld-x86-64/tlsbindesc.s new file mode 100644 index 00000000000..cbebf02171d --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsbindesc.s @@ -0,0 +1,128 @@ + /* Force .data aligned to 4K, so that .got very likely gets at + 0x5021a0 (0x60 bytes .tdata and 0x140 bytes .dynamic) */ + .data + .balign 4096 + .section ".tdata", "awT", @progbits + .globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8 + .globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 + .hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 +sg1: .long 17 +sg2: .long 18 +sg3: .long 19 +sg4: .long 20 +sg5: .long 21 +sg6: .long 22 +sg7: .long 23 +sg8: .long 24 +sl1: .long 65 +sl2: .long 66 +sl3: .long 67 +sl4: .long 68 +sl5: .long 69 +sl6: .long 70 +sl7: .long 71 +sl8: .long 72 +sh1: .long 257 +sh2: .long 258 +sh3: .long 259 +sh4: .long 260 +sh5: .long 261 +sh6: .long 262 +sh7: .long 263 +sh8: .long 264 + /* Force .text aligned to 4K, so it very likely gets at 0x401000. */ + .text + .balign 4096 + .globl fn2 + .type fn2,@function +fn2: + pushq %rbp + movq %rsp, %rbp + + /* GD -> IE because variable is not defined in executable */ + leaq sG1@tlsdesc(%rip), %rax + call *sG1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE because variable is not defined in executable where + the variable is referenced through IE too */ + leaq sG2@tlsdesc(%rip), %rax + call *sG2@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> LE with global variable defined in executable */ + leaq sg1@tlsdesc(%rip), %rax + call *sg1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> LE with local variable defined in executable */ + leaq sl1@tlsdesc(%rip), %rax + call *sl1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> LE with hidden variable defined in executable */ + leaq sh1@tlsdesc(%rip), %rax + call *sh1@tlscall(%rax) + nop;nop;nop;nop + + /* LD -> LE */ + leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax + call *_TLS_MODULE_BASE_@tlscall(%rax) + nop;nop + leaq 1+sl1@dtpoff(%rax), %rdx + nop;nop + leaq sl2@dtpoff+2(%rax), %r9 + nop;nop;nop;nop + + /* LD -> LE against hidden variables */ + leaq sh1@dtpoff(%rax), %rdx + nop;nop + leaq 3+sh2@dtpoff(%rax), %rcx + nop;nop;nop;nop + + /* IE against global var */ + movq %fs:0, %r9 + nop;nop + addq sG2@gottpoff(%rip), %r9 + nop;nop;nop;nop + + /* IE -> LE against global var defined in exec */ + movq %fs:0, %r10 + nop;nop + addq sg1@gottpoff(%rip), %r10 + nop;nop;nop;nop + + /* IE -> LE against local var */ + movq %fs:0, %rax + nop;nop + addq sl1@gottpoff(%rip), %rax + nop;nop;nop;nop + + /* IE -> LE against hidden var */ + movq %fs:0, %rcx + nop;nop + addq sh1@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* Direct access through %fs */ + + /* IE against global var */ + movq sG5@gottpoff(%rip), %rcx + nop;nop + movq %fs:(%rcx), %rdx + nop;nop;nop;nop + + /* IE->LE against local var */ + movq sl5@gottpoff(%rip), %r11 + nop;nop + movq %fs:(%r11), %r12 + nop;nop;nop;nop + + /* IE->LE against hidden var */ + movq sh5@gottpoff(%rip), %rdx + nop;nop + movq %fs:(%rdx), %rdx + nop;nop;nop;nop + + leave + ret diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.sd b/ld/testsuite/ld-x86-64/tlsbindesc.sd new file mode 100644 index 00000000000..fd0519fb929 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsbindesc.sd @@ -0,0 +1,12 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -sj.got +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Contents of section .got: + 501358 00000000 00000000 00000000 00000000 .* + 501368 00000000 00000000 00000000 00000000 .* diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.td b/ld/testsuite/ld-x86-64/tlsbindesc.td new file mode 100644 index 00000000000..226e52e6280 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsbindesc.td @@ -0,0 +1,16 @@ +#source: tlsbindesc.s +#source: tlsbin.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -sj.tdata +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Contents of section .tdata: + 5011f6 11000000 12000000 13000000 14000000 .* + 501206 15000000 16000000 17000000 18000000 .* + 501216 41000000 42000000 43000000 44000000 .* + 501226 45000000 46000000 47000000 48000000 .* + 501236 01010000 02010000 03010000 04010000 .* + 501246 05010000 06010000 07010000 08010000 .* diff --git a/ld/testsuite/ld-x86-64/tlsdesc.dd b/ld/testsuite/ld-x86-64/tlsdesc.dd new file mode 100644 index 00000000000..656e2411c66 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsdesc.dd @@ -0,0 +1,204 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -drj.text +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Disassembly of section .text: + +0+[0-9a-f]+ : + +[0-9a-f]+: 55[ ]+push %rbp + +[0-9a-f]+: 48 89 e5[ ]+mov %rsp,%rbp + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD + +[0-9a-f]+: 48 8d 05 89 03 10 00[ ]+lea 1049481\(%rip\),%rax +# 101398 <.*> +# -> R_X86_64_TLSDESC sg1 + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE because variable is referenced through IE too + +[0-9a-f]+: 48 8b 05 1c 03 10 00[ ]+mov 1049372\(%rip\),%rax +# 101338 <.*> +# -> R_X86_64_TPOFF64 sg2 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD against local variable + +[0-9a-f]+: 48 8d 05 3f 03 10 00[ ]+lea 1049407\(%rip\),%rax +# 101368 <.*> +# -> R_X86_64_TLSDESC [0 0x2000000000000000] + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE against local variable referenced through IE too + +[0-9a-f]+: 48 8b 05 d2 02 10 00[ ]+mov 1049298\(%rip\),%rax +# 101308 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x24 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD against hidden and local variable + +[0-9a-f]+: 48 8d 05 65 03 10 00[ ]+lea 1049445\(%rip\),%rax +# 1013a8 <.*> +# -> R_X86_64_TLSDESC [0 0x4000000000000000] + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden and local variable referenced through IE too + +[0-9a-f]+: 48 8b 05 f0 02 10 00[ ]+mov 1049328\(%rip\),%rax +# 101340 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x44 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD against hidden but not local variable + +[0-9a-f]+: 48 8d 05 1b 03 10 00[ ]+lea 1049371\(%rip\),%rax +# 101378 <.*> +# -> R_X86_64_TLSDESC [0 0x6000000000000000] + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE against hidden but not local variable referenced through IE too + +[0-9a-f]+: 48 8b 05 ae 02 10 00[ ]+mov 1049262\(%rip\),%rax +# 101318 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x64 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# LD + +[0-9a-f]+: 48 8d 05 11 03 10 00[ ]+lea 1049361\(%rip\),%rax +# 101388 <.*> +# -> R_X86_64_TLSDESC [0 0x000000000000000] + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 8d 90 20 00 00 00[ ]+lea 0x20\(%rax\),%rdx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 4c 8d 88 26 00 00 00[ ]+lea 0x26\(%rax\),%r9 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# LD against hidden and local variables + +[0-9a-f]+: 48 8d 90 40 00 00 00[ ]+lea 0x40\(%rax\),%rdx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 8d 88 47 00 00 00[ ]+lea 0x47\(%rax\),%rcx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# LD against hidden but not local variables + +[0-9a-f]+: 4c 8d a0 60 00 00 00[ ]+lea 0x60\(%rax\),%r12 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 8d 88 65 00 00 00[ ]+lea 0x65\(%rax\),%rcx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against global var + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 71 02 10 00[ ]+add 1049201\(%rip\),%rcx +# 101338 <.*> +# -> R_X86_64_TPOFF64 sg2 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against local var + +[0-9a-f]+: 64 4c 8b 34 25 00 00[ ]+mov %fs:0x0,%r14 + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 4c 03 35 2b 02 10 00[ ]+add 1049131\(%rip\),%r14 +# 101308 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x24 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against hidden and local var + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 4d 02 10 00[ ]+add 1049165\(%rip\),%rcx +# 101340 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x44 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against hidden but not local var + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 0f 02 10 00[ ]+add 1049103\(%rip\),%rcx +# 101318 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x64 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# Direct access through %fs +# IE against global var + +[0-9a-f]+: 48 8b 0d 0c 02 10 00[ ]+mov 1049100\(%rip\),%rcx +# 101320 <.*> +# -> R_X86_64_TPOFF64 sg5 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 64 48 8b 11[ ]+mov %fs:\(%rcx\),%rdx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against local var + +[0-9a-f]+: 4c 8b 15 eb 01 10 00[ ]+mov 1049067\(%rip\),%r10 +# 101310 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x30 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 64 4d 8b 22[ ]+mov %fs:\(%r10\),%r12 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against hidden and local var + +[0-9a-f]+: 48 8b 15 f2 01 10 00[ ]+mov 1049074\(%rip\),%rdx +# 101328 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x50 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 64 48 8b 12[ ]+mov %fs:\(%rdx\),%rdx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE against hidden but not local var + +[0-9a-f]+: 48 8b 0d e9 01 10 00[ ]+mov 1049065\(%rip\),%rcx +# 101330 <.*> +# -> R_X86_64_TPOFF64 *ABS*+0x70 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 64 48 8b 11[ ]+mov %fs:\(%rcx\),%rdx + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: c9[ ]+leaveq * + +[0-9a-f]+: c3[ ]+retq * + +[0-9a-f]+: 90[ ]+nop * diff --git a/ld/testsuite/ld-x86-64/tlsdesc.pd b/ld/testsuite/ld-x86-64/tlsdesc.pd new file mode 100644 index 00000000000..aea1bab46ba --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsdesc.pd @@ -0,0 +1,26 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -drj.plt +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Disassembly of section .plt: + +0000000000000470 <.*@plt-0x10>: + 470: ff 35 e2 0e 10 00 pushq 1052386\(%rip\) # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8> + 476: ff 25 e4 0e 10 00 jmpq \*1052388\(%rip\) # 101360 <_GLOBAL_OFFSET_TABLE_\+0x10> + 47c: 90 nop * + 47d: 90 nop * + 47e: 90 nop * + 47f: 90 nop * +0000000000000480 <.*@plt>: + 480: ff 35 d2 0e 10 00 pushq 1052370\(%rip\) # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8> + 486: ff 25 bc 0e 10 00 jmpq \*1052348\(%rip\) # 101348 <_DYNAMIC\+0x190> + 48c: 90 nop * + 48d: 90 nop * + 48e: 90 nop * + 48f: 90 nop * + diff --git a/ld/testsuite/ld-x86-64/tlsdesc.rd b/ld/testsuite/ld-x86-64/tlsdesc.rd new file mode 100644 index 00000000000..e7e21ed1d75 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsdesc.rd @@ -0,0 +1,164 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --64 +#ld: -shared -melf_x86_64 +#readelf: -WSsrld +#target: x86_64-*-* + +There are 16 section headers, starting at offset 0x[0-9a-f]+: + +Section Headers: + \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al + \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0 + \[ 1\] .hash +.* + \[ 2\] .dynsym +.* + \[ 3\] .dynstr +.* + \[ 4\] .rela.dyn +.* + \[ 5\] .rela.plt +.* + \[ 6\] .plt +PROGBITS +0+470 0+470 0+20 10 +AX +0 +0 +4 + \[ 7\] .text +PROGBITS +0+1000 0+1000 0+154 00 +AX +0 +0 4096 + \[ 8\] .tdata +PROGBITS +0+101154 0+1154 0+60 00 WAT +0 +0 +1 + \[ 9\] .tbss +NOBITS +0+1011b4 0+11b4 0+20 00 WAT +0 +0 +1 + \[10\] .dynamic +DYNAMIC +0+1011b8 0+11b8 0+150 10 +WA +3 +0 +8 + \[11\] .got +PROGBITS +0+101308 0+1308 0+48 08 +WA +0 +0 +8 + \[12\] .got.plt +PROGBITS +0+101350 0+1350 0+68 08 +WA +0 +0 +8 + \[13\] .shstrtab +.* + \[14\] .symtab +.* + \[15\] .strtab +.* +Key to Flags: +.* +.* +.* + +Elf file type is DYN \(Shared object file\) +Entry point 0x1000 +There are 4 program headers, starting at offset [0-9]+ + +Program Headers: + Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align + LOAD +0x0+ 0x0+ 0x0+ 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x100000 + LOAD +0x0+1154 0x0+101154 0x0+101154 0x0+264 0x0+264 RW +0x100000 + DYNAMIC +0x0+11b8 0x0+1011b8 0x0+1011b8 0x0+150 0x0+150 RW +0x8 + TLS +0x0+1154 0x0+101154 0x0+101154 0x0+60 0x0+80 R +0x1 + + Section to Segment mapping: + Segment Sections... + 00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text * + 01 +.tdata .dynamic .got .got.plt * + 02 +.dynamic * + 03 +.tdata .tbss * + +Dynamic section at offset 0x[0-9a-f]+ contains 16 entries: + +Tag +Type +Name/Value + 0x[0-9a-f]+ +\(HASH\).* + 0x[0-9a-f]+ +\(STRTAB\).* + 0x[0-9a-f]+ +\(SYMTAB\).* + 0x[0-9a-f]+ +\(STRSZ\).* + 0x[0-9a-f]+ +\(SYMENT\).* + 0x[0-9a-f]+ +\(PLTGOT\).* + 0x[0-9a-f]+ +\(PLTRELSZ\).* + 0x[0-9a-f]+ +\(PLTREL\).* + 0x[0-9a-f]+ +\(JMPREL\).* + 0x[0-9a-f]+ +\(TLSDESC_PLT\) +0x480 + 0x[0-9a-f]+ +\(TLSDESC_GOT\) +0x101348 + 0x[0-9a-f]+ +\(RELA\).* + 0x[0-9a-f]+ +\(RELASZ\).* + 0x[0-9a-f]+ +\(RELAENT\).* + 0x[0-9a-f]+ +\(FLAGS\).* + 0x[0-9a-f]+ +\(NULL\).* + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries: + +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend +0+101308 0+12 R_X86_64_TPOFF64 +0+24 +0+101310 0+12 R_X86_64_TPOFF64 +0+30 +0+101318 0+12 R_X86_64_TPOFF64 +0+64 +0+101328 0+12 R_X86_64_TPOFF64 +0+50 +0+101330 0+12 R_X86_64_TPOFF64 +0+70 +0+101340 0+12 R_X86_64_TPOFF64 +0+44 +0+101320 0+700000012 R_X86_64_TPOFF64 +0+10 sg5 \+ 0 +0+101338 0+b00000012 R_X86_64_TPOFF64 +0+4 sg2 \+ 0 + +Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 5 entries: + +Offset +Info +Type +Symbol's Value Symbol's Name \+ Addend +0+101398 0+800000024 R_X86_64_TLSDESC +0+ sg1 \+ 0 +0+101368 0+24 R_X86_64_TLSDESC +0+20 +0+1013a8 0+24 R_X86_64_TLSDESC +0+40 +0+101378 0+24 R_X86_64_TLSDESC +0+60 +0+101388 0+24 R_X86_64_TLSDESC +0+ + +Symbol table '.dynsym' contains 16 entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8 + +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3 + +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4 + +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1 + +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2 + +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6 + +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +Symbol table '.symtab' contains 55 entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +1 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +2 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +3 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +4 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +5 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +10 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +11 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +12 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +13 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +14 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +15 * + +[0-9]+: 0+20 +0 TLS +LOCAL DEFAULT +8 sl1 + +[0-9]+: 0+24 +0 TLS +LOCAL DEFAULT +8 sl2 + +[0-9]+: 0+28 +0 TLS +LOCAL DEFAULT +8 sl3 + +[0-9]+: 0+2c +0 TLS +LOCAL DEFAULT +8 sl4 + +[0-9]+: 0+30 +0 TLS +LOCAL DEFAULT +8 sl5 + +[0-9]+: 0+34 +0 TLS +LOCAL DEFAULT +8 sl6 + +[0-9]+: 0+38 +0 TLS +LOCAL DEFAULT +8 sl7 + +[0-9]+: 0+3c +0 TLS +LOCAL DEFAULT +8 sl8 + +[0-9]+: 0+60 +0 TLS +LOCAL HIDDEN +9 sH1 + +[0-9]+: 0+ +0 TLS +LOCAL HIDDEN +8 _TLS_MODULE_BASE_ + +[0-9]+: 0+1011b8 +0 OBJECT LOCAL HIDDEN ABS _DYNAMIC + +[0-9]+: 0+48 +0 TLS +LOCAL HIDDEN +8 sh3 + +[0-9]+: 0+64 +0 TLS +LOCAL HIDDEN +9 sH2 + +[0-9]+: 0+78 +0 TLS +LOCAL HIDDEN +9 sH7 + +[0-9]+: 0+58 +0 TLS +LOCAL HIDDEN +8 sh7 + +[0-9]+: 0+5c +0 TLS +LOCAL HIDDEN +8 sh8 + +[0-9]+: 0+6c +0 TLS +LOCAL HIDDEN +9 sH4 + +[0-9]+: 0+4c +0 TLS +LOCAL HIDDEN +8 sh4 + +[0-9]+: 0+68 +0 TLS +LOCAL HIDDEN +9 sH3 + +[0-9]+: 0+50 +0 TLS +LOCAL HIDDEN +8 sh5 + +[0-9]+: 0+70 +0 TLS +LOCAL HIDDEN +9 sH5 + +[0-9]+: 0+74 +0 TLS +LOCAL HIDDEN +9 sH6 + +[0-9]+: 0+7c +0 TLS +LOCAL HIDDEN +9 sH8 + +[0-9]+: 0+40 +0 TLS +LOCAL HIDDEN +8 sh1 + +[0-9]+: 0+101350 +0 OBJECT LOCAL HIDDEN ABS _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+44 +0 TLS +LOCAL HIDDEN +8 sh2 + +[0-9]+: 0+54 +0 TLS +LOCAL HIDDEN +8 sh6 + +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8 + +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3 + +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4 + +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1 + +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2 + +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6 + +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end diff --git a/ld/testsuite/ld-x86-64/tlsdesc.s b/ld/testsuite/ld-x86-64/tlsdesc.s new file mode 100644 index 00000000000..ec6d190d6e6 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsdesc.s @@ -0,0 +1,157 @@ + /* Force .data aligned to 4K, so .got very likely gets at 0x102190 + (0x60 bytes .tdata and 0x130 bytes .dynamic) */ + .data + .balign 4096 + .section ".tdata", "awT", @progbits + .globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8 + .globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 + .hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8 +sg1: .long 17 +sg2: .long 18 +sg3: .long 19 +sg4: .long 20 +sg5: .long 21 +sg6: .long 22 +sg7: .long 23 +sg8: .long 24 +sl1: .long 65 +sl2: .long 66 +sl3: .long 67 +sl4: .long 68 +sl5: .long 69 +sl6: .long 70 +sl7: .long 71 +sl8: .long 72 +sh1: .long 257 +sh2: .long 258 +sh3: .long 259 +sh4: .long 260 +sh5: .long 261 +sh6: .long 262 +sh7: .long 263 +sh8: .long 264 + /* Force .text aligned to 4K, so it very likely gets at 0x1000. */ + .text + .balign 4096 + .globl fn1 + .type fn1,@function +fn1: + pushq %rbp + movq %rsp, %rbp + nop;nop;nop;nop + + /* GD */ + leaq sg1@tlsdesc(%rip), %rax + call *sg1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE because variable is referenced through IE too */ + leaq sg2@tlsdesc(%rip), %rax + call *sg2@tlscall(%rax) + nop;nop;nop;nop + + /* GD against local variable */ + leaq sl1@tlsdesc(%rip), %rax + call *sl1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE against local variable referenced through IE too */ + leaq sl2@tlsdesc(%rip), %rax + call *sl2@tlscall(%rax) + nop;nop;nop;nop + + /* GD against hidden and local variable */ + leaq sh1@tlsdesc(%rip), %rax + call *sh1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE against hidden and local variable referenced through + IE too */ + leaq sh2@tlsdesc(%rip), %rax + call *sh2@tlscall(%rax) + nop;nop;nop;nop + + /* GD against hidden but not local variable */ + leaq sH1@tlsdesc(%rip), %rax + call *sH1@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE against hidden but not local variable referenced through + IE too */ + leaq sH2@tlsdesc(%rip), %rax + call *sH2@tlscall(%rax) + nop;nop;nop;nop + + /* LD */ + leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax + call *_TLS_MODULE_BASE_@tlscall(%rax) + nop;nop + leaq sl1@dtpoff(%rax), %rdx + nop;nop + leaq 2+sl2@dtpoff(%rax), %r9 + nop;nop;nop;nop + + /* LD against hidden and local variables */ + leaq sh1@dtpoff(%rax), %rdx + nop;nop + leaq sh2@dtpoff+3(%rax), %rcx + nop;nop;nop;nop + + /* LD against hidden but not local variables */ + leaq sH1@dtpoff(%rax), %r12 + nop;nop + leaq sH2@dtpoff+1(%rax), %rcx + nop;nop + + /* IE against global var */ + movq %fs:0, %rcx + nop;nop + addq sg2@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* IE against local var */ + movq %fs:0, %r14 + nop;nop + addq sl2@gottpoff(%rip), %r14 + nop;nop;nop;nop + + /* IE against hidden and local var */ + movq %fs:0, %rcx + nop;nop + addq sh2@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* IE against hidden but not local var */ + movq %fs:0, %rcx + nop;nop + addq sH2@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* Direct access through %fs */ + + /* IE against global var */ + movq sg5@gottpoff(%rip), %rcx + nop;nop + movq %fs:(%rcx), %rdx + nop;nop;nop;nop + + /* IE against local var */ + movq sl5@gottpoff(%rip), %r10 + nop;nop + movq %fs:(%r10), %r12 + nop;nop;nop;nop + + /* IE against hidden and local var */ + movq sh5@gottpoff(%rip), %rdx + nop;nop + movq %fs:(%rdx), %rdx + nop;nop;nop;nop + + /* IE against hidden but not local var */ + movq sH5@gottpoff(%rip), %rcx + nop;nop + movq %fs:(%rcx), %rdx + nop;nop;nop;nop + + leave + ret diff --git a/ld/testsuite/ld-x86-64/tlsdesc.sd b/ld/testsuite/ld-x86-64/tlsdesc.sd new file mode 100644 index 00000000000..8eb5d9cd572 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsdesc.sd @@ -0,0 +1,23 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -s -j.got -j.got.plt +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Contents of section \.got: + 101308 00000000 00000000 00000000 00000000 .* + 101318 00000000 00000000 00000000 00000000 .* + 101328 00000000 00000000 00000000 00000000 .* + 101338 00000000 00000000 00000000 00000000 .* + 101348 00000000 00000000 .* +Contents of section \.got\.plt: + 101350 b8111000 00000000 00000000 00000000 .* + 101360 00000000 00000000 00000000 00000000 .* + 101370 00000000 00000000 00000000 00000000 .* + 101380 00000000 00000000 00000000 00000000 .* + 101390 00000000 00000000 00000000 00000000 .* + 1013a0 00000000 00000000 00000000 00000000 .* + 1013b0 00000000 00000000 .* diff --git a/ld/testsuite/ld-x86-64/tlsdesc.td b/ld/testsuite/ld-x86-64/tlsdesc.td new file mode 100644 index 00000000000..dd79816c4aa --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsdesc.td @@ -0,0 +1,16 @@ +#source: tlsdesc.s +#source: tlspic2.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -sj.tdata +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Contents of section .tdata: + 101154 11000000 12000000 13000000 14000000 .* + 101164 15000000 16000000 17000000 18000000 .* + 101174 41000000 42000000 43000000 44000000 .* + 101184 45000000 46000000 47000000 48000000 .* + 101194 01010000 02010000 03010000 04010000 .* + 1011a4 05010000 06010000 07010000 08010000 .* diff --git a/ld/testsuite/ld-x86-64/tlsgdesc.dd b/ld/testsuite/ld-x86-64/tlsgdesc.dd new file mode 100644 index 00000000000..b0e7c058440 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgdesc.dd @@ -0,0 +1,167 @@ +#source: tlsgdesc.s +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -drj.text +#target: x86_64-*-* + +.*: +file format elf64-x86-64 + +Disassembly of section .text: + +0+[0-9a-f]+ : + +[0-9a-f]+: 55[ ]+push %rbp + +[0-9a-f]+: 48 89 e5[ ]+mov %rsp,%rbp + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 5e 02 10 00[ ]+add 1049182\(%rip\),%rcx +# 100660 <.*> +# -> R_X86_64_TPOFF64 sG3 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 68 02 10 00[ ]+add 1049192\(%rip\),%rcx +# 100680 <.*> +# -> R_X86_64_TPOFF64 sG4 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD, gd first + +[0-9a-f]+: 66 48 8d 3d 6c 02 10[ ]+lea 1049196\(%rip\),%rdi +# 100690 <.*> + +[0-9a-f]+: 00 * +# -> R_X86_64_DTPMOD64 sG1 + +[0-9a-f]+: 66 66 48 e8 9c ff ff[ ]+callq [0-9a-f]+ <.*> + +[0-9a-f]+: ff[ ]+ +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 8d 05 a1 02 10 00[ ]+lea 1049249\(%rip\),%rax +# 1006d8 <.*> +# -> R_X86_64_TLSDESC sG1 + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD, desc first + +[0-9a-f]+: 48 8d 05 84 02 10 00[ ]+lea 1049220\(%rip\),%rax +# 1006c8 <.*> +# -> R_X86_64_TLSDESC sG2 + +[0-9a-f]+: ff 10[ ]+callq \*\(%rax\) + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 66 48 8d 3d 1e 02 10[ ]+lea 1049118\(%rip\),%rdi +# 100670 <.*> + +[0-9a-f]+: 00 * +# -> R_X86_64_DTPMOD64 sG2 + +[0-9a-f]+: 66 66 48 e8 6e ff ff[ ]+callq [0-9a-f]+ <.*> + +[0-9a-f]+: ff[ ]+ +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE, gd first, after IE use + +[0-9a-f]+: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 48 03 05 f2 01 10 00[ ]+add 1049074\(%rip\),%rax +# 100660 <.*> +# -> R_X86_64_TPOFF64 sG3 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 8b 05 e7 01 10 00[ ]+mov 1049063\(%rip\),%rax +# 100660 <.*> +# -> R_X86_64_TPOFF64 sG3 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE, desc first, after IE use + +[0-9a-f]+: 48 8b 05 fa 01 10 00[ ]+mov 1049082\(%rip\),%rax +# 100680 <.*> +# -> R_X86_64_TPOFF64 sG4 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 48 03 05 e4 01 10 00[ ]+add 1049060\(%rip\),%rax +# 100680 <.*> +# -> R_X86_64_TPOFF64 sG4 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE, gd first, before IE use + +[0-9a-f]+: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 48 03 05 b8 01 10 00[ ]+add 1049016\(%rip\),%rax +# 100668 <.*> +# -> R_X86_64_TPOFF64 sG5 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 8b 05 ad 01 10 00[ ]+mov 1049005\(%rip\),%rax +# 100668 <.*> +# -> R_X86_64_TPOFF64 sG5 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# GD -> IE, desc first, before IE use + +[0-9a-f]+: 48 8b 05 c0 01 10 00[ ]+mov 1049024\(%rip\),%rax +# 100688 <.*> +# -> R_X86_64_TPOFF64 sG6 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 48 03 05 aa 01 10 00[ ]+add 1049002\(%rip\),%rax +# 100688 <.*> +# -> R_X86_64_TPOFF64 sG6 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 74 01 10 00[ ]+add 1048948\(%rip\),%rcx +# 100668 <.*> +# -> R_X86_64_TPOFF64 sG5 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * +# IE + +[0-9a-f]+: 64 48 8b 0c 25 00 00[ ]+mov %fs:0x0,%rcx + +[0-9a-f]+: 00 00 * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 48 03 0d 7e 01 10 00[ ]+add 1048958\(%rip\),%rcx +# 100688 <.*> +# -> R_X86_64_TPOFF64 sG6 + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: 90[ ]+nop * + +[0-9a-f]+: c9[ ]+leaveq * + +[0-9a-f]+: c3[ ]+retq * diff --git a/ld/testsuite/ld-x86-64/tlsgdesc.rd b/ld/testsuite/ld-x86-64/tlsgdesc.rd new file mode 100644 index 00000000000..2f7621b001d --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgdesc.rd @@ -0,0 +1,107 @@ +#source: tlsgdesc.s +#as: --64 +#ld: -shared -melf64_x86_64 +#readelf: -WSsrl +#target: x86_64-*-* + +There are [0-9]+ section headers, starting at offset 0x.*: + +Section Headers: + \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al + \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0 + \[ 1\] \.hash +.* + \[ 2\] \.dynsym +.* + \[ 3\] \.dynstr +.* + \[ 4\] \.rela.dyn +.* + \[ 5\] \.rela.plt +.* + \[ 6\] \.plt +.* + \[ 7\] \.text +.* + \[ 8\] \.dynamic +.* + \[ 9\] \.got +.* + \[10\] \.got.plt +.* + \[11\] \.shstrtab +.* + \[12\] \.symtab +.* + \[13\] \.strtab +.* +Key to Flags: +.* +.* +.* + +Elf file type is DYN \(Shared object file\) +Entry point 0x[0-9a-f]+ +There are [0-9]+ program headers, starting at offset [0-9]+ + +Program Headers: + Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align + LOAD.* + LOAD.* + DYNAMIC.* + + Section to Segment mapping: + Segment Sections... + 00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text * + 01 +.dynamic .got .got.plt * + 02 +.dynamic * + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries: + +Offset +Info +Type +Symbol's Value Symbol's Name \+ Addend +[0-9a-f]+ 0+200000012 R_X86_64_TPOFF64 +0+ sG3 \+ 0 +[0-9a-f]+ 0+300000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0 +[0-9a-f]+ 0+400000010 R_X86_64_DTPMOD64 +0+ sG2 \+ 0 +[0-9a-f]+ 0+400000011 R_X86_64_DTPOFF64 +0+ sG2 \+ 0 +[0-9a-f]+ 0+500000012 R_X86_64_TPOFF64 +0+ sG4 \+ 0 +[0-9a-f]+ 0+800000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0 +[0-9a-f]+ 0+a00000010 R_X86_64_DTPMOD64 +0+ sG1 \+ 0 +[0-9a-f]+ 0+a00000011 R_X86_64_DTPOFF64 +0+ sG1 \+ 0 + +Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 3 entries: + +Offset +Info +Type +Symbol's Value Symbol's Name \+ Addend +[0-9a-f]+ 0+600000007 R_X86_64_JUMP_SLOT +0+ __tls_get_addr \+ 0 +[0-9a-f]+ 0+a00000024 R_X86_64_TLSDESC +0+ sG1 \+ 0 +[0-9a-f]+ 0+400000024 R_X86_64_TLSDESC +0+ sG2 \+ 0 + +Symbol table '.dynsym' contains 13 entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG4 + +[0-9]+: 0+ +0 NOTYPE GLOBAL DEFAULT UND __tls_get_addr + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end + +Symbol table '.symtab' contains 27 entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name + +[0-9]+: 0+ +0 NOTYPE LOCAL DEFAULT UND * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +1 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +2 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +3 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +4 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +5 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +6 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +7 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +8 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +9 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +10 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +11 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +12 * + +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL DEFAULT +13 * + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN ABS _DYNAMIC + +[0-9]+: [0-9a-f]+ +0 OBJECT LOCAL HIDDEN ABS _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG3 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG5 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG2 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG4 + +[0-9]+: 0+ +0 NOTYPE GLOBAL DEFAULT UND __tls_get_addr + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS __bss_start + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG6 + +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1 + +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT UND sG1 + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _edata + +[0-9]+: [0-9a-f]+ +0 NOTYPE GLOBAL DEFAULT ABS _end diff --git a/ld/testsuite/ld-x86-64/tlsgdesc.s b/ld/testsuite/ld-x86-64/tlsgdesc.s new file mode 100644 index 00000000000..6657e72aa6d --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgdesc.s @@ -0,0 +1,106 @@ + .text + .globl fc1 + .type fc1,@function +fc1: + pushq %rbp + movq %rsp, %rbp + nop;nop;nop;nop + + /* IE against global var. */ + movq %fs:0, %rcx + nop;nop + addq sG3@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* IE against global var. */ + movq %fs:0, %rcx + nop;nop + addq sG4@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* GD, gd first. */ + .byte 0x66 + leaq sG1@tlsgd(%rip), %rdi + .word 0x6666 + rex64 + call __tls_get_addr@plt + nop;nop;nop;nop + + leaq sG1@tlsdesc(%rip), %rax + call *sG1@tlscall(%rax) + nop;nop;nop;nop + + /* GD, desc first. */ + leaq sG2@tlsdesc(%rip), %rax + call *sG2@tlscall(%rax) + nop;nop;nop;nop + + .byte 0x66 + leaq sG2@tlsgd(%rip), %rdi + .word 0x6666 + rex64 + call __tls_get_addr@plt + nop;nop;nop;nop + + /* GD -> IE, gd first, after IE use. */ + .byte 0x66 + leaq sG3@tlsgd(%rip), %rdi + .word 0x6666 + rex64 + call __tls_get_addr@plt + nop;nop;nop;nop + + leaq sG3@tlsdesc(%rip), %rax + call *sG3@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE, desc first, after IE use. */ + leaq sG4@tlsdesc(%rip), %rax + call *sG4@tlscall(%rax) + nop;nop;nop;nop + + .byte 0x66 + leaq sG4@tlsgd(%rip), %rdi + .word 0x6666 + rex64 + call __tls_get_addr@plt + nop;nop;nop;nop + + /* GD -> IE, gd first, before IE use. */ + .byte 0x66 + leaq sG5@tlsgd(%rip), %rdi + .word 0x6666 + rex64 + call __tls_get_addr@plt + nop;nop;nop;nop + + leaq sG5@tlsdesc(%rip), %rax + call *sG5@tlscall(%rax) + nop;nop;nop;nop + + /* GD -> IE, desc first, before IE use. */ + leaq sG6@tlsdesc(%rip), %rax + call *sG6@tlscall(%rax) + nop;nop;nop;nop + + .byte 0x66 + leaq sG6@tlsgd(%rip), %rdi + .word 0x6666 + rex64 + call __tls_get_addr@plt + nop;nop;nop;nop + + /* IE against global var. */ + movq %fs:0, %rcx + nop;nop + addq sG5@gottpoff(%rip), %rcx + nop;nop;nop;nop + + /* IE against global var. */ + movq %fs:0, %rcx + nop;nop + addq sG6@gottpoff(%rip), %rcx + nop;nop;nop;nop + + leave + ret diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 409a65d34c7..5285f3efd0b 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -1,5 +1,5 @@ # Expect script for ld-x86_64 tests -# Copyright (C) 2002 Free Software Foundation +# Copyright (C) 2002, 2005, 2006 Free Software Foundation # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -39,6 +39,11 @@ set x86_64tests { {{readelf -WSsrl tlspic.rd} {objdump -drj.text tlspic.dd} {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}} "libtlspic.so"} + {"TLS descriptor -fpic -shared transitions" "-shared -melf_x86_64" + "--64" {tlsdesc.s tlspic2.s} + {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd} + {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td} + {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"} {"Helper shared library" "-shared -melf_x86_64" "--64" {tlslib.s} {} "libtlslib.so"} {"TLS -fpic and -fno-pic exec transitions" @@ -46,6 +51,15 @@ set x86_64tests { {{readelf -WSsrl tlsbin.rd} {objdump -drj.text tlsbin.dd} {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}} "tlsbin"} + {"TLS descriptor -fpic and -fno-pic exec transitions" + "-melf_x86_64 tmpdir/libtlslib.so" "--64" {tlsbindesc.s tlsbin.s} + {{readelf -WSsrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd} + {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}} + "tlsbindesc"} + {"TLS with global dynamic and descriptors" + "-shared -melf_x86_64" "--64" {tlsgdesc.s} + {{readelf -WSsrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}} + "libtlsgdesc.so"} {"TLS in debug sections" "-melf_x86_64" "--64" {tlsg.s} {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}