aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2007-08-14 19:48:21 +0000
committerH.J. Lu <hjl.tools@gmail.com>2007-08-14 19:48:21 +0000
commita3fadc9a17972a899c807f1ed3c8044066a68857 (patch)
tree76f351a35da7e7cc0506ebb6be7ac3de42bbb77f /bfd/elf64-x86-64.c
parent6d307763fb4e0224a97d3f44150b8e07c0943af9 (diff)
downloadgdb-a3fadc9a17972a899c807f1ed3c8044066a68857.zip
gdb-a3fadc9a17972a899c807f1ed3c8044066a68857.tar.gz
gdb-a3fadc9a17972a899c807f1ed3c8044066a68857.tar.bz2
bfd/
2007-08-14 H.J. Lu <hongjiu.lu@intel.com> PR ld/4918 * elf32-i386.c (elf_i386_relocate_section): Allow R_386_PC32 on ___tls_get_addr for GD->LE/LD->LE transitions when not building shared library. * elf64-x86-64.c (elf64_x86_64_relocate_section): Allow R_X86_64_PC32 on __tls_get_addr for GD->LE/LD->LE transitions when not building shared library. ld/testsuite/ 2007-08-14 H.J. Lu <hongjiu.lu@intel.com> PR ld/4918 * ld-i386/i386.exp (i386tests): Add tlsgd1 and tlsld1 tests. * ld-x86-64/x86-64.exp (x86_64tests): Likewise. * ld-i386/tlsgd1.dd: New file. * ld-i386/tlsgd1.s: Likewise. * ld-i386/tlsld1.dd: Likewise. * ld-i386/tlsld1.s: Likewise. * ld-x86-64/tlsgd1.dd: Likewise. * ld-x86-64/tlsgd1.s: Likewise. * ld-x86-64/tlsld1.dd: Likewise. * ld-x86-64/tlsld1.s: Likewise.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 389c89a..6d2d59d 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2527,10 +2527,12 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
unsigned int i;
static unsigned char tlsgd[8]
= { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 };
+ unsigned long tls_r_symndx;
+ struct elf_link_hash_entry *tls_h;
/* GD->LE transition.
.byte 0x66; leaq foo@tlsgd(%rip), %rdi
- .word 0x6666; rex64; call __tls_get_addr@plt
+ .word 0x6666; rex64; call __tls_get_addr
Change it into:
movq %fs:0, %rax
leaq foo@tpoff(%rax), %rax */
@@ -2545,13 +2547,22 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
contents + rel->r_offset + 4 + i)
== tlsgd[i+4]);
BFD_ASSERT (rel + 1 < relend);
- BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+ tls_r_symndx = ELF64_R_SYM (rel[1].r_info);
+ BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+ tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+ BFD_ASSERT (tls_h != NULL
+ && tls_h->root.root.string != NULL
+ && strcmp (tls_h->root.root.string,
+ "__tls_get_addr") == 0);
+ BFD_ASSERT ((! info->shared
+ && ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32)
+ || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
memcpy (contents + rel->r_offset - 4,
"\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
16);
bfd_put_32 (output_bfd, tpoff (info, relocation),
contents + rel->r_offset + 8);
- /* Skip R_X86_64_PLT32. */
+ /* Skip R_X86_64_PC32/R_X86_64_PLT32. */
rel++;
continue;
}
@@ -2919,9 +2930,12 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
case R_X86_64_TLSLD:
if (! info->shared)
{
+ unsigned long tls_r_symndx;
+ struct elf_link_hash_entry *tls_h;
+
/* LD->LE transition:
Ensure it is:
- leaq foo@tlsld(%rip), %rdi; call __tls_get_addr@plt.
+ leaq foo@tlsld(%rip), %rdi; call __tls_get_addr.
We change it into:
.word 0x6666; .byte 0x66; movl %fs:0, %rax. */
BFD_ASSERT (rel->r_offset >= 3);
@@ -2935,10 +2949,18 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
== 0xe8);
BFD_ASSERT (rel + 1 < relend);
- BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+ tls_r_symndx = ELF64_R_SYM (rel[1].r_info);
+ BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+ tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+ BFD_ASSERT (tls_h != NULL
+ && tls_h->root.root.string != NULL
+ && strcmp (tls_h->root.root.string,
+ "__tls_get_addr") == 0);
+ BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32
+ || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
memcpy (contents + rel->r_offset - 3,
"\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
- /* Skip R_X86_64_PLT32. */
+ /* Skip R_X86_64_PC32/R_X86_64_PLT32. */
rel++;
continue;
}