一. 目标文件的概念
- 编译器编译源代码后生成的文件叫做目标文件。
- 从结构上讲,它是编译后的可执行文件格式,只是还没有经过链接过程。
二. 目标文件的格式
PC平台上主流的可执行文件格式(Executable)主要有
- Windows下的PE(Portable Executable)
- Linux的ELF(Executable)
它们都是COFF(Common file format)格式的变种。
ELF分类
ELF文件类型 说明 实例 可重定位文件(Relocateable File) 包含代码和数据,可以链接成可执行文件或共享目标文件 Linux的 .o .a,Windows的.obj .lib 可执行文件(Executeable File) 包含可直接执行的程序,它的代表就是ELF可执行文件 Linux的/bin/bash文件,Windows的.exe 共享目标文件(Shared Object File) 包含代码和数据。链接器可以使用它跟其他可重定位文件或共享目标文件链接,产生新的目标文件。 动态链接器可以将几个共享目标文件与可执行文件结合,作为进程映像的一部分来运行 Linux的.so,Windows的.dll 核心转存储文件(Core Dump File) 当进程意外终止时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转存储到核心转存储文件 Linux下的core dump
三. 目标文件是什么样的
段 | 内容 |
---|---|
File Header | 描述整个文件的属性,包括文件是否可执行,是静态链接还是动态链接以及入口地址(如果是位置相关的可执行文件),目标硬件,目标操作系统等信息,文件头还包括一个段表(Section Table) |
.text(or .code) section | 代码段 |
.data section | 已初始化的全局变量和静态变量 |
.bss section | 未初始化的全局变量和静态变量 |
目标文件可分为程序指令和程序数据,这样做的好处有以下几个方面:
- 程序被装载后,数据和指令分别被映射到两个虚拟区域,数据区可读写,指令区只读,这样可以防止程序指令被改写。
- 现代CPU的缓存一般都被设计成数据缓存和指令缓存分离,所以程序的指令和数据分离对提高CPU的缓存命中率有好处。
- 副本进程之间可以共享程序指令。
四. 通过一个.o来了解目标文件的段
实验环境为:
GNU ld version 2.23.52.0.1-55.el7 20130226
gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
CentOS Linux release 7.2.1511 (Core)
源代码如下:
int g_init_var = 84;
int g_unint_var;
void func1(int i) {
printf("%d\n", i);
}
int main(void) {
static int static_var = 85;
static int static_var2;
int a = 1;
int b;
func1(static_var2 + static_var + a + b);
return a;
}
执行
$ gcc -c SimpleSection.c
编译结果为 SimpleSection.o。执行
$ objdump -h SimpleSection.o
查看段基本信息。
SimpleSection.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000054 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000008 0000000000000000 0000000000000000 00000094 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000004 0000000000000000 0000000000000000 0000009c 2**2
ALLOC
3 .rodata 00000004 0000000000000000 0000000000000000 0000009c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000002d 0000000000000000 0000000000000000 000000a0 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000cd 2**0
CONTENTS, READONLY
6 .eh_frame 00000058 0000000000000000 0000000000000000 000000d0 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
每个段信息的第二行中的CONTENTS、ALLOC等表示了该段的属性,CONTENTS表示该段在ELF文件中存在。
4.1. 代码段
执行
$ objdump -s -d SimpleSection.o
看所有段信息,以及反汇编结果。
SimpleSection.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000054 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000008 0000000000000000 0000000000000000 00000094 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000004 0000000000000000 0000000000000000 0000009c 2**2
ALLOC
3 .rodata 00000004 0000000000000000 0000000000000000 0000009c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000002d 0000000000000000 0000000000000000 000000a0 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000cd 2**0
CONTENTS, READONLY
6 .eh_frame 00000058 0000000000000000 0000000000000000 000000d0 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
[tiger@app-20-39 ~]$ objdump -s -d SimpleSection.o
SimpleSection.o: file format elf64-x86-64
Contents of section .text:
0000 554889e5 4883ec10 897dfc8b 45fc89c6 UH..H....}..E...
0010 bf000000 00b80000 0000e800 000000c9 ................
0020 c3554889 e54883ec 10c745fc 01000000 .UH..H....E.....
0030 8b150000 00008b05 00000000 01c28b45 ...............E
0040 fc01c28b 45f801d0 89c7e800 0000008b ....E...........
0050 45fcc9c3 E...
Contents of section .data:
0000 54000000 55000000 T...U...
Contents of section .rodata:
0000 25640a00 %d..
Contents of section .comment:
0000 00474343 3a202847 4e552920 342e382e .GCC: (GNU) 4.8.
0010 35203230 31353036 32332028 52656420 5 20150623 (Red
0020 48617420 342e382e 352d3429 00 Hat 4.8.5-4).
Contents of section .eh_frame:
0000 14000000 00000000 017a5200 01781001 .........zR..x..
0010 1b0c0708 90010000 1c000000 1c000000 ................
0020 00000000 21000000 00410e10 8602430d ....!....A....C.
0030 065c0c07 08000000 1c000000 3c000000 .\..........<...
0040 00000000 33000000 00410e10 8602430d ....3....A....C.
0050 066e0c07 08000000 .n......
Disassembly of section .text:
0000000000000000 <func1>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 89 7d fc mov %edi,-0x4(%rbp)
b: 8b 45 fc mov -0x4(%rbp),%eax
e: 89 c6