[U-Boot] weak functions not being over-ridden (location dependent)

Hi All,
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
common.h defines reset_cpu() thusly:
void reset_cpu (ulong addr);
in cpu/i386/reset.c I have:
void __reset_cpu(ulong addr) { printf("Resetting using i386 Triple Fault\n"); set_vector(13, generate_gpf); /* general protection fault handler */ set_vector(8, generate_gpf); /* double fault handler */ generate_gpf(); /* start the show */ } void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu")));
Now, if I implement reset_cpu () in cpu/i386/sc520/reset.c
void reset_cpu(ulong addr) { printf("Resetting using SC520 MMCR\n"); /* Write a '1' to the SYS_RST of the RESCFG MMCR */ write_mmcr_word(SC520_RESCFG, 0x0001);
/* NOTREACHED */ }
and issue a reset from the prompt, it uses the Triple Fault
If I move reset_cpu () in board/eNET/eNET.c, it uses the MMCR
Now, if I remove __reset_cpu () (and the weak definition) and leave the reset_cpu in cpu/i386/sc520/reset.c, it uses the MMCR to reset the CPU. So /cpu/i386/sc520/reset.c is being compiled and the library is being linked in.
If I go back to __reset_cpu(), weak function and reset_cpu () in cpu/i386/sc520, u-boot.map reveals:
.text 0x000000003804ecd4 0x6d cpu/i386/libi386.a(reset.o) 0x000000003804ecdb __reset_cpu 0x000000003804ecd4 generate_gpf 0x000000003804ed10 do_reset 0x000000003804ecdb reset_cpu
and no other references to reset_cpu
Move reset_cpu () to board/eNET/eNET.c and I get
.text 0x00000000380499a0 0x312 board/eNET/libeNET.a(eNET.o) 0x00000000380499f8 dram_init 0x00000000380499e4 last_stage_init 0x0000000038049a07 init_sc520_enet 0x0000000038049a46 reset_cpu 0x0000000038049a69 board_init 0x00000000380499bb board_flash_get_legacy . . . .text 0x000000003804ecf8 0x6d cpu/i386/libi386.a(reset.o) 0x000000003804ecff __reset_cpu 0x000000003804ecf8 generate_gpf 0x000000003804ed34 do_reset
If I do not define the weak function and implement reset_cpu () in BOTH cpu/i386/reset.c and cpu/i386/sc520/reset.c I get no complaints from the linker, and the reset is performed via triple-fault. u-boot.map reveals:
.text 0x000000003804ecd4 0x6d cpu/i386/libi386.a(reset.o) 0x000000003804ecd4 generate_gpf 0x000000003804ed10 do_reset 0x000000003804ecdb reset_cpu
Why is the linker silently discarding an obvious symbol conflict?
Any ideas?
Thanks,
Graeme

Hello Graeme,
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
You are not the only one, I have seen this also with the LED interface in U-boot. My workaround was simple: remove the weak functions... I never took the time to figure it out exactly, so I am curious if anyone knows the real answer.
Remy
2008/11/26 Graeme Russ graeme.russ@gmail.com:
Hi All,
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
common.h defines reset_cpu() thusly:
void reset_cpu (ulong addr);
in cpu/i386/reset.c I have:
void __reset_cpu(ulong addr) { printf("Resetting using i386 Triple Fault\n"); set_vector(13, generate_gpf); /* general protection fault handler */ set_vector(8, generate_gpf); /* double fault handler */ generate_gpf(); /* start the show */ } void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu")));
Now, if I implement reset_cpu () in cpu/i386/sc520/reset.c
void reset_cpu(ulong addr) { printf("Resetting using SC520 MMCR\n"); /* Write a '1' to the SYS_RST of the RESCFG MMCR */ write_mmcr_word(SC520_RESCFG, 0x0001);
/* NOTREACHED */
}
and issue a reset from the prompt, it uses the Triple Fault
If I move reset_cpu () in board/eNET/eNET.c, it uses the MMCR
Now, if I remove __reset_cpu () (and the weak definition) and leave the reset_cpu in cpu/i386/sc520/reset.c, it uses the MMCR to reset the CPU. So /cpu/i386/sc520/reset.c is being compiled and the library is being linked in.
If I go back to __reset_cpu(), weak function and reset_cpu () in cpu/i386/sc520, u-boot.map reveals:
.text 0x000000003804ecd4 0x6d cpu/i386/libi386.a(reset.o) 0x000000003804ecdb __reset_cpu 0x000000003804ecd4 generate_gpf 0x000000003804ed10 do_reset 0x000000003804ecdb reset_cpu
and no other references to reset_cpu
Move reset_cpu () to board/eNET/eNET.c and I get
.text 0x00000000380499a0 0x312 board/eNET/libeNET.a(eNET.o) 0x00000000380499f8 dram_init 0x00000000380499e4 last_stage_init 0x0000000038049a07 init_sc520_enet 0x0000000038049a46 reset_cpu 0x0000000038049a69 board_init 0x00000000380499bb board_flash_get_legacy . . . .text 0x000000003804ecf8 0x6d cpu/i386/libi386.a(reset.o) 0x000000003804ecff __reset_cpu 0x000000003804ecf8 generate_gpf 0x000000003804ed34 do_reset
If I do not define the weak function and implement reset_cpu () in BOTH cpu/i386/reset.c and cpu/i386/sc520/reset.c I get no complaints from the linker, and the reset is performed via triple-fault. u-boot.map reveals:
.text 0x000000003804ecd4 0x6d cpu/i386/libi386.a(reset.o) 0x000000003804ecd4 generate_gpf 0x000000003804ed10 do_reset 0x000000003804ecdb reset_cpu
Why is the linker silently discarding an obvious symbol conflict?
Any ideas?
Thanks,
Graeme
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Dear Remy,
In message 3efb10970811260501h6dcf87b9idf3d80981ceee07b@mail.gmail.com you wrote:
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
You are not the only one, I have seen this also with the LED interface in U-boot. My workaround was simple: remove the weak functions... I never took the time to figure it out exactly, so I am curious if anyone knows the real answer.
I think this has been answered before: it doesn't work when the functions are in libraries. It only works when the respective functions are in explicitely linked object files.
Jean-Christophe is planning to switch to linking objects like the Linux kernel does, but this is a medium/long term task.
For now, check if you can separately link the respective object files.
See the ML archive for the previous discussion.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Remy,
In message 3efb10970811260501h6dcf87b9idf3d80981ceee07b@mail.gmail.com you wrote:
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
You are not the only one, I have seen this also with the LED interface in U-boot.
I think this has been answered before: it doesn't work when the functions are in libraries. It only works when the respective functions are in explicitely linked object files.
This doesn't seem right - reset_cpu () will be in a library no matter where I put it (either libsc520.a or libeNET.a)
Maybe its a binutils issue
Regards,
Graeme

