我被问到一个问题:“什么是'目标文件'?”。
看了Wiki,只知道里面有对象。
但是这些对象是什么,为什么有人这样称呼它们?
目标文件(或目标代码)是编译器从源代码生成的机器代码文件。
与可执行文件的区别在于目标文件没有链接,因此还没有定义对函数、符号等的引用(它们的内存地址基本上是空白的)。
使用 GCC 编译 C 文件时:
gcc -Wall -o test test.c
在这里,您正在编译和链接。因此,您将获得一个可执行文件,其中包含它所包含的符号(库、标头等)的所有内存地址引用。
但是当你这样做时:
gcc -Wall -o test.o -c test.c
您将生成目标文件。它也是机器代码,但需要链接才能生成可执行文件或库。
当您有一个包含许多 C 文件的项目(例如)时,您会将每个 C 文件编译为目标代码,然后将所有目标文件链接在一起以生成最终产品。
例如:
gcc -Wall -o foo.o -c foo.c // Object file for foo.c
gcc -Wall -o bar.o -c bar.c // Object file for bar.c
gcc -Wall -o main.o -c main.c // Object file for main.c
gcc -Wall -o software foo.o bar.o main.o // Executable (foo + bar + main)
术语对象在这里代表未链接的机器代码序列(基本上)。对象文件包含对象。
你问:为什么这样叫。我真的无法回答。为什么“蓝色”被命名为“蓝色”?; )
这只是从……嗯,几十年……开始使用的术语。
有关信息,GCC 内部文档仅将目标代码定义为:
作品的“源代码”是指对作品进行修改的首选形式。“目标代码”是指任何非源代码形式的作品。
历史原因很模糊...
我只是希望你现在更好地理解什么是目标文件。我认为这比知道为什么这样称呼它更重要,因为单词只是,嗯,单词……
我相信这个名字与区分:
目标文件包含:
- 标头信息:有关文件的总体信息,例如代码大小、翻译源文件的名称和创建日期。
- 目标代码:由编译器或汇编器生成的二进制指令和数据。
- 重定位:当链接器更改目标代码的地址时,目标代码中必须修复的位置列表。
- Symbols:在该模块中定义的全局符号,要从其他模块导入或由链接器定义的符号。
- 调试信息:关于链接不需要但用于调试器的目标代码的其他信息。这包括源文件和行号信息、局部符号、目标代码使用的数据结构的描述,例如 C 结构定义。
来源:这里
目标文件是源(文本)文件的二进制表示。它是不同部分的集合,将数据类型划分为:
根据您的编译器/环境,这些可能会有所不同。
例如在 *nix 系统上:
objdump -d a.out <--- 如果我们编译了 a.cpp
disassembly of section .init:
08048278 <_init>:
8048278: 55 push %ebp
8048279: 89 e5 mov %esp,%ebp
804827b: 83 ec 08 sub $0x8,%esp
804827e: e8 61 00 00 00 call 80482e4 <call_gmon_start>
8048283: e8 b3 00 00 00 call 804833b <frame_dummy>
8048288: e8 9f 01 00 00 call 804842c <__do_global_ctors_aux>
804828d: c9 leave
804828e: c3 ret
Disassembly of section .plt:
08048290 <puts@plt-0x10>:
8048290: ff 35 78 95 04 08 pushl 0x8049578
8048296: ff 25 7c 95 04 08 jmp *0x804957c
804829c: 00 00 add %al,(%eax)
...
080482a0 <puts@plt>:
80482a0: ff 25 80 95 04 08 jmp *0x8049580
80482a6: 68 00 00 00 00 push $0x0
80482ab: e9 e0 ff ff ff jmp 8048290 <_init+0x18>
080482b0 <__libc_start_main@plt>:
80482b0: ff 25 84 95 04 08 jmp *0x8049584
80482b6: 68 08 00 00 00 push $0x8
80482bb: e9 d0 ff ff ff jmp 8048290 <_init+0x18>
Disassembly of section .text:
然后这里的各种调用命令被各种库喜欢来调用实际的函数。
根据您链接的页面,每个序列或对象通常包含主机完成某些任务的指令,可能伴随着相关数据和元数据(例如重定位信息、堆栈展开信息、注释、程序符号、调试或分析信息)。
基本上,目标文件中的每个对象都是一个函数,以及链接器将其包含到完整程序中的相关信息。