【问题标题】:Different addresses in ELF header and process virtual memoryELF头和进程虚拟内存中的不同地址
【发布时间】:2012-04-03 02:47:02
【问题描述】:

我在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二进制不同,程序如何执行?

【问题讨论】:

    标签: memory-management process operating-system kernel elf


    【解决方案1】:

    ELF 程序的加载方式(以及通常从文件中映射的内存)是基于页面的。所以涉及的地址、文件中的偏移量、大小都必须是页面大小的倍数。

    但是,程序加载器足够聪明,可以通过将其四舍五入到页面边界来处理不完全在页面边界上开始或结束的部分,映射超出了所需的范围。所以会从文件中加载一些额外的数据来填充页面,但不应该访问它,所以这无关紧要。

    在您的示例中,代码段从偏移量 0x0 加载到地址 0x08048000,大小为 0x448。地址和偏移量是对齐的,因此只需将大小四舍五入到整页。数据段从偏移量 0x448 加载到 0x08049448。这些不对齐,但兼容——加载器向下舍入到页面倍数(0x08049000 和 0x000)并在该页面中映射。请注意,这最终与文件中的代码段相同,因此该页面在两个不同的地址加载,一个是只读的,另一个是读写非共享的。所以代码和数据最终都在过程映像的两个地方可见,但这并不重要——代码在 0x8048000..0x8048447 处结束,数据在 0x8049448..0x804954b 处结束,仅此而已很重要。

    【讨论】:

      猜你喜欢
      • 2020-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 2016-04-28
      • 2018-07-09
      • 2011-12-27
      相关资源
      最近更新 更多