]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86: check reloc types for relaxable branches
authorJan Beulich <jbeulich@suse.com>
Fri, 5 Sep 2025 06:33:27 +0000 (08:33 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 5 Sep 2025 06:33:27 +0000 (08:33 +0200)
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.

gas/config/tc-i386.c
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/reloc16.l [new file with mode: 0644]
gas/testsuite/gas/i386/reloc16.s [new file with mode: 0644]

index e758fa393c9be82455f7d2fae18b6caeab639b1d..fefd587ac7fa38dfb5f833f3b5ee98bbb127af0e 100644 (file)
@@ -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:
index b068b327af3bddbdf6217bda5aec5f72286d931b..137c10020732c2270fe00a474ff3436f7771f850 100644 (file)
@@ -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 (file)
index 0000000..9abe379
--- /dev/null
@@ -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 (file)
index 0000000..c5da920
--- /dev/null
@@ -0,0 +1,6 @@
+       .code16
+       .text
+plt:
+       call    func@plt
+       jz      func@plt
+       jmp     func@plt