在链接期间,库中的弱符号可以解决吗?

我的场景是关于交叉编译到Arduino Due(ARM目标),但我想这是一个通用的C弱符号问题。

我想将我的固件分成3个部分:1。硬件库(CMSIS,中间件) – > libHardware.a 2.实时操作系统库 – > libOS.a 3.应用程序代码 – > Output.elf链接到上面。

引用的CMSIS实现已声明如下:

void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); // ...and a few dozen IRQ handler hook skipped for brevity 

CMSIS设计的想法是让应用程序代码有选择地实现和处理一些IRQ。

nm报告了libHardware.a

 startup_sam3xa.o: 00000000 W SysTick_Handler ... 

在我的场景中,我想在libOS.a中实现这些IRQ处理程序。

我实现了void SysTick_Handler(void),nm报告:

 cortex_handlers.o: 00000000 T SysTick_Handler .... 

然后我将它们连接在一起,这基本上归结为

 g++ -o app.elf -Wl,--start-group app.o libHardware.a libOS.a -Wl,--end-group 

(分组是必要的,因为OS依赖于低级硬件function。硬件需要调用操作系统提供的IRQ / main()函数)

nm报告:

 ... 00080124 W SysTick_Handler ... 

它仍然很弱! 我希望它使用libOS.a中定义的强符号。 最后,SysTick没有得到处理,这当然会导致灾难性的失败。

另一方面,如果我没有在libHardware / startup_sam3xa.c中将它们声明为弱,那么一切正常。 如果我选择在app / app.c中实现SysTick_Handler,它也会强烈关联。

所以我的问题是:libOS.a如何实现libHardware.a中定义的弱处理程序? 或者这些固件开发方案中的最佳实践是什么?

SysTick_Handler中定义SysTick_Handler ,它定义了正常的入口点。 但是只有当链接器获得链接特定目标文件的请求时,它才会覆盖弱符号(来自libOS.a)。

libHardware.a通常定义引用SysTick_Handler的中断向量表。 这是这个实际名称在游戏中出现的唯一指针。 (对于ARM,它只是向量表中的一个条目。)同一个库已经提供了一个弱符号。 因此,链接器不再搜索该符号。 当你想覆盖cortex_handlers.c中的符号时,你需要引用该文件中的任何符号,使链接器使用cortex_handlers.o 。 这将开启弱势符号。

 // cortex_handlers.c void SysTick_Handler() { } int link_my_cortex_handlers_file; 

只需引用符号link_my_cortex_handlers_file

感谢harper的上述回答,我发现Arduino通过将所有弱定义从startup_sam3xa.c移动到他们的cortex_handlers.c文件来解决这个问题,以便弱defs属于“OS”而不是硬件(使用OP的语言)。

另一个解决方案是将处理程序(或其他)的源保持独立,但是将#include到源文件中,在使用库时必须始终引用该文件(如果您的库有这样的东西并且不是全部可选的。)使用不同的单词而不是另一个答案,链接器在检查库时.a以目标文件为单位工作.o:如果目标文件具有任何符号,当链接器通过存档中的.o单位时解析未解析的符号(链接器可以进行多次传递,链接器将目标文件中的所有符号放入链接的二进制文件中,解析未解析的符号并覆盖弱定义。 链接命令中的库顺序很重要,您可能需要一个库在链接命令中出现两次。 链接器标志整个存档也可以解决问题。 我的回答很简洁,但可能是错的。