From: Jan Beulich Date: Fri, 5 Sep 2025 06:33:27 +0000 (+0200) Subject: x86: check reloc types for relaxable branches X-Git-Tag: gdb-17-branchpoint~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=496e01123d85e3a8c3d8fabae11867206e15cc1e;p=thirdparty%2Fbinutils-gdb.git 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 --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