我在linux下通过pmap看过程图像:
08048000 0 4 0 r-x-- [my program]
08049000 0 4 4 rw--- [my program]
上面的三个部分是代码,rodata和数据段,它们都与PAGESIZE(4K)对齐,但是当我输入命令objdump -h时,ELF标题显示如下:
read-only code segment
Load off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x00000448 memsz 0x00000448 flags r-x
read/write data segment
Load off 0x00000448 vaddr 0x08049448 paddr 0x08049448 align 2**12
filesz 0x000000e8 memsz 0x00000104 flag rw-
据说在ELF头中,代码段和数据段分别从虚拟地址中的0x08048000,0x049448寻址,这与内存中的过程映像不同。我知道应该将代码/数据段分配给不同的PAGESIZE,这可以赋予它们不同的保护权限。但是,如果真实虚拟与elf二进制文件不同,程序如何执行?
答案 0 :(得分:4)
ELF程序加载的方式(以及文件中的内存映射)基于页面。因此,涉及的地址,文件中的偏移量和大小都必须是页面大小的倍数。
然而,程序加载器足够智能,可以通过将它们四舍五入到页面边界来处理不完全在页面边界上开始或结束的部分,映射超出了所需的范围。因此,将从文件中加载一些额外的数据以填充页面,但不应该访问它,因此无关紧要。
在您的示例中,代码段从地址0x08048000加载偏移量0x0,大小为0x448。地址和偏移量是对齐的,因此只需要将大小四舍五入为整页。数据段从偏移量0x448加载到0x08049448。那些没有对齐,但是可以兼容 - 加载器将两者都向下舍入到页面倍数(0x08049000和0x000)并映射到该页面。请注意,这最终与文件中的代码段相同,因此该页面将加载到两个不同的地址,一个是只读的,另一个是读写非共享的。所以代码和数据都在过程映像中的两个位置最终可见,但这并不重要 - 代码最终rx在0x8048000..0x8048447,数据最终rw-在0x8049448..0x804954b,这就是全部的事项。