bug-binutils
[Top][All Lists]
Advanced

[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.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]