【问题标题】:Difference between the ELF vs MAP fileELF 与 MAP 文件之间的区别
【发布时间】:2021-05-10 04:10:06
【问题描述】:

链接器可以输出 ELF 和 MAP 文件。这些文件在嵌入式系统领域尤其重要,因为 ELF 文件通常用于读取变量或函数的地址。此外,ELF 文件被不同的嵌入式测量或分析工具使用。

当我打开一个 MAP 文件时,我可以在其中看到每个全局变量和每个外部函数的以下信息:分配的地址、符号名称、分配的字节、内存单元和内存部分。

另一方面,一旦我打开 ELF 文件,它就是一个二进制文件,人类不可读。但是,我使用的一些工具能够读出并解释它。这些工具可以解释ELF文件,获取变量/函数的符号名及其地址信息,甚至显示函数原型。

据我了解,ELF 和 MAP 文件基本上包含相同的信息,只是第一个是二进制文件,后一个是文本文件。 那么从内容的角度来看,这两个文件之间的实际区别是什么?

提前谢谢你!

【问题讨论】:

  • 鉴于任何可能回答的人都必须隐含地知道这些文件是什么,您真的不需要尝试解释或猜测。简短的问题相当长。
  • @Clifford 这是一个很好的观点。然而,虽然提出带有额外信息的“大声思考”问题可能会使问题更长,但另一方面,它也可能导致提问者做出额外的结论。因此,这可能会导致更精确的最终问题。
  • 好的,可能。这无疑使我解决了明显的误解,而不仅仅是差异。

标签: linker embedded elf


【解决方案1】:

链接器的主要输出(即其主要目的)是生成完全链接的可执行代码。那就是ELF(可执行链接格式)文件。如您所见,ELF 文件可能包含符号 - 这些符号用于调试。它还可能包含将机器代码与生成它的源代码相关联的元数据。但它的大部分内容(以及非可选的部分)是可执行的机器代码和作为您的应用程序的数据对象。

MAP 文件是可选的仅供参考人类可读的输出,其中包含有关应用程序中代码和数据对象的位置和大小的信息。 MAP 文件包含一个摘要,显示代码的总大小和内存使用情况。

在嵌入式交叉开发环境中,ELF 文件中的符号信息在代码加载到源代码级符号调试器时使用。调试器获取 ELF 文件中的二进制代码/数据段并将它们加载到目标上(通常使用 JTAG 或其他调试/编程硬件工具),它将符号和源级调试元数据加载到调试器中,然后当真正的机器代码在目标上执行时,该执行会反映在原始源代码的调试器中,您可以在源代码级别查看、单步执行和断点代码。

简而言之,ELF 文件就是您的程序。 MAP 文件,顾名思义,是可执行文件的映射 - 它告诉您可执行文件中的内容。

【讨论】:

  • 感谢您的回答。尽管如此,我有一点要说。您写了关于 ELF 文件的文章:“它还可能包含将机器代码与生成它的源代码相关联的元数据。”。根据我有限的理解,元数据实际上将机器代码与汇编代码相关联?至少这是我的印象,因为我使用的工具可以重建应用程序的调用图,其中包括图中每个函数的汇编指令。只有在您加载源文件后,该工具才能除了程序集之外还显示应用程序源代码。还是我错了?
  • @SimpleThings 元数据包括与源代码相关的行号信息。机器代码与汇编代码的关联隐含在符号表中,因为汇编指令和机器代码指令之间存在直接关系。您所指的工具是生成反汇编(汇编的机器代码)。如果您要求,编译器可以从源代码生成汇编代码。一些编译器将其作为中间步骤,然后将其组装起来。如果您从源代码生成汇编列表,那么列表中很可能会有一行
  • 我尝试使用 readELF 工具读出一个 ELF 文件。其符号表包含AddressSymbol nameSizeType等字段(OBJ、FUNC、SECTION)、Bind(LOCAL、GLOBAL)等。但我不明白如何从中重建原始应用程序代码/程序集?我找不到提到的汇编指令和机器代码指令之间的直接关系
  • @SimpleThings ReadElf 显然没有呈现 elf 文件的所有内容,它的输出是元数据。要查看任何可读格式的代码,您需要一个反汇编程序。您不能从目标代码复制源代码。这就像试图用卫生纸重建一棵树。
  • 是的,我知道您无法在没有其他信息的情况下从二进制代码重建源代码,我在上一个声明中也没有说过这一点。您的句子是否还意味着 ELF 文件包含原始应用程序的二进制代码?这是否也意味着当调试器单步执行代码时,它必须通过也存储在 ELF 文件中的元数据来重构,即解散,即原始应用程序?
猜你喜欢
  • 2019-04-08
  • 2011-10-01
  • 2013-06-04
  • 1970-01-01
  • 2016-03-29
  • 1970-01-01
  • 2016-01-14
相关资源
最近更新 更多