二进制文件(PE/COFF和ELF)格式和术语的澄清

20

我对这些术语感到有些困惑。

输入链接器的文件称为目标文件,链接器生成的映像文件被加载器用作输入。

这段内容来自于《MS PE & COFF规范》。

问题1:映像文件也称为二进制映像二进制文件或者只是二进制。对吗?

问题2:根据上述术语,PE/ELF/COFF是映像文件的格式,而不是目标文件的格式,对吗?但http://www.sco.com/developers/gabi/latest/ch4.intro.html中写道:

本章介绍了名为 ELF(可执行和链接格式)的目标文件格式。有三种主要类型的目标文件。

  • 可重定位文件包含适合与其他目标文件链接以创建可执行文件或共享对象文件的代码和数据。

  • 可执行文件包含适合执行的程序;该文件指定了如何通过exec(BA_OS)创建程序的过程图像。

  • 共享对象文件包含适合在两个上下文中链接的代码和数据。首先,链接编辑器[参见ld(BA_OS)]将共享对象文件与其他可重定位和共享对象文件一起处理以创建另一个目标文件。其次,动态链接器将其与可执行文件和其他共享对象组合以创建进程图像。

他矛盾地说,目标文件映像文件都是 ELF 格式,并且根本没有区分目标文件和映像文件,而是通常将它们称为目标文件。这不对吗?

问题3. 我知道PE格式是从COFF演变而来的。但为什么微软的PE格式规范被命名为“Microsoft Portable Executable and Common Object File Format Specification”?他们是否还支持COFF?如果支持,是在哪个操作系统上?我以为很久以前PE就完全替代了COFF。

答:尽管PE是从COFF演变而来的,但是微软将PE规范命名为“Microsoft Portable Executable and Common Object File Format Specification”,并不意味着他们不再支持COFF。实际上,微软仍然支持COFF,并且它被广泛用于Windows操作系统中的静态库和驱动程序等方面。 PE已经成为Windows操作系统中可执行文件和动态链接库的标准格式,同时也支持32位和64位平台。因此,虽然PE已经取代了COFF作为Windows中应用程序的主要格式,但COFF仍然被用于某些特定领域。


在第二遍阅读后,我不确定你的问题是什么-你是在问PE、COFF和ELF之间的区别是什么,链接/加载是如何工作和地址是如何解决的,还是其他问题? - Michael Burr
我把我的问题分成了两个问题:关于VA&RVA的另一个问题是https://dev59.com/p3I95IYBdhLWcg3wvwsQ - claws
@Michael Burr:1. 我对PE/COFF和ELF规范中使用的“目标文件”和“映像文件”的术语差异感到困惑。 2. 遵循上述“目标文件”和“映像文件”的术语,Windows上的“目标文件”是否也采用PE/COFF格式,Linux上是否采用ELF格式? - claws
@ Michael Burr:是你发布了答案并将其删除了吗?如果是的话,请重新发布答案,因为它清楚地回答了我的第一个问题。 - claws
@claws:我恢复了我的回答。但是仅供参考,我最初删除它是因为它似乎在很大程度上重申了你在问题中已经提到的信息,而不是回答它。 - Michael Burr
@Michael Burr:我的帖子只是“澄清”(见标题):)。只是想确保我理解得正确。:D - claws
5个回答

22

我是题主。每个人的答案都是部分答案。因此,我将结合其他答案和我的学习来完成答案。

这是"通常"使用的术语。

  • 作为链接器输入的文件(汇编器输出的文件)称为Object FileRelocatable File

  • 链接器产生一个Image file,然后由加载器作为输入使用。现在,Image file可以是Executable fileLibrary file。这些'Library files'有两种:

    1. 静态库(*.lib文件用于windows, *.a用于linux)
    2. 共享/动态库:DLL(*在windows上为.dll)和Shared Object file(*在Linux上为.so)
  • 术语Binary File/Binary可用于指代ObjectFile或ImageFile。根据上下文理解。这是一个非常普遍的术语。

  • 当加载器将图像文件加载到内存时,它被称为Module(我不确定Linux的人,但是Windows的人称其为Module)。

