(三)目标文件里有什么

编译器编译源代码后生成的文件叫做目标文件。

3.1 目标文件的格式是什么

可执行文件格式:

- PE Portable Executable (windows)
- ELF Executable Linkable Format (Linux)

目标文件:源代码编译后但未进行链接的哪些中间文件windows下的.obj和linux下的.o

1
2
# 使用file命令查看响应的文件格式
file filename.o

3.2 目标文件是什么样的

一般目标文件将信息按照不同的属性按照节的形式存储,有时候也叫段。
在一般情况下,他们都表示一个一定长度的区域,基本上不加以区分别。

代码段:.code .text ===> 程序指令
数据段: .data ===> 程序数据

  • C语言编译后的执行语句都编译成机器代码,保存在.text段
  • 已经初始化的全局变量和局部变量都保存在.data段
  • 未初始化的全局变量和局部静态变量默认值都为0存在.bss段,.bss段只是预留空间没有内容,不占空间

    3.3 挖掘SimpleSection.o

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int printf( const char* format, ...);

int global_init_var = 84;
int global_uninit_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 = 2;

func1 ( static_var + static_var2 + a + b);

return a;
}

gcc -c SimpleSection.c 得到SimpleSection.o文件

objdump -h SimpleSection.o 查看目标文件的结构和内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000058 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000008 0000000000000000 0000000000000000 00000098 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000004 0000000000000000 0000000000000000 000000a0 2**2 没有COMMNETS 长度为0
ALLOC
3 .rodata 00000004 0000000000000000 0000000000000000 000000a0 2**0 只读数据段
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000002e 0000000000000000 0000000000000000 000000a4 2**0 注释信息段
CONTENTS, READONLY
5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000d2 2**0 堆栈提示段 长度为0
CONTENTS, READONLY
6 .eh_frame 00000058 0000000000000000 0000000000000000 000000d8 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

属性分析:

- Size 段的长度
- File Off 段的位置
- CONTENTS、ALLOC等表示段的各种属性
OtherData 0x00000450
.comment 0X000000a4
.rodata 1 0X000000a0
.data 0X00000098
.text 0X00000040
ELF Header 0X00000000

有一个专门的命令叫做size,用来查看ELF文件的代码段、数据段和BSS段的长度,dec表示3个段长度的和的十进制,hex表示长度和的十六进制

size SimpleSection.o

1
2
text	   data	    bss	    dec	    hex	filename
180 8 4 192 c0 main.o

3.3.1 代码段

objdump -s 参数可以将所有端的内容以16禁止的方式打印出来

-d 参数可以将所有包含指令的段反汇编

objdump -s -d SimpleSection.o

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
main.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 10c745f8 01000000 .UH..H....E.....
0030 c745fc02 0000008b 15000000 008b0500 .E..............
0040 0000008d 04020345 f80345fc 89c7e800 .......E..E.....
0050 0000008b 45f8c9c3 ....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 342e342e .GCC: (GNU) 4.4.
0010 37203230 31323033 31332028 52656420 7 20120313 (Red
0020 48617420 342e342e 372d3138 2900 Hat 4.4.7-18).
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 37000000 00410e10 8602430d ....7....A....C.
0050 06720c07 08000000 .r......

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 mov %eax,%esi
10: bf 00 00 00 00 mov $0x0,%edi
15: b8 00 00 00 00 mov $0x0,%eax
1a: e8 00 00 00 00 callq 1f <func1+0x1f>
1f: c9 leaveq
20: c3 retq

0000000000000021 <main>:
21: 55 push %rbp
22: 48 89 e5 mov %rsp,%rbp
25: 48 83 ec 10 sub $0x10,%rsp
29: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%rbp)
30: c7 45 fc 02 00 00 00 movl $0x2,-0x4(%rbp)
37: 8b 15 00 00 00 00 mov 0x0(%rip),%edx # 3d <main+0x1c>
3d: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 43 <main+0x22>
43: 8d 04 02 lea (%rdx,%rax,1),%eax
46: 03 45 f8 add -0x8(%rbp),%eax
49: 03 45 fc add -0x4(%rbp),%eax
4c: 89 c7 mov %eax,%edi
4e: e8 00 00 00 00 callq 53 <main+0x32>
53: 8b 45 f8 mov -0x8(%rbp),%eax
56: c9 leaveq
57: c3 retq

3.3.2 数据段和只读数据段

  • .data段保存的是那些已经初始化了的全局静态变量和局部静态变量
  • .dodata端存放的是只读数据,一般是程序里面的只读变量,如const修饰的变量和

3.3.3 BSS段

.bss段存放的是未初始化的全局变量和局部静态变量

字符串常量

3.4 ELF文件结构描述

3.5 链接的接口–符号

3.6 调试信息

3.7 本章小结