可重定位目标文件(Relocatable Object Files)。
代码示例:
#include <stdio.h>
int count = 10;
int value;
void func(int sum)
{
printf("sum is:%d\n", sum);
}
int main()
{
static int a = 1;
static int b = 0;
int x = 1;
func(a + b + x);
return 0;
}
编译为可重定位目标文件.o,-c编译选项表示只进行编译和汇编,不执行链接操作。
gcc -c main.c
//-c : Compile and assemble, but do not link
使用wc(Word Count)命令查看main.o的大小,-c选项表示查看文件包含的字节。
wc -c main.o
1848 main.o
可重定位目标文件可分为三个部分,分别是ELF header,不同的section,以及描述这些section信息的表。其中ELF是可执行可链接格式的首字母缩写(Executable and Linkable Format, ELF)。
图示:
ELF header
使用readelf查看ELF header的具体内容,-h选项表示只显示header信息。
- 开头4字节7f 45 4c 46称为ELF文件的魔数,分别与ASCII码中的DEL控制符、字符E、字符L、字符F对应,用于操作系统加载文件时确认文件类型。
- 第5字节表示ELF文件类型,01表示32位,02表示64位。
- 第6字节表示字节序,01表示小端序,02表示大端序。
- 第7字节表示ELF文件版本号,通常都是1。
- 最后9个字节ELF的标准中没有定义,用0填充。
# readelf -h main.o
ELF 头:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
类别: ELF64
数据: 2 补码,小端序 (little endian)
版本: 1 (current)
OS/ABI: UNIX - System V
ABI 版本: 0
类型: REL (可重定位文件)
系统架构: Advanced Micro Devices X86-64
版本: 0x1
入口点地址: 0x0
程序头起点: 0 (bytes into file)
Start of section headers: 1016 (bytes into file)
标志: 0x0
本头的大小: 64 (字节)
程序头大小: 0 (字节)
Number of program headers: 0
节头大小: 64 (字节)
节头数量: 13
字符串表索引节头: 12
ELF Section header table
使用readelf查看表信息,-S选项表示打印整个表信息。除了表中第一项,其他每一个表项都对应着一个section,整个ELF文件包含12个section。offset偏移量表示每个section的起始位置,size表示section的大小。根据offset和size可以确定每个section在ELF文件中的具体位置。
- .text段存放编译好的机器代码。查看机器代码,需要使用反汇编工具objdump将机器代码转换成汇编代码。由于4字节对齐,.text大小为0x51,实际占用空间大小为0x54。
- .data段用来存放已初始化的全局变量和静态变量的值。
- .bss段存放未初始化的全局变量和静态变量,需要注意的是,被初始化为0的全局变量和静态变量也存放在bss中。bss可理解为Better Save Space。局部变量既不在data中,也不在bss中。实际上bss段并不占据实际的空间,它仅仅是只是一个占位符。
- .rodata段存放只读数据,ro是read only的缩写。例如printf中的格式串和switch语句中的跳转表就是存放在这个区域。
# readelf -S main.o
共有 13 个节头,从偏移量 0x3f8 开始:
节头:
[号] 名称 类型 地址 偏移量
大小 全体大小 旗标 链接 信息 对齐
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000000051 0000000000000000 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 000002e8
0000000000000078 0000000000000018 I 10 1 8
[ 3] .data PROGBITS 0000000000000000 00000094
0000000000000008 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 0000009c
0000000000000004 0000000000000000 WA 0 0 4
[ 5] .rodata PROGBITS 0000000000000000 0000009c
000000000000000b 0000000000000000 A 0 0 1
[ 6] .comment PROGBITS 0000000000000000 000000a7
000000000000002e 0000000000000001 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 000000d5
0000000000000000 0000000000000000 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 000000d8
0000000000000058 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 00000360
0000000000000030 0000000000000018 I 10 8 8
[10] .symtab SYMTAB 0000000000000000 00000130
0000000000000180 0000000000000018 11 11 8
[11] .strtab STRTAB 0000000000000000 000002b0
0000000000000035 0000000000000000 0 0 1
[12] .shstrtab STRTAB 0000000000000000 00000390
0000000000000061 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
图示:
反汇编工具objdump
查看机器代码,需要使用反汇编工具objdump将机器代码转换成汇编代码。
# objdump -s -d main.o
string.o: 文件格式 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 fc01d089 c7e80000 0000b800 000000c9 ................
0050 c3 .
Contents of section .data:
0000 0a000000 01000000 ........
Contents of section .rodata:
0000 73756d20 69733a25 640a00 sum is:%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 352d3434 2900 Hat 4.8.5-44).
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 30000000 00410e10 8602430d ....0....A....C.
0050 066b0c07 08000000 .k......
Disassembly of section .text:
0000000000000000 <func>:
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 <func+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 fc 01 00 00 00 movl $0x1,-0x4(%rbp)
30: 8b 15 00 00 00 00 mov 0x0(%rip),%edx # 36 <main+0x15>
36: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 3c <main+0x1b>
3c: 01 c2 add %eax,%edx
3e: 8b 45 fc mov -0x4(%rbp),%eax
41: 01 d0 add %edx,%eax
43: 89 c7 mov %eax,%edi
45: e8 00 00 00 00 callq 4a <main+0x29>
4a: b8 00 00 00 00 mov $0x0,%eax
4f: c9 leaveq
50: c3 retq