【问题标题】:override a weak function A with a function B用函数 B 覆盖弱函数 A
【发布时间】:2018-05-18 17:35:15
【问题描述】:

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

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 上,我想闪烁 LED。于是我就这样写了一个强大的函数ISR78

void ISR78(void)
{
    blinkLed();
}

我想知道是否有解决方案可以直接通过blinkLed 覆盖弱函数ISR78ieblinkLed 的地址存储在__vector_table 内而不修改它或重命名函数? p>


编辑:

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

【问题讨论】:

  • 一些编译器(不知道你的)支持符号别名,这可能需要研究一下。
  • 另外,您应该非常具体地了解函数类型:void func(void)(无参数)和void func()(未指定数量的参数)是不同的类型。始终将void 用于不带参数的函数以避免出现问题。
  • @user694733 谢谢你的建议,我会注意的
  • 可能我不是问题的全球视野,但weak 旨在允许“覆盖”功能,不是吗?因此,您可以定义/实现您的 same_name_function 以覆盖 weak 之一。
  • @LPs 我已经这样做了。我用 same_name_function 覆盖weak 函数,用作包装器来执行实际工作。我想知道一种方法可以直接覆盖weak 函数,函数做真正的工作

标签: c ld weak-linking


【解决方案1】:

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

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

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

不过,我认为这是一种 hack。

如果_vector_table 是全局可访问的并且在可写内存中(不假设,这可能太简单了......),你可以简单地用你自己的代码修补它

_vector_table [0x78] = blink;

在运行时。

【讨论】:

  • 我来看看这个方法。我更喜欢使用 __attribute__ 或任何特定或通用 C 代码或链接器(链接器选项或链接器脚本)的方法,但它已经是第一种方法。我同意你认为这是一种黑客行为。此外,如果在其他地方使用 blink 可能会很危险(但因为它管理 ISR,所以不应该在其他地方调用它)
  • @Garf365 也许您可以将ld--defsym 命令与ISR78=blink 之类的参数一起使用(或者反过来?)-但是,我自己从未尝试过并且真的不知道这可能会产生什么其他影响或它是否会起作用。
  • 最后,这不是我想要的答案,但它似乎是唯一可能的答案。非常感谢
  • @Garf365 你试过我最后的提议了吗?这对我来说很有希望。
  • 我没有尝试你的最后一个建议,因为__vector_table 在只读存储器中......但是谢谢,如果你将 __vector_table 移动到 RAM 中,我会记住它
【解决方案2】:

tl;dr:您已经有了一个可行的解决方案,这似乎是首先使用弱符号明确支持和鼓励的解决方案。您希望从不同的解决方案中获得哪些改进?


链接器符号是按名称查找的,因此使用预期名称的唯一替代方法是:

  1. tofro 建议直接修改链接步骤
  2. 自己修改函数指针表

首先使 ISR78 成为弱符号的全部意义在于允许完全覆盖您已经使用过的(按符号名称)。

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

【讨论】:

  • 我可以理解 OP 想要删除一个间接(通常会评估为一个分支指令) - 每个周期都很重要。
  • 哪个间接?您正在通过表格进行调用,链接器将在链接时修复表格 - 包括在弱符号和其他符号之间进行选择。在函数调用时,您选择其中的任何一个都没有影响(除非您使用动态链接并且至少有蹦床函数)。
猜你喜欢
  • 1970-01-01
  • 2021-11-10
  • 2010-10-25
  • 2018-06-15
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多