[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
ld bug when linking for Ubicom IP2K processor using --relax option
From: |
Ryan Stone |
Subject: |
ld bug when linking for Ubicom IP2K processor using --relax option |
Date: |
Tue, 16 Mar 2004 14:40:11 -0500 |
User-agent: |
KMail/1.5.3 |
I originally posted this to address@hidden Hopefully I'm sending it
to the right mailing list now.
ld has a bug when using the --relax option that causes it to generate invalid
code for the Ubicom IP2022 processor. Some jumps and calls go to the wrong
address in memory. It's easiest to show this with a small testcase:
void foo(unsigned char x, unsigned char y) __attribute__((section(".pram")));
void bar() __attribute__((section(".pram")));
int main(int argc, char * argv)
{
foo('r', 's');
bar();
return 0;
}
void foo(unsigned char x, unsigned char y)
{
}
void bar()
{
}
I compiled this with the gcc(version 3.3.3 20040105 (prerelease))
cross-compiler for the IP2K using only the -c option, and link with ld
(version 2.14) using only the --relax option. I'll show some snippets of the
disassembly to illustrate the bug:
in main:
/*calling bar()*/
page $00000
call $00010
However, bar() starts at address 0x0000e, not 0x00010. This bug does not
occur if --relax is not used. In main, it still calls address 0x00010, but
bar() really does start at that address if --relax is not used.
As far as I can tell, the problem is that linker relaxation is run after the
linker turns symbols in jump and call instructions into absolute addresses.
The relaxation step removes any redundant page instructions. This moves any
instructions after the page instruction up two bytes in memory. But jumps
and calls have already reference absolute addresses. These absolute
addresses are invalid if the relaxation has stripped out any page
instructions.
Unfortunately, this is a chicken-and-the-egg problem. The relaxation phase
can only remove page instructions if it is sure that the page instruction and
the symbol it references are in the same page in flash. So it needs to
compare absolute addresses. But after the relaxation, those addresses might
be invalid. So assigning addresses to symbols has to be done after
relaxation. I'm not sure how to fix this, if this really is the problem. It
definitely seems to be. In my example above, the call to bar is off by 2
bytes, which is the length of one instruction. There will be a single
redundant page instruction in foo() that eliminated by linker relaxation. If
a call to bar() is inserted into foo(), that will produce a second redundant
page instruction, and if you compile, link and then look at the disassembly,
the call to bar() in main() is off by 4 bytes.
I'm not sure if my explanation of the bug was coherent enough, so I'll give a
really small example below:
.global _main
_main:
page foo
jmp foo
foo:
ret
Here's what will happen when this is assembled and linked(with relaxation):
* _main is assigned an absolute address(let's say 0x00000)
* foo is assigned the address 0x00004 (_main + 2 instructions). The symbol
foo in the jmp instruction is turned into the absolute address of 0x0004
* The relaxation phase sees that the page instruction is redundant, and
removes it. The jmp instruction is now at address 0x00000, and the ret
instruction is now at 0x00002. The jmp instruction still jumps to 0x00004.
I'd suggest that anyone who uses ld for linking for the IP2K not use linker
relaxation unless this bug is fixed.
Ryan Stone
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- ld bug when linking for Ubicom IP2K processor using --relax option,
Ryan Stone <=