目标文件包含什么?

时间:2010-06-15 13:33:28

标签: c++ c compilation

在C或C ++编译的各个阶段,我知道生成了一个目标文件(即any_name.o文件)。这个.o文件包含什么?我无法打开它,因为它是一个二进制文件。

有人可以帮帮我吗?目标文件的内容是否主要依赖于我们在Unix上使用的编译器?

8 个答案:

答案 0 :(得分:46)

对象文件可以包含很多东西:基本上它是以下列表中的部分或全部:

  • 符号名称
  • 已编译的代码
  • 常数,例如。字符串
  • 导入 - 编译代码引用的符号(由链接器修复)
  • 导出 - 目标文件可用于OTHER目标文件的符号。

链接器将一堆目标文件转换为可执行文件,方法是匹配所有导入和导出,并修改已编译的代码,以便调用正确的函数。

答案 1 :(得分:8)

有几种标准化格式(在Unix上使用COFF,ELF),基本上它们是与可执行文件相同格式但是缺少某些信息的变体。链接时将完成这些缺失的信息。

对象文件格式基本上包含相同的信息:

  • 编译产生的二进制代码(对于目标处理器)
  • 程序的该部分使用的静态数据(如常量字符串等)。您可以在BSS(导出数据)和Text(程序不会修改的数据)之间进行更精细的区分。但这对编译器和链接器来说非常重要。请注意,与二进制代码一样,数据也依赖于目标(big-endian,little-endian,32bits,64bits)。
  • 程序的这一部分导出的符号表(主要是函数入口点)
  • 本部分程序使用的外部符号表

当对象链接在一起时,引用外部符号的代码部分将被实际值替换(好吧,仍然过于简单,最后一部分将在加载时运行程序时完成,但这就是主意。)

目标文件还可能包含更多解析导入和导出所必需的符号信息(对调试很有用)。可以使用strip命令删除该信息。

答案 2 :(得分:5)

首先阅读wiki page。您可以使用 objdump 来检查此类文件:)

答案 3 :(得分:4)

使用file命令执行此类操作。它是现代Linux系统上的ELF目标文件。例如。如果编译为32位x86。

ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

相反,动态链接的可执行文件可能如下所示:

ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped

要查看标题,包括章节名称,您可以使用:

objdump -x any_name.o

要反汇编:

objdump -d any_name.o

答案 4 :(得分:3)

目标文件是已编译的源。

这意味着它是机器代码,它依赖于目标平台(如果你真的想要,你可以在Windows上编译Unix)和使用的编译器。不同的编译器将从同一源文件生成不同的机器代码。

答案 5 :(得分:3)

首先,可以打开二进制文件 !不要害怕它,你需要正确的工具!作为二进制数据,文本编辑器当然不是正确的工具;正确的工具可以是十六进制编辑器,也可以是像emacs这样的高级编辑器,或者是一种工具,它不是简单地以“十六进制”表示形式“输出”字节,而是让你单独对数据进行解释,就知道特定的格式和“在某种程度上正确地解释“数据”(例如,GIMP将PNG文件解释为图像并显示它,PNG分析器将“分解”PNG部分内的数据,显示告诉您某些字节中的标志,......等)。

在您的情况下,一般的答案是目标文件包含已编译的代码(和数据),以及链接器所需的所有额外信息,最终还有更多。

这些信息如何“组织”,在某些情况下,“最终更多”的组成部分取决于具体的对象格式。一些维基百科链接列出了一些可能性thisthisthisthis ......

其中每一个都可能有分析内容的工具;例如ELF为readelfobjdump为多种格式(尝试objdump -i),具体取决于编译方式。

答案 6 :(得分:1)

该文件包含二进制数据,必须通过linker运行才能生成可执行文件。它本质上是一堆带有命名部分的机器代码指令(对应于您的函数)。来自维基百科的“Object File”文章:

  

在计算机科学中,目标文件是   有组织的分开的集合,   命名的机器序列   代码[引证需要]。每个序列,   或对象,通常包含   主机的说明   可能完成一些任务   附有相关数据和   元数据(例如搬迁   信息,堆栈展开   信息,评论,计划   符号,调试或分析   信息)。通常是链接器   用于生成可执行文件或   通过组合对象的部分库   文件。

答案 7 :(得分:1)

在GNU编译环境中,您可以在可执行文件和目标文件中查看objdump。

正如您所看到的,该对象仅包含已编译文件中声明/引用的函数代码(该文件仅包含带有scanf调用和printf调用的main函数)。

$ objdump -t scanf_sample.o

scanf_sample.o:     file format pe-i386

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 scanf_sample.c
File
[  2](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _main
[  3](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .text
AUX scnlen 0x91 nreloc 9 nlnno 0
[  5](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[  7](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[  9](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x54 nreloc 0 nlnno 0
[ 11](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 13](sec  0)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 __alloca
[ 14](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _memset
[ 15](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _scanf
[ 16](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _printf

如果对可执行文件使用objdump,则可以看到更多函数(除了在对象中找到的函数)。这证明了目标文件仅包含源文件中定义的函数以及对其他函数的引用。这些参考文献将在链接阶段得到解决。

详细了解linkingcompilationobjects