使用函数B覆盖弱函数A.

时间:2016-08-01 09:55:13

标签: c ld weak-linking

对于嵌入式设备,我的文件包含一个带有存储中断处理程序的函数指针的数组,这样定义(我不能修改它):

typedef void (*const ISRFunction)(void);

__attribute__((weak)) void ISR0(void){ for(;;); }
__attribute__((weak)) void ISR1(void){ for(;;); }
...
__attribute__((weak)) void ISR78(void){ for(;;); }
...

ISRFunction __vector_table[0x79] = 
{
    (ISRFunction)&ISR0,
    (ISRFunction)&ISR1,
    ...
    (ISRFunction)&ISR78,
    ...
}

我有第二个文件定义了一些我无法修改的函数。这个文件就像:

void blinkLed(void)
{ ... }

最后,我有一个主要源文件,具有main功能和设备配置。在中断78,我想闪烁领导。所以我写了一个强大的函数ISR78

void ISR78(void)
{
    blinkLed();
}

我想知道是否有一个解决方案直接通过ISR78覆盖弱函数blinkLedblinkLed内存储__vector_table的地址修改或重命名功能?

编辑:

我实际上使用GNU gcc 4.9.3和相关链接器(GNU ld 2.24.0)。我可以修改与项目关联的main.c和Makefile。

2 个答案:

答案 0 :(得分:1)

我看到实现您想要做的唯一方法是使用blink符号修补包含ISR78符号的目标文件的符号表。

  

objcopy [...] --redefine-sym blink = ISR78

应该这样做。然后,链接器应自动将前一个blink的地址插入到向量表中。显然,你的blink符号在此之后消失了,不应该从其他地方调用。

但是,我会认为这是一个黑客攻击。

如果_vector_table是全局可访问的并且在可写内存中(未假设,这可能太简单了......),您只需通过自己的代码修补它

_vector_table [0x78] = blink;

在运行时。

答案 1 :(得分:0)

tl; dr:您已经有了一个可行的解决方案,它似乎是首先使用弱符号明确支持和鼓励的解决方案。您对其他解决方案有何改进?

链接器符号按名称查找,因此使用预期名称的唯一选择是:

  1. tofro建议直接修改链接步骤
  2. 自己修改函数指针表
  3. 首先,使ISR78成为弱符号的重点是准确地允许你已经使用的覆盖(通过符号名称)。

    我看不出修改中断向量表的方法是更好而不是直接使用预期的函数名,即使它是可能的。