diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2014-11-07 12:22:53 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2014-11-07 12:22:53 -0800 |
commit | cf61b7473a8ee3b43c4f8f2776075ec8d81d7495 (patch) | |
tree | 0aeca9ef993f4b362aaa7649228120a4302c5532 /bfd/elf64-x86-64.c | |
parent | 9de00a4aa026297eae42bafd8ab413cfc1a53e3a (diff) | |
download | gdb-cf61b7473a8ee3b43c4f8f2776075ec8d81d7495.zip gdb-cf61b7473a8ee3b43c4f8f2776075ec8d81d7495.tar.gz gdb-cf61b7473a8ee3b43c4f8f2776075ec8d81d7495.tar.bz2 |
X32: Add REX prefix to encode R_X86_64_GOTTPOFF
Structions with R_X86_64_GOTTPOFF relocation must be encoded with REX
prefix even if it isn't required by destination register. Otherwise
linker can't safely perform IE -> LE optimization.
bfd/
PR ld/17482
* elf64-x86-64.c (elf_x86_64_relocate_section): Update comments
for IE->LE transition.
gas/
PR ld/17482
* config/tc-i386.c (output_insn): Add a dummy REX_OPCODE prefix
for structions with R_X86_64_GOTTPOFF relocation for x32 if needed.
gas/testsuite/
PR ld/17482
* gas/i386/ilp32/x32-tls.d: New file.
* gas/i386/ilp32/x32-tls.s: Likewise.
ld/testsuite/
PR ld/17482
* ld-x86-64/tlsie4.dd: Updated.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 6c3a65a..d0ed8a7 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -4283,17 +4283,27 @@ direct: else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTTPOFF) { /* IE->LE transition: - Originally it can be one of: + For 64bit, originally it can be one of: movq foo@gottpoff(%rip), %reg addq foo@gottpoff(%rip), %reg We change it into: movq $foo, %reg leaq foo(%reg), %reg - addq $foo, %reg. */ + addq $foo, %reg. + For 32bit, originally it can be one of: + movq foo@gottpoff(%rip), %reg + addl foo@gottpoff(%rip), %reg + We change it into: + movq $foo, %reg + leal foo(%reg), %reg + addl $foo, %reg. */ unsigned int val, type, reg; - val = bfd_get_8 (input_bfd, contents + roff - 3); + if (roff >= 3) + val = bfd_get_8 (input_bfd, contents + roff - 3); + else + val = 0; type = bfd_get_8 (input_bfd, contents + roff - 2); reg = bfd_get_8 (input_bfd, contents + roff - 1); reg >>= 3; @@ -4313,8 +4323,8 @@ direct: } else if (reg == 4) { - /* addq -> addq - addressing with %rsp/%r12 is - special */ + /* addq/addl -> addq/addl - addressing with %rsp/%r12 + is special */ if (val == 0x4c) bfd_put_8 (output_bfd, 0x49, contents + roff - 3); @@ -4328,7 +4338,7 @@ direct: } else { - /* addq -> leaq */ + /* addq/addl -> leaq/leal */ if (val == 0x4c) bfd_put_8 (output_bfd, 0x4d, contents + roff - 3); |