Bug 13352 - microblaze linker relocation bug: R_MICROBLAZE_64_NONE
Summary: microblaze linker relocation bug: R_MICROBLAZE_64_NONE
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-10-27 17:28 UTC by Barry Keane
Modified: 2018-01-09 21:30 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Tarball contains two C source files. Please compile and link as described above. (1.68 KB, application/x-compressed-tar)
2011-10-27 17:28 UTC, Barry Keane
Details
regression introduced by patch (359 bytes, text/plain)
2018-01-09 21:27 UTC, wbx
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Barry Keane 2011-10-27 17:28:25 UTC
Created attachment 6037 [details]
Tarball contains two C source files. Please compile and link as described above.

In certain cases the mb-gcc linker doesn't update the IMM operand when address mode optimization (a.k.a. relaxation, ld -relax) shrinks a R_MICROBLAZE_64_NONE relocation. I believe the assembler generates this relocation type for a BRLID to a function declared static in the same module. If the relocation target in the BRLID instruction is further than 64kbytes away _before_ relaxation (i.e. on output from the assembler) but changes to less than 64Kbytes away _after_ relaxation, the linker updates the BRLID immediate operand but fails to update the IMM operand.

Note this only happens when an input .o is fairly large (at least 64KB of .text).
 
One workaround is to invoke ld directly and omit the -relax option.
 
I'm using Xilinx EDK 12.4. "mb-gcc -v" says:
gcc version 4.1.2 20070214 (Xilinx 12.3 Build EDK_MS3.66 14 Jul 2010)
 
To reproduce the problem:
 
1) unpack the two source files from the attached tarball
2) mb-gcc -v -mcpu=v8.00.b -mno-xl-soft-mul -O -o relax relax.c relax2.c
3) mb-objdump -d relax | grep brlid | grep -v '//'
 
The last command will print the line of the badly-linked subroutine call.
Comment 1 Barry Keane 2011-10-27 17:40:17 UTC
I should clarify a little more. The problematic IMM+BRLID instruction pair lies at text addresses 0x100A8 and 0x100AC in the linker output.

   100a8:       b000fffe        imm     -2
   100ac:       b9f4015c        brlid   r15, 348

The target subroutine address (atoi0000) lies at 0x0208.
The BRLID interprets its address as a PC-relative (not absolute) address, hence the linker relocation result should be the difference:
    atoi0000 address: 0x208:
    BRLID address: 0x100AC
    difference:  0xFFFF015C 
Instead the linker produces 0xFFFE015C, which is a bug.

If you look at the .o assembler output you'll see that that the assembler produces a correct PC-relative address in which the IMM operand is 0xFFFE.

   10270:       b000fffe        imm     -2
   10274:       b9f4fd8c        brlid   r15, -628       // 0 <atoi0000>

At this point (before relaxation) the target is more than 64KB away from the BRLID instruction: 0xFFFEFD8C (66164 decimal) bytes. After relaxation the target is less than 64KB away: 0xFFFF015C (65188 decimal) bytes.

It looks to me like the linker's relaxation optimization updated the BRLID operand but neglected to update the IMM operand.
Comment 2 wbx 2018-01-09 21:27:57 UTC
Created attachment 10724 [details]
regression introduced by patch
Comment 3 wbx 2018-01-09 21:30:59 UTC
sorry for the spam, bugzilla took me to next bug and I didn't see it.