aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2014-11-07 12:22:53 -0800
committerH.J. Lu <hjl.tools@gmail.com>2014-11-07 12:22:53 -0800
commitcf61b7473a8ee3b43c4f8f2776075ec8d81d7495 (patch)
tree0aeca9ef993f4b362aaa7649228120a4302c5532 /bfd/elf64-x86-64.c
parent9de00a4aa026297eae42bafd8ab413cfc1a53e3a (diff)
downloadgdb-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.c22
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);