Graeme,
Graeme Russ wrote:
Wolfgang Denk wrote:
Dear Remy,
In message 3efb10970811260501h6dcf87b9idf3d80981ceee07b@mail.gmail.com you wrote:
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
You are not the only one, I have seen this also with the LED interface in U-boot.
I think this has been answered before: it doesn't work when the functions are in libraries. It only works when the respective functions are in explicitely linked object files.
This doesn't seem right - reset_cpu () will be in a library no matter where I put it (either libsc520.a or libeNET.a)
Is the overriding function the only one in the source file (and thus the object file)? I've found that overriding functions will link only if there's other code in the source file that is strongly-linked.
regards, Ben

Ben Warren wrote:
Graeme,
Graeme Russ wrote:
Wolfgang Denk wrote:
I think this has been answered before: it doesn't work when the functions are in libraries. It only works when the respective functions are in explicitely linked object files.
This doesn't seem right - reset_cpu () will be in a library no matter where I put it (either libsc520.a or libeNET.a)
Is the overriding function the only one in the source file (and thus the object file)? I've found that overriding functions will link only if there's other code in the source file that is strongly-linked.
regards, Ben
That solves the problem - Thanks
I think this is an ld bug IMHO - will submit to binutils mailing list for comment
In the meantime, I need to dream up a strongly linked function which will be useful ;)
Regards,
Graeme

Graeme Russ wrote:
Ben Warren wrote:
Graeme,
Graeme Russ wrote:
Wolfgang Denk wrote:
I think this has been answered before: it doesn't work when the functions are in libraries. It only works when the respective functions are in explicitely linked object files.
This doesn't seem right - reset_cpu () will be in a library no matter where I put it (either libsc520.a or libeNET.a)
Is the overriding function the only one in the source file (and thus the object file)? I've found that overriding functions will link only if there's other code in the source file that is strongly-linked.
regards, Ben
That solves the problem - Thanks
I think this is an ld bug IMHO - will submit to binutils mailing list for comment
I found discussions through Google where this was talked about, and for whatever reason it's intended behavior. There are ways to force linking with ld switches, but they're only supported in newer versions of gcc/binutils and we're constrained here to supporting older tools.
From a software architecture standpoint, it seems wrong, but the easy fix is to add your overriding functions to existing files. For example, you'll see that all implementations of cpu_eth_init() are in cpu/<cpu>/cpu.c, although I would have preferred to create a new file called something like cpu/<cpu>/enet.c
Fun stuff...
cheers, Ben

On Wednesday 26 November 2008 14:32:48 Graeme Russ wrote:
Wolfgang Denk wrote:
In message ... you wrote:
I have a very strange problem - I am trying to define a weak function, but whether or not the function is overridden depends on where I put the overriding function. Case in point:
You are not the only one, I have seen this also with the LED interface in U-boot.
I think this has been answered before: it doesn't work when the functions are in libraries. It only works when the respective functions are in explicitely linked object files.
This doesn't seem right - reset_cpu () will be in a library no matter where I put it (either libsc520.a or libeNET.a)
the linker treates archives differently from shared libraries by design. "linked objects" refers to .o object files, not .a archives. -mike
participants (5)
-
Ben Warren
-
Graeme Russ
-
Mike Frysinger
-
Remy Bohmer
-
Wolfgang Denk