[binutils-gdb] x86: check reloc types for relaxable branches
Jan Beulich
jbeulich@sourceware.org
Fri Sep 5 06:34:44 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=496e01123d85e3a8c3d8fabae11867206e15cc1e
commit 496e01123d85e3a8c3d8fabae11867206e15cc1e
Author: Jan Beulich <jbeulich@suse.com>
Date: Fri Sep 5 08:33:27 2025 +0200
x86: check reloc types for relaxable branches
Bypassing _reloc() isn't a good idea, as there are various errors
checked for there. For example 16-bit JMP or Jcc may not use the @plt
form (resulting in a 32-bit relocation to be emitted for a 16-bit
field), which so far we only reject for 16-bit CALL. In exchange this
allows simplifying the setting up of the "reloc_type" local variable.
Diff:
---
gas/config/tc-i386.c | 27 +++++++++++++++------------
gas/testsuite/gas/i386/i386.exp | 1 +
gas/testsuite/gas/i386/reloc16.l | 4 ++++
gas/testsuite/gas/i386/reloc16.s | 6 ++++++
4 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index e758fa393c9..fefd587ac7f 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -16154,18 +16154,15 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
int old_fr_fix;
fixS *fixP = NULL;
- if (fragP->fr_var != NO_RELOC)
- reloc_type = (enum bfd_reloc_code_real) fragP->fr_var;
- else if (size == 2)
- reloc_type = BFD_RELOC_16_PCREL;
+ reloc_type = (enum bfd_reloc_code_real) fragP->fr_var;
#ifdef OBJ_ELF
- else if (fragP->tc_frag_data.code == CODE_64BIT
- && fragP->fr_offset == 0
- && need_plt32_p (fragP->fr_symbol))
+ if (reloc_type == NO_RELOC
+ && size != 2
+ && fragP->tc_frag_data.code == CODE_64BIT
+ && fragP->fr_offset == 0
+ && need_plt32_p (fragP->fr_symbol))
reloc_type = BFD_RELOC_X86_64_PLT32;
#endif
- else
- reloc_type = BFD_RELOC_32_PCREL;
old_fr_fix = fragP->fr_fix;
opcode = (unsigned char *) fragP->fr_opcode;
@@ -16179,7 +16176,9 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
fixP = fix_new (fragP, old_fr_fix, size,
fragP->fr_symbol,
fragP->fr_offset, 1,
- reloc_type);
+ _reloc (size, 1, 1, reloc_type,
+ fragP->tc_frag_data.code == CODE_64BIT,
+ fragP->fr_file, fragP->fr_line));
break;
case COND_JUMP86:
@@ -16198,7 +16197,9 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
fix_new (fragP, old_fr_fix + 2, 2,
fragP->fr_symbol,
fragP->fr_offset, 1,
- reloc_type);
+ _reloc (size, 1, 1, reloc_type,
+ fragP->tc_frag_data.code == CODE_64BIT,
+ fragP->fr_file, fragP->fr_line));
break;
}
/* Fall through. */
@@ -16224,7 +16225,9 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
fixP = fix_new (fragP, old_fr_fix + 1, size,
fragP->fr_symbol,
fragP->fr_offset, 1,
- reloc_type);
+ _reloc (size, 1, 1, reloc_type,
+ fragP->tc_frag_data.code == CODE_64BIT,
+ fragP->fr_file, fragP->fr_line));
break;
default:
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index b068b327af3..137c1002073 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -881,6 +881,7 @@ if {[is_elf_format] || [istarget "*-*-vxworks*"]} then {
}
run_dump_test "code16-2"
+ run_list_test "reloc16"
if {![istarget "*-*-dragonfly*"]
&& ![istarget "*-*-gnu*"]
diff --git a/gas/testsuite/gas/i386/reloc16.l b/gas/testsuite/gas/i386/reloc16.l
new file mode 100644
index 00000000000..9abe379f4d6
--- /dev/null
+++ b/gas/testsuite/gas/i386/reloc16.l
@@ -0,0 +1,4 @@
+.*: Assembler messages:
+.*:4: Error: .*4-byte reloc.*2-byte field.*
+.*:5: Error: .*4-byte reloc.*2-byte field.*
+.*:6: Error: .*4-byte reloc.*2-byte field.*
diff --git a/gas/testsuite/gas/i386/reloc16.s b/gas/testsuite/gas/i386/reloc16.s
new file mode 100644
index 00000000000..c5da920c1f2
--- /dev/null
+++ b/gas/testsuite/gas/i386/reloc16.s
@@ -0,0 +1,6 @@
+ .code16
+ .text
+plt:
+ call func@plt
+ jz func@plt
+ jmp func@plt
More information about the Binutils-cvs
mailing list