可执行部分 Headers - 含义和用途?

Executable Section Headers - Meaning and use?

通过使用 7zip 打开 Windows 中的许多 executable(.exe..msi)文件,我注意到许多不同的文件类型很常见。这些包括 .text、.data、.bss、.rdata、.pdata 等。我试图获取有关它们的信息,但我无法找出它们的全部含义。这是其中的一些:

还有很多其他的,很常见,我找不到任何信息。大多数是:.pdata.tls.reloc、证书、.rsrc_1.aspack.adata.INITDATA, CODE, .ctors.

其中大部分还包含一个rsrc文件夹,其中包含BITMAP、CURSOR、ICON、GROUP_CURSOR、GROUP_ICON、MENU、VERSION等文件夹。

一些 executables 里面还包含更多的 executables,.html 文件,.txt 文件等。我还打开了一个什么都没有的文件(至少用 7zip 打开它没有任何显示)! [ 我用 7zip 打开了它们。 ]


问题

  1. 我 post 编辑的那些部分/片段是做什么的?有没有我可以找到所有这些的网站?
  2. 我看的都是Windows的PE。这些格式是否标准并以类似/相同的方式适用于 LINUX、UNIX 等?
  3. 为什么有些executable里面包含其他executable,或者.html,.txt等文件?当您启动 executable 时,这些是如何处理的?他们该怎么办? AFAIK executable 中的所有内容都应该只有那些类似于汇编代码部分的 "segments"。
  4. rsrc文件夹有什么用?它拥有什么样的资源?

如果你能post关于为什么使用所有这些(尽可能低级别)以及 executable 结构通常应该是什么样子的更多信息/链接,我将不胜感激, 它应该包含什么等等

这就是全部。


编辑

我找到了其他常用部分 header 名称。为了完整起见,我将 post 它们的含义放在这里。

这里没有魔法,也没有构建可执行文件的通用规则。您必须遵循相关操作系统的规则,并只提供它可以理解的可执行格式。但即便如此,尽管几十年来编译器之间的使用非常普遍,但这些部分在技术上是任意的。你基本上完成了你需要做的所有工作并回答了你自己的问题。

操作系统只需要知道一些事情。这个文件有多少实际上是可加载的数据,我在哪里加载它。操作系统没有 know/see 来自 .data 的 .text,它看到可加载的块。它将这些块从文件复制到内存中,然后它看到一个定义的入口点,它分支到那个入口点。其余信息是...信息...对于调试器来说,无论是软件还是有兴趣查看编译器在 .data 部分中放置了多少或什么的人。

正确使用这些部分直接或间接取决于程序员,通常程序员不会直接参与。名为 bootstrap 的软件会根据需要执行处理这些部分的工作。例如,bootstrap 通常将 .bss 部分置零,这是编译器工具链中的系统设计解决方案,告诉 bootstrap .bss 的大小和起始地址,而 bootstrap 将 ram 置零.

.data 和 .text 通常只是由操作系统加载,不需要进一步注意,因为它们正在加载到 ram 中。但是例如,如果这是一个微控制器,我们需要将我们的 non-zero 全局 .data 存储在 non-volatile 存储 (flash/rom) 中,但是当我们启动并 运行 编译我们的我们在 ram 中需要它的代码。所以 bootstrap 通常会使用编译器系统设计解决方案来完成将 .data 从闪存复制到 ram 的工作,以告诉 bootstrap 闪存中的起始地址和 ram 中的起始地址以及要复制多少。

我说的系统设计是一个变量,如果你愿意汇编语言(否则就是先有鸡还是先有蛋的问题)bootstrap在链接器完成后由链接器填充它的工作,并计算出所有东西的数量以及它们在二进制或内存映像中的位置。

数据就是数据,你可以在你的二进制文件中嵌入数据,无论是文本还是html或者图像(jpg,bmp,png等)或其他,正确的hexdump工具可以显示,使用的工具链甚至可能对该数据有特殊的部分名称。

