哪个部分的ELF文件必须加载到内存中?

ven*_*s.w 17 c linux memory elf

可执行文件的ELF文件有一个程序(段)标题和一个节头,可以看到readelf -a,这是一个例子:

在此输入图像描述

在此输入图像描述

上面的两张图分别是节标题和节目(段)标题.可以看出,段头由若干段头组成,用于将程序加载到存储器中.

是否只需将.text,.rodata,.data,.bss部分加载到内存中?

段中的所有其他部分(例如,第3段中的.ctors,.dtors .jcr)是否用于对齐?

R..*_*R.. 23

部分和段完全是两个不同的概念.部分属于存储在那里的数据的语义(即它将用于什么),并且一旦程序或共享库被链接,实际上是无关紧要的,除了调试目的.你甚至可以完全删除部分标题(或用随机垃圾覆盖它们),程序仍然可以工作.

段(即程序头加载指令)是内核和/或动态链接器在加载程序时实际查看的内容.例如,在您的情况下,您有两个加载指令.第一个导致文件的第一个4k(1页)映射到地址0x08048000,并指示实际上只使用该映射的第一个0x4b8字节(其余的是对齐).第二个导致文件的前8k(2页)映射到地址0x08049000.其中绝大多数是一致的.第一个0xf14字节不是load指令的一部分(只是对齐)并且将被浪费.从0x08049f14开始,实际使用从文件映射的0x108字节,并且加载器(内核或动态链接器)将另外的0x10字节(达到0x118的MemSize)填充为零.这跨越到0x0804a02c(在第二个映射页面中).第二个映射页面的其余部分未使用/浪费(但malloc可能能够将其恢复以用作堆的一部分).

最后,虽然根本不会使用节标题,但程序在运行时可能会使用许多不同节的内容.请注意,地址范围.ctors.dtors位于第二个加载映射的开头,因此它们在运行时被映射并可由程序访问(运行时启动/退出代码将使用它们来运行全局构造函数和析构函数,如果是C++或"GNU"使用C"具有ctor/dtor属性的代码).另请注意,.data从第二个映射页面中的地址0x0804a00c开始.这允许在应用重定位后将第一页保护为只读(程序头中的RELRO指令).

  • @Soumen:我想我可能说得不好。它更像是打包而不是对齐,这是一种权衡,可以节省少量(逻辑上的,甚至可能不是实际的)磁盘空间,以换取运行时浪费额外的页面。前 0xf14 字节是 ELF 标头和第一个(只读)加载段的内容。如果链接器一直等到偏移量 0x1000 才开始第二个加载映射,那么它将全部装入一页。 (2认同)