什么是一个目标文件包含?

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

有谁能帮我吗? 目标文件的内容主要依赖于我们在Unix上使用的编译器吗?

对象文件可以包含一些东西:基本上它是下面的一些或全部列表:

  • 符号名称
  • 编译代码
  • 常量数据,例如。 string
  • 导入 – 已编译代码引用的哪些符号(由链接器修复)
  • 导出 – 对象文件的哪些符号可用于OTHER对象文件。

链接器通过匹配所有的导入和导出,修改编译后的代码,将一堆目标文件转换成一个可执行文件,从而调用正确的函数。

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

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

  • 编译后的二进制代码(对于目标处理器)
  • 程序那部分使用的静态数据(如常量string等)。 您可以在BSS(导出数据)和文本(不会被程序修改的数据)之间进行更好的区分。 但是这对于编译器和链接器来说是非常重要的。 请注意,与二进制代码一样,数据也依赖于目标(大端,小端,32位,64位)。
  • 这部分程序导出的符号表(主要是函数入口点)
  • 该部分程序使用的外部符号表

当对象被连接在一起时,引用外部符号的代码部分将被实际的值所代替(当然,这仍然是过于简化的,在运行程序时加载时会有最后一部分,但这是理念)。

目标文件还可能包含更多符号信息,这些信息对于parsing导入和导出(对debugging有用)而言是非常必要的。 该信息可以使用strip命令删除。

首先阅读维基页面 。 你可以使用objdump来检查这样的文件:)

目标文件是编译后的源文件。

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

使用文件命令这样的事情。 这是一个现代Linux系统上的ELF对象文件。 例如,如果编译为32位x86。

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

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

 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 

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

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

这些信息是如何“组织的”,在某些情况下,“最终更多”是什么,取决于具体的对象格式。 一些维基百科链接列出的一些可能性是这个 , 这个 , 这个 , 这 …

其中每一个都可能有其工具来分析内容; 例如ELF的readelfobjdump的几种格式(尝试objdump -i )取决于它是如何编译的。

该文件包含必须通过链接器运行以生成可执行文件的二进制数据。 它本质上是一堆带有命名部分(对应于你的function)的机器代码指令。 从维基百科的“ 对象文件 ”文章:

在计算机科学中,目标文件是机器代码的单独命名序列的有组织的集合[需要的引证]。 每个序列或对象通常包含主机完成一些任务的指令,可能伴随着相关的数据和元数据(例如重定位信息,堆栈展开信息,注释,程序符号,debugging或分析信息)。 链接器通常用于通过组合部分目标文件来生成可执行文件或库。

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

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

 $ 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,则可以看到更多的function(除了在对象内部find的function外)。 这certificate了目标文件只包含源文件中定义的函数,并引用了其他函数。 这些引用将在链接阶段解决。

阅读关于链接 , 编译和对象的更多信息。