[binutils-gdb/binutils-2_42-branch] x86: Check MODRM for call and jmp in binutils older than 2.45

H.J. Lu hjl@sourceware.org
Thu May 22 20:42:52 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f9488b0d92b591bdf3ff8cce485cb0e1b3727cc0

commit f9488b0d92b591bdf3ff8cce485cb0e1b3727cc0
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu May 22 11:29:49 2025 +0800

    x86: Check MODRM for call and jmp in binutils older than 2.45
    
    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)

Diff:
---
 bfd/elf32-i386.c   | 9 +++++++++
 bfd/elf64-x86-64.c | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index e2f88a11487..f11500ff880 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1335,6 +1335,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 2ed120af780..abf97b2dde5 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1851,6 +1851,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".  */


More information about the Binutils-cvs mailing list