这与对齐有关。看readelf -eW <ELF_NAME>
。有趣的是
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000401000 001000 00000c 00 AX 0 0 1
请注意Off
柱子。这是文件中的偏移量,.text
部分开头为0x1000
,即 4K。
如果你看同样的图片程序头。用零填充的空间位于 ELF 标头末尾和 0x1000 之间。
为什么是这样?
首先,因为 ELF 标准规定
可加载进程段的 p_vaddr 和 p_offset 必须具有一致的值(以页面大小为模)。
(see man elf
)。你的系统(我的系统)上的页面大小是 4K。这就是您在中看到的值p_align
.
其次,链接器分配给“文本”段开头的虚拟地址 - 与.text
此处的部分,因为这就是该部分包含的全部内容 - 是0x0000000000401000
。因此,文件中“文本”段偏移量的十六进制表示必须以000
。但是 0 已经被包含 ELF 标头(文件的最开头)的只读段占用。第二个选择是0x1000
.
为什么链接器选择 0x401000 作为文本部分的虚拟地址?我不知道。我认为,如果稍微调整链接器脚本,您将能够得到更小的结果可执行文件。
正如彼得和其他人指出的那样,可以使用以下命令禁用页面大小对齐-n
链接器选项:
'-n'
'--nmagic'
Turn off page alignment of sections, and disable linking against
shared libraries[…]
这样我就得到
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 1] .text PROGBITS 0000000000400078 000078 00000c 00 AX 0 0 1
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000078 0x0000000000400078 0x0000000000400078 0x00000c 0x00000c R E 0x1
可执行文件的大小降至 664 字节(之后为 344 字节)strip
ping).
通过 GNU ld,您可以使用链接描述文件精细控制链接器输出文件的布局。ld.bfd
(通常也称为只是ld
) 如果用户未指定链接描述文件,则解释默认链接描述文件。它可以通过以下方式获得ld --verbose
。然后您可以编辑它并提供您的版本而不是默认版本-T <your-script>
.
我删除了第一个出现的
. = ALIGN(CONSTANT (MAXPAGESIZE));
(before .text
)并得到 720(当strip
ped)字节。这与使用的结果不同-n
选项。你仍然得到 2 个可加载的段,以及它们的p_align
还是0x1000
.
存在效率影响p_align
< MAX_PAGE_SIZE
我不完全明白。 (由于地址计算更困难,页面加载速度不会那么快?我认为应该有更好的解释。)如果您了解更多有关此内容或解释的地方,请随意编辑答案。