ron*_*dau 5 c linker attributes gcc
我的 C 代码中有一个函数被隐式调用,并被链接器转储。我怎样才能防止这种现象?
我正在使用 gcc 和链接器标志 -gc-sections 进行编译,我不想从标志中排除整个文件。我尝试使用属性:“used”和“externally_visible”,但都没有奏效。
void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}
Run Code Online (Sandbox Code Playgroud)
在地图文件上,我可以看到该函数已编译但未链接。我用错了吗?有没有其他方法可以做到?
你误解了 used属性
用过的
附加到函数的此属性意味着必须为该函数发出代码,即使该函数似乎没有被引用...
即编译器必须发出函数定义,即使函数看起来没有被引用。如果函数具有外部链接,编译器将永远不会得出未引用函数的结论。所以在这个程序中:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译:
$ gcc -c -O1 main1.c
Run Code Online (Sandbox Code Playgroud)
foo根本没有发出的定义:
$ nm main1.o
0000000000000000 T main
Run Code Online (Sandbox Code Playgroud)
因为 foo在翻译单元中没有被引用,也不是外部的,所以可能会被优化掉。
但是在这个程序中:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
__attribute__((used)) 强制编译器发出本地定义:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
Run Code Online (Sandbox Code Playgroud)
但这并不能阻止链接器丢弃foo已定义的部分-gc-sections,即使foo 是外部的,如果该部分未使用:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用函数部分编译:
$ gcc -c -ffunction-sections -O1 main3.c
Run Code Online (Sandbox Code Playgroud)
的全局定义foo在目标文件中:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
Run Code Online (Sandbox Code Playgroud)
但链接后:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
Run Code Online (Sandbox Code Playgroud)
foo未在定义程序:
$ nm a.out | grep foo; echo Done
Done
Run Code Online (Sandbox Code Playgroud)
并且函数部分定义foo被丢弃:
地图文件
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
Run Code Online (Sandbox Code Playgroud)
根据 Eric Postpischil 的评论,要强制链接器保留明显未使用的函数部分,您必须告诉它假设程序引用未使用的函数,并使用链接器选项{-u|--undefined} foo:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你不告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
Run Code Online (Sandbox Code Playgroud)
foo程序中没有定义。如果你告诉它:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
Run Code Online (Sandbox Code Playgroud)
它被定义。属性没有用used。
| 归档时间: |
|
| 查看次数: |
1257 次 |
| 最近记录: |