aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2025-05-22 11:29:49 +0800
committerH.J. Lu <hjl.tools@gmail.com>2025-05-23 04:45:33 +0800
commit893d5e8c935fb83e085cd0003e2578442c764a09 (patch)
treeb4e3f37299d218adb789a90e0444be83d6f241bd
parent060bfd90813b829e7c6a8f7347d5f834d406c29b (diff)
downloadbinutils-binutils-2_40-branch.zip
binutils-binutils-2_40-branch.tar.gz
binutils-binutils-2_40-branch.tar.bz2
x86: Check MODRM for call and jmp in binutils older than 2.45binutils-2_40-branch
When i386 glibc was assembled with commit: commit 11c2852449825a5f486f63bc40aabed56b7c04c1 (HEAD) Author: Jan Beulich <jbeulich@suse.com> Date: Fri Feb 21 10:24:50 2025 +0100 x86: widen @got{,pcrel} support to PUSH and APX IMUL With us doing the transformation to an immediate operand for MOV and various ALU insns, there's little reason to then not support the same conversion for the other two insns which have respective immediate operand forms. Unfortunately for IMUL (due to the 0F opcode prefix) there's no suitable relocation, so the pre-APX forms cannot be marked for relaxation in the assembler. "pushl main@GOT(%ebx)" in sysdeps/i386/start.S was assembled to 1c: ff b3 00 00 00 00 push 0x0(%ebx) 1e: R_386_GOT32X main Linkers in binutils versions older than 2.45 treated it as jmp and relaxed it to 22c: e9 cf ff ff ff jmp 200 <main> 231: 90 nop Update elf_i386_convert_load_reloc in binutils versions older than 2.45 to check MODRM for call and jmp to work with i386 glibc assembled with binutils 2.45 or newer. Do the same in elf_x86_64_convert_load_reloc. PR ld/32991 * elf32-i386.c (elf_i386_convert_load_reloc): Check MODRM for call and jmp. * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise. Signed-off-by: H.J. Lu <hjl.tools@gmail.com> (cherry picked from commit 452f5511154ca02095a271cf085e17f536587207)
-rw-r--r--bfd/elf32-i386.c9
-rw-r--r--bfd/elf64-x86-64.c9
2 files changed, 18 insertions, 0 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 9e398ea..7d96153 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1315,6 +1315,15 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
if (opcode == 0xff)
{
+ switch (modrm & 0x38)
+ {
+ case 0x10: /* CALL */
+ case 0x20: /* JMP */
+ break;
+ default:
+ return true;
+ }
+
/* We have "call/jmp *foo@GOT[(%reg)]". */
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 914f82d..32acf32 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1740,6 +1740,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
/* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to
R_X86_64_PC32. */
modrm = bfd_get_8 (abfd, contents + roff - 1);
+ switch (modrm & 0x38)
+ {
+ case 0x10: /* CALL */
+ case 0x20: /* JMP */
+ break;
+ default:
+ return true;
+ }
+
if (modrm == 0x25)
{
/* Convert to "jmp foo nop". */