C语言 用函数B覆盖弱函数A

ekqde3dh  于 2023-10-15  发布在  其他
关注(0)|答案(3)|浏览(144)

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

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,我想 Flink 的领导。所以我写了一个强函数ISR78

void ISR78(void)
{
    blinkLed();
}

我想知道是否有一个解决方案可以直接通过blinkLed覆盖弱函数ISR78,* 即 * 将blinkLed的地址存储在__vector_table中而不修改它或重命名函数?
编辑:
我实际上使用的是GNU gcc 4.9.3和相关的链接器(GNU ld 2.24.0)。我可以修改与项目关联的main.c和Makefile。

0md85ypi

0md85ypi1#

我看到的实现您想要做的事情的唯一方法是用ISR78符号修补包含blink符号的对象文件的符号表。
objcopy [.] --redefine-sym blink=ISR78
应该这样做。然后,链接器应自动将前一个blink的地址插入向量表。显然,在此之后blink符号已经消失,不应该从其他地方调用。
不过,我认为这是一种黑客行为。
如果_vector_table是全局可访问的,并且在可写内存中(不是假设的,这可能太简单了...),您可以简单地通过以下方式从自己的代码中修补它:

_vector_table [0x78] = blink;

at runtime运行时.

am46iovg

am46iovg2#

tl;dr:你已经有了一个可行的解决方案,这似乎是一开始就通过使用弱符号来明确支持和鼓励的解决方案。您希望从不同的解决方案中获得哪些改进?
链接器符号是按名称查找的,因此使用预期名称的唯一替代方法是:

  1. tofro建议直接修改链接步骤
    1.自己修改函数指针表
    首先,将ISR 78设置为弱符号的全部意义在于允许您已经使用的覆盖(通过符号名称)。
    我看不出修改中断向量表比直接使用预期的函数名更好的方法,即使这是可能的。
wgx48brx

wgx48brx3#

你可以使用__asm("symbolname")来实现。这使您可以将对象文件中使用的符号的名称更改为特定字符串。gcc和clang都支持这一点。
范例:

void blinkLed(void) __asm("ISR78");  // Can only be used on a prototype
void blinkLed(void)
{ ... }

在你的代码中,任何东西都可以使用blinkLed这个名字。但在对象文件中,名称将是ISR78,它将覆盖弱版本并用作中断向量。
这也是一种避免C++名称混乱的方法,即使你不能使用extern "C"

template <int id>
struct Timer {
   static void blinkled();
};

template <> Timer<1>::blinkled() __asm("ISR71");
template <> Timer<2>::blinkled() __asm("ISR72");

上面我们有一个带有ISR的类模板,blinkled(),作为一个静态方法。然后,我们为两个不同的定时器定义ISR的两个专门化,并为它所在的中断向量给予每个正确的名称。

相关问题