]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86: Check MODRM for call and jmp in binutils older than 2.45 binutils-2_40-branch
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 22 May 2025 03:29:49 +0000 (11:29 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 22 May 2025 20:45:33 +0000 (04:45 +0800)
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)

bfd/elf32-i386.c
bfd/elf64-x86-64.c

index 9e398eacb81b55c8221059826f553563b8de10f1..7d96153a4f98b52206d0ae6e88f45afe292a933c 100644 (file)
@@ -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)
index 914f82d015191ffa99f0796f9d01b4945165decf..32acf32ccb1b4c3d7bd30e42afe48f86f76cb723 100644 (file)
@@ -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".  */