如何在 C 中为外部定义的函数创建别名?

Imm*_*uka 7 c alias gcc weak

在编译此 C 代码期间

extern void Default_Handler(void);
void NMI_Handler(void) __attribute__ ((weak, alias ("Default_Handler")));
Run Code Online (Sandbox Code Playgroud)

我收到了这个

extern void Default_Handler(void);
void NMI_Handler(void) __attribute__ ((weak, alias ("Default_Handler")));
Run Code Online (Sandbox Code Playgroud)

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

编译器:

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

mon*_*gen 7

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

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

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

int
coolguy (int x, int y) __attribute__((alias("myadd")));
Run Code Online (Sandbox Code Playgroud)

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

# compile
$ cc -c myimp.c
# look at the symbols
$ nm myimp.o
0000000000000000 T coolguy
0000000000000000 T myadd
Run Code Online (Sandbox Code Playgroud)

所以我们可以看到,__attribute__((alias("myadd"))只是添加一个coolguy具有相同值的符号,0000000000000000,如myadd。如果您在man页面中查找 nm,它会说这T意味着它是该部分中的全局符号.text。这是有道理的,因为函数不是static并且包含指令(而不是数据)。

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

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

// myimp2.c
int
myadd(int x, int y)
{
    return x+y;
}
Run Code Online (Sandbox Code Playgroud)

按照上面的方式编译,我们会得到myimp2.o,其符号表工具如下:

# look at the symbols
$ nm myimp2.o
0000000000000000 T myadd
Run Code Online (Sandbox Code Playgroud)

所以我们要添加coolguy符号,如下所示

# objcopy --add-symbol coolguy=.text:0000000000000000,global myimp2.o myimp2_augmented.o
Run Code Online (Sandbox Code Playgroud)

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

尝试运行nmmyimp2_augmented.o你会看到我们已经添加了符号。

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


Par*_*iya 1

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

  • 如果您的代码未将 NMI_Handler 或 Default_Handler 包含在编译中,则需要定义 NMI_Handler 或 Default_Handler。 (2认同)
  • 问题是(根据 GCC 手册)给定 `void f () __attribute__ ((weak, alias ("fred")));`,“如果在同一翻译单元中未定义 'fred',则会出现错误。” 这里讨论的情况是 fred 在_another_翻译单元中定义的情况。 (2认同)