静态库中定义的IRQ符号不会覆盖ARM / GCC启动时的弱IRQ定义

时间:2017-02-16 09:26:42

标签: c gcc assembly arm keil

我已经构建了一个静态库(* .a用于gcc,* .lib用于keil)。其源文件之一,编译成库,包含RADIO_IRQHandler的定义。此源文件的摘录名为" ral_irq_handlers.c",如下所示:

...
void ral_symbol_import(void) //dummy function
{
    return;
}
...
void RADIO_IRQHandler(void)
{
    ...
}
...

此IRQ符号定义应覆盖在启动文件中声明的弱定义。启动文件不会编译到任何静态库中,只是项目中的常规文件。

下面是arm_startup_xxx.s文件(keil工具链)的摘录:

Default_Handler PROC
                ...
                EXPORT   RADIO_IRQHandler [WEAK]
                ...
...
RADIO_IRQHandler
...
                B .
                ENDP
                ALIGN

下面列出了类似gcc_startup_xxx.s文件(gcc工具链)的摘录:

.globl  Default_Handler
.type   Default_Handler, %function
Default_Handler:
    b       .
    .size   Default_Handler, . - Default_Handler

    .macro  IRQ handler
    .weak   \handler
    .set    \handler, Default_Handler
    .endm    
    ...
    IRQ  RADIO_IRQHandler
    ...
    .end

然后我发现了一种奇怪的行为。当我使用" ral_irq_handlers.c"中的任何API函数时在其中一个项目源文件中的源文件(编译到库中),链接正确完成。例如:

...
int main(void)
{
    ral_symbol_import();
    ...
}
...

但是,如果我不使用" ral_irq_handlers.c"的任何API函数。源文件,链接器找不到我的库中定义的RADIO_IRQHandler符号。如果没有这个丑陋的黑客(调用虚函数强制正确链接),我能以某种方式做到这一点吗?

我想只修改库代码而不触及启动文件。

1 个答案:

答案 0 :(得分:1)

据我所知你不能轻易做到这一点,因为链接器只会搜索你的库,如果它找不到处理程序的符号。正如它可以找到的那样(启动时的弱定义)它看起来没有任何进展。

但是你可以通过链接你的库来解决它:

... -Wl,--whole-archive -l:path/to/our/library.a -Wl,--no-whole-archive ...

此外,您实际上不必调用虚函数来导致模块的链接。您所需要的就是告诉链接器您需要它,例如:

void ral_symbol_import(void);
void (* const variable)() = &ral_symbol_import;