Arm Gcc 弱别名重新定义
Arm Gcc Weak Alias Redefinition
我想为几个函数创建弱别名,这样我就可以在头文件中声明它,然后在不同的文件中定义它。出于某种原因,我仍然从 gcc 收到重新定义错误。
理想情况下,对于没有实现的函数,我希望它默认返回别名。
我已经尝试删除别名 ("Default_Handler"),它似乎可以编译,但它有点破坏了我尝试编写此应用程序的意图。
vector_table.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
startup.c
#include "vector_table.h"
void Default_Handler(void){
for(;;);
}
void NMI_Handler(void){
for(;;);
}
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wall -Wno-unused -Wextra -pedantic -H -g3 -gdwarf-2 -O0 -std=c90 -ffreestanding -c startup.c
startup.c:93:6: error: redefinition of 'NMI_Handler'
void NMI_Handler(void){
^
In file included from startup.c:3:0:
vector_table.h:17:6: note: previous definition of 'NMI_Handler' was here
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
TL;DR:不要将 __weak__
或 __alias__
放入 .h
文件中。将 __weak__
和 __alias__
放入 .c
文件。
弱符号理论上是这样工作的:
- 有一个
.o
文件带有 __weak__
符号。
- 还有一个
.o
文件具有正常的符号。
- 链接器看到两个符号并选择 non-weak 符号。
.o
object 个文件是从 .c
个文件生成的。 .c
里面的符号定义应该是weak.
应用于声明的属性也应用于看到它的定义。在声明中的 header 中执行 __weak__
标记 all 定义,这些定义将此符号的声明视为 __weak__
.
alias
的工作方式就像您会做的那样:
static inline void NMI_Handler(void) {
Default_Handler();
}
它的工作原理与 as-if 相同,但没有分支(并且输入更少)。而且无论如何,因为 alias
创建了符号,所以它充当定义 - 它也属于 .c
文件。这就是您出现多重定义错误的原因 - __alias__
定义了符号 NMI_Handler
,您稍后又定义了 void NMI_Handler(void) {}
。
你想做的我想是这样的:
// vector_table.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void);
// startup.c
void Default_Handler(void){
for(;;);
}
__attribute__((__weak__, __alias__("NMI_Handler")))
void NMI_Handler(void);
这与 gcc documentation about function attributes 中解释的示例用法相同。文档指出,必须在同一个事务单元中定义另一个别名的符号(读作:在同一个 .c
文件中)。
请记住,将符号声明为弱并不意味着链接器会达到强符号的峰值 - 当使用静态库进行编译时,有时会发生奇怪的事情。仅使用 object 编译或使用 -Wl,-start-group
链接器选项。我认为 infocenter.arm 对此有最好的解释。
我想为几个函数创建弱别名,这样我就可以在头文件中声明它,然后在不同的文件中定义它。出于某种原因,我仍然从 gcc 收到重新定义错误。
理想情况下,对于没有实现的函数,我希望它默认返回别名。
我已经尝试删除别名 ("Default_Handler"),它似乎可以编译,但它有点破坏了我尝试编写此应用程序的意图。
vector_table.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
startup.c
#include "vector_table.h"
void Default_Handler(void){
for(;;);
}
void NMI_Handler(void){
for(;;);
}
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wall -Wno-unused -Wextra -pedantic -H -g3 -gdwarf-2 -O0 -std=c90 -ffreestanding -c startup.c
startup.c:93:6: error: redefinition of 'NMI_Handler'
void NMI_Handler(void){
^
In file included from startup.c:3:0:
vector_table.h:17:6: note: previous definition of 'NMI_Handler' was here
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
TL;DR:不要将 __weak__
或 __alias__
放入 .h
文件中。将 __weak__
和 __alias__
放入 .c
文件。
弱符号理论上是这样工作的:
- 有一个
.o
文件带有__weak__
符号。 - 还有一个
.o
文件具有正常的符号。 - 链接器看到两个符号并选择 non-weak 符号。
.o
object 个文件是从 .c
个文件生成的。 .c
里面的符号定义应该是weak.
应用于声明的属性也应用于看到它的定义。在声明中的 header 中执行 __weak__
标记 all 定义,这些定义将此符号的声明视为 __weak__
.
alias
的工作方式就像您会做的那样:
static inline void NMI_Handler(void) {
Default_Handler();
}
它的工作原理与 as-if 相同,但没有分支(并且输入更少)。而且无论如何,因为 alias
创建了符号,所以它充当定义 - 它也属于 .c
文件。这就是您出现多重定义错误的原因 - __alias__
定义了符号 NMI_Handler
,您稍后又定义了 void NMI_Handler(void) {}
。
你想做的我想是这样的:
// vector_table.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void);
// startup.c
void Default_Handler(void){
for(;;);
}
__attribute__((__weak__, __alias__("NMI_Handler")))
void NMI_Handler(void);
这与 gcc documentation about function attributes 中解释的示例用法相同。文档指出,必须在同一个事务单元中定义另一个别名的符号(读作:在同一个 .c
文件中)。
请记住,将符号声明为弱并不意味着链接器会达到强符号的峰值 - 当使用静态库进行编译时,有时会发生奇怪的事情。仅使用 object 编译或使用 -Wl,-start-group
链接器选项。我认为 infocenter.arm 对此有最好的解释。