https://sourceware.org/bugzilla/show_bug.cgi?id=21407
Bug ID: 21407 Summary: gas -relax option on SPARC generates incorrect code Product: binutils Version: 2.28 Status: UNCONFIRMED Severity: normal Priority: P2 Component: gas Assignee: unassigned at sourceware dot org Reporter: jeremygccb at baymoo dot org Target Milestone: --- Created attachment 10002 --> https://sourceware.org/bugzilla/attachment.cgi?id=10002&action=edit Patch for -relax on gas for SPARC BACKGROUND The "-relax" option on SPARC gas attempts to find "call" instructions that can be relaxed into branch instructions in certain cases. The function md_apply_fix() in t-sparc.c does the work of this feature, and while it finds and modifies such call instructions, it forgets to change the relocation type of the instruction as well. This can cause the instruction to be corrupted when it is later fixed up by the linker, especially if fix-up value is negative at link time. FIX The fix is to make sure to change the relocation type when changing the instruction. There appear to be two conversion cases in the 2.28 code. Both cases begin by matching qualified "call" instructions, but the action each takes differs depending on the target architecture. * "call" to "ba,pt" conversion in 64-bit SPARC v9 or greater When converting from "call" to "ba,pt" (under 64-bit SPARC v9+) the relocation type should be changed from its original BFD_RELOC_32_PCREL_S2 to BFD_RELOC_SPARC_WDISP19. * "call" to "b" conversion in all other SPARC architectures When converting from "call" to "b" the relocation type should be changed from its original BFD_RELOC_32_PCREL_S2 to BFD_RELOC_SPARC_WDISP22. A patch is attached. If I had more time I would write a regression test for the test suite, but I will leave that up to someone who knows the test suite better. EXAMPLE Here is a very short example which illustrates the problem. It is a portion of the code that is generated by GCC when building its libgcc helper library. example.s: f0: sethi %hi(0), %i0 call _atexit, 0 restore %i0, %lo(0), %o0 And to force the issue, we use another small file to create a resolution for the reference to "_atexit". atexit.s: .global _atexit _atexit: nop # Assemble atexit.o for later use % sparc-as atexit.s -o atexit.o BEFORE FIX Before the fix the assembled "call" instruction will be changed into a branch as normal, but the marked relocation type for the instruction will remain at the WDISP30 value that was generated when the "call" instruction was originally assembled. % sparc-as -relax example.s -o example.o % sparc-objdump -D -x example.o ... 00000000 <f0>: 0: 31 00 00 00 sethi %hi(0), %i0 4: 10 80 00 00 b 4 <f0+0x4> 4: WDISP30 _atexit-0x4 <-- Inappropriate reloc. type 8: 91 ee 20 00 restore %i0, 0, %o0 c: 01 00 00 00 nop ... When the linker applies a negative fix-up value to this instruction it will inadvertently overwrite a part of the instruction bits, turning it into an invalid instruction: # Link atexit.o first so that jump from example.o is negative. % sparc-ld -o example atexit.o example.o % sparc-objdump -D example ... 00002020 <_atexit>: 2020: 01 00 00 00 nop 2024: 01 00 00 00 nop 00002028 <f0>: 2028: 31 00 00 00 sethi %hi(0), %i0 202c: 3f ff ff fd cb012,a 2020 <_atexit> <--- Corrupted instruction 2030: 91 ee 20 00 restore %i0, 0, %o0 2034: 01 00 00 00 nop ... AFTER FIX After applying the patch attached to this report, the transformed "b" instruction will have the correct relocation type, WDISP22: % sparc-as.patched -relax example.s -o example.o % sparc-objdump -D -x example.o ... 00000000 <f0>: 0: 31 00 00 00 sethi %hi(0), %i0 4: 10 80 00 00 b 4 <f0+0x4> 4: WDISP22 _atexit-0x4 <-- Corrected relocation type 8: 91 ee 20 00 restore %i0, 0, %o0 c: 01 00 00 00 nop ... And the resulting final link will keep the instruction intact, despite applying a negative fix-up value: % sparc-ld -o example atexit.o example.o % sparc-objdump -D example ... 00002020 <_atexit>: 2020: 01 00 00 00 nop 2024: 01 00 00 00 nop 00002028 <f0>: 2028: 31 00 00 00 sethi %hi(0), %i0 202c: 10 bf ff fd b 2020 <_atexit> <--- Instruction is now correct 2030: 91 ee 20 00 restore %i0, 0, %o0 2034: 01 00 00 00 nop ... FURTHER DETAILS Not that it should matter for this simple test case, but I configured binutils as follows when I discovered the bug. ./configure --target=sparc-sun-sunos4.1.3 -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils