Fix R_386_GOT32X relaxation of push sym@GOT(%reg) on i686, backport of upstream 11c2852449825a5f486f63bc40aabed56b7c04c1 limited to bfd/elf32-i386.c

This commit is contained in:
eabdullin 2026-08-13 15:34:16 +03:00
parent 09b2ba648b
commit e47bd4bcfe
2 changed files with 123 additions and 0 deletions

View File

@ -43,6 +43,7 @@ actions:
- modify_release:
- suffix: ".alma.1"
enabled: true
auto_increment: true
- changelog_entry:
- name: "Andrew Lukoshko"
@ -51,3 +52,12 @@ actions:
- "Add bison to BuildRequires for RISC-V"
- "Disable LTO for RISC-V"
- "Disable testsuite for RISC-V"
- name: "Eduard Abdullin"
email: "eabdullin@almalinux.org"
line:
- "Fix R_386_GOT32X relaxation of push sym@GOT(%reg) on i686, backport of upstream 11c2852449825a5f486f63bc40aabed56b7c04c1 limited to bfd/elf32-i386.c"
- add_files:
- type: "patch"
name: "0001-x86-widen-got-pcrel-support-to-PUSH-and-APX-IMUL.patch"
number: 9001

View File

@ -0,0 +1,113 @@
From 11c2852449825a5f486f63bc40aabed56b7c04c1 Mon Sep 17 00:00:00 2001
From: Jan Beulich <jbeulich@suse.com>
Date: Fri, 21 Feb 2025 10:24:50 +0100
Subject: [PATCH] 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.
Backported to binutils 2.41: limited to bfd/elf32-i386.c (the x86-64 and
gas parts of the commit depend on APX support that 2.41 does not have) and
hunk contexts adjusted; the resulting code is identical to upstream.
---
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1199,6 +1199,10 @@
to
test $foo, %reg1
and convert
+ push foo@GOT[(%reg)]
+ to
+ push $foo
+ and convert
binop foo@GOT[(%reg1)], %reg2
to
binop $foo, %reg2
@@ -1223,7 +1227,7 @@
unsigned int addend;
unsigned int nop;
bfd_vma nop_offset;
- bool is_pic;
+ bool is_pic, is_branch = false;
bool to_reloc_32;
bool abs_symbol;
unsigned int r_type;
@@ -1285,6 +1289,23 @@
opcode = bfd_get_8 (abfd, contents + roff - 2);
+ if (opcode == 0xff)
+ {
+ switch (modrm & 0x38)
+ {
+ case 0x10: /* CALL */
+ case 0x20: /* JMP */
+ is_branch = true;
+ break;
+
+ case 0x30: /* PUSH */
+ break;
+
+ default:
+ return true;
+ }
+ }
+
/* Convert to R_386_32 if PIC is false or there is no base
register. */
to_reloc_32 = !is_pic || baseless;
@@ -1295,7 +1316,7 @@
reloc. */
if (h == NULL)
{
- if (opcode == 0x0ff)
+ if (is_branch)
/* Convert "call/jmp *foo@GOT[(%reg)]". */
goto convert_branch;
else
@@ -1311,7 +1332,7 @@
&& !eh->linker_def
&& local_ref)
{
- if (opcode == 0xff)
+ if (is_branch)
{
/* No direct branch to 0 for PIC. */
if (is_pic)
@@ -1327,7 +1348,7 @@
}
}
- if (opcode == 0xff)
+ if (is_branch)
{
/* We have "call/jmp *foo@GOT[(%reg)]". */
if ((h->root.type == bfd_link_hash_defined
@@ -1383,7 +1404,8 @@
else
{
/* We have "mov foo@GOT[(%re1g)], %reg2",
- "test %reg1, foo@GOT(%reg2)" and
+ "test %reg1, foo@GOT(%reg2)",
+ "push foo@GOT[(%reg)]", or
"binop foo@GOT[(%reg1)], %reg2".
Avoid optimizing _DYNAMIC since ld.so may use its
@@ -1437,6 +1459,13 @@
modrm = 0xc0 | (modrm & 0x38) >> 3;
opcode = 0xf7;
}
+ else if (opcode == 0xff)
+ {
+ /* Convert "push foo@GOT(%reg)" to
+ "push $foo". */
+ modrm = 0x68; /* Really the opcode. */
+ opcode = 0x2e; /* Really a meaningless %cs: prefix. */
+ }
else
{
/* Convert "binop foo@GOT(%reg1), %reg2" to