Bug 11085

Summary: Incorrect address calculation for Microblaze assembler code when using -relax and --gc-sections options
Product: binutils Reporter: Michael Engel <michael.engel>
Component: ldAssignee: unassigned
Status: NEW ---    
Severity: normal CC: bug-binutils, ecos
Priority: P2    
Version: 2.20   
Target Milestone: ---   
Host: i386-pc-linux-gnu Target: microblaze-unknown-none
Build: Last reconfirmed:

Description Michael Engel 2009-12-11 16:47:05 UTC
When linking object files using the options --gc-sections and -relax (MicroBlaze specific option that 
removes superfluous "imm 0" instructions), the addresses for some labels are miscalculated. 
Apparently this problem is caused by removing the "imm 0" instructions without changing the labels' 
addresses accordingly (e.g., when 2 "imm 0" instructions are removed, the address is off by 2 
instructions). It seems this only occurs in files generated from assembler source code. We did not 
notice this behavior in linked object files compiled from C/C++ Code.

gcc/g++ by default passes -relax to ld when compiling for microblaze, so many users may be unaware 
of what causes that but. 

The effect shows when using ld compiled from the current version out of cvs (GNU ld (GNU Binutils) 
2.20.51.20091211) as well as older versions (e.g., 2.16) distributed with Xilinx EDK 10 and 11.

Code example:

Without using the -relax option, objdump shows the correct code:
00000050 <_myStart>:
  50:   80000000        or      r0, r0, r0
  54:   80000000        or      r0, r0, r0
  58:   b0000000        imm     0
  5c:   b9f40028        brlid   r15, 40 // 84 <main>
  60:   b800000c        bri     12      // 6c <_bla>
  64:   80000000        or      r0, r0, r0
  68:   b800ffe8        bri     -24     // 50 <_TEXT_START_ADDR>

0000006c <_bla>:
  6c:   b8000000        bri     0       // 6c <_bla>

00000070 <_foobar>:
  70:   32e0002a        addik   r23, r0, 42
  74:   32e00017        addik   r23, r0, 23
  78:   80000000        or      r0, r0, r0

Using both -relax and --gc-sections the objdump shows:
00000050 <_myStart>:
  50:   80000000        or      r0, r0, r0
  54:   80000000        or      r0, r0, r0
  58:   b9f40028        brlid   r15, 40 // 80 <main>
  5c:   b8000010        bri     16      // 6c <_bla>
  60:   80000000        or      r0, r0, r0
  64:   b800ffec        bri     -20     // 50 <_TEXT_START_ADDR>
  68:   b8000004        bri     4       // 6c <_bla>

0000006c <_bla>:
  6c:   32e0002a        addik   r23, r0, 42

00000070 <_foobar>:
  70:   32e00017        addik   r23, r0, 23
  74:   80000000        or      r0, r0, r0

Both labels _bla and _foobar are at the wrong address.
Comment 1 Christophe coutand 2011-03-01 20:48:26 UTC
Hi,

Just to say that I have similar problems with my build ( GNU ld (GNU Binutils) 2.20.51.20100410 ). When removing the -relax, everything is fine. 

Christophe