[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug gas/21407] New: gas -relax option on SPARC generates incorrect code
From: |
jeremygccb at baymoo dot org |
Subject: |
[Bug gas/21407] New: gas -relax option on SPARC generates incorrect code |
Date: |
Thu, 20 Apr 2017 23:27:27 +0000 |
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 gas/21407] New: gas -relax option on SPARC generates incorrect code,
jeremygccb at baymoo dot org <=
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jeremygccb at baymoo dot org, 2017/04/20
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jose.marchesi at oracle dot com, 2017/04/24
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jose.marchesi at oracle dot com, 2017/04/24
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jose.marchesi at oracle dot com, 2017/04/24
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jeremygccb at baymoo dot org, 2017/04/24
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jose.marchesi at oracle dot com, 2017/04/24
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, jeremygccb at baymoo dot org, 2017/04/24
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, cvs-commit at gcc dot gnu.org, 2017/04/25
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, cvs-commit at gcc dot gnu.org, 2017/04/26
- [Bug gas/21407] gas -relax option on SPARC generates incorrect code, nickc at redhat dot com, 2017/04/26