-fffunction节-fdata节和--gc节是否不工作?
我想在编译时从代码中删除未使用的函数。然后我编写一些代码(main.c): 生成文件-fffunction节-fdata节和--gc节是否不工作?,c,linux,gcc,C,Linux,Gcc,我想在编译时从代码中删除未使用的函数。然后我编写一些代码(main.c): 生成文件 test1 : rm -f a.out *.o *.a gcc -ffunction-sections -fdata-sections -c main.c getall.c ar cr libgetall.a getall.o gcc -Wl,--gc-sections main.o -L. -lgetall 运行make test1&&ob
test1 :
rm -f a.out *.o *.a
gcc -ffunction-sections -fdata-sections -c main.c getall.c
ar cr libgetall.a getall.o
gcc -Wl,--gc-sections main.o -L. -lgetall
运行make test1&&objdump--sym a.out | grep get
后,我只找到下面两行输出:
0000000000000000 l df *ABS* 0000000000000000 getall.c
0000000000400535 g F .text 000000000000000b get1
我猜get2
和get3
被删除了。但是当我通过vim打开a.out时,我发现存在s97symmqdn-1 s97symmqdn-2 s97symmqdn-3
。
函数get2
get3
真的被删除了吗?如何删除符号s97symmqdn-2 s97symmqdn-3
?谢谢你的回复。
我的系统是centos7,gcc版本是4.8.5,编译选项是
-fffunction-sections-fdata-sections
和链接选项是-gc-sections
在您的示例中工作正常。您的静态库是多余的,因此它可以
简化为:
$ gcc -ffunction-sections -fdata-sections -c main.c getall.c
$ gcc -Wl,--gc-sections main.o getall.o -Wl,-Map=mapfile
在其中,我还需要链接器的映射文件
可执行文件中没有未使用的函数get2
和get3
:
$ nm a.out | grep get
0000000000000657 T get1
映射文件显示未使用的函数部分.text.get2
和.text.get3
,其中get2
和get3
是
在链接中丢弃了分别定义的链接:
地图文件(1)
然而,正如您所发现的,所有三个字符串文字“s97symmqdn-(1 | 2 | 3)”
在该计划中:
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
s97symmqdn-2
s97symmqdn-3
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
这是因为-fdata节
仅适用于
适用于1,即适用于定义
已经存在的变量的集合。它不适用于像您的
“s97symmqdn-(1 | 2 | 3)”
。它们都像往常一样放在.rodata
部分,
在那里我们发现了他们:
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
06ed 73393773 796d6d71 646e2d31 00733937 s97symmqdn-1.s97
06fd 73796d6d 71646e2d 32007339 3773796d symmqdn-2.s97sym
070d 6d71646e 2d3300 mqdn-3.
--gc节不允许链接器从程序中丢弃.rodata
因为它不是未使用的部分:它包含引用的“s97symmqdn-1”
在程序中,通过get1
以及未引用的字符串“s97symmqdn-2”
和“s97symmqdn-3”
修复
要将这三个字符串文本分隔为不同的数据部分,需要
需要将它们分配给不同的命名对象,例如
getcall.c(2)
如果我们重新编译并重新链接该更改,我们会看到:
地图文件(2)
现在有两个新的废弃数据部分,其中包含
正如我们在对象文件中看到的,我们不需要的两个字符串文本:
$ objdump -s -j .rodata.s.1797 getall.o
getall.o: file format elf64-x86-64
Contents of section .rodata.s.1797:
0000 73393773 796d6d71 646e2d32 00 s97symmqdn-2.
以及:
现在,只有引用的字符串“s97symmqdn-1”
出现在程序中的任何位置:
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
s97symmqdn-2
s97symmqdn-3
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
它是程序的.rodata
中唯一的字符串:
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
06f0 73393773 796d6d71 646e2d31 00 s97symmqdn-1.
[1] 同样,
-功能部分
与限定
每个函数的定义
foo
都有\uuuu属性((\uuu section\uuuu(.text.foo))
您可能应该使用-O1
或更高版本进行编译。我使用了-O1,但它仍然存在s97symmqdn-2 s97symmqdn-3。这不是一个缺陷吗?为什么要这样实施?我希望这些文字也会消失。。。另一个观察结果——如果使用_func__/_PRETTY_func__/etc而不是文字——它将被丢弃。确保这一点的机制是什么?还有一个观察:-flto
是解决OP问题的另一种方法(甚至不需要-fdata节
)
$ objdump -s -j .rodata.s.1797 getall.o
getall.o: file format elf64-x86-64
Contents of section .rodata.s.1797:
0000 73393773 796d6d71 646e2d32 00 s97symmqdn-2.
$ objdump -s -j .rodata.s.1800 getall.o
getall.o: file format elf64-x86-64
Contents of section .rodata.s.1800:
0000 73393773 796d6d71 646e2d33 00 s97symmqdn-3.
$ strings a.out | egrep 's97symmqdn-(1|2|3)'
s97symmqdn-1
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
06f0 73393773 796d6d71 646e2d31 00 s97symmqdn-1.