为何edata减去etext的值无法得到正确的文本段大小?
问题描述
测试代码
#include <stdio.h> extern char etext, edata, end; int main(int argc, char* argv[], char* envp[]) { printf("TEXT END: %p\n", &etext); printf("DATA END: %p\n", &edata); printf("PROG BRK: %p\n", &end); register long volatile sp asm("rsp"); printf("STCK PTR: %p\n", sp); return 0; }
运行输出
TEXT END: 0x5565d48661d5 DATA END: 0x5565d4869018 PROG BRK: 0x5565d4869020 STCK PTR: 0x7fff8f6f34d0
疑问
原本认为text段、data段和bss段在内存中连续排布,彼此无间隔。但计算(&edata - &etext)得到的结果为0x2e43,而执行size -x a.out命令得到的data段大小仅为0x250,请问这种差异的原因是什么?
环境:gcc 12.2.0、Linux x86_64 5.19.9
原因分析
&etext到&edata的跨度包含多段内容:etext标记text段(代码段)的结束地址,但text段之后并非直接是data段。在ELF可执行文件的内存布局中,text段结束后会依次包含只读数据段(.rodata)、动态链接相关段(如.interp、.dynsym、.dynstr、.gnu.hash)、注释段(.comment)等辅助段,这些段都会占用内存空间,直到data段结束的edata地址。size命令的统计范围有限:size -x a.out输出的data值,仅统计**已初始化数据段(.data)**的大小,不包含text段与data段之间的其他只读/辅助段。而&edata - &etext计算的是从text段结束到data段结束的总内存跨度,包含了中间所有额外段的空间,因此数值远大于size给出的data段大小。内存对齐的额外填充:
ELF文件加载到内存时,每个段会按照系统要求的对齐规则(x86_64下通常为4KB页对齐)分配内存,段与段之间可能会因对齐要求产生填充空间,这也会进一步拉大两者的数值差异。
内容的提问来源于stack exchange,提问作者ZarakshR
相关产品推荐
相关产品推荐

