Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
-fffunction节-fdata节和--gc节是否不工作?_C_Linux_Gcc - Fatal编程技术网

-fffunction节-fdata节和--gc节是否不工作?

-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

我想在编译时从代码中删除未使用的函数。然后我编写一些代码(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&&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.