http://www.gliffy.com/pubdoc/1978433/L.jpg alt text http://www.gliffy.com/pubdoc/1978433/L.jpg

正如我所说,这些是"通常"使用的术语。对于术语'binary file'、'image file'或'object file',没有严格的定义。

在特定情况下,“目标文件”这个术语有时可能指由编译器输出供链接器使用的中间文件,但在另一种情况下可能意味着可执行文件。

特别是在不同平台上,它们可能用于引用不同或类似的东西。即使在讨论单个平台的问题时,一个作者也可能会稍微不同地使用这些术语。

  • 在 Windows 中,ObjectFile和ImageFile都是PE格式,在Linux中是ELF格式。
  • ELF不仅是映像文件的格式,还是目标文件的格式。
  • 每个ELF文件都以一个ELF头开始。 ELF头的第二个字段是e_type; 此字段告诉我们文件是目标文件(在ELF术语中称为可重定位文件),还是映像(可以是可执行文件或共享对象),或者其他内容(核心文件也是ELF文件)。
  • 我不知道头部是否有任何位可以区分目标文件和映像文件。 需要检查。

我知道PE是从COFF派生出来的。 但是为什么Microsoft 的PE格式规范被命名为 “Microsoft Portable Executable”和 “Common Object File Format Specification”。他们还支持 COFF吗?如果支持,在哪个操作系统上?我认为 PE很久以前就完全替换了COFF。

至于“PE”与“COFF”,我的记忆是Microsoft使用“COFF”规范作为“PE”规范的起点,但根据他们的需要进行了扩展。因此严格来说,“PE”文件不是“COFF”文件,但在许多方面非常相似。


实际上,使用术语“模块”来描述已加载的PE映像取决于上下文。在用户模式中的图像加载器中,这是一个常见的术语,因为用模块之间的依赖关系来描述EXE和DLL之间或两个DLL之间的符号依赖关系是有意义的。然而,从内核模式内存管理器的角度来看(描述节和段对象时),已加载的映像仍然只被称为“映像”,因为用“模块”来描述内存映射是没有意义的。 - Erlend Graff
看起来其中一个图像链接已经失效了,有人知道这个图像曾经是什么吗?我在archive.org上也找不到它。 - jrh
“静态库”是输入给链接器,而不是加载器。它们本质上是一组带有某些内容表头的个别目标文件的归档文件。 - Ofek Shilon

3

对于术语“二进制文件”、“图像文件”或“目标文件”,没有严格的定义。

特别是,“目标文件”一词有时可能用于表示编译器输出的中间文件,供链接器使用,但在另一种情况下可能表示可执行文件。

尤其是在不同的平台上,它们可能用于指代不同或类似的东西。即使在讨论单个平台的问题时,一个作者可能会与另一个作者稍微不同地使用这些术语。

就“PE”与“COFF”而言,我记得微软使用“COFF”规范作为“PE”规范的起点,但为了满足其需求进行了扩展。因此,严格来说,“PE”文件不是“COFF”文件,但在许多方面非常相似。


1

在Linux系统上,gcc -c会生成一个.o文件,它是elf格式的目标文件。在我的机器上,使用file命令描述一个.o文件为"ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV)"。


1
关于 ELF 的 Q2,ELF 不仅是图像文件的格式,而且也是目标文件的格式。
每个 ELF 文件都以 ELF Header 开始。 ELF Header 的第二个字段是 e_type;这个字段让我们知道文件是一个目标文件(在 ELF 术语中称为可重定位文件),一个图像(可以是可执行文件或共享对象)还是其他内容(核心文件也是 ELF 文件)。

太棒了!!那是一条有价值的信息。你知道PE是否也是类似情况吗? - claws
是的,从这个文档(http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx)可以看出,PE也做了类似的事情(“在一个对象文件的开头,或者在映像文件的签名之后,是一个标准的COFF文件头”). - R Samuel Klatchko
我不是指PE头。我知道PE文件有一个头部。我想问的是这样一个标志位。PE是否也有任何标志,可以将ObjectFile与ImageFile区分开来? - claws

0
顺便说一下,我知道在Solaris上的核心转储(我猜其他Unix版本也是如此)可以采用ELF格式。

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