aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2011-03-03 22:11:33 +0000
committerH.J. Lu <hjl.tools@gmail.com>2011-03-03 22:11:33 +0000
commit4a4c5f250b2251c4f6a11b748061d044a6919b9b (patch)
treecb051b2d2a71ebfed2896442b9ef706a81f75fd5 /bfd/elf64-x86-64.c
parent2e3fd7679d44288bc1f0e9cf28fe3a04c854e08d (diff)
downloadgdb-4a4c5f250b2251c4f6a11b748061d044a6919b9b.zip
gdb-4a4c5f250b2251c4f6a11b748061d044a6919b9b.tar.gz
gdb-4a4c5f250b2251c4f6a11b748061d044a6919b9b.tar.bz2
Supprt TLS x32 IE->LE transition.
bfd/ 2011-03-03 H.J. Lu <hongjiu.lu@intel.com> * elf64-x86-64.c (elf_x86_64_check_tls_transition): Supprt TLS x32 IE->LE transition. (elf_x86_64_relocate_section): Likewise. ld/testsuite/ 2011-03-03 H.J. Lu <hongjiu.lu@intel.com> * ld-x86-64/tlsie4.dd: New. * ld-x86-64/tlsie4.s: Likewise. * ld-x86-64/x86-64.exp (x86_64tests): Add tlsie4.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 343abce..56eb62e 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -913,16 +913,29 @@ elf_x86_64_check_tls_transition (bfd *abfd,
case R_X86_64_GOTTPOFF:
/* Check transition from IE access model:
- movq foo@gottpoff(%rip), %reg
- addq foo@gottpoff(%rip), %reg
+ mov foo@gottpoff(%rip), %reg
+ add foo@gottpoff(%rip), %reg
*/
- if (offset < 3 || (offset + 4) > sec->size)
- return FALSE;
-
- val = bfd_get_8 (abfd, contents + offset - 3);
- if (val != 0x48 && val != 0x4c)
- return FALSE;
+ /* Check REX prefix first. */
+ if (offset >= 3 && (offset + 4) <= sec->size)
+ {
+ val = bfd_get_8 (abfd, contents + offset - 3);
+ if (val != 0x48 && val != 0x4c)
+ {
+ /* X32 may have 0x44 REX prefix or no REX prefix. */
+ if (ABI_64_P (abfd))
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* X32 may not have any REX prefix. */
+ if (ABI_64_P (abfd))
+ return FALSE;
+ if (offset < 2 || (offset + 3) > sec->size)
+ return FALSE;
+ }
val = bfd_get_8 (abfd, contents + offset - 2);
if (val != 0x8b && val != 0x03)
@@ -3505,6 +3518,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (val == 0x4c)
bfd_put_8 (output_bfd, 0x49,
contents + roff - 3);
+ else if (!ABI_64_P (output_bfd) && val == 0x44)
+ bfd_put_8 (output_bfd, 0x41,
+ contents + roff - 3);
bfd_put_8 (output_bfd, 0xc7,
contents + roff - 2);
bfd_put_8 (output_bfd, 0xc0 | reg,
@@ -3517,6 +3533,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (val == 0x4c)
bfd_put_8 (output_bfd, 0x49,
contents + roff - 3);
+ else if (!ABI_64_P (output_bfd) && val == 0x44)
+ bfd_put_8 (output_bfd, 0x41,
+ contents + roff - 3);
bfd_put_8 (output_bfd, 0x81,
contents + roff - 2);
bfd_put_8 (output_bfd, 0xc0 | reg,
@@ -3528,6 +3547,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (val == 0x4c)
bfd_put_8 (output_bfd, 0x4d,
contents + roff - 3);
+ else if (!ABI_64_P (output_bfd) && val == 0x44)
+ bfd_put_8 (output_bfd, 0x45,
+ contents + roff - 3);
bfd_put_8 (output_bfd, 0x8d,
contents + roff - 2);
bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3),