C语言 目标文件包含什么?

mum43rcc  于 2023-04-19  发布在  其他
关注(0)|答案(8)|浏览(142)

在C或C++编译的各个阶段,我知道会生成一个目标文件(即any_name.o文件)。这个.o文件包含什么?我无法打开它,因为它是一个二进制文件。
有谁能帮帮我吗?目标文件的内容主要取决于我们在Unix上使用的编译器吗?

5m1hhzi4

5m1hhzi41#

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

  • 符号名称
  • 编译代码
  • 常量数据,例如字符串
  • 导入-编译代码引用的符号(由链接器修复)
  • 导出-对象文件使哪些符号可用于其他对象文件。

链接器通过匹配所有的导入和导出,并修改编译后的代码,以便调用正确的函数,从而将一组对象文件转换为可执行文件。

mo49yndu

mo49yndu2#

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

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

当对象链接在一起时,引用外部符号的代码部分将被实际值替换(好吧,这仍然过于简化,最后一部分将在运行程序时加载时完成,但这就是想法)。
目标文件还可能包含更多的符号信息,这些信息是解析导入和导出所必需的(对调试很有用)。这些信息可以使用strip命令删除。

sqxo8psd

sqxo8psd3#

首先读取wiki page,可以使用**objdump**检查这样的文件:)

mm9b1k5b

mm9b1k5b4#

在现代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
wlp8pajw

wlp8pajw5#

首先,二进制文件 * 可以 * 打开!不要害怕它,你需要正确的工具!作为二进制数据,文本编辑器当然不是正确的工具;一个合适的工具可以是十六进制编辑器,或者像emacs这样的高级编辑器,或者是一个工具,它不是简单地“输出”十六进制表示的字节,让您独自解释数据,而是知道特定的格式并在某种程度上正确地“解释”数据。(例如,GIMP将PNG文件解释为图像并显示它,PNG分析器将“分解”PNG部分中的数据,告诉您某些字节中的标志,...等)。
在您的情况下,一般的答案是目标文件包含您编译的代码(和数据),加上链接器所需的所有额外信息,最终更多。
这些信息是如何“组织”的,在某些情况下,“最终更多”由什么组成,这取决于具体的对象格式。一些维基百科链接列出了一些可能性是thisthisthisthis...
其中每一个都可能有其分析内容的工具;例如,readelf用于ELF,objdump用于几种格式(尝试objdump -i),这取决于它是如何编译的。

brc7rcf0

brc7rcf06#

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

myzjeezk

myzjeezk7#

该文件包含二进制数据,必须通过linker运行才能生成可执行文件。它本质上是一堆带有命名部分的机器代码指令(对应于您的函数)。来自wikipedia的' Object File '文章:
在计算机科学中,目标文件是一个有组织的独立的、命名的机器代码序列的集合。每个序列或对象通常包含主机完成某项任务的指令,可能还伴随有相关的数据和元数据(例如重定位信息、堆栈展开信息、注解、程序符号链接器通常用于通过组合对象文件的部分来生成可执行文件或库。

a11xaf1n

a11xaf1n8#

在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的信息。

相关问题