正如手册页所述:
- 功能段
- fdata-截面
将每个函数或数据项放置到
如果目标支持任意节,则返回输出文件。
函数的名称或数据项的名称确定
输出文件中节的名称。
编译完这些代码后:
...
int bss_var_1 = 0;
int bss_var_2;
int bss_var_3;
int data_var_1 = 90;
int data_var_2 = 47;
int data_var_3[128] = {212};
int foo() {
printf("hello, foo()\n");
}
int func() {
printf("hello, func()\n");
}
int main(void) {
...
}
我把main.o
放进了我的文件夹,然后我列出了它的所有部分,它确实把每个函数和数据都放进了自己的部分,但是开发人员为什么需要这两个选项呢?(例如,完成工作的任何特殊用法)
$ readelf build/main.o -S
There are 34 section headers, starting at offset 0xeb0:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000000 00 AX 0 0 2
[ 2] .data PROGBITS 00000000 000034 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00000000 000034 000000 00 WA 0 0 1
[ 4] .bss.bss_var_1 NOBITS 00000000 000034 000004 00 WA 0 0 4
[ 5] .bss.bss_var_2 NOBITS 00000000 000034 000004 00 WA 0 0 4
[ 6] .bss.bss_var_3 NOBITS 00000000 000034 000004 00 WA 0 0 4
[ 7] .data.data_var_1 PROGBITS 00000000 000034 000004 00 WA 0 0 4
[ 8] .data.data_var_2 PROGBITS 00000000 000038 000004 00 WA 0 0 4
[ 9] .data.data_var_3 PROGBITS 00000000 00003c 000200 00 WA 0 0 4
[10] .rodata PROGBITS 00000000 00023c 000047 00 A 0 0 4
[11] .text.foo PROGBITS 00000000 000284 000014 00 AX 0 0 4
[12] .rel.text.foo REL 00000000 000b78 000010 08 I 31 11 4
[13] .text.func PROGBITS 00000000 000298 000014 00 AX 0 0 4
[14] .rel.text.func REL 00000000 000b88 000010 08 I 31 13 4
[15] .text.main PROGBITS 00000000 0002ac 000028 00 AX 0 0 4
[16] .rel.text.main REL 00000000 000b98 000020 08 I 31 15 4
...
1条答案
按热度按时间nimxete21#
这允许链接器删除未使用的节[source]
从最终可执行文件中消除未使用的代码和数据的操作直接由链接器执行。
为此,它必须使用通过以下选项编译的对象:- 函数段-fdata段。
这些选项可用于C和Ada文件。它们将把每个函数或数据分别放在结果目标文件的单独部分中。
一旦使用这些选项创建了对象和静态库,链接器就可以执行死代码消除。您可以通过将-Wl,--gc-sections选项设置为gcc命令或gnatmake的-largs部分来执行此操作。这将对从未引用的代码和数据执行垃圾收集。
此外,Haris链接到的标志的文档中提供了使用指南:
这些选项与链接器垃圾收集(linker --gc-sections选项)一起可能会导致静态链接的可执行文件变小(剥离后)。
在ELF/DWARF系统上,这些选项不会降低调试信息的质量。其他目标文件/调试信息格式可能会有问题。
仅当使用这些选项有显著好处时才使用它们。指定这些选项时,汇编器和链接器创建的对象和可执行文件较大,速度也较慢。2这些选项影响代码生成。3它们阻止编译器和汇编器使用翻译单元内的相对位置进行优化,因为位置在链接之前是未知的。这种优化的示例是放松对短调用指令的调用。