[U-Boot-Users] Can't get strong symbol to override weak one

Hi,
Not specifically U-boot related, but hopefully a smart person here can help.
I have a weak symbol defined as: int cpu_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init"))); (1)
I've created a new file in cpu/mpc83xx that includes a real implementation of the function: int cpu_eth_init(bd_t *bis) (2)
Using objdump, I've verified that this function is making it into libmpc8xxx.a, however it doesn't get linked into the final U-boot executable. System.map shows cpu_eth_init at the same address as __def_eth_init.
If I change (1) to: extern int cpu_eth_init(bd_t *bis), (2) gets linked in OK. Of course, that's not what I want to do.
I've tried changing the order of the archives that get linked together by ld, but nothing seems to work. Since I don't really know what I'm doing, I guess that shouldn't be surprising.
Any help would be appreciated.
thanks, Ben

Hello,
On Tue, Jun 10, 2008 at 10:55 PM, Ben Warren biggerbadderben@gmail.com wrote:
Hi,
Not specifically U-boot related, but hopefully a smart person here can help.
I have a weak symbol defined as: int cpu_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init"))); (1)
I've created a new file in cpu/mpc83xx that includes a real implementation of the function: int cpu_eth_init(bd_t *bis) (2)
Using objdump, I've verified that this function is making it into libmpc8xxx.a, however it doesn't get linked into the final U-boot executable. System.map shows cpu_eth_init at the same address as __def_eth_init.
If I change (1) to: extern int cpu_eth_init(bd_t *bis), (2) gets linked in OK. Of course, that's not what I want to do.
I've tried changing the order of the archives that get linked together by ld, but nothing seems to work. Since I don't really know what I'm doing, I guess that shouldn't be surprising.
Any help would be appreciated.
thanks, Ben
I've played around a bit more and found that if I move my function to an existing file containing functions called from elsewhere, my code gets linked in. Further research shows that a 'feature' of ld is that it won't pull in a module that only has symbols that have already been resolved, even if the previously found version is weak.
Mike F, please correct me if I'm wrong but that's what I gather from a conversion I found you having with the binutils mailing list:
http://sourceware.org/ml/binutils/2008-01/msg00302.html
IMHO, developers should be able to write board and cpu code to override weak symbols in libraries/drivers without having to worry about whether the intention was obeyed or not. ld has a switch '--whole-archive', that will pull in an entire archive, not just the modules that are referenced elsewhere with strong linkage.
I propose to wrap both the 'board/$(BOARDDIR)/lib$(BOARD).a' and 'cpu/$(CPU)/lib$(CPU).a' arguments to ld in --whole-module/--no-whole-module in order to accomplish this goal. We definitely don't want to do this across the board because image size will increase quite a bit due to unused code. I believe that the board and cpu code, though, should be mostly free of cruft. If not, it should be restructured with appropriate CONFIGs, either in Makefiles or C code.
thoughts?
regards, Ben

In message f8328f7c0806122238p24054afcx5190acfda8a794c6@mail.gmail.com you wrote:
I've played around a bit more and found that if I move my function to an existing file containing functions called from elsewhere, my code gets linked in. Further research shows that a 'feature' of ld is that it won't pull in a module that only has symbols that have already been resolved, even if the previously found version is weak.
Argh...
That's evil, but given the way ld works, I think I can understand it.
IMHO, developers should be able to write board and cpu code to override weak symbols in libraries/drivers without having to worry about whether the intention was obeyed or not. ld has a switch '--whole-archive', that will pull in an entire archive, not just the modules that are referenced elsewhere with strong linkage.
Oh no. Please don;t even mention this...
I propose to wrap both the 'board/$(BOARDDIR)/lib$(BOARD).a' and 'cpu/$(CPU)/lib$(CPU).a' arguments to ld in --whole-module/--no-whole-module in order to accomplish this goal. We definitely don't want to do this across the board because image size will increase quite a bit due to unused code. I believe that the board and cpu code, though, should be mostly free of cruft. If not, it should be restructured with appropriate CONFIGs, either in Makefiles or C code.
No, please do NOT do that. This will become a PITA.
Maybe somebody has a really clever idea, but I'm afraid we might end up having to put all "strong" functions that are supposed to overwrite weak ones into separate modules that get pulled in unconditionally :-(
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Fri, Jun 13, 2008 at 12:09 AM, Wolfgang Denk wd@denx.de wrote:
In message f8328f7c0806122238p24054afcx5190acfda8a794c6@mail.gmail.com you wrote:
I've played around a bit more and found that if I move my function to an existing file containing functions called from elsewhere, my code gets linked in. Further research shows that a 'feature' of ld is that it won't pull in a module that only has symbols that have already been resolved, even if the previously found version is weak.
Argh...
That's evil, but given the way ld works, I think I can understand it.
IMHO, developers should be able to write board and cpu code to override weak symbols in libraries/drivers without having to worry about whether the intention was obeyed or not. ld has a switch '--whole-archive', that will pull in an entire archive, not just the modules that are referenced elsewhere with strong linkage.
Oh no. Please don;t even mention this...
I propose to wrap both the 'board/$(BOARDDIR)/lib$(BOARD).a' and 'cpu/$(CPU)/lib$(CPU).a' arguments to ld in --whole-module/--no-whole-module in order to accomplish this goal. We definitely don't want to do this across the board because image size will increase quite a bit due to unused code. I believe that the board and cpu code, though, should be mostly free of cruft. If not, it should be restructured with appropriate CONFIGs, either in Makefiles or C code.
No, please do NOT do that. This will become a PITA.
OK. We'll try to figure out something else. Makefile modification looked like a major PITA to do this anyway, which is why I didn't just go ahead and do it.
Maybe somebody has a really clever idea, but I'm afraid we might end up having to put all "strong" functions that are supposed to overwrite weak ones into separate modules that get pulled in unconditionally :-(
Best regards,
Wolfgang Denk
thanks, Ben

"Ben Warren" biggerbadderben@gmail.com wrote:
I propose to wrap both the 'board/$(BOARDDIR)/lib$(BOARD).a' and 'cpu/$(CPU)/lib$(CPU).a' arguments to ld in --whole-module/--no-whole-module in order to accomplish this goal. We definitely don't want to do this across the board because image size will increase quite a bit due to unused code.
You can counter that additional size and more by adding --gc-sections to the linker command line and -ffunction-sections -fdata-sections to gcc. That will probably even get rid of the weak implementation if a strong definition is provided.
There's a catch though -- if your linker script isn't prepared for this, things will break.
Haavard

Hi Haavard,
On Fri, Jun 13, 2008 at 1:44 AM, Haavard Skinnemoen haavard.skinnemoen@atmel.com wrote:
"Ben Warren" biggerbadderben@gmail.com wrote:
I propose to wrap both the 'board/$(BOARDDIR)/lib$(BOARD).a' and 'cpu/$(CPU)/lib$(CPU).a' arguments to ld in --whole-module/--no-whole-module in order to accomplish this goal. We definitely don't want to do this across the board because image size will increase quite a bit due to unused code.
You can counter that additional size and more by adding --gc-sections to the linker command line and -ffunction-sections -fdata-sections to gcc. That will probably even get rid of the weak implementation if a strong definition is provided.
There's a catch though -- if your linker script isn't prepared for this, things will break.
Haavard
From what I've read, this --gc-sections thing is pretty new, and lots
of people are using older tools, so that idea has to be thrown out. Fun stuff...
regards, Ben

In message 20080613104406.3116ac16@hskinnemo-gx745.norway.atmel.com you wrote:
"Ben Warren" biggerbadderben@gmail.com wrote:
I propose to wrap both the 'board/$(BOARDDIR)/lib$(BOARD).a' and 'cpu/$(CPU)/lib$(CPU).a' arguments to ld in --whole-module/--no-whole-module in order to accomplish this goal. We definitely don't want to do this across the board because image size will increase quite a bit due to unused code.
You can counter that additional size and more by adding --gc-sections to the linker command line and -ffunction-sections -fdata-sections to gcc. That will probably even get rid of the weak implementation if a strong definition is provided.
There's a catch though -- if your linker script isn't prepared for this, things will break.
... and it probably doesn't work with older toolchains either.
Best regards,
Wolfgang Denk
participants (3)
-
Ben Warren
-
Haavard Skinnemoen
-
Wolfgang Denk