我的 C 代码中有一个函数被隐式调用,并被链接器转储。我怎样才能防止这种现象?
我正在使用 gcc 和链接器标志 -gc-sections 进行编译,我不想从标志中排除整个文件。我尝试使用属性:“used”和“externally_visible”,但都没有用。
void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}
在映射文件上,我可以看到该函数已编译但未链接。我用错了吗?还有其他方法吗?
最佳答案
您误解了 used
attribute
used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced...
即 编译器 必须发出函数定义,即使函数出现 未被引用。编译器永远不会断定函数未被引用 如果它有外部链接。所以在这个程序中:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
编译:
$ gcc -c -O1 main1.c
根本没有发出 foo
的定义:
$ nm main1.o
0000000000000000 T main
因为 foo
在翻译单元中没有被引用,不是外部的,
因此可能会被优化掉。
但是在这个程序中:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used))
强制编译器发出本地定义:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
但这并不能阻止链接器丢弃一个部分
在 -gc-sections
存在的情况下定义了 foo
,即使 foo
是 外部的,如果该部分未使用:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
使用函数段编译:
$ gcc -c -ffunction-sections -O1 main3.c
foo
的全局定义在目标文件中:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
但是链接之后:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
foo
未在程序中定义:
$ nm a.out | grep foo; echo Done
Done
定义 foo
的函数部分被丢弃了:
map 文件
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
根据 Eric Postpischil 的评论,强制链接器保留
一个明显未使用的功能部分,您必须告诉它假设该程序
引用未使用的函数,带有链接器选项 {-u|--undefined} foo
:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
如果你不告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
foo
未在程序中定义。如果你告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
它被定义了。 used
属性没有用。
关于c - 如何防止链接器丢弃函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53985290/