diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2007-08-14 19:48:21 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2007-08-14 19:48:21 +0000 |
commit | a3fadc9a17972a899c807f1ed3c8044066a68857 (patch) | |
tree | 76f351a35da7e7cc0506ebb6be7ac3de42bbb77f /bfd | |
parent | 6d307763fb4e0224a97d3f44150b8e07c0943af9 (diff) | |
download | gdb-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')
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/elf32-i386.c | 29 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 34 |
3 files changed, 64 insertions, 10 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 33e7871..5f5d291 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +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. + 2007-08-14 Jan Kratochvil <jan.kratochvil@redhat.com> * elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): LOADBASE is now diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index c50e98d..0e50e9e 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -2652,6 +2652,8 @@ elf_i386_relocate_section (bfd *output_bfd, { unsigned int val, type; bfd_vma roff; + unsigned long tls_r_symndx; + struct elf_link_hash_entry *tls_h; /* GD->LE transition. */ BFD_ASSERT (rel->r_offset >= 2); @@ -2662,7 +2664,16 @@ elf_i386_relocate_section (bfd *output_bfd, contents + rel->r_offset + 4) == 0xe8); BFD_ASSERT (rel + 1 < relend); - BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); + tls_r_symndx = ELF32_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 + && ELF32_R_TYPE (rel[1].r_info) == R_386_PC32) + || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); roff = rel->r_offset + 5; val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); @@ -2707,7 +2718,7 @@ elf_i386_relocate_section (bfd *output_bfd, } bfd_put_32 (output_bfd, tpoff (info, relocation), contents + roff); - /* Skip R_386_PLT32. */ + /* Skip R_386_PC32/R_386_PLT32. */ rel++; continue; } @@ -3191,6 +3202,8 @@ elf_i386_relocate_section (bfd *output_bfd, if (! info->shared) { unsigned int val; + unsigned long tls_r_symndx; + struct elf_link_hash_entry *tls_h; /* LD->LE transition: Ensure it is: @@ -3206,10 +3219,18 @@ elf_i386_relocate_section (bfd *output_bfd, BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4) == 0xe8); BFD_ASSERT (rel + 1 < relend); - BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); + tls_r_symndx = ELF32_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 (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32 + || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); memcpy (contents + rel->r_offset - 2, "\x65\xa1\0\0\0\0\x90\x8d\x74\x26", 11); - /* Skip R_386_PLT32. */ + /* Skip R_386_PC32/R_386_PLT32. */ rel++; continue; } 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; } |