23

不要通过查看问题标题来误解我的意思 - 我知道它们是什么(可移植可执行文件的格式)。但我的兴趣范围略有不同

我的困惑

我参与重新托管/重新定位最初来自第三方的应用程序。问题是有时目标代码的格式也是 .elf、.COFF 格式,并且仍然显示“可执行和可链接”。

我主要是 Windows 用户,并且知道当您编译和组装 C/C++ 代码时,您会得到类似于 .o 或 .obj 的内容。是不可执行的(好吧,我从来没有尝试过执行它们)。但是当您完成链接静态库和动态库并完成构建时,会出现可执行文件。我的理解是,如果需要,您可以使用某种形式的脚本链接该可执行文件或“bash”对其进行测试。

但是,在 Linux(或类 UNIX 系统)中,在编译和汇编 C/C++ 代码后会有 .o 文件。一旦链接完成,可执行文件就是 a.out 格式(至少在 Linux 的 Ubuntu 发行版中)。它很可能是其他发行版中的 .elf。在我的快速网络搜索中,没有任何来源提到任何关于 .o 文件作为可执行文件的内容。

问题

因此我的问题变成了以下几点:

  1. 可移植可执行文件和目标代码的真正定义是什么?

  2. Windows 和 UNIX 平台如何涵盖相同文件格式(.COFF、.elf)下的可执行文件和目标代码。

  3. 我是否误解了“可链接”?我对“可链接”的解释是编译后的目标代码,然后可以“链接”到其他静态/动态链接库。这是一个愚蠢的想法吗?

  4. 基于问题 1.(也许是 2)我是否需要将符号表(例如 .LUM 或 .MAP 文件)与目标代码一起使用?调试符号中的符号,并在不同机器上重新托管可执行文件/目标文件时使用它们。

在此先感谢您的正确推动。同时,如有必要,我将继续挖掘和更新问题。

更新

我已经设法从某个地方挖出了:(对我来说似乎有很多东西要吞下去。

4

1 回答 1

18

我主要是 Windows 用户,并且知道当您编译 C/C++ 代码时,您会得到类似于 .o 或 .obj 的内容。不可执行的

嗯,上次我在 Windows 上编译的东西,编译的结果一个.obj文件,这正是它的名字所暗示的:它是一个目标文件。你是对的,它本身不是可执行文件。它包含的机器代码(还没有)包含足够的信息来直接在 CPU 上运行。

但是,在 Linux(或类 UNIX 系统)中,编译 C/C++ 代码后会有 .o 文件。一旦链接完成,可执行文件就是 a.out 格式(至少在 Linux 的 Ubuntu 发行版中)。它很可能是其他发行版中的 .elf。

生活在 90 年代,即 :P 我所知道的没有现代编译器将a.out格式作为目标代码的默认输出格式。a.out当没有指定明确的输出文件名时,将目标代码放入一个调用的文件中可能是 GCC 的一个误导性默认设置,但是如果您在file上运行该命令a.out,您会发现它是一个 ELF 文件。格式很古老,a.out有点“事实上已经过时”。

可移植可执行文件和目标代码的真正定义是什么?

您已经获得了目标文件的 Wikipedia 链接,这里是 "Portable Executable" 的链接。

Windows 和 UNIX 平台如何涵盖相同文件格式(.COFF、.elf)下的可执行文件和目标代码。

因为 ELF 格式(显然也是 COFF)就是这样设计的。那么为何不?毕竟它只是相同的机器代码,在所有编译步骤中使用一种文件格式似乎很合乎逻辑。就像我们不喜欢动态库和独立可执行文件有不同的格式一样。(这就是 ELF 被称为 ELF 的原因——它是一种“可执行可链接格式”。)

我是否误解了“可链接”?

我不知道。从您的问题来看,我不清楚您认为“可链接”是什么。一般来说,这意味着它是一个可以链接的文件,即一个库。

基于问题 1。(也许是 2)我是否需要将符号表(例如 .LUM 或 .MAP 文件)与目标代码一起使用?调试符号中的符号,并在将目标文件重新托管在不同的机器上时使用它们。

我认为这与使用的可执行格式无关。如果要调试,无论如何都要生成调试信息。但是,如果您不需要调试,那么您当然可以随意省略它们。

于 2013-06-27T06:57:08.223 回答