有关可重定位目标文件以下面这段代码(a.c)为例:
#include <stdio.h>
int time;
int foo(int a) {
int b = a + 1;
return b;
}
int main(int argc, char *argv[])
{
printf("%d\n", foo(5));
return 0;
}
如何得到可重定位目标文件呢
gcc -c a.c -o a.o
用该指令可以直接得到a.o(可重定位目标文件)
得到的a.o内容是二进制形式,无法直接查看
这条指令可以帮助我们查看它的大致内容
objdump a.o -D
a.o: file format elf32-i386
Disassembly of section .text:
00000000 <foo>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: 8b 45 08 mov 0x8(%ebp),%eax
9: 83 c0 01 add $0x1,%eax
c: 89 45 fc mov %eax,-0x4(%ebp)
f: 8b 45 fc mov -0x4(%ebp),%eax
12: c9 leave
13: c3 ret
00000014 <main>:
14: 55 push %ebp
15: 89 e5 mov %esp,%ebp
17: 83 e4 f0 and $0xfffffff0,%esp
1a: 83 ec 10 sub $0x10,%esp
1d: c7 04 24 05 00 00 00 movl $0x5,(%esp)
24: e8 fc ff ff ff call 25 <main+0x11>
29: 89 44 24 04 mov %eax,0x4(%esp)
2d: c7 04 24 00 00 00 00 movl $0x0,(%esp)
34: e8 fc ff ff ff call 35 <main+0x21>
39: b8 00 00 00 00 mov $0x0,%eax
3e: c9 leave
3f: c3 ret
Disassembly of section .rodata:
00000000 <.rodata>:
0: 25 .byte 0x25
1: 64 0a 00 or %fs:(%eax),%al
Disassembly of section .comment:
00000000 <.comment>:
0: 00 47 43 add %al,0x43(%edi)
3: 43 inc %ebx
4: 3a 20 cmp (%eax),%ah
6: 28 55 62 sub %dl,0x62(%ebp)
9: 75 6e jne 79 <main+0x65>
b: 74 75 je 82 <main+0x6e>
d: 20 34 2e and %dh,(%esi,%ebp,1)
10: 38 2e cmp %ch,(%esi)
12: 32 2d 31 39 75 62 xor 0x62753931,%ch
18: 75 6e jne 88 <main+0x74>
1a: 74 75 je 91 <main+0x7d>
1c: 31 29 xor %ebp,(%ecx)
1e: 20 34 2e and %dh,(%esi,%ebp,1)
21: 38 2e cmp %ch,(%esi)
23: 32 00 xor (%eax),%al
Disassembly of section .eh_frame:
00000000 <.eh_frame>:
0: 14 00 adc $0x0,%al
2: 00 00 add %al,(%eax)
4: 00 00 add %al,(%eax)
6: 00 00 add %al,(%eax)
8: 01 7a 52 add %edi,0x52(%edx)
b: 00 01 add %al,(%ecx)
d: 7c 08 jl 17 <.eh_frame+0x17>
f: 01 1b add %ebx,(%ebx)
11: 0c 04 or $0x4,%al
13: 04 88 add $0x88,%al
15: 01 00 add %eax,(%eax)
17: 00 1c 00 add %bl,(%eax,%eax,1)
1a: 00 00 add %al,(%eax)
1c: 1c 00 sbb $0x0,%al
1e: 00 00 add %al,(%eax)
20: 00 00 add %al,(%eax)
22: 00 00 add %al,(%eax)
24: 14 00 adc $0x0,%al
26: 00 00 add %al,(%eax)
28: 00 41 0e add %al,0xe(%ecx)
2b: 08 85 02 42 0d 05 or %al,0x50d4202(%ebp)
31: 50 push %eax
32: c5 0c 04 lds (%esp,%eax,1),%ecx
35: 04 00 add $0x0,%al
37: 00 1c 00 add %bl,(%eax,%eax,1)
3a: 00 00 add %al,(%eax)
3c: 3c 00 cmp $0x0,%al
3e: 00 00 add %al,(%eax)
40: 14 00 adc $0x0,%al
42: 00 00 add %al,(%eax)
44: 2c 00 sub $0x0,%al
46: 00 00 add %al,(%eax)
48: 00 41 0e add %al,0xe(%ecx)
4b: 08 85 02 42 0d 05 or %al,0x50d4202(%ebp)
51: 68 c5 0c 04 04 push $0x4040cc5
...
现代x86-64 Linux和Unix使用可执行可链接格式(ELF),
一个典型的ELF可重定位目标文件的格式
.text:已编译程序的机器代码
.rodata:只读数据
.data:已初始化的全局和静态C变量
.bss:未初始化的全局和静态C变量及被初始化为0的全局或静态变量
.symtab:在程序中定义和引用的函数和全局变量的信息
.rel.text:.text节中位置的列表
.rel.data:被模块定义或引用的所有全局变量的重定位信息
.debug:调试符号表
.line:原始c源程序中的行号和.text节中机器指令之间的映射
.strtab:字符串表
可以使用readelf查看一些节的信息,如:
readelf -s a.o
得到.symtab的信息
Symbol table '.symtab' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS a.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000004 4 OBJECT GLOBAL DEFAULT COM time
10: 00000000 20 FUNC GLOBAL DEFAULT 1 foo
11: 00000014 44 FUNC GLOBAL DEFAULT 1 main
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf