4

在编译此 C 代码期间

extern void Default_Handler(void);
void NMI_Handler(void) __attribute__ ((weak, alias ("Default_Handler")));

我收到了这个

error: 'NMI_Handler' aliased to undefined symbol 'Default_Handler'

如何在外部定义的函数上创建别名?

编译器:

gcc version 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204] (GNU Tools for Arm Embedded Processors 7-2017-q4-major)
4

4 回答 4

6

要为外部函数设置别名,您可以使用objcopy. 这是一个例子:

假设我有一个函数的定义,我给它起了别名,就像在下面的程序(称为myimp.c)中一样:

// myimp.c
int
myadd(int x, int y)
{
    return x+y;
}

int
coolguy (int x, int y) __attribute__((alias("myadd")));

如果我们编译它(但不链接),我们会得到一个目标文件,我们可以检查它的符号:

# compile
$ cc -c myimp.c
# look at the symbols
$ nm myimp.o
0000000000000000 T coolguy
0000000000000000 T myadd

所以我们可以看到,它只是简单地添加一个具有相同值__attribute__((alias("myadd"))的符号,0000000000000000,作为。如果您在页面中查找 nm,它会说这意味着它是该部分中的全局符号。这是有道理的,因为该功能不是并且包含指令(与数据相反)。coolguymyaddmanT.textstatic

因此,如果我们有目标文件,但没有源文件,并且我们想添加一个函数别名,我们可以使用objcopy --add-symbol.

假设我们有编译此源代码产生的目标文件:

// myimp2.c
int
myadd(int x, int y)
{
    return x+y;
}

如上编译,我们将得到myimp2.o,其符号表工具如下:

# look at the symbols
$ nm myimp2.o
0000000000000000 T myadd

所以我们要添加coolguy符号,我们这样做如下

# objcopy --add-symbol coolguy=.text:0000000000000000,global myimp2.o myimp2_augmented.o

查看页面中的--add-symbol文档objcopy man。基本上.text指定部分,冒号后的值,然后global我通过传递错误类型找到并objcopy失败并告诉我有效类型的列表,我从中选择了global.

尝试在nm上运行myimp2_augmented.o,你会看到我们已经添加了符号。

现在您应该能够链接 withmyimp2_augmented.o而不是,myimp.o并且您的程序可以coolguy在没有链接错误的情况下调用。

于 2019-09-26T14:39:42.443 回答
1

正如这里所建议的,将以下内容添加到您的链接器命令文件中:

PROVIDE(NMI_Handler = Default_Handler);

(并从 C 代码中删除弱别名声明。)

于 2020-09-25T14:53:28.897 回答
1

这里 NMI_Handler 有一个弱定义属性意味着如果 NMI_Handler 没有定义,那么 Default_Handler 的定义将用于 NMI_Handler。通常对于 NMI_Handler 或 Default_Handler 之类的中断有很强的定义。您可能需要在编译中添加这些文件以删除错误。如果您想以自己的方式处理 NMI_Handler,那么您可以在某处定义它,并且该定义将被包含在内弱者的。

于 2018-02-07T10:30:38.513 回答
0

使用员工弱和别名属性来实现原生 C 项目的覆盖机制很受欢迎,尤其是在固件项目的情况下。

声明和定义都可以注意__attribute__((weak)),其链接优先级规则与头文件中是否存在任何声明有关。

仅仅编码和编译它是一个很好的策略。然后看看链接时会发生什么是寻找它的定义。-Wl,-trace,-trace-symbol=ANY_FUNCTION_NAME_YOU_WANT我通常用和来检查符号nm OBJECT_FILE_NAME

通常我只是创建一个弱属性函数定义并让其他对象覆盖它。示例如下所示:

In C file:

//non-exported weak attribute definition
__attribute__((weak)) void startup_handler_dummy(void) {
        printf("[%s][%s]Entry (NO OVERRIDE HANLDER COMES HERE)\n", __FILE__, __func__);
}

//weak and alias attribute declaration
void startup_handler_dummy_impl(void) __attribute__((weak, alias("startup_handler_dummy")));

//exported weak attribute definition
__attribute__((weak)) void startup_handler(void) {
    startup_handler_dummy_impl();
}

In header file:

#ifndef _BOARD_H_
#define _BOARD_H_
#define STARTUP_HANDLER startup_handler //to export symbol
#endif

希望我的代码可以帮助:)

您可以在MyGitHub上查看更多详细信息和程序屏幕截图。

于 2021-02-22T09:39:25.587 回答