我正在使用gcc版本4.8.2 (Debian 4.8.2-21)在x86_64机器上静态编译一个非常简单的hello-world代码:
gcc test.c -static -o test
我得到了一个可执行的ELF文件,其中包括以下几个部分:
[17] .tdata PROGBITS 00000000006b4000 000b4000
0000000000000020 0000000000000000 WAT 0 0 8
[18] .tbss NOBITS 00000000006b4020 000b4020
0000000000000030 0000000000000000 WAT 0 0 8
[19] .init_array INIT_ARRAY 00000000006b4020 000b4020
0000000000000010 0000000000000000 WA 0 0 8
[20] .fini_array FINI_ARRAY 00000000006b4030 000b4030
0000000000000010 0000000000000000 WA 0 0 8
[21] .jcr PROGBITS 00000000006b4040 000b4040
0000000000000008 0000000000000000 WA 0 0 8
[22] .data.rel.ro PROGBITS 00000000006b4060 000b4060
00000000000000e4 0000000000000000 WA 0 0 32
请注意,
.tbss
段分配在地址0x6b4020..0x6b4050(0x30字节),并且与.init_array
段在0x6b4020..0x6b4030(0x10字节)和.fini_array
段交叉分配在0x6b4030..0x6b4040(0x10字节),并且与.jcr
段在0x6b4040..0x6b4048(8字节)交叉。请注意,它不会与以下部分相交,例如
.data.rel.ro
,但这可能是因为.data.rel.ro
的对齐方式为32,因此它不能放置在0x6b4060之前。生成的文件可以正常运行,但我仍然不确定它是如何工作的。从我在glibc文档中阅读的内容来看,
.tbss
只是用于线程本地存储(即分配的内存临时空间,实际上未映射到物理文件)的.bss
段。是否.tbss
段非常特殊,以至于它可以重叠其他段?.init_array
、.fini_array
和.jcr
是否非常无用(例如,当TLS相关代码运行时它们不再需要),因此它们可以被bss覆盖?还是这是某种错误?基本上,如果我尝试读取地址0x6b4020,我会得到什么内容?
.tbss
的内容还是.init_array
的指针?为什么?
.bss
,即零初始化数据部分。只要我们知道该部分是零初始化的,就没有必要在文件中实际存储零,知道大小就足够了。 - ach