ELF文件-什么是“节”以及为什么我们需要它?

10

我一直在阅读ELF标准,链接在这里。据我所知,每个ELF文件都包含ELF头、程序头(为什么会有多个?)和段头。请问有人能解释一下以下问题:

  1. ELF文件是如何生成的?是编译器的责任吗?
  2. 什么是段(section),我们为什么需要它们?
  3. 什么是程序头(program headers),我们为什么需要它们?
  4. 在程序头中,字段p_vaddr和p_paddr的含义是什么?
  5. 每个段都有自己的段头吗?

或者,有没有更友好的ELF文档链接?

4个回答

8
  1. ELF文件是如何生成的?编译器是否负责此过程?

    它们可以由编译器、汇编器或任何其他可以生成它们的工具生成。甚至你自己编写用于生成ELF文件的程序也可以 ;) 它们只是字节流,因此可以通过以二进制模式将字节写入文件来生成它们。您也可以这样做。

  2. 什么是节(section),为什么我们需要它们?

    ELF文件被细分为节。节是文件中最小的连续区域。您可以将它们视为组织者中的页面,每个页面都有自己的名称和类型,描述了其中包含的内容。链接器使用此信息将来自不同模块的程序的不同部分合并为一个可执行文件或库,通过合并相同类型的节(如果您愿意的话,就像粘合页面一样)。

    在可执行文件中,节是可选的,但通常会描述文件中的内容以及其开始位置以及占用多少字节。

  3. 什么是程序头(program headers),我们为什么需要它们?

    它们主要用于制作可执行文件。为了运行程序,节是不够的,因为您不仅必须指定文件中有什么,还必须指定它应加载到运行进程的内存中的位置。程序头正是为此目的而存在:它们描述了段(segment),这些段是运行进程中具有不同访问权限和其他属性的内存区域。

    每个程序头描述一个段。它告诉加载器应在内存中将文件的某个区域加载到何处,并为该区域设置哪些权限(例如,是否允许从中执行代码?是否可写或只读?)

    段可以进一步细分为节。例如,如果您必须指定您的代码段进一步细分为用于显示程序消息的代码和静态只读字符串。或者您的数据段被细分为时髦数据和硬核数据 :J 这取决于您。

    在可执行文件中,节是可选的,但最好有它们,因为它们描述了文件中的内容并允许转储其中的选定部分(例如,使用objdump工具)。有时需要它们来存储动态链接信息、符号表、调试信息等。

  4. 在程序头中,字段p_vaddrp_paddr的含义是什么?

    这些是文件中的数据将加载到的地址。它们将文件的内容映射到相应的内存位置。第一个是虚拟地址,第二个是物理地址。

    物理地址是“原始”内存地址。在现代操作系统中,它们不再在用户空间中使用。相反,用户空间程序使用虚拟地址。操作系统欺骗用户空间程序,使其认为自己独占内存,并且整个地址空间都可用于它。在幕后,操作系统将这些虚拟地址映射到实际内存中的物理地址,并且对程序来说是透明的。

    当然,并非虚拟地址空间中的每个地址都同时可用。实际物理内存可用时会有限制。因此,操作系统仅映射程序实际使用的段的内存(这就是


0

0

这个链接包含了一个更好的解释。

  1. ELF文件是如何生成的?这是编译器的责任吗?

    这取决于架构。

  2. 什么是段(sections),为什么我们需要它们?

    不同的段包含不同的信息,例如代码、初始化数据、未初始化数据等。这些信息将被编译器和链接器使用。

  3. 什么是程序头(program headers),为什么我们需要它们?

    当操作系统加载可执行文件时,程序头用于指导操作系统加载过程。这些头部包含有关段(连续内存块)的信息,例如哪些部分需要加载、解释器信息等。

  4. 在程序头中,字段 p_vaddr 和 p_paddr 的意义是什么?

    通常情况下,虚拟地址和物理地址是相同的。但在不同的系统上可能会有所不同。

  5. 每个段都有自己的段头吗?

    是的。每个段在段头表中都有一个段头条目。


-1

2 - 有许多不同的节区,例如:重定位节区记录了许多重定位符号的信息。我使用这些信息来加载 ELF 对象并运行/重定位对象。 另一个例子:调试节区记录调试信息,GDB 使用这些数据显示调试消息。 符号节区记录符号信息。

3 - 程序头由加载器使用,加载器通过查找程序头加载 ELF 可执行文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接