几乎所有这些部分名称部分用于调试编译器输出,部分用于提供信息。一个特定的工具链有它使用的特定部分名称,或者甚至可能允许用户(程序员)创建他们自己的任意名称,因为它们就是这样。那个特定的工具链使用该信息作为其系统设计的一部分,编译器从数据中挑选出程序,它不必但在历史上从假设开始全局数据为零的 non-zero 全局数据中挑选出来。也许比只读 non-zero 数据更深。它用名称标记这些对象 blob,以便链接器可以收集所有命名的 blob,并使用链接器脚本完成将这些 blob 组装成更大的 blob 并为它们分配地址的工作。然后根据需要修补二进制文件以解决外部 addresses/variables.

问题 1:不,没有可以找到所有工具链的网站,即使不容易证明至少有一个工具链允许用户发明自己的部分名称,也是很有可能的,因此这是不可能的用于一个或多个网站,以涵盖某些程序员可能想出的所有可能的部分名称和这些部分名称的定义。

问题 2:有一个通用集 .text、.data、.bss 已被所有目标系统(windows、unix 等)上的大多数(如果不是全部)工具链广泛采用和使用这是工具链的功能,而不是操作系统的功能,因为操作系统不知道也不关心。它只是将可加载的 blob 和分支加载到入口点。由于这些名称是任意的,并且只需要在工具链的系统设计中工作,所以询问操作系统没有意义

问题 3:所有部分,无论是否奇怪,都由工具链间接管理或在库中链接或由程序员直接管理。从 .bss 到 .somethingimadeup.

问题 4:听起来特定于操作系统。了解操作系统定义了支持的可执行格式及其组成。编译器必须符合这一点才能制作有效的二进制文件。例如,像 windows 这样的操作系统可能非常希望在 "binary" 中有一个图标位图,这样它就可以在桌面上显示在程序名称旁边,这也是二进制文件中的信息。因此,除了二进制文件格式需要具有的显而易见的东西(文件中的偏移量以及大小和目标内存中用于可加载数据块的离子地址,以及执行入口点)文件格式可能具有其他信息或其他项目。 "windows shortcut" 的文件格式可能是子集或特殊 "binary" 格式,其信息是另一个文件的路径和文件名,而不是您实际加载的代码和 运行。或快捷方式,例如您可能有一个包含 url 的 "binary" 文件格式。但这在很大程度上取决于操作系统的定义和依赖性。

节名与文件格式无关,工具链(通常是链接器)可以随意选择。操作系统不使用名称来查找它关心的部分,它使用文件头中的 data directory。其中包含数字,而不是名称。该名称仅用作帮助识别部分的助记符。或者可能用于帮助语言运行时或调试器找到数据目录未涵盖的部分。

部分名称有一些 一致性,主要是按照惯例。像 BSS 这样古怪的部分名称可以追溯到 50 年代,在 Fortran 中使用,Fortran 是 Block Started by Symbol 的首字母缩写词。猜测它今天的用途没有多大帮助 :) 并且您可以假设名为 CODE 的部分将包含可执行代码并且等同于 .text,这是更常见的名称选择。 .tls 和 .reloc 之类的名称可以毫不费力地映射到相应的数据目录条目。

.rsrc 的相同 receipe,映射到数据目录中的第三个条目。 OS 很重要,像 LoadString 这样的 winapi 函数需要它。

但是,只有详细了解工具链才能真正了解古怪的工具。

操作系统加载程序通过使用可执行文件作为后备存储的 memory-mapped 文件将一个部分直接放入虚拟内存中。这就是 .text、.data 和 .bss 等部分的使用方式,请注意它们在数据目录中没有相应的条目。链接器负责生成正确的地址,这是 25 多年前完成的方式,不需要 OS 的帮助。除了 .reloc 部分,如果文件无法映射到其首选基地址,那是旧的。