+ linaro-toolchain
Hello Ulrich,
I want to revisit this old thread. Sorry for the sloppy follow-up. But, this time around I have more data.
On Tue, Mar 15, 2011 at 9:00 PM, Ulrich Weigand Ulrich.Weigand@de.ibm.com wrote:
Aneesh V aneesh@ti.com wrote:
I was trying to build u-boot in Thumb2 for OMAP4. Everything was fine until I added some patches recently. One of these patches introduced an API (let's say foo()) that has a weakly linked alias(let's say __foo()) and a strongly linked implementation(the real foo()) in an assembly file.
Although I give -mthumb and -mthumb-interwork for all the files, apparently GCC generates ARM code for assembly files. In the final image foobar() calls foo() using a BL. Since foobar() is in Thumb and foo() in ARM, it ends up crashing. Looks like foobar() assumed foo() to be Thumb because __foo() is Thumb.
I'm unable to reproduce this. Do you have a complete test case?
I've tried with the following small example:
foo1.c:
extern void foo (void) __attribute__ ((weak, alias ("__foo")));
void __foo (void) { }
int main (void) { foo (); }
foo2.S: .text .align 2 .global foo .type foo, %function foo: push {r7} add r7, sp, #0 mov sp, r7 pop {r7} bx lr .size foo, .-foo
When building just "gcc foo1.c", I get:
0000835c <__foo>: 835c: b480 push {r7} 835e: af00 add r7, sp, #0 8360: 46bd mov sp, r7 8362: bc80 pop {r7} 8364: 4770 bx lr 8366: bf00 nop
00008368 <main>: 8368: b580 push {r7, lr} 836a: af00 add r7, sp, #0 836c: f7ff fff6 bl 835c <__foo> 8370: 4618 mov r0, r3 8372: bd80 pop {r7, pc}
When building both files "gcc foo1.c foo2.S", I get instead:
00008368 <main>: 8368: b580 push {r7, lr} 836a: af00 add r7, sp, #0 836c: f000 e802 blx 8374 <foo> 8370: 4618 mov r0, r3 8372: bd80 pop {r7, pc}
00008374 <foo>: 8374: e92d0080 push {r7} 8378: e28d7000 add r7, sp, #0 837c: e1a0d007 mov sp, r7 8380: e8bd0080 pop {r7} 8384: e12fff1e bx lr
So it seems to me the linker is handling this correctly ...
(This is on Ubuntu Natty using system gcc and binutils.)
I could reproduce the problem on older tool-chain(Sourcery G++ Lite 2010q1-202) [1] with a modified version of your sample code:
a.c: ==== extern void foo (void) __attribute__ ((weak, alias ("__foo")));
void __foo (void) { }
extern void call_foo(void);
int main (void) { call_foo (); }
b.S: ==== .text .align 2 .global foo foo: push {r7} add r7, sp, #0 mov sp, r7 pop {r7} bx lr .size foo, .-foo
c.S .text .align 2
.global call_foo call_foo: bl foo bx lr
.global __aeabi_unwind_cpp_pr0 __aeabi_unwind_cpp_pr0: bx lr
Now, I build them using the following commands, which is similar to what U-Boot does:
arm-none-linux-gnueabi-gcc -mthumb -mthumb-interwork -c a.c arm-none-linux-gnueabi-gcc -mthumb -mthumb-interwork -c b.S arm-none-linux-gnueabi-gcc -mthumb -mthumb-interwork -c c.S arm-none-linux-gnueabi-ld -r a.o -o alib.o arm-none-linux-gnueabi-ld -r b.o -o blib.o arm-none-linux-gnueabi-ld -r c.o -o clib.o arm-none-linux-gnueabi-ld --start-group clib.o alib.o blib.o --end-group -o a.out armobjdump -S --reloc a.out
You will get something like: 00008094 <call_foo>: 8094: fa000006 blx 80b4 <foo> 8098: e12fff1e bx lr
Please note that that the 'blx' is not correct. Now, do the following change:
diff --git a/b.S b/b.S index e0f2de9..96dba1f 100644 --- a/b.S +++ b/b.S @@ -1,5 +1,6 @@ .text .align 2 +.type foo, %function .global foo foo: push {r7}
And build it again the same way and you will see: 00008094 <call_foo>: 8094: eb000006 bl 80b4 <foo> 8098: e12fff1e bx lr
I can't reproduce this on Linaro GCC 2012.01, so looks like the problem is solved in recent tool-chains. However, sadly I could reproduce a different but similar problem with Linaro GCC 2012.01. This time the call is from C(Thumb) to assembly(ARM) and no weakly linked symbols are involved.
a.c: ==== int main (void) { foo (); }
b.S: ==== .text .align 2 .global foo foo: push {r7} add r7, sp, #0 mov sp, r7 pop {r7} bx lr .size foo, .-foo
.global __aeabi_unwind_cpp_pr0 __aeabi_unwind_cpp_pr0: bx lr
arm-linux-gnueabi-gcc -mthumb -mthumb-interwork -c a.c arm-linux-gnueabi-gcc -mthumb -mthumb-interwork -c b.S arm-linux-gnueabi-ld -r a.o -o alib.o arm-linux-gnueabi-ld -r b.o -o blib.o arm-linux-gnueabi-ld --start-group alib.o blib.o --end-group -o a.out arm-linux-gnueabi-objdump -S --reloc a.out
gives: 8076: af00 add r7, sp, #0 8078: f000 f802 bl 8080 <foo> 807c: 4618 mov r0, r3
It should have been "blx 8080 <foo>", isn't it? Again, %function solves it.
I agree that not marking the assembly functions ' %function' is a problem in the code, so it's not a critical bug. But I would've been happier if the linker refused to link it rather than branching with the wrong instruction. Isn't that a problem?
Problem No:2 ************* Linaro GCC 2012.01 is giving a new problem w.r.to Thumb build that is not existing in Sourcery G++ Lite 2010q1-202. However, I couldn't reproduce this problem with a small program like above. So, let me give you reference to the original u-boot code that shows the problem and steps to reproduce it.
tree: git://github.com/aneeshv/u-boot.git branch: thumb
The above branch has mainline u-boot with 4 additional patches from me for enabling Thumb build. You can build it like this:
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm distclean make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm omap4_sdp4430
This builds two images u-boot and u-boot-spl. SPL is a tiny u-boot that runs from internal RAM and loads the u-boot to SDRAM. Now, please have a look at the map file of u-boot-spl which is at: spl/u-boot-spl.map
I see the following in my map file:
/spl/u-boot-spl.map: ================= .rodata.wkup_padconf_array_essential_4460 0x40309583 0x4 board/ti/sdp4430/libsdp4430.o 0x40309583 wkup_padconf_array_essential_4460 .rodata.wkup_padconf_array_essential 0x40309587 0xc board/ti/sdp4430/libsdp4430.o 0x40309587 wkup_padconf_array_essential .rodata.core_padconf_array_essential 0x40309593 0x60 board/ti/sdp4430/libsdp4430.o 0x40309593 core_padconf_array_essential
Please note that the .rodata symbols have odd addresses. These arrays actually need to be aligned at least to half-word boundary. In fact, in the image I verified that they are put at even addresses. So, the symbols have been kept as real address +1. I understand that this is the convention for Thumb functions. I guess the tool-chain did it for data too?? And I am getting unaligned access aborts on accessing them.
I notice that this doesn't happen with all .rodata. symbols in the image. I couldn't see any difference between working and non-working files nor any difference in the command used to build them!
Well, this doesn't happen if I don't use "-fdata-sections" in gcc options. So, apply the following patch and you will see that those symbols have even addresses now.
diff --git a/config.mk b/config.mk index ddaa477..723286a 100644 --- a/config.mk +++ b/config.mk @@ -190,7 +190,7 @@ CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \
# Enable garbage collection of un-used sections for SPL ifeq ($(CONFIG_SPL_BUILD),y) -CPPFLAGS += -ffunction-sections -fdata-sections +CPPFLAGS += -ffunction-sections LDFLAGS_FINAL += --gc-sections endif
/spl/u-boot-spl.map: ================= .rodata 0x40309204 0x38c board/ti/sdp4430/libsdp4430.o 0x40309204 core_padconf_array_essential 0x40309264 wkup_padconf_array_essential 0x40309270 wkup_padconf_array_essential_4460 0x40309274 core_padconf_array_non_essential 0x40309540 wkup_padconf_array_non_essential 0x40309588 wkup_padconf_array_non_essential_4430
Will you be able to look into these?
Thanks, Aneesh
[1] Sourcery G++ Lite 2010q1-202 arm-none-linux-gnueabi-gcc (Sourcery G++ Lite 2010q1-202) 4.4.1 GNU ld (Sourcery G++ Lite 2010q1-202) - binutils 2.19.51.20090709
[2] Linaro 4.6-2012.01 arm-linux-gnueabi-gcc (crosstool-NG linaro-1.13.1-2012.01-20120125 - Linaro GCC 2012.01) 4.6.3 20120105 (prerelease) GNU ld (crosstool-NG linaro-1.13.1-2012.01-20120125 - Linaro GCC 2012.01) 2.22