我一直在这里阅读 ELF 标准。据我了解,每个 ELF 都包含 ELF 标头、程序标头(为什么不止一个?)和节标头。谁能解释一下:
- ELF 文件是如何生成的?是编译器的责任吗?
- 什么是部分,为什么我们需要它们?
- 什么是程序头,我们为什么需要它们?
- 在程序头中,字段 p_vaddr 和 p_paddr 的含义是什么?
- 每个部分都有自己的部分标题吗?
或者,是否有人链接到更友好的 ELF 文档?
ELF 文件是如何生成的?是编译器的责任吗?
它们可以由编译器、汇编器或任何其他可以生成它们的工具生成。即使是您自己编写的用于生成 ELF 文件的程序;)毕竟它们只是字节流,因此只需将字节以二进制模式写入文件即可生成它们。你也可以那样做。
什么是部分,为什么我们需要它们?
ELF 文件被细分为多个部分。节是文件中最小的连续区域。您可以将它们视为管理器中的页面,每个页面都有自己的名称和类型,用于描述其中包含的内容。链接器使用此信息将来自不同模块的程序的不同部分合并到一个可执行文件或库中,方法是合并相同类型的部分(如果您愿意,将页面粘合在一起)。
在可执行文件中,节是可选的,但它们通常用于描述文件中的内容、文件的开始位置以及占用的字节数。
什么是程序头,我们为什么需要它们?
它们主要用于制作可执行文件。为了运行程序,只需要部分是不够的,因为您不仅必须指定文件中的内容,还必须指定在运行过程中应该将其加载到内存中的哪个位置。程序标头仅用于此目的:它们描述了段,它们是正在运行的进程中的内存区域,具有不同的访问权限和内容。
每个程序头描述一个段。它告诉加载器应该将文件中的某个区域加载到内存中的哪个位置,以及它应该为该区域设置什么权限(例如,是否应该允许它从中执行代码?它应该是可写的还是只是为了读取?)
段可以进一步细分为部分。例如,如果您必须指定您的代码段进一步细分为程序显示的消息的代码和静态只读字符串。或者您的数据段细分为时髦数据和核心数据:J 由您决定。
在可执行文件中,节是可选的,但拥有它们很好,因为它们描述了文件中的内容并允许转储文件的选定部分(例如使用objdump
工具)。但是,有时需要它们来存储动态链接信息、符号表、调试信息等。
p_vaddr
在程序头中,字段和的含义是什么p_paddr
?
这些是加载文件中数据的地址。它们将文件的内容映射到相应的内存位置。第一个是虚拟地址,第二个是物理地址。
物理地址是“原始”内存地址。在现代操作系统上,这些不再在用户空间中使用。相反,用户态程序使用虚拟地址。操作系统欺骗用户空间程序,认为它在内存中是单独的,并且整个地址空间都可供它使用。在后台,操作系统将这些虚拟地址映射到实际内存中的物理地址,并且对程序透明地执行此操作。
当然,并不是虚拟地址空间中的每个地址都同时可用。实际可用的物理内存存在限制。所以操作系统只是为程序实际使用的段映射内存(这里是 ELF 文件的程序头中的“段”部分发挥作用的地方)。如果进程试图访问一些未映射的内存,操作系统会介入并说:“对不起,伙计,这块内存不属于你”。(程序可以解决它,但它不能访问它。)
每个部分都有自己的部分标题吗?
是的。如果它在 Section Headers Table 中没有条目,则它不是一个部分:q 因为他们唯一的方法来判断文件的某些部分是否是一个部分,是查看 Section Headers Table 它告诉你哪些部分在文件中定义,您可以在哪里找到它们。
您可以将章节标题表视为一本书中的目录。没有目录,毕竟没有任何章节,因为它们没有在任何地方列出。这本书可能有标题,但内容没有细分为可以通过目录找到的逻辑章节。ELF 文件中的部分也是如此:可能有一些数据区域,但如果没有 SHT 的“目录”,您将无法分辨。
这是我找到的最好的文档:http ://www.skyfree.org/linux/references/ELF_Format.pdf
此链接包含更好的解释。
ELF 文件是如何生成的?是编译器的责任吗?*
它依赖于架构。
什么是部分,为什么我们需要它们?
不同的部分有不同的信息,例如代码、初始化数据、未初始化数据等。这些信息将被编译器和链接器使用。
什么是程序头,我们为什么需要它们?
操作系统在加载可执行文件时会使用程序头。这些标头包含有关段的信息(具有某些权限的连续内存块),例如需要加载哪些部分、解释器信息等。
在程序头中,字段 p_vaddr 和 p_paddr 的含义是什么?
一般来说,虚拟地址和物理地址是相同的。但可能因系统而异。
每个部分都有自己的部分标题吗?
是的。每个节在节头表中都有一个节头条目。
2 - 有许多不同的部分,例如:重定位部分为重定位符号提供了许多信息。我使用信息加载一个精灵对象并运行/重新定位该对象。另一个例子:调试部分记录调试信息,gdb 使用数据显示调试信息。符号部分记录符号信息。
3 - loader使用的programming header,loader通过查找programming header来加载一个elf执行文件。