ELF文件执行过程中, 重定位和动态链接是两个重要的步骤;
本文原文描述了重定位类型对应的原C程序的语句情景, 和重定位类型指示linker editor和dynamic llinker尤其是前者所做的重定位修正. 可以做为ELF File Format文章的辅助研究文章. 熟悉重定位, 对于了解动态链接有重要的意义; 特别是了解了R_386_GLOB_DAT和R_386_JMP_SLOT两个类型后, 加上PLT和GOT, 动态链接也就有基本轮廓了.
本加评版参考ELF File Format对一些细节做了评注, 增加了R_386_JMP_SLOT重定位类型的描述, 增加了对动态链接的描述, 加上.plt和.got.plt的关系, 动态链接的行为就可以把握了.
为了便于分析, 把原文中分析使用的附件文件内容提前, 小部分内容做了调整.
随着编译器的发展, 编译出的实际的ELF的节区也有了小量改变, 如.rel.plt / .rel.dyn / .got.plt等
一些基础知识, 可以参考经典老牌: <<linker and loaders>>
重定位过程涉及的点:
对目标文件, 绝大部分是根据.rel.text对.text做重定文, 其余还有.data / .rodata / ...等
对可执行文件和共享库文件主要是根据.rel.dyn / .rel.plt对访问.got和.plt的代码做修正, 使对绝对地址符号的引用都集中到.got / .got.plt中, 使GOT执行逻辑之前都是位置无关代码.
原文链接: http://blog.chinaunix.net/uid-725631-id-253156.html
重定位类型分析(1-3, 总结)
重定位目标文件:位置相关 gcc -c 1.c -o 1.o
PIC重定位目标文件:位置无关 gcc -fPIC -c 1.c -o 1.o
静态库文件:多个重定位目标文件的集合 ar c lib.a 1.o 2.o
共享库:动态链接库 ld -shared 1.o -o 1.so
可执行文件:静态链接 gcc 2.o 1.o -o 3 or gcc 2.o lib.a -o 3
可执行文件:动态链接 gcc 2.o 1.so -o 3
重定位分两个步骤
目标文件中的重定位信息,指导ld如何连接时重定位(静态)
可执行文件中的重定位信息,指导/lib/ld-linux.so.2如何执行时重定位(动态)
重定位类型解析(1)
由于是重定位目标文件,所以Offset是相对于节的偏移。.rel.text说明要重定位的节是.text.
找节表,.rel.text节的Info指向1节,即.text.(可发现Addr全0)
Info字段分成两部分,第八位为重定位类型,高24位为符号表索引,据此可找到重定位的符号。这里的符号表是.symtab.
附件1
1.c.txt
[root@proxy ~/3]# cat 1.c
#include <stdio.h>
char *s="hello World!\n";
char *t="abc\n";
void f()
{
printf(s);
}
void g()
{
printf(t);
}
[root@proxy ~/3]# gcc -c 1.c -o 1.o
[root@proxy ~/3]# objdump -dj .text 1.o
1.o: file format elf32-i386
Disassembly of section .text:
00000000 <f>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: 83 ec 0c sub $0xc,%esp
9: ff 35 00 00 00 00 pushl 0x0
f: e8 fc ff ff ff call 10 <f+0x10>
14: 83 c4 10 add $0x10,%esp
17: c9 leave
18: c3 ret
19: 8d 76 00 lea 0x0(%esi),%esi
0000001c <g>:
1c: 55 push %ebp
1d: 89 e5 mov %esp,%ebp
1f: 83 ec 08 sub $0x8,%esp
22: 83 ec 0c sub $0xc,%esp
25: ff 35 00 00 00 00 pushl 0x0
2b: e8 fc ff ff ff call 2c <g+0x10>
30: 83 c4 10 add $0x10,%esp
33: c9 leave
34: c3 ret
35: 8d 76 00 lea 0x0(%esi),%esi
[root@proxy ~/3]# readelf -a 1.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 296 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 12
Section header string table index: 9
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000038 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00040c 000020 08 10 1 4
[ 3] .data PROGBITS 00000000 00006c 000008 00 WA 0 0 4
[ 4] .rel.data REL 00000000 00042c 000010 08 10 3 4
[ 5] .bss NOBITS 00000000 000074 000000 00 WA 0 0 4
[ 6] .note NOTE 00000000 000074 000014 00 0 0 1
[ 7] .rodata PROGBITS 00000000 000088 000013 00 A 0 0 1
[ 8] .comment PROGBITS 00000000 00009b 000036 00 0 0 1
[ 9] .shstrtab STRTAB 00000000 0000d1 000057 00 0 0 1
[10] .symtab SYMTAB 00000000 000308 0000e0 10 11 9 4
[11] .strtab STRTAB 00000000 0003e8 000023 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no program headers in this file.
There is no dynamic segment in this file.
Relocation section '.rel.text' at offset 0x40c contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000b 00901 R_386_32 00000000 s
00000010 00c02 R_386_PC32 00000000 printf
00000027 00a01 R_386_32 00000004 t
0000002c 00c02 R_386_PC32 00000000 printf
Relocation section '.rel.data' at offset 0x42c contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name
00000000 00601 R_386_32 00000000 .rodata
00000004 00601 R_386_32 00000000 .rodata
There are no unwind sections in this file.
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS 1.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 gcc2_compiled.
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 0 SECTION LOCAL DEFAULT 8
9: 00000000 4 OBJECT GLOBAL DEFAULT 3 s
10: 00000004 4 OBJECT GLOBAL DEFAULT 3 t
11: 00000000 25 FUNC GLOBAL DEFAULT 1 f
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
13: 0000001c 25 FUNC GLOBAL DEFAULT 1 g
No version information found in this file.
附件2
3.c.txt
[root@proxy ~/3]# cat 3.c
void f();
int main()
{
f();
g();
return 0;
}
[root@proxy ~/3]# gcc -c 3.c -o 3.o
[root@proxy ~/3]# objdump -dj .text 3.o
3.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: e8 fc ff ff ff call 7 <main+0x7>
b: e8 fc ff ff ff call c <main+0xc>
10: b8 00 00 00 00 mov $0x0,%eax
15: c9 leave
16: c3 ret
17: 90 nop
[root@proxy ~/3]# readelf -a 3.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 220 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 10
Section header string table index: 7
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000018 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00033c 000010 08 8 1 4
[ 3] .data PROGBITS 00000000 00004c 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 00004c 000000 00 WA 0 0 4
[ 5] .note NOTE 00000000 00004c 000014 00 0 0 1
[ 6] .comment PROGBITS 00000000 000060 000036 00 0 0 1
[ 7] .shstrtab STRTAB 00000000 000096 000045 00 0 0 1
[ 8] .symtab SYMTAB 00000000 00026c 0000b0 10 9 8 4
[ 9] .strtab STRTAB 00000000 00031c 00001d 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no program headers in this file.
There is no dynamic segment in this file.
Relocation section '.rel.text' at offset 0x33c contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name
00000007 00902 R_386_PC32 00000000 f
0000000c 00a02 R_386_PC32 00000000 g
There are no unwind sections in this file.
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS 3.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 NOTYPE LOCAL DEFAULT 1 gcc2_compiled.
6: 00000000 0 SECTION LOCAL DEFAULT 5
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 23 FUNC GLOBAL DEFAULT 1 main
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND f
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND g
No version information found in this file.
附件3
4.out.txt
[root@proxy ~/3]# gcc 1.o 3.o -o 4
[root@proxy ~/3]# ./4
hello World!
abc
[root@proxy ~/3]# objdump -dj .text 4
4: file format elf32-i386
Disassembly of section .text:
08048360 <_start>:
8048360: 31 ed xor %ebp,%ebp
8048362: 5e pop %esi
8048363: 89 e1 mov %esp,%ecx
8048365: 83 e4 f0 and $0xfffffff0,%esp
8048368: 50 push %eax
8048369: 54 push %esp
804836a: 52 push %edx
804836b: 68 f0 84 04 08 push $0x80484f0
8048370: 68 e4 82 04 08 push $0x80482e4
8048375: 51 push %ecx
8048376: 56 push %esi
8048377: 68 98 84 04 08 push $0x8048498
804837c: e8 ab ff ff ff call 804832c <_init+0x48>
8048381: f4 hlt
8048382: 89 f6 mov %esi,%esi
08048384 <call_gmon_start>:
8048384: 55 push %ebp
8048385: 89 e5 mov %esp,%ebp
8048387: 53 push %ebx
8048388: 50 push %eax
8048389: e8 00 00 00 00 call 804838e <call_gmon_start+0xa>
804838e: 5b pop %ebx
804838f: 81 c3 ca 11 00 00 add $0x11ca,%ebx
8048395: 8b 83 20 00 00 00 mov 0x20(%ebx),%eax
804839b: 85 c0 test %eax,%eax
804839d: 74 02 je 80483a1 <call_gmon_start+0x1d>
804839f: ff d0 call *%eax
80483a1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80483a4: c9 leave
80483a5: c3 ret
80483a6: 89 f6 mov %esi,%esi
80483a8: 90 nop
80483a9: 90 nop
80483aa: 90 nop
80483ab: 90 nop
80483ac: 90 nop
80483ad: 90 nop
80483ae: 90 nop
80483af: 90 nop
080483b0 <__do_global_dtors_aux>:
80483b0: 55 push %ebp
80483b1: 89 e5 mov %esp,%ebp
80483b3: 83 ec 08 sub $0x8,%esp
80483b6: 8b 15 38 95 04 08 mov 0x8049538,%edx
80483bc: 85 d2 test %edx,%edx
80483be: 75 49 jne 8048409 <__do_global_dtors_aux+0x59>
80483c0: 8b 15 34 95 04 08 mov 0x8049534,%edx
80483c6: 8b 02 mov (%edx),%eax
80483c8: 85 c0 test %eax,%eax
80483ca: 74 1a je 80483e6 <__do_global_dtors_aux+0x36>
80483cc: 8d 74 26 00 lea 0x0(%esi,1),%esi
80483d0: 8d 42 04 lea 0x4(%edx),%eax
80483d3: a3 34 95 04 08 mov %eax,0x8049534
80483d8: ff 12 call *(%edx)
80483da: 8b 15 34 95 04 08 mov 0x8049534,%edx
80483e0: 8b 0a mov (%edx),%ecx
80483e2: 85 c9 test %ecx,%ecx
80483e4: 75 ea jne 80483d0 <__do_global_dtors_aux+0x20>
80483e6: b8 1c 83 04 08 mov $0x804831c,%eax
80483eb: 85 c0 test %eax,%eax
80483ed: 74 10 je 80483ff <__do_global_dtors_aux+0x4f>
80483ef: 83 ec 0c sub $0xc,%esp
80483f2: 68 44 95 04 08 push $0x8049544
80483f7: e8 20 ff ff ff call 804831c <_init+0x38>
80483fc: 83 c4 10 add $0x10,%esp
80483ff: b8 01 00 00 00 mov $0x1,%eax
8048404: a3 38 95 04 08 mov %eax,0x8049538
8048409: 89 ec mov %ebp,%esp
804840b: 5d pop %ebp
804840c: c3 ret
804840d: 8d 76 00 lea 0x0(%esi),%esi
08048410 <fini_dummy>:
8048410: 55 push %ebp
8048411: 89 e5 mov %esp,%ebp
8048413: 83 ec 08 sub $0x8,%esp
8048416: 89 ec mov %ebp,%esp
8048418: 5d pop %ebp
8048419: c3 ret
804841a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
08048420 <frame_dummy>:
8048420: 55 push %ebp
8048421: b8 0c 83 04 08 mov $0x804830c,%eax
8048426: 89 e5 mov %esp,%ebp
8048428: 83 ec 08 sub $0x8,%esp
804842b: 85 c0 test %eax,%eax
804842d: 74 15 je 8048444 <frame_dummy+0x24>
804842f: 83 ec 08 sub $0x8,%esp
8048432: 68 44 96 04 08 push $0x8049644
8048437: 68 44 95 04 08 push $0x8049544
804843c: e8 cb fe ff ff call 804830c <_init+0x28>
8048441: 83 c4 10 add $0x10,%esp
8048444: 89 ec mov %ebp,%esp
8048446: 5d pop %ebp
8048447: c3 ret
8048448: 90 nop
8048449: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi
08048450 <init_dummy>:
8048450: 55 push %ebp
8048451: 89 e5 mov %esp,%ebp
8048453: 83 ec 08 sub $0x8,%esp
8048456: 89 ec mov %ebp,%esp
8048458: 5d pop %ebp
8048459: c3 ret
804845a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
08048460 <f>:
8048460: 55 push %ebp
8048461: 89 e5 mov %esp,%ebp
8048463: 83 ec 08 sub $0x8,%esp
8048466: 83 ec 0c sub $0xc,%esp
8048469: ff 35 3c 95 04 08 pushl 0x804953c
804846f: e8 c8 fe ff ff call 804833c <_init+0x58>
8048474: 83 c4 10 add $0x10,%esp
8048477: c9 leave
8048478: c3 ret
8048479: 8d 76 00 lea 0x0(%esi),%esi
0804847c <g>:
804847c: 55 push %ebp
804847d: 89 e5 mov %esp,%ebp
804847f: 83 ec 08 sub $0x8,%esp
8048482: 83 ec 0c sub $0xc,%esp
8048485: ff 35 40 95 04 08 pushl 0x8049540
804848b: e8 ac fe ff ff call 804833c <_init+0x58>
8048490: 83 c4 10 add $0x10,%esp
8048493: c9 leave
8048494: c3 ret
8048495: 8d 76 00 lea 0x0(%esi),%esi
08048498 <main>:
8048498: 55 push %ebp
8048499: 89 e5 mov %esp,%ebp
804849b: 83 ec 08 sub $0x8,%esp
804849e: e8 bd ff ff ff call 8048460 <f>
80484a3: e8 d4 ff ff ff call 804847c <g>
80484a8: b8 00 00 00 00 mov $0x0,%eax
80484ad: c9 leave
80484ae: c3 ret
80484af: 90 nop
080484b0 <__do_global_ctors_aux>:
80484b0: 55 push %ebp
80484b1: 89 e5 mov %esp,%ebp
80484b3: 53 push %ebx
80484b4: 83 ec 04 sub $0x4,%esp
80484b7: a1 48 95 04 08 mov 0x8049548,%eax
80484bc: bb 48 95 04 08 mov $0x8049548,%ebx
80484c1: 83 f8 ff cmp $0xffffffff,%eax
80484c4: 74 16 je 80484dc <__do_global_ctors_aux+0x2c>
80484c6: 8d 76 00 lea 0x0(%esi),%esi
80484c9: 8d bc 27 00 00 00 00 lea 0x0(%edi,1),%edi
80484d0: 83 eb 04 sub $0x4,%ebx
80484d3: ff d0 call *%eax
80484d5: 8b 03 mov (%ebx),%eax
80484d7: 83 f8 ff cmp $0xffffffff,%eax
80484da: 75 f4 jne 80484d0 <__do_global_ctors_aux+0x20>
80484dc: 58 pop %eax
80484dd: 5b pop %ebx
80484de: 5d pop %ebp
80484df: c3 ret
080484e0 <init_dummy>:
80484e0: 55 push %ebp
80484e1: 89 e5 mov %esp,%ebp
80484e3: 83 ec 08 sub $0x8,%esp
80484e6: 89 ec mov %ebp,%esp
80484e8: 5d pop %ebp
80484e9: c3 ret
80484ea: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
[root@proxy ~/3]# readelf -a 4
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048360
Start of program headers: 52 (bytes into file)
Start of section headers: 10844 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 27
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 080480f4 0000f4 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048108 000108 000020 00 A 0 0 4
[ 3] .hash HASH 08048128 000128 000034 04 A 4 0 4
[ 4] .dynsym DYNSYM 0804815c 00015c 000080 10 A 5 1 4
[ 5] .dynstr STRTAB 080481dc 0001dc 000095 00 A 0 0 1
[ 6] .gnu.version VERSYM 08048272 000272 000010 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 08048284 000284 000030 00 A 5 1 4
[ 8] .rel.dyn REL 080482b4 0002b4 000008 08 A 4 0 4
[ 9] .rel.plt REL 080482bc 0002bc 000028 08 A 4 b 4
[10] .init PROGBITS 080482e4 0002e4 000018 00 AX 0 0 4
[11] .plt PROGBITS 080482fc 0002fc 000060 04 AX 0 0 4
[12] .text PROGBITS 08048360 000360 000190 00 AX 0 0 16
[13] .fini PROGBITS 080484f0 0004f0 00001e 00 AX 0 0 4
[14] .rodata PROGBITS 08048510 000510 00001b 00 A 0 0 4
[15] .data PROGBITS 0804952c 00052c 000018 00 WA 0 0 4
[16] .eh_frame PROGBITS 08049544 000544 000004 00 WA 0 0 4
[17] .ctors PROGBITS 08049548 000548 000008 00 WA 0 0 4
[18] .dtors PROGBITS 08049550 000550 000008 00 WA 0 0 4
[19] .got PROGBITS 08049558 000558 000024 04 WA 0 0 4
[20] .dynamic DYNAMIC 0804957c 00057c 0000c8 08 WA 5 0 4
[21] .sbss PROGBITS 08049644 000644 000000 00 W 0 0 1
[22] .bss NOBITS 08049644 000644 000018 00 WA 0 0 4
[23] .stab PROGBITS 00000000 000644 0007a4 0c 24 0 4
[24] .stabstr STRTAB 00000000 000de8 001983 00 0 0 1
[25] .comment PROGBITS 00000000 00276b 00017a 00 0 0 1
[26] .note NOTE 00000000 0028e5 00008c 00 0 0 1
[27] .shstrtab STRTAB 00000000 002971 0000e9 00 0 0 1
[28] .symtab SYMTAB 00000000 002f0c 000540 10 29 3d 4
[29] .strtab STRTAB 00000000 00344c 000234 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4
INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x0052b 0x0052b R E 0x1000
LOAD 0x00052c 0x0804952c 0x0804952c 0x00118 0x00130 RW 0x1000
DYNAMIC 0x00057c 0x0804957c 0x0804957c 0x000c8 0x000c8 RW 0x4
NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata
03 .data .eh_frame .ctors .dtors .got .dynamic .bss
04 .dynamic
05 .note.ABI-tag
Dynamic segment at offset 0x57c contains 20 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x80482e4
0x0000000d (FINI) 0x80484f0
0x00000004 (HASH) 0x8048128
0x00000005 (STRTAB) 0x80481dc
0x00000006 (SYMTAB) 0x804815c
0x0000000a (STRSZ) 127 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x8049558
0x00000002 (PLTRELSZ) 40 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x80482bc
0x00000011 (REL) 0x80482b4
0x00000012 (RELSZ) 8 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x8048284
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x8048272
0x00000000 (NULL) 0x0
Relocation section '.rel.dyn' at offset 0x2b4 contains 1 entries:
Offset Info Type Symbol's Value Symbol's Name
08049578 00706 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x2bc contains 5 entries:
Offset Info Type Symbol's Value Symbol's Name
08049564 00107 R_386_JUMP_SLOT 0804830c __register_frame_info
08049568 00207 R_386_JUMP_SLOT 0804831c __deregister_frame_info
0804956c 00307 R_386_JUMP_SLOT 0804832c __libc_start_main
08049570 00407 R_386_JUMP_SLOT 0804833c printf
08049574 00507 R_386_JUMP_SLOT 0804834c __cxa_finalize
There are no unwind sections in this file.
Symbol table '.dynsym' contains 8 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 0804830c 129 FUNC WEAK DEFAULT UND __register_frame_info@GLIBC_2.0 (2)
2: 0804831c 172 FUNC WEAK DEFAULT UND __deregister_frame_info@GLIBC_2.0 (2)
3: 0804832c 202 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2)
4: 0804833c 50 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.0 (2)
5: 0804834c 157 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.1.3 (3)
6: 08048514 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
7: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Symbol table '.symtab' contains 84 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 080480f4 0 SECTION LOCAL DEFAULT 1
2: 08048108 0 SECTION LOCAL DEFAULT 2
3: 08048128 0 SECTION LOCAL DEFAULT 3
4: 0804815c 0 SECTION LOCAL DEFAULT 4
5: 080481dc 0 SECTION LOCAL DEFAULT 5
6: 08048272 0 SECTION LOCAL DEFAULT 6
7: 08048284 0 SECTION LOCAL DEFAULT 7
8: 080482b4 0 SECTION LOCAL DEFAULT 8
9: 080482bc 0 SECTION LOCAL DEFAULT 9
10: 080482e4 0 SECTION LOCAL DEFAULT 10
11: 080482fc 0 SECTION LOCAL DEFAULT 11
12: 08048360 0 SECTION LOCAL DEFAULT 12
13: 080484f0 0 SECTION LOCAL DEFAULT 13
14: 08048510 0 SECTION LOCAL DEFAULT 14
15: 0804952c 0 SECTION LOCAL DEFAULT 15
16: 08049544 0 SECTION LOCAL DEFAULT 16
17: 08049548 0 SECTION LOCAL DEFAULT 17
18: 08049550 0 SECTION LOCAL DEFAULT 18
19: 08049558 0 SECTION LOCAL DEFAULT 19
20: 0804957c 0 SECTION LOCAL DEFAULT 20
21: 08049644 0 SECTION LOCAL DEFAULT 21
22: 08049644 0 SECTION LOCAL DEFAULT 22
23: 00000000 0 SECTION LOCAL DEFAULT 23
24: 00000000 0 SECTION LOCAL DEFAULT 24
25: 00000000 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 SECTION LOCAL DEFAULT 26
27: 00000000 0 SECTION LOCAL DEFAULT 27
28: 00000000 0 SECTION LOCAL DEFAULT 28
29: 00000000 0 SECTION LOCAL DEFAULT 29
30: 00000000 0 FILE LOCAL DEFAULT ABS initfini.c
31: 08048384 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
32: 08048384 0 FUNC LOCAL DEFAULT 12 call_gmon_start
33: 00000000 0 FILE LOCAL DEFAULT ABS init.c
34: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
35: 080483b0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
36: 08049534 0 OBJECT LOCAL DEFAULT 15 p.0
37: 08049550 0 OBJECT LOCAL DEFAULT 18 __DTOR_LIST__
38: 08049538 0 OBJECT LOCAL DEFAULT 15 completed.1
39: 080483b0 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
40: 08049544 0 OBJECT LOCAL DEFAULT 16 __EH_FRAME_BEGIN__
41: 08048410 0 FUNC LOCAL DEFAULT 12 fini_dummy
42: 08049644 24 OBJECT LOCAL DEFAULT 22 object.2
43: 08048420 0 FUNC LOCAL DEFAULT 12 frame_dummy
44: 08048450 0 FUNC LOCAL DEFAULT 12 init_dummy
45: 0804953c 0 OBJECT LOCAL DEFAULT 15 force_to_data
46: 08049548 0 OBJECT LOCAL DEFAULT 17 __CTOR_LIST__
47: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
48: 080484b0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
49: 080484b0 0 FUNC LOCAL DEFAULT 12 __do_global_ctors_aux
50: 0804954c 0 OBJECT LOCAL DEFAULT 17 __CTOR_END__
51: 080484e0 0 FUNC LOCAL DEFAULT 12 init_dummy
52: 08049544 0 OBJECT LOCAL DEFAULT 15 force_to_data
53: 08049554 0 OBJECT LOCAL DEFAULT 18 __DTOR_END__
54: 08049544 0 OBJECT LOCAL DEFAULT 16 __FRAME_END__
55: 00000000 0 FILE LOCAL DEFAULT ABS initfini.c
56: 080484f0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
57: 00000000 0 FILE LOCAL DEFAULT ABS 1.c
58: 08048460 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
59: 00000000 0 FILE LOCAL DEFAULT ABS 3.c
60: 08048498 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
61: 08049540 4 OBJECT GLOBAL DEFAULT 15 t
62: 0804957c 0 OBJECT GLOBAL DEFAULT 20 _DYNAMIC
63: 08048460 25 FUNC GLOBAL DEFAULT 12 f
64: 0804830c 129 FUNC WEAK DEFAULT UND __register_frame_info@@GLIBC_2.0
65: 08048510 4 NOTYPE GLOBAL DEFAULT 14 _fp_hw
66: 0804847c 25 FUNC GLOBAL DEFAULT 12 g
67: 080482e4 0 FUNC GLOBAL DEFAULT 10 _init
68: 0804831c 172 FUNC WEAK DEFAULT UND __deregister_frame_info@@GLIBC_2.0
69: 08048360 0 FUNC GLOBAL DEFAULT 12 _start
70: 08049644 0 OBJECT GLOBAL DEFAULT ABS __bss_start
71: 08048498 23 FUNC GLOBAL DEFAULT 12 main
72: 0804832c 202 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.0
73: 0804952c 0 NOTYPE WEAK DEFAULT 15 data_start
74: 0804833c 50 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.0
75: 080484f0 0 FUNC GLOBAL DEFAULT 13 _fini
76: 0804953c 4 OBJECT GLOBAL DEFAULT 15 s
77: 0804834c 157 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.1.3
78: 08049644 0 OBJECT GLOBAL DEFAULT ABS _edata
79: 08049558 0 OBJECT GLOBAL DEFAULT 19 _GLOBAL_OFFSET_TABLE_
80: 0804965c 0 OBJECT GLOBAL DEFAULT ABS _end
81: 08048514 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
82: 0804952c 0 NOTYPE GLOBAL DEFAULT 15 __data_start
83: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Histogram for bucket list length (total of 3 buckets):
Length Number % of total Coverage
0 0 ( 0.0%)
1 1 ( 33.3%) 14.3%
2 0 ( 0.0%) 14.3%
3 2 ( 66.7%) 100.0%
Version symbols section '.gnu.version' contains 8 entries:
Addr: 0000000008048272 Offset: 0x000272 Link: 4 (.dynsym)
000: 0 (*local*) 2 (GLIBC_2.0) 2 (GLIBC_2.0) 2 (GLIBC_2.0)
004: 2 (GLIBC_2.0) 3 (GLIBC_2.1.3) 1 (*global*) 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x0000000008048284 Offset: 0x000284 Link to section: 5 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 2
0x0010: Name: GLIBC_2.1.3 Flags: none Version: 3
0x0020: Name: GLIBC_2.0 Flags: none Version: 2
本节分析开始处:
s变量: 0000000b 00901 R_386_32 00000000 s
可见009在.symtab索引到的项为
9: 00000000 4 OBJECT GLOBAL DEFAULT 3 s
名字为s, st_value值为0,大小为4字节(指针变量),节索引为3,即在.data节中.
t变量: 00000027 00a01 R_386_32 00000004 t
可见00a在.symtab索引到的项为
10: 00000004 4 OBJECT GLOBAL DEFAULT 3 t
名字为t, st_value值为4,大小为4字节(指针变量),节索引为3,即在.data节中.
(还可以发现符号表中f()和g()的大小正好等于其代码长度, 如f大小25,代码长度0~0x18,...)
这里的值指的是该符号在所在的节中的偏移。
[root@proxy ~/3]# objdump -sj .data 1.o
1.o: file format elf32-i386
Contents of section .data:
0000 00000000 0e000000 ........
可见,s指向的值是0,t指向的值是0xe.这就是变量的s和t的值。
实际上,这两个值是指向.rodata节的偏移。
[root@proxy ~/3]# objdump -sj .rodata 1.o
1.o: file format elf32-i386
Contents of section .rodata:
0000 68656c6c 6f20576f 726c6421 0a006162 hello World!..ab
0010 630a00 c..
即s指向hello world! t指向abc; 和程序中的意思一样。
再看看重定位中的偏移Offset.
Relocation section '.rel.text' at offset 0x40c contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000b 00901 R_386_32 00000000 s
00000010 00c02 R_386_PC32 00000000 printf
00000027 00a01 R_386_32 00000004 t
0000002c 00c02 R_386_PC32 00000000 printf
可以在objdump -dj .text 1.o中查找对应的位置
假设现在1.o要和另一个目标文件2.o连接成可执行文件,由于ld要合并相同的节,1.o中符号原来的地址变成无效地址了,因此1.o中的符号必须被重定位
R_386_32重定位方法:.data节被合并到新的地址处,假设为x, 则s的值就修正为x+0, t的值被修正为x+4(此时是地址,而不再是节偏移), 然后把该值写入Offset处
参看3.o调用1.o的f和g
R_386_PC32重定位方法: .text节被合并到新的地址处,假设为y,则f的值被修正为y+0,g的值被修正为y+0x1c. 然后把该值和Offset之差写入Offset处。
因此就不难理解下面的意思了
R_386_NONE 0 none none
R_386_32 1 word32 S + A
R_386_PC32 2 word32 S + A - P
S即修正后的符号值(变量地址),A即Offset处值,P即Offset
[评] =>
从ELF File Format规范Relocation的下面一段中,
It first decides how to combine and locate the input files,
then updates the symbol values, and
finally performs the relocation.
可知所有符号都根据combination做了更新, 最后要做的是对引用符号的受影响的地方做重定位.
S是符号的更新后的相对于ModuleBase的st_value值; A为Addent, 是Offset处的值; P为Offset在section重定位后的地址。
注意,重定位类型为R_386_PC32时, Addent为0xFFFFFFFC, 这是因为相对跳转/调用指令的偏移是相对于跳转/偏移指令的下一条指令, 而Offset是指令的操作数开始, 所以需要减4, Addent为-4. 一般针对i386体系是__x86.get_thunk_pc.bx/cx
最后, s, t, f, g都是模块内的全局符号,非位置无关时重定位后直接得到地址;而printf是其他模块的外部符号,需要dynamic link,所以其call是 call .plt entry,见下节。
重定位类型分析(2)
本节分析R_386_GOTPC, R_386_GOT32, R_386_GLOB_DAT和R_386_PLT32
PIC位置无关代码,使用-fPIC参数就可以编译得到
附件1
1.c.txt
[root@proxy ~/3]# cat 1.c
#include <stdio.h>
char *s="hello World!\n";
char *t="abc\n";
void f()
{
printf(s);
}
void g()
{
printf(t);
}
[root@proxy ~/3]# gcc -fPIC -S 1.c
[root@proxy ~/3]# cat 1.s
.file "1.c"
.version "01.01"
gcc2_compiled.:
.globl s
.section .rodata
.LC0:
.string "hello World!\n"
.data
.align 4
.type s,@object
.size s,4
s:
.long .LC0
.globl t
.section .rodata
.LC1:
.string "abc\n"
.data
.align 4
.type t,@object
.size t,4
t:
.long .LC1
.text
.align 4
.globl f
.type f,@function
f:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $4, %esp
call .L3
.L3:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L3], %ebx
subl $12, %esp
movl s@GOT(%ebx), %eax
pushl (%eax)
call printf@PLT
addl $16, %esp
movl -4(%ebp), %ebx
leave
ret
.Lfe1:
.size f,.Lfe1-f
.align 4
.globl g
.type g,@function
g:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $4, %esp
call .L5
.L5:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L5], %ebx
subl $12, %esp
movl t@GOT(%ebx), %eax
pushl (%eax)
call printf@PLT
addl $16, %esp
movl -4(%ebp), %ebx
leave
ret
.Lfe2:
.size g,.Lfe2-g
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-98)"
[评]=>由于编译器的发展,汇编代码已经不再是大部分文章描述时的样子
xp010548@cnbjlx6066:~/test_elf$ cat 1.s
.file "1.c"
.globl s
.section .rodata
.LC0:
.string "hello World!\n"
.section .data.rel.local,"aw",@progbits
.align 8
.type s, @object
.size s, 8
s:
.quad .LC0
.globl t
.section .rodata
.LC1:
.string "abc\n"
.section .data.rel.local
.align 8
.type t, @object
.size t, 8
t:
.quad .LC1
.text
.globl f
.type f, @function
f:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movq s@GOTPCREL(%rip), %rax
movq (%rax), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
leave
ret
.cfi_endproc
.LFE0:
.size f, .-f
.globl g
.type g, @function
g:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movq t@GOTPCREL(%rip), %rax
movq (%rax), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
leave
ret
.cfi_endproc
.LFE1:
.size g, .-g
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3"
.section .note.GNU-stack,"",@progbits
[root@proxy ~/3]# gcc -fPIC -c 1.c -o 1.o
[root@proxy ~/3]# objdump -dj .text 1.o
1.o: file format elf32-i386
Disassembly of section .text:
00000000 <f>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 53 push %ebx
4: 83 ec 04 sub $0x4,%esp
7: e8 00 00 00 00 call c <f+0xc>
c: 5b pop %ebx
d: 81 c3 03 00 00 00 add $0x3,%ebx
13: 83 ec 0c sub $0xc,%esp
16: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax
1c: ff 30 pushl (%eax)
1e: e8 fc ff ff ff call 1f <f+0x1f>
23: 83 c4 10 add $0x10,%esp
26: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
29: c9 leave
2a: c3 ret
2b: 90 nop
0000002c <g>:
2c: 55 push %ebp
2d: 89 e5 mov %esp,%ebp
2f: 53 push %ebx
30: 83 ec 04 sub $0x4,%esp
33: e8 00 00 00 00 call 38 <g+0xc>
38: 5b pop %ebx
39: 81 c3 03 00 00 00 add $0x3,%ebx
3f: 83 ec 0c sub $0xc,%esp
42: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax
48: ff 30 pushl (%eax)
4a: e8 fc ff ff ff call 4b <g+0x1f>
4f: 83 c4 10 add $0x10,%esp
52: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
55: c9 leave
56: c3 ret
57: 90 nop
[root@proxy ~/3]# readelf -a 1.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 328 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 12
Section header string table index: 9
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000058 00 AX 0 0 4
[ 2] .rel.text REL 00000000 000454 000030 08 10 1 4
[ 3] .data PROGBITS 00000000 00008c 000008 00 WA 0 0 4
[ 4] .rel.data REL 00000000 000484 000010 08 10 3 4
[ 5] .bss NOBITS 00000000 000094 000000 00 WA 0 0 4
[ 6] .note NOTE 00000000 000094 000014 00 0 0 1
[ 7] .rodata PROGBITS 00000000 0000a8 000013 00 A 0 0 1
[ 8] .comment PROGBITS 00000000 0000bb 000036 00 0 0 1
[ 9] .shstrtab STRTAB 00000000 0000f1 000057 00 0 0 1
[10] .symtab SYMTAB 00000000 000328 0000f0 10 11 9 4
[11] .strtab STRTAB 00000000 000418 000039 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no program headers in this file.
There is no dynamic segment in this file.
Relocation section '.rel.text' at offset 0x454 contains 6 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000f 00c0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
00000018 00903 R_386_GOT32 00000000 s
0000001f 00d04 R_386_PLT32 00000000 printf
0000003b 00c0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
00000044 00a03 R_386_GOT32 00000004 t
0000004b 00d04 R_386_PLT32 00000000 printf
Relocation section '.rel.data' at offset 0x484 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name
00000000 00601 R_386_32 00000000 .rodata
00000004 00601 R_386_32 00000000 .rodata
There are no unwind sections in this file.
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS 1.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 gcc2_compiled.
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 0 SECTION LOCAL DEFAULT 8
9: 00000000 4 OBJECT GLOBAL DEFAULT 3 s
10: 00000004 4 OBJECT GLOBAL DEFAULT 3 t
11: 00000000 43 FUNC GLOBAL DEFAULT 1 f
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
13: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
14: 0000002c 43 FUNC GLOBAL DEFAULT 1 g
No version information found in this file.
附件2
4.out.txt
[root@proxy ~/3]# gcc 1.o 3.o -o 4
[root@proxy ~/3]# ./4
hello World!
abc
[root@proxy ~/3]# objdump -dj .text 4
4: file format elf32-i386
Disassembly of section .text:
080483a0 <_start>:
80483a0: 31 ed xor %ebp,%ebp
80483a2: 5e pop %esi
80483a3: 89 e1 mov %esp,%ecx
80483a5: 83 e4 f0 and $0xfffffff0,%esp
80483a8: 50 push %eax
80483a9: 54 push %esp
80483aa: 52 push %edx
80483ab: 68 50 85 04 08 push $0x8048550
80483b0: 68 24 83 04 08 push $0x8048324
80483b5: 51 push %ecx
80483b6: 56 push %esi
80483b7: 68 f8 84 04 08 push $0x80484f8
80483bc: e8 ab ff ff ff call 804836c <_init+0x48>
80483c1: f4 hlt
80483c2: 89 f6 mov %esi,%esi
080483c4 <call_gmon_start>:
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 53 push %ebx
80483c8: 50 push %eax
80483c9: e8 00 00 00 00 call 80483ce <call_gmon_start+0xa>
80483ce: 5b pop %ebx
80483cf: 81 c3 ea 11 00 00 add $0x11ea,%ebx
80483d5: 8b 83 28 00 00 00 mov 0x28(%ebx),%eax
80483db: 85 c0 test %eax,%eax
80483dd: 74 02 je 80483e1 <call_gmon_start+0x1d>
80483df: ff d0 call *%eax
80483e1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80483e4: c9 leave
80483e5: c3 ret
80483e6: 89 f6 mov %esi,%esi
80483e8: 90 nop
80483e9: 90 nop
80483ea: 90 nop
80483eb: 90 nop
80483ec: 90 nop
80483ed: 90 nop
80483ee: 90 nop
80483ef: 90 nop
080483f0 <__do_global_dtors_aux>:
80483f0: 55 push %ebp
80483f1: 89 e5 mov %esp,%ebp
80483f3: 83 ec 08 sub $0x8,%esp
80483f6: 8b 15 98 95 04 08 mov 0x8049598,%edx
80483fc: 85 d2 test %edx,%edx
80483fe: 75 49 jne 8048449 <__do_global_dtors_aux+0x59>
8048400: 8b 15 94 95 04 08 mov 0x8049594,%edx
8048406: 8b 02 mov (%edx),%eax
8048408: 85 c0 test %eax,%eax
804840a: 74 1a je 8048426 <__do_global_dtors_aux+0x36>
804840c: 8d 74 26 00 lea 0x0(%esi,1),%esi
8048410: 8d 42 04 lea 0x4(%edx),%eax
8048413: a3 94 95 04 08 mov %eax,0x8049594
8048418: ff 12 call *(%edx)
804841a: 8b 15 94 95 04 08 mov 0x8049594,%edx
8048420: 8b 0a mov (%edx),%ecx
8048422: 85 c9 test %ecx,%ecx
8048424: 75 ea jne 8048410 <__do_global_dtors_aux+0x20>
8048426: b8 5c 83 04 08 mov $0x804835c,%eax
804842b: 85 c0 test %eax,%eax
804842d: 74 10 je 804843f <__do_global_dtors_aux+0x4f>
804842f: 83 ec 0c sub $0xc,%esp
8048432: 68 a4 95 04 08 push $0x80495a4
8048437: e8 20 ff ff ff call 804835c <_init+0x38>
804843c: 83 c4 10 add $0x10,%esp
804843f: b8 01 00 00 00 mov $0x1,%eax
8048444: a3 98 95 04 08 mov %eax,0x8049598
8048449: 89 ec mov %ebp,%esp
804844b: 5d pop %ebp
804844c: c3 ret
804844d: 8d 76 00 lea 0x0(%esi),%esi
08048450 <fini_dummy>:
8048450: 55 push %ebp
8048451: 89 e5 mov %esp,%ebp
8048453: 83 ec 08 sub $0x8,%esp
8048456: 89 ec mov %ebp,%esp
8048458: 5d pop %ebp
8048459: c3 ret
804845a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
08048460 <frame_dummy>:
8048460: 55 push %ebp
8048461: b8 4c 83 04 08 mov $0x804834c,%eax
8048466: 89 e5 mov %esp,%ebp
8048468: 83 ec 08 sub $0x8,%esp
804846b: 85 c0 test %eax,%eax
804846d: 74 15 je 8048484 <frame_dummy+0x24>
804846f: 83 ec 08 sub $0x8,%esp
8048472: 68 ac 96 04 08 push $0x80496ac
8048477: 68 a4 95 04 08 push $0x80495a4
804847c: e8 cb fe ff ff call 804834c <_init+0x28>
8048481: 83 c4 10 add $0x10,%esp
8048484: 89 ec mov %ebp,%esp
8048486: 5d pop %ebp
8048487: c3 ret
8048488: 90 nop
8048489: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi
08048490 <init_dummy>:
8048490: 55 push %ebp
8048491: 89 e5 mov %esp,%ebp
8048493: 83 ec 08 sub $0x8,%esp
8048496: 89 ec mov %ebp,%esp
8048498: 5d pop %ebp
8048499: c3 ret
804849a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
080484a0 <f>:
80484a0: 55 push %ebp
80484a1: 89 e5 mov %esp,%ebp
80484a3: 53 push %ebx
80484a4: 83 ec 04 sub $0x4,%esp
80484a7: e8 00 00 00 00 call 80484ac <f+0xc>
80484ac: 5b pop %ebx
80484ad: 81 c3 0c 11 00 00 add $0x110c,%ebx
80484b3: 83 ec 0c sub $0xc,%esp
80484b6: 8b 83 24 00 00 00 mov 0x24(%ebx),%eax
80484bc: ff 30 pushl (%eax)
80484be: e8 b9 fe ff ff call 804837c <_init+0x58>
80484c3: 83 c4 10 add $0x10,%esp
80484c6: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80484c9: c9 leave
80484ca: c3 ret
80484cb: 90 nop
080484cc <g>:
80484cc: 55 push %ebp
80484cd: 89 e5 mov %esp,%ebp
80484cf: 53 push %ebx
80484d0: 83 ec 04 sub $0x4,%esp
80484d3: e8 00 00 00 00 call 80484d8 <g+0xc>
80484d8: 5b pop %ebx
80484d9: 81 c3 e0 10 00 00 add $0x10e0,%ebx
80484df: 83 ec 0c sub $0xc,%esp
80484e2: 8b 83 20 00 00 00 mov 0x20(%ebx),%eax
80484e8: ff 30 pushl (%eax)
80484ea: e8 8d fe ff ff call 804837c <_init+0x58>
80484ef: 83 c4 10 add $0x10,%esp
80484f2: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80484f5: c9 leave
80484f6: c3 ret
80484f7: 90 nop
080484f8 <main>:
80484f8: 55 push %ebp
80484f9: 89 e5 mov %esp,%ebp
80484fb: 83 ec 08 sub $0x8,%esp
80484fe: e8 9d ff ff ff call 80484a0 <f>
8048503: e8 c4 ff ff ff call 80484cc <g>
8048508: b8 00 00 00 00 mov $0x0,%eax
804850d: c9 leave
804850e: c3 ret
804850f: 90 nop
08048510 <__do_global_ctors_aux>:
8048510: 55 push %ebp
8048511: 89 e5 mov %esp,%ebp
8048513: 53 push %ebx
8048514: 83 ec 04 sub $0x4,%esp
8048517: a1 a8 95 04 08 mov 0x80495a8,%eax
804851c: bb a8 95 04 08 mov $0x80495a8,%ebx
8048521: 83 f8 ff cmp $0xffffffff,%eax
8048524: 74 16 je 804853c <__do_global_ctors_aux+0x2c>
8048526: 8d 76 00 lea 0x0(%esi),%esi
8048529: 8d bc 27 00 00 00 00 lea 0x0(%edi,1),%edi
8048530: 83 eb 04 sub $0x4,%ebx
8048533: ff d0 call *%eax
8048535: 8b 03 mov (%ebx),%eax
8048537: 83 f8 ff cmp $0xffffffff,%eax
804853a: 75 f4 jne 8048530 <__do_global_ctors_aux+0x20>
804853c: 58 pop %eax
804853d: 5b pop %ebx
804853e: 5d pop %ebp
804853f: c3 ret
08048540 <init_dummy>:
8048540: 55 push %ebp
8048541: 89 e5 mov %esp,%ebp
8048543: 83 ec 08 sub $0x8,%esp
8048546: 89 ec mov %ebp,%esp
8048548: 5d pop %ebp
8048549: c3 ret
804854a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
[root@proxy ~/3]# readelf -a 4
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x80483a0
Start of program headers: 52 (bytes into file)
Start of section headers: 10948 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 27
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 080480f4 0000f4 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048108 000108 000020 00 A 0 0 4
[ 3] .hash HASH 08048128 000128 00003c 04 A 4 0 4
[ 4] .dynsym DYNSYM 08048164 000164 0000a0 10 A 5 1 4
[ 5] .dynstr STRTAB 08048204 000204 000099 00 A 0 0 1
[ 6] .gnu.version VERSYM 0804829e 00029e 000014 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 080482b4 0002b4 000030 00 A 5 1 4
[ 8] .rel.dyn REL 080482e4 0002e4 000018 08 A 4 0 4
[ 9] .rel.plt REL 080482fc 0002fc 000028 08 A 4 b 4
[10] .init PROGBITS 08048324 000324 000018 00 AX 0 0 4
[11] .plt PROGBITS 0804833c 00033c 000060 04 AX 0 0 4
[12] .text PROGBITS 080483a0 0003a0 0001b0 00 AX 0 0 16
[13] .fini PROGBITS 08048550 000550 00001e 00 AX 0 0 4
[14] .rodata PROGBITS 08048570 000570 00001b 00 A 0 0 4
[15] .data PROGBITS 0804958c 00058c 000018 00 WA 0 0 4
[16] .eh_frame PROGBITS 080495a4 0005a4 000004 00 WA 0 0 4
[17] .ctors PROGBITS 080495a8 0005a8 000008 00 WA 0 0 4
[18] .dtors PROGBITS 080495b0 0005b0 000008 00 WA 0 0 4
[19] .got PROGBITS 080495b8 0005b8 00002c 04 WA 0 0 4
[20] .dynamic DYNAMIC 080495e4 0005e4 0000c8 08 WA 5 0 4
[21] .sbss PROGBITS 080496ac 0006ac 000000 00 W 0 0 1
[22] .bss NOBITS 080496ac 0006ac 000018 00 WA 0 0 4
[23] .stab PROGBITS 00000000 0006ac 0007a4 0c 24 0 4
[24] .stabstr STRTAB 00000000 000e50 001983 00 0 0 1
[25] .comment PROGBITS 00000000 0027d3 00017a 00 0 0 1
[26] .note NOTE 00000000 00294d 00008c 00 0 0 1
[27] .shstrtab STRTAB 00000000 0029d9 0000e9 00 0 0 1
[28] .symtab SYMTAB 00000000 002f74 000540 10 29 3d 4
[29] .strtab STRTAB 00000000 0034b4 000234 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4
INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x0058b 0x0058b R E 0x1000
LOAD 0x00058c 0x0804958c 0x0804958c 0x00120 0x00138 RW 0x1000
DYNAMIC 0x0005e4 0x080495e4 0x080495e4 0x000c8 0x000c8 RW 0x4
NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata
03 .data .eh_frame .ctors .dtors .got .dynamic .bss
04 .dynamic
05 .note.ABI-tag
Dynamic segment at offset 0x5e4 contains 20 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048324
0x0000000d (FINI) 0x8048550
0x00000004 (HASH) 0x8048128
0x00000005 (STRTAB) 0x8048204
0x00000006 (SYMTAB) 0x8048164
0x0000000a (STRSZ) 131 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x80495b8
0x00000002 (PLTRELSZ) 40 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x80482fc
0x00000011 (REL) 0x80482e4
0x00000012 (RELSZ) 24 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x80482b4
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x804829e
0x00000000 (NULL) 0x0
Relocation section '.rel.dyn' at offset 0x2e4 contains 3 entries:
Offset Info Type Symbol's Value Symbol's Name
080495d8 00106 R_386_GLOB_DAT 080495a0 t
080495dc 00606 R_386_GLOB_DAT 0804959c s
080495e0 00906 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x2fc contains 5 entries:
Offset Info Type Symbol's Value Symbol's Name
080495c4 00207 R_386_JUMP_SLOT 0804834c __register_frame_info
080495c8 00307 R_386_JUMP_SLOT 0804835c __deregister_frame_info
080495cc 00407 R_386_JUMP_SLOT 0804836c __libc_start_main
080495d0 00507 R_386_JUMP_SLOT 0804837c printf
080495d4 00707 R_386_JUMP_SLOT 0804838c __cxa_finalize
There are no unwind sections in this file.
Symbol table '.dynsym' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 080495a0 4 OBJECT GLOBAL DEFAULT 15 t
2: 0804834c 129 FUNC WEAK DEFAULT UND __register_frame_info@GLIBC_2.0 (2)
3: 0804835c 172 FUNC WEAK DEFAULT UND __deregister_frame_info@GLIBC_2.0 (2)
4: 0804836c 202 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2)
5: 0804837c 50 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.0 (2)
6: 0804959c 4 OBJECT GLOBAL DEFAULT 15 s
7: 0804838c 157 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.1.3 (3)
8: 08048574 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
9: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Symbol table '.symtab' contains 84 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 080480f4 0 SECTION LOCAL DEFAULT 1
2: 08048108 0 SECTION LOCAL DEFAULT 2
3: 08048128 0 SECTION LOCAL DEFAULT 3
4: 08048164 0 SECTION LOCAL DEFAULT 4
5: 08048204 0 SECTION LOCAL DEFAULT 5
6: 0804829e 0 SECTION LOCAL DEFAULT 6
7: 080482b4 0 SECTION LOCAL DEFAULT 7
8: 080482e4 0 SECTION LOCAL DEFAULT 8
9: 080482fc 0 SECTION LOCAL DEFAULT 9
10: 08048324 0 SECTION LOCAL DEFAULT 10
11: 0804833c 0 SECTION LOCAL DEFAULT 11
12: 080483a0 0 SECTION LOCAL DEFAULT 12
13: 08048550 0 SECTION LOCAL DEFAULT 13
14: 08048570 0 SECTION LOCAL DEFAULT 14
15: 0804958c 0 SECTION LOCAL DEFAULT 15
16: 080495a4 0 SECTION LOCAL DEFAULT 16
17: 080495a8 0 SECTION LOCAL DEFAULT 17
18: 080495b0 0 SECTION LOCAL DEFAULT 18
19: 080495b8 0 SECTION LOCAL DEFAULT 19
20: 080495e4 0 SECTION LOCAL DEFAULT 20
21: 080496ac 0 SECTION LOCAL DEFAULT 21
22: 080496ac 0 SECTION LOCAL DEFAULT 22
23: 00000000 0 SECTION LOCAL DEFAULT 23
24: 00000000 0 SECTION LOCAL DEFAULT 24
25: 00000000 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 SECTION LOCAL DEFAULT 26
27: 00000000 0 SECTION LOCAL DEFAULT 27
28: 00000000 0 SECTION LOCAL DEFAULT 28
29: 00000000 0 SECTION LOCAL DEFAULT 29
30: 00000000 0 FILE LOCAL DEFAULT ABS initfini.c
31: 080483c4 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
32: 080483c4 0 FUNC LOCAL DEFAULT 12 call_gmon_start
33: 00000000 0 FILE LOCAL DEFAULT ABS init.c
34: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
35: 080483f0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
36: 08049594 0 OBJECT LOCAL DEFAULT 15 p.0
37: 080495b0 0 OBJECT LOCAL DEFAULT 18 __DTOR_LIST__
38: 08049598 0 OBJECT LOCAL DEFAULT 15 completed.1
39: 080483f0 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
40: 080495a4 0 OBJECT LOCAL DEFAULT 16 __EH_FRAME_BEGIN__
41: 08048450 0 FUNC LOCAL DEFAULT 12 fini_dummy
42: 080496ac 24 OBJECT LOCAL DEFAULT 22 object.2
43: 08048460 0 FUNC LOCAL DEFAULT 12 frame_dummy
44: 08048490 0 FUNC LOCAL DEFAULT 12 init_dummy
45: 0804959c 0 OBJECT LOCAL DEFAULT 15 force_to_data
46: 080495a8 0 OBJECT LOCAL DEFAULT 17 __CTOR_LIST__
47: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
48: 08048510 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
49: 08048510 0 FUNC LOCAL DEFAULT 12 __do_global_ctors_aux
50: 080495ac 0 OBJECT LOCAL DEFAULT 17 __CTOR_END__
51: 08048540 0 FUNC LOCAL DEFAULT 12 init_dummy
52: 080495a4 0 OBJECT LOCAL DEFAULT 15 force_to_data
53: 080495b4 0 OBJECT LOCAL DEFAULT 18 __DTOR_END__
54: 080495a4 0 OBJECT LOCAL DEFAULT 16 __FRAME_END__
55: 00000000 0 FILE LOCAL DEFAULT ABS initfini.c
56: 08048550 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
57: 00000000 0 FILE LOCAL DEFAULT ABS 1.c
58: 080484a0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
59: 00000000 0 FILE LOCAL DEFAULT ABS 3.c
60: 080484f8 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
61: 080495a0 4 OBJECT GLOBAL DEFAULT 15 t
62: 080495e4 0 OBJECT GLOBAL DEFAULT 20 _DYNAMIC
63: 080484a0 43 FUNC GLOBAL DEFAULT 12 f
64: 0804834c 129 FUNC WEAK DEFAULT UND __register_frame_info@@GLIBC_2.0
65: 08048570 4 NOTYPE GLOBAL DEFAULT 14 _fp_hw
66: 080484cc 43 FUNC GLOBAL DEFAULT 12 g
67: 08048324 0 FUNC GLOBAL DEFAULT 10 _init
68: 0804835c 172 FUNC WEAK DEFAULT UND __deregister_frame_info@@GLIBC_2.0
69: 080483a0 0 FUNC GLOBAL DEFAULT 12 _start
70: 080496ac 0 OBJECT GLOBAL DEFAULT ABS __bss_start
71: 080484f8 23 FUNC GLOBAL DEFAULT 12 main
72: 0804836c 202 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.0
73: 0804958c 0 NOTYPE WEAK DEFAULT 15 data_start
74: 0804837c 50 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.0
75: 08048550 0 FUNC GLOBAL DEFAULT 13 _fini
76: 0804959c 4 OBJECT GLOBAL DEFAULT 15 s
77: 0804838c 157 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.1.3
78: 080496ac 0 OBJECT GLOBAL DEFAULT ABS _edata
79: 080495b8 0 OBJECT GLOBAL DEFAULT 19 _GLOBAL_OFFSET_TABLE_
80: 080496c4 0 OBJECT GLOBAL DEFAULT ABS _end
81: 08048574 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
82: 0804958c 0 NOTYPE GLOBAL DEFAULT 15 __data_start
83: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Histogram for bucket list length (total of 3 buckets):
Length Number % of total Coverage
0 0 ( 0.0%)
1 1 ( 33.3%) 11.1%
2 0 ( 0.0%) 11.1%
3 0 ( 0.0%) 11.1%
4 2 ( 66.7%) 100.0%
Version symbols section '.gnu.version' contains 10 entries:
Addr: 000000000804829e Offset: 0x00029e Link: 4 (.dynsym)
000: 0 (*local*) 1 (*global*) 2 (GLIBC_2.0) 2 (GLIBC_2.0)
004: 2 (GLIBC_2.0) 2 (GLIBC_2.0) 1 (*global*) 3 (GLIBC_2.1.3)
008: 1 (*global*) 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x00000000080482b4 Offset: 0x0002b4 Link to section: 5 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 2
0x0010: Name: GLIBC_2.1.3 Flags: none Version: 3
0x0020: Name: GLIBC_2.0 Flags: none Version: 2
本节分析开始处:
R_386_GOTPC
[评]=>通常是_GLOBAL_OFFSET_TABLE_.
看看第一个重定位符号的重定位信息(此处是引用s@GOT的汇编指令)
在汇编源文件中:
call .L3 //.L3地址压栈
.L3:
popl %ebx //.L3地址弹到ebx中
addl $_GLOBAL_OFFSET_TABLE_+[.-.L3], %ebx //计算got的地址到ebx中
subl $12, %esp
movl s@GOT(%ebx), %eax
[评]=>
在此处直接解释这段汇编代码的意义, 列在此处,后面能更方便说明原文的错误.
首先call/popl组合是得到运行时.L3标号的PC值, 这是自定位程序典型的汇编代码使用技巧;
而[.-.L3]是编译时当前指令和.L3的偏移, 此处是popl指令的长度,为1;
$_GLOBAL_OFFSET_TABLE_符号的意义是当前指令到GOT表的偏移, 此处是addl指令到GOT的偏移, 生成目标文件时没有GOT, 这个是需要链接时才能确定的;
所以$_GLOBAL_OFFSET_TABLE_加上[.-.L3]构成[.L3]即popl指令到GOT的偏移, 而加上运行时[.L3]的PC即得到运行时GOT的地址.
在目标文件中:
7: e8 00 00 00 00 call c <f+0xc>
c: 5b pop %ebx
d: 81 c3 03 00 00 00 add $0x3, %ebx
13: 83 ec 0c sub $0xc,%esp
16: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax
[评]=>
此处add指令中的3是重定位时的Addent, 当然并不是[.-.L3], 而是重定位Offset运行时的地址与%ebx的偏差, 是编译器做为Addent记录在这儿, 并不是编译时$_GLOBAL_OFFSET_TABLE_+[.-.L3]的值, 因为编译目标文件时还没有GOT, $_GLOBAL_OFFSET_TABLE_符号还根本没有意义. 此处先解释到这个程度.
.rel.text中的项:
0000000f 00c0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
在链接生成的可执行文件中:
查看ld后的结果4.out.txt中的.got section, got地址是080495b8
[19] .got PROGBITS 080495b8 0005b8 00002c 04 WA 0 0 4
80484a7: e8 00 00 00 00 call 80484ac <f+0xc>
80484ac: 5b pop %ebx ; ebx<=0x80484ac
80484ad: 81 c3 0c 11 00 00 add $0x110c,%ebx ; ebx为got地址
80484b3: 83 ec 0c sub $0xc,%esp
80484b6: 8b 83 24 00 00 00 mov 0x24(%ebx),%eax
80484bc: ff 30 pushl (%eax)
执行pop %ebx,ebx中的值为80484ac
执行add $0x110c,%ebx后,ebx中的值是80495B8,正是got的地址
那么0x110c是怎么来的呢?
0x110c-3=0x1109,修正处的偏移是0x80484af,0x80484af+0x1109=0x80495b8,正是.got地址(0x80495b8) 所以0x110c=0x80495b8-0x0x80484af+3,即修正值为got-Offset+[.-.L3].
因此R_386_GOTPC的重定位方法是:
指示连接器将GOT的地址和Offset的差加上原值写入Offset处。
前面的[.-.L3]=3,即5b 81 c3这几个字节的长度,因此[.-.L3]代表指令中操作数所在地址和.L3差值,而一般的.代表指令的地址.
[评]=>
上面的一段中是有错误的, 首先(.-.L3)的值是1而不是3! 在汇编中,‘.’总是指当前汇编指令的PC值, 而绝对不会是操作数的偏移.
上面中描述中0x110c=0x80495b8-0x0x80484af+3和指示连接器将GOT的地址和Offset的差加上原值写入Offset处, 是正确的; 但是其余的却不对. 正确的对于重定位类型为R_386_GOTPC的修正是GOT+A-P; 其中GOT为GOT基址, A为Addent, P为Offset偏移.
此处使用Addent和Offset可以精确地得到[.L3]的地址, 而将Addent由编译器记录在Offset处, 链接时直接使用而不需要再繁琐地根据不同指令不同指令操作码长度进行修正, 比如leal $_GLOBAL_OFFSET_TABLE_+[.-.L3], %eax指令的操作码可能是1字节, 那么此时Addent就是2, 这样就避免了链接时查看指令, 而链接时需要查看指令不仅仅是没有效率, 在非执行时查看指令的设计(调试器除外)是相当拙劣的!
R_386_GOT32和R_386_GLOB_DAT
R_386_GOT32 This relocation type computes the distance from the base of the global offset table to the symbol’s global offset table entry. It additionally instructs the link editor to build a global offset table.
在目标文件中:
movl s@GOT(%ebx), %eax
pushl (%eax)
16: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax
1c: ff 30 pushl (%eax)
.rel.text项
00000018 00903 R_386_GOT32 00000000 s
查看ld后的结果4.out.txt中
80484b6: 8b 83 24 00 00 00 mov 0x24(%ebx),%eax
80484bc: ff 30 pushl (%eax)
got+0x24=0x80495DC
[评]=>
使用GOT访问全局符号; 这样, 在访问GOT之前的代码都是位置无关的代码! 无需再多言.
[root@proxy ~/3]# objdump -sj .got 4
4: file format elf32-i386
Contents of section .got:
80495b8 e4950408 00000000 00000000 52830408 ............R...
80495c8 62830408 72830408 82830408 92830408 b...r...........
80495d8 00000000 00000000 00000000 ............
可见该地址在got中(即GOT+s@GOT),这里该地址的值为全0. 关于R_386_GOT32就此结束
下面看R_386_GLOB_DAT.
查看4.out.txt的重定位节(exe/out和so文件中只有.rel.dyn和.rel.plt了).
.rel.dyn项:
080495dc 00606 R_386_GLOB_DAT 0804959c s
重定位P处(r_offset计算出)0x080495dc(即GOT+s@GOT)处的值为0x0804959c(即为变量s的地址), 应该在.data中.
[评]=>
此项为.rel.got项, 较新的编译器中已经没有了.rel.got节区,对于全局变量的放在了.rel.dyn中; 对于函数的放在了.rel.plt中.
[评]=>
注意此时针对数据的重定位类型为R_386_GLOB_DAT的项, 在可执行文件或共享库文件中, 是在.rel.dyn中; 与针对函数的重定位的R_386_JUMP_SLOT对比看.
ELF File Format中, 针对R_386_GLOB_DAT重定位项计算方法是S, 即Symbol地址直接写入GOT.
下面与R_386_GLOB_DAT无关了, 即与变量的引用无关了; 再多追踪一点变量的值.
[root@proxy ~/3]# objdump -sj .data 4
4: file format elf32-i386
Contents of section .data:
804958c 00000000 00000000 b4950408 00000000 ................
804959c 78850408 86850408 x.......
值为08045878, 即为变量s的值,应该指向.rodata
[root@proxy ~/3]# objdump -sj .rodata 4
4: file format elf32-i386
Contents of section .rodata:
8048570 03000000 01000200 68656c6c 6f20576f ........hello Wo
8048580 726c6421 0a006162 630a00 rld!..abc..
果然, 08045878处的值就是字符串hello world!
因此
R_386_GOT32的重定位方法是: 指示连接器将符号在GOT中的地址和GOT的地址差值写入Offset处。
R_386_GLOB_DAT的重定位方法是: 指示连接器将符号的值写入Offset处。
[评]=>
此处是分两个阶段的, 更精确地说:
R_386_GOT32是指示link editor将符号在GOT中的地址和GOT的地址差值写入Offset处。
R_386_GLOB_DAT是指示dynamic linker动态解析变量符号的地址写入Offset处, 该Offset处为变量对应的GOT项处。
R_386_PLT32
R_386_PLT32 This relocation type computes the address of the symbol’s procedure linkage table entry and additionally instructs the link editor to build a procedure linkage table.
在目标文件中:
call printf@PLT
1e: e8 fc ff ff ff call 1f <f+0x1f>
.rel.text项:
0000001f 00d04 R_386_PLT32 00000000 printf
在可执行文件中, 查看4.out.txt
80484be: e8 b9 fe ff ff call 804837c <_init+0x58>
填入的值是0xfffffeb9,相对跳转,为0x804837c处,在.plt节中
[root@proxy ~/3]# objdump -dj .plt 4
4: file format elf32-i386
Disassembly of section .plt:
0804833c <.plt>:
804833c: ff 35 bc 95 04 08 pushl 0x80495bc
8048342: ff 25 c0 95 04 08 jmp *0x80495c0
8048348: 00 00 add %al,(%eax)
804834a: 00 00 add %al,(%eax)
804834c: ff 25 c4 95 04 08 jmp *0x80495c4
8048352: 68 00 00 00 00 push $0x0
8048357: e9 e0 ff ff ff jmp 804833c <_init+0x18>
804835c: ff 25 c8 95 04 08 jmp *0x80495c8
8048362: 68 08 00 00 00 push $0x8
8048367: e9 d0 ff ff ff jmp 804833c <_init+0x18>
804836c: ff 25 cc 95 04 08 jmp *0x80495cc
8048372: 68 10 00 00 00 push $0x10
8048377: e9 c0 ff ff ff jmp 804833c <_init+0x18>
804837c: ff 25 d0 95 04 08 jmp *0x80495d0 //<<指向这里
8048382: 68 18 00 00 00 push $0x18
8048387: e9 b0 ff ff ff jmp 804833c <_init+0x18>
804838c: ff 25 d4 95 04 08 jmp *0x80495d4
8048392: 68 20 00 00 00 push $0x20
8048397: e9 a0 ff ff ff jmp 804833c <_init+0x18>
说明R_386_PLT32的重定位方法是: 将符号在.plt节中的地址和Offset差值还要加Addent填入Offset(此处是.text中引用函数符号的地方, 由PLT实现位置无关).
R_386_JUMP_SLOT 用于函数,执行时重定位; [从第三节挪到此处]
应该修正为符号的实际值S(例如函数f的地址)
.rela.plt--This relocation table is similar to the one in .rela.dyn section; the difference is this one is for functions, not variables.
The relocation type of entries in this table is R_386_JMP_SLOT or R_X86_64_JUMP_SLOT and the "offset" refers to memory addresses which are inside .got.plt section.
Simply put, this table holds information to relocate entries in .got.plt section.
.plt section
This section contains trampolines for functions defined in dynamic libraries. A sample disassembly (run the command objdump -M intel -dj .plt a.out) will show the following:
4003c0 <printf@plt-0x10>:
4003c0: push QWORD PTR [RIP+0x2004d2] # 600898 <_GLOBAL_OFFSET_TABLE_+0x8>
4003c6: jmp QWORD PTR [RIP+0x2004d4] # 6008a0 <_GLOBAL_OFFSET_TABLE_+0x10>
4003cc: nop DWORD PTR [RAX+0x0]
4003d0 <printf@plt>:
4003d0: jmp QWORD PTR [RIP+0x2004d2] # 6008a8 <_GLOBAL_OFFSET_TABLE_+0x18>
4003d6: push 0
4003db: jmp 4003c0 <printf@plt-0x10>
4003e0 <__libc_start_main@plt>:
4003e0: jmp QWORD PTR [RIP+0x2004ca] # 6008b0 <_GLOBAL_OFFSET_TABLE_+0x20>
4003e6: push 1
4003eb: jmp 4003c0 <printf@plt-0x10>
The _GLOBAL_OFFSET_TABLE_ (labeled as R_X86_64_JUMP_SLOT and starts at address 0x600890) is located in .got.plt section (to see this, run the command objdump -h a.out |grep -A 1 600890 or the command readelf -r a.out) The data in .got.plt section look like the following during runtime (use gdb to see them)
(gdb) b *0x4003d0
(gdb) run
(gdb) x/6a 0x600890
0x600890: 0x6006e8 <_DYNAMIC>--GOT[0] 0x32696159a8 --GOT[1] link_map *
0x6008a0: 0x326950aa20 <_dl_runtime_resolve> GOT[2] 0x4003d6 <printf@plt+6>
0x6008b0: 0x326971c3f0 <__libc_start_main> 0x0
When printf is called the first time in the user program, the jump at 4003d0 will jump to 4003d6, which is just the next instruction (push 0) The it jumps to 4003c0, which does not have a function name (so it is shown as <printf@plt-0x10>). At 4003c6, it will jumps to _dl_runtime_resolve. This function (in Glibc's source file sysdeps/x86_64/dl-trampoline.S) is a trampoline to _dl_fixup (in Glibc's source file elf/dl-runtime.c). _dl_fixup again, is part of Glibc runtime linker ld.so. In particular, it will change the address stored at 6008a8 to the actual address of printf in libc.so.6. To see this, set up a hardware watchpoint
(gdb) watch *0x6008a8
(gdb) cont
Continuing.
Hardware watchpoint 2: *0x6008a8
Old value = 4195286
New value = 1769244016
0x000000326950abc2 in fixup () from /lib64/ld-linux-x86-64.so.2
If we continue execution, printf will be called, as expected. When printf is called again in the user program, the jump at 4003d0 will bounce directly to printf:
(gdb) x/6a 0x600890
0x600890: 0x6006e8 <_DYNAMIC> 0x32696159a8
0x6008a0: 0x326950aa20 <_dl_runtime_resolve> 0x3269748570 <printf>
0x6008b0: 0x326971c3f0 <__libc_start_main> 0x0
R_3862_JMP_SLOT The link editor creates this relocation type for dynamic linking. Its offset member gives the location of a procedure linkage table entry. The dynamic linker modifies the procedure linkage table entry to transfer control to the designated symbol’s address [see ‘‘Procedure Linkage Table’’ in Part 2].
[评]=>
ELF File Format中的这段话不管其表达, 正确意思是: r_Offset给出的偏移地址是函数在GOT中对应的项; .plt entry是不被改动的, 修正的是GOT项的值. r_Offset处即GOT项初始值应该是plt项中的偏移,在386上就是初始化为下条pushl的地址.
Following the steps below, the dynamic linker and the program ‘‘cooperate’’ to resolve symbolic references through the procedure linkage table and the global offset table.
1 . When first creating the memory image of the program, the dynamic linker sets the second and the third entries in the global offset table to special values. Steps below explain more about these values.
2 . If the procedure linkage table is position-independent, the address of the global offset table must reside in %ebx. Each shared object file in the process image has its own procedure linkage table, and control transfers to a procedure linkage table entry only from within the same object file. Consequently, the calling function is responsible for setting the global offset table base register before calling the procedure linkage table entry.
3 . For illustration, assume the program calls name1, which transfers control to the label .PLT1.(name1@PLT)
4 . The first instruction jumps to the address in the global offset table entry for name1 in GOT. Initially, the global offset table holds the address of the following pushl instruction, not the real address of name1.
5 . Consequently, the program pushes a relocation offset (offset) on the stack. The relocation offset is a 32-bit, non-negative byte offset into the relocation table(如果说这个offset在.rel.plt中有项对应,则可以解释过去;否则该Offset对应GOT中的某一项). The designated relocation entry will have type R_386_JMP_SLOT, and its offset will specify the global offset table entry used in the previous jmp instruction(这是准确无误的). The relocation entry also contains a symbol table index, thus telling the dynamic linker what symbol is being referenced, name1 in this case.
6 . After pushing the relocation offset, the program then jumps to .PLT0, the first entry in the procedure linkage table. The pushl instruction places the value of the second global offset table entry (got_plus_4 or 4(%ebx)) on the stack, thus giving the dynamic linker one word of identifying information. The program then jumps to the address in the third global offset table entry (got_plus_8 or 8(%ebx)), which transfers control to the dynamic linker.
7 . When the dynamic linker receives control, it unwinds the stack, looks at the designated relocation entry, finds the symbol’s value, stores the ‘‘real’’ address for name1 in its global offset table entry, and transfers control to the desired destination.
8 . Subsequent executions of the procedure linkage table entry will transfer directly to name1, without calling the dynamic linker a second time. That is, the jmp instruction at .PLT1 will transfer to name1, instead of ‘‘falling through’’ to the pushl instruction.
The LD_BIND_NOW environment variable can change dynamic linking behavior. If its value is non-null, the dynamic linker evaluates procedure linkage table entries before transferring control to the program. That is, the dynamic linker processes relocation entries of type R_386_JMP_SLOT during process initialization. Otherwise, the dynamic linker evaluates procedure linkage table entries lazily, delaying symbol resolution and relocation until the first execution of a table entry.
不难理解ELF File Format中Relocation段落中的描述
R_386_GOTPC 10 word32 GOT + A - P //GOT即GOT地址,A为Offset处的值,P为Offset.
R_386_GOT32 3 word32 G + A - P //G为符号在GOT中地址,A为Offset处的值,P为Offset
R_386_GLOB_DAT 6 word32 S //S为调整后的符号值
R_386_PLT32 4 word32 L + A - P //L为符号在plt中的地址,A为Offset处的值,P为Offset
重定位类型分析(3)
本文分析剩下的四种类型R_386_COPY,R_386_JUMP_SLOT,R_386_RELATIVE,R_386_GOTOFF
R_386_RELATIVE 8 word32 B + A
R_386_JUMP_SLOT 7 word32 S
R_386_GOTOFF 9 word32 S + A - GOT
R_386_COPY 5 none none
附件1
1.c
[root@proxy ~/3]# cat 1.c
#include <stdio.h>
static char *s="hello World!\n";
char *t="abc";
void f()
{
printf(s);
}
void g()
{
printf(t);
}
[root@proxy ~/3]# gcc -fPIC -S 1.c
[root@proxy ~/3]# cat 1.s
.file "1.c"
.version "01.01"
gcc2_compiled.:
.section .rodata
.LC0:
.string "hello World!\n"
.data
.align 4
.type s,@object
.size s,4
s:
.long .LC0
.globl t
.section .rodata
.LC1:
.string "abc"
.data
.align 4
.type t,@object
.size t,4
t:
.long .LC1
.text
.align 4
.globl f
.type f,@function
f:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $4, %esp
call .L3
.L3:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L3], %ebx
subl $12, %esp
pushl s@GOTOFF(%ebx)
call printf@PLT
addl $16, %esp
movl -4(%ebp), %ebx
leave
ret
.Lfe1:
.size f,.Lfe1-f
.align 4
.globl g
.type g,@function
g:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $4, %esp
call .L5
.L5:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L5], %ebx
subl $12, %esp
movl t@GOT(%ebx), %eax
pushl (%eax)
call printf@PLT
addl $16, %esp
movl -4(%ebp), %ebx
leave
ret
.Lfe2:
.size g,.Lfe2-g
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-98)"
[root@proxy ~/3]# gcc -fPIC -c 1.c -o 1.o
[root@proxy ~/3]# ld -shared 1.o -o 1.so
[root@proxy ~/3]# objdump -dj .text 1.o
1.o: file format elf32-i386
Disassembly of section .text:
00000000 <f>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 53 push %ebx
4: 83 ec 04 sub $0x4,%esp
7: e8 00 00 00 00 call c <f+0xc>
c: 5b pop %ebx
d: 81 c3 03 00 00 00 add $0x3,%ebx
13: 83 ec 0c sub $0xc,%esp
16: ff b3 00 00 00 00 pushl 0x0(%ebx)
1c: e8 fc ff ff ff call 1d <f+0x1d>
21: 83 c4 10 add $0x10,%esp
24: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
27: c9 leave
28: c3 ret
29: 8d 76 00 lea 0x0(%esi),%esi
0000002c <g>:
2c: 55 push %ebp
2d: 89 e5 mov %esp,%ebp
2f: 53 push %ebx
30: 83 ec 04 sub $0x4,%esp
33: e8 00 00 00 00 call 38 <g+0xc>
38: 5b pop %ebx
39: 81 c3 03 00 00 00 add $0x3,%ebx
3f: 83 ec 0c sub $0xc,%esp
42: 8b 83 00 00 00 00 mov 0x0(%ebx),%eax
48: ff 30 pushl (%eax)
4a: e8 fc ff ff ff call 4b <g+0x1f>
4f: 83 c4 10 add $0x10,%esp
52: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
55: c9 leave
56: c3 ret
57: 90 nop
[root@proxy ~/3]# readelf -a 1.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 328 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 12
Section header string table index: 9
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000058 00 AX 0 0 4
[ 2] .rel.text REL 00000000 000454 000030 08 10 1 4
[ 3] .data PROGBITS 00000000 00008c 000008 00 WA 0 0 4
[ 4] .rel.data REL 00000000 000484 000010 08 10 3 4
[ 5] .bss NOBITS 00000000 000094 000000 00 WA 0 0 4
[ 6] .note NOTE 00000000 000094 000014 00 0 0 1
[ 7] .rodata PROGBITS 00000000 0000a8 000012 00 A 0 0 1
[ 8] .comment PROGBITS 00000000 0000ba 000036 00 0 0 1
[ 9] .shstrtab STRTAB 00000000 0000f0 000057 00 0 0 1
[10] .symtab SYMTAB 00000000 000328 0000f0 10 11 a 4
[11] .strtab STRTAB 00000000 000418 000039 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no program headers in this file.
There is no dynamic segment in this file.
Relocation section '.rel.text' at offset 0x454 contains 6 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000f 00c0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
00000018 00309 R_386_GOTOFF 00000000 .data
0000001d 00d04 R_386_PLT32 00000000 printf
0000003b 00c0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
00000044 00a03 R_386_GOT32 00000004 t
0000004b 00d04 R_386_PLT32 00000000 printf
Relocation section '.rel.data' at offset 0x484 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name
00000000 00601 R_386_32 00000000 .rodata
00000004 00601 R_386_32 00000000 .rodata
There are no unwind sections in this file.
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS 1.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 gcc2_compiled.
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 4 OBJECT LOCAL DEFAULT 3 s
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 0 SECTION LOCAL DEFAULT 8
10: 00000004 4 OBJECT GLOBAL DEFAULT 3 t
11: 00000000 41 FUNC GLOBAL DEFAULT 1 f
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
13: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
14: 0000002c 43 FUNC GLOBAL DEFAULT 1 g
No version information found in this file.
[root@proxy ~/3]# objdump -dj .text 1.so
1.so: file format elf32-i386
Disassembly of section .text:
0000035c <f>:
35c: 55 push %ebp
35d: 89 e5 mov %esp,%ebp
35f: 53 push %ebx
360: 83 ec 04 sub $0x4,%esp
363: e8 00 00 00 00 call 368 <f+0xc>
368: 5b pop %ebx
369: 81 c3 68 10 00 00 add $0x1068,%ebx
36f: 83 ec 0c sub $0xc,%esp
372: ff b3 f8 ff ff ff pushl 0xfffffff8(%ebx)
378: e8 cf ff ff ff call 34c <f-0x10>
37d: 83 c4 10 add $0x10,%esp
380: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
383: c9 leave
384: c3 ret
385: 8d 76 00 lea 0x0(%esi),%esi
00000388 <g>:
388: 55 push %ebp
389: 89 e5 mov %esp,%ebp
38b: 53 push %ebx
38c: 83 ec 04 sub $0x4,%esp
38f: e8 00 00 00 00 call 394 <g+0xc>
394: 5b pop %ebx
395: 81 c3 3c 10 00 00 add $0x103c,%ebx
39b: 83 ec 0c sub $0xc,%esp
39e: 8b 83 10 00 00 00 mov 0x10(%ebx),%eax
3a4: ff 30 pushl (%eax)
3a6: e8 a1 ff ff ff call 34c <f-0x10>
3ab: 83 c4 10 add $0x10,%esp
3ae: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
3b1: c9 leave
3b2: c3 ret
3b3: 90 no
[root@proxy ~/3]# readelf -a 1.so
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x35c
Start of program headers: 52 (bytes into file)
Start of section headers: 1348 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 19
Section header string table index: 16
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .hash HASH 00000094 000094 0000b0 04 A 2 0 4
[ 2] .dynsym DYNSYM 00000144 000144 000190 10 A 3 10 4
[ 3] .dynstr STRTAB 000002d4 0002d4 000045 00 A 0 0 1
[ 4] .rel.dyn REL 0000031c 00031c 000018 08 A 2 0 4
[ 5] .rel.plt REL 00000334 000334 000008 08 A 2 6 4
[ 6] .plt PROGBITS 0000033c 00033c 000020 04 AX 0 0 4
[ 7] .text PROGBITS 0000035c 00035c 000058 00 AX 0 0 4
[ 8] .rodata PROGBITS 000003b4 0003b4 000012 00 A 0 0 1
[ 9] .data PROGBITS 000013c8 0003c8 000008 00 WA 0 0 4
[10] .got PROGBITS 000013d0 0003d0 000014 04 WA 0 0 4
[11] .dynamic DYNAMIC 000013e4 0003e4 000090 08 WA 3 0 4
[12] .sbss PROGBITS 00001474 000474 000000 00 W 0 0 1
[13] .bss NOBITS 00001474 000474 000000 00 WA 0 0 4
[14] .comment PROGBITS 00000000 000474 000036 00 0 0 1
[15] .note NOTE 00000000 0004aa 000014 00 0 0 1
[16] .shstrtab STRTAB 00000000 0004be 000084 00 0 0 1
[17] .symtab SYMTAB 00000000 00083c 0001f0 10 18 16 4
[18] .strtab STRTAB 00000000 000a2c 00005a 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x003c6 0x003c6 R E 0x1000
LOAD 0x0003c8 0x000013c8 0x000013c8 0x000ac 0x000ac RW 0x1000
DYNAMIC 0x0003e4 0x000013e4 0x000013e4 0x00090 0x00090 RW 0x4
Section to Segment mapping:
Segment Sections...
00 .hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text .rodata
01 .data .got .dynamic
02 .dynamic
Dynamic segment at offset 0x3e4 contains 14 entries:
Tag Type Name/Value
0x00000004 (HASH) 0x94
0x00000005 (STRTAB) 0x2d4
0x00000006 (SYMTAB) 0x144
0x0000000a (STRSZ) 69 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000003 (PLTGOT) 0x13d0
0x00000002 (PLTRELSZ) 8 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x334
0x00000011 (REL) 0x31c
0x00000012 (RELSZ) 24 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 2
0x00000000 (NULL) 0x0
Relocation section '.rel.dyn' at offset 0x31c contains 3 entries:
Offset Info Type Symbol's Value Symbol's Name
000013c8 00008 R_386_RELATIVE
000013cc 00008 R_386_RELATIVE
000013e0 01006 R_386_GLOB_DAT 000013cc t
Relocation section '.rel.plt' at offset 0x334 contains 1 entries:
Offset Info Type Symbol's Value Symbol's Name
000013dc 01107 R_386_JUMP_SLOT 00000000 printf
There are no unwind sections in this file.
Symbol table '.dynsym' contains 25 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000094 0 SECTION LOCAL DEFAULT 1
2: 00000144 0 SECTION LOCAL DEFAULT 2
3: 000002d4 0 SECTION LOCAL DEFAULT 3
4: 0000031c 0 SECTION LOCAL DEFAULT 4
5: 00000334 0 SECTION LOCAL DEFAULT 5
6: 0000033c 0 SECTION LOCAL DEFAULT 6
7: 0000035c 0 SECTION LOCAL DEFAULT 7
8: 000003b4 0 SECTION LOCAL DEFAULT 8
9: 000013c8 0 SECTION LOCAL DEFAULT 9
10: 000013d0 0 SECTION LOCAL DEFAULT 10
11: 000013e4 0 SECTION LOCAL DEFAULT 11
12: 00001474 0 SECTION LOCAL DEFAULT 12
13: 00001474 0 SECTION LOCAL DEFAULT 13
14: 00000000 0 SECTION LOCAL DEFAULT 14
15: 00000000 0 SECTION LOCAL DEFAULT 15
16: 000013cc 4 OBJECT GLOBAL DEFAULT 9 t
17: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
18: 000013e4 0 OBJECT GLOBAL DEFAULT ABS _DYNAMIC
19: 0000035c 41 FUNC GLOBAL DEFAULT 7 f
20: 00000388 43 FUNC GLOBAL DEFAULT 7 g
21: 00001474 0 OBJECT GLOBAL DEFAULT ABS __bss_start
22: 00001474 0 OBJECT GLOBAL DEFAULT ABS _edata
23: 000013d0 0 OBJECT GLOBAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
24: 00001474 0 OBJECT GLOBAL DEFAULT ABS _end
Symbol table '.symtab' contains 31 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000094 0 SECTION LOCAL DEFAULT 1
2: 00000144 0 SECTION LOCAL DEFAULT 2
3: 000002d4 0 SECTION LOCAL DEFAULT 3
4: 0000031c 0 SECTION LOCAL DEFAULT 4
5: 00000334 0 SECTION LOCAL DEFAULT 5
6: 0000033c 0 SECTION LOCAL DEFAULT 6
7: 0000035c 0 SECTION LOCAL DEFAULT 7
8: 000003b4 0 SECTION LOCAL DEFAULT 8
9: 000013c8 0 SECTION LOCAL DEFAULT 9
10: 000013d0 0 SECTION LOCAL DEFAULT 10
11: 000013e4 0 SECTION LOCAL DEFAULT 11
12: 00001474 0 SECTION LOCAL DEFAULT 12
13: 00001474 0 SECTION LOCAL DEFAULT 13
14: 00000000 0 SECTION LOCAL DEFAULT 14
15: 00000000 0 SECTION LOCAL DEFAULT 15
16: 00000000 0 SECTION LOCAL DEFAULT 16
17: 00000000 0 SECTION LOCAL DEFAULT 17
18: 00000000 0 SECTION LOCAL DEFAULT 18
19: 00000000 0 FILE LOCAL DEFAULT ABS 1.c
20: 0000035c 0 NOTYPE LOCAL DEFAULT 7 gcc2_compiled.
21: 000013c8 4 OBJECT LOCAL DEFAULT 9 s
22: 000013cc 4 OBJECT GLOBAL DEFAULT 9 t
23: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
24: 000013e4 0 OBJECT GLOBAL DEFAULT ABS _DYNAMIC
25: 0000035c 41 FUNC GLOBAL DEFAULT 7 f
26: 00000388 43 FUNC GLOBAL DEFAULT 7 g
27: 00001474 0 OBJECT GLOBAL DEFAULT ABS __bss_start
28: 00001474 0 OBJECT GLOBAL DEFAULT ABS _edata
29: 000013d0 0 OBJECT GLOBAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
30: 00001474 0 OBJECT GLOBAL DEFAULT ABS _end
Histogram for bucket list length (total of 17 buckets):
Length Number % of total Coverage
0 9 ( 52.9%)
1 7 ( 41.2%) 77.8%
2 1 ( 5.9%) 100.0%
No version information found in this file.
附件2
4.c
[root@proxy ~/3]# cat 2.c
#include <stdio.h>
extern char *t;
int main()
{
f();
g();
printf(t);
return 0;
}
[root@proxy ~/3]# gcc -c 2.c -o 2.o
[root@proxy ~/3]# gcc 2.o 1.so -o 4
[root@proxy ~/3]# objdump -dj .text 4
4: file format elf32-i386
Disassembly of section .text:
08048490 <_start>:
8048490: 31 ed xor %ebp,%ebp
8048492: 5e pop %esi
8048493: 89 e1 mov %esp,%ecx
8048495: 83 e4 f0 and $0xfffffff0,%esp
8048498: 50 push %eax
8048499: 54 push %esp
804849a: 52 push %edx
804849b: 68 00 86 04 08 push $0x8048600
80484a0: 68 ec 83 04 08 push $0x80483ec
80484a5: 51 push %ecx
80484a6: 56 push %esi
80484a7: 68 90 85 04 08 push $0x8048590
80484ac: e8 a3 ff ff ff call 8048454 <_init+0x68>
80484b1: f4 hlt
80484b2: 89 f6 mov %esi,%esi
080484b4 <call_gmon_start>:
80484b4: 55 push %ebp
80484b5: 89 e5 mov %esp,%ebp
80484b7: 53 push %ebx
80484b8: 50 push %eax
80484b9: e8 00 00 00 00 call 80484be <call_gmon_start+0xa>
80484be: 5b pop %ebx
80484bf: 81 c3 8e 11 00 00 add $0x118e,%ebx
80484c5: 8b 83 28 00 00 00 mov 0x28(%ebx),%eax
80484cb: 85 c0 test %eax,%eax
80484cd: 74 02 je 80484d1 <call_gmon_start+0x1d>
80484cf: ff d0 call *%eax
80484d1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80484d4: c9 leave
80484d5: c3 ret
80484d6: 89 f6 mov %esi,%esi
80484d8: 90 nop
80484d9: 90 nop
80484da: 90 nop
80484db: 90 nop
80484dc: 90 nop
80484dd: 90 nop
80484de: 90 nop
80484df: 90 nop
080484e0 <__do_global_dtors_aux>:
80484e0: 55 push %ebp
80484e1: 89 e5 mov %esp,%ebp
80484e3: 83 ec 08 sub $0x8,%esp
80484e6: 8b 15 34 96 04 08 mov 0x8049634,%edx
80484ec: 85 d2 test %edx,%edx
80484ee: 75 49 jne 8048539 <__do_global_dtors_aux+0x59>
80484f0: 8b 15 30 96 04 08 mov 0x8049630,%edx
80484f6: 8b 02 mov (%edx),%eax
80484f8: 85 c0 test %eax,%eax
80484fa: 74 1a je 8048516 <__do_global_dtors_aux+0x36>
80484fc: 8d 74 26 00 lea 0x0(%esi,1),%esi
8048500: 8d 42 04 lea 0x4(%edx),%eax
8048503: a3 30 96 04 08 mov %eax,0x8049630
8048508: ff 12 call *(%edx)
804850a: 8b 15 30 96 04 08 mov 0x8049630,%edx
8048510: 8b 0a mov (%edx),%ecx
8048512: 85 c9 test %ecx,%ecx
8048514: 75 ea jne 8048500 <__do_global_dtors_aux+0x20>
8048516: b8 44 84 04 08 mov $0x8048444,%eax
804851b: 85 c0 test %eax,%eax
804851d: 74 10 je 804852f <__do_global_dtors_aux+0x4f>
804851f: 83 ec 0c sub $0xc,%esp
8048522: 68 38 96 04 08 push $0x8049638
8048527: e8 18 ff ff ff call 8048444 <_init+0x58>
804852c: 83 c4 10 add $0x10,%esp
804852f: b8 01 00 00 00 mov $0x1,%eax
8048534: a3 34 96 04 08 mov %eax,0x8049634
8048539: 89 ec mov %ebp,%esp
804853b: 5d pop %ebp
804853c: c3 ret
804853d: 8d 76 00 lea 0x0(%esi),%esi
08048540 <fini_dummy>:
8048540: 55 push %ebp
8048541: 89 e5 mov %esp,%ebp
8048543: 83 ec 08 sub $0x8,%esp
8048546: 89 ec mov %ebp,%esp
8048548: 5d pop %ebp
8048549: c3 ret
804854a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
08048550 <frame_dummy>:
8048550: 55 push %ebp
8048551: b8 24 84 04 08 mov $0x8048424,%eax
8048556: 89 e5 mov %esp,%ebp
8048558: 83 ec 08 sub $0x8,%esp
804855b: 85 c0 test %eax,%eax
804855d: 74 15 je 8048574 <frame_dummy+0x24>
804855f: 83 ec 08 sub $0x8,%esp
8048562: 68 4c 97 04 08 push $0x804974c
8048567: 68 38 96 04 08 push $0x8049638
804856c: e8 b3 fe ff ff call 8048424 <_init+0x38>
8048571: 83 c4 10 add $0x10,%esp
8048574: 89 ec mov %ebp,%esp
8048576: 5d pop %ebp
8048577: c3 ret
8048578: 90 nop
8048579: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi
08048580 <init_dummy>:
8048580: 55 push %ebp
8048581: 89 e5 mov %esp,%ebp
8048583: 83 ec 08 sub $0x8,%esp
8048586: 89 ec mov %ebp,%esp
8048588: 5d pop %ebp
8048589: c3 ret
804858a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
08048590 <main>:
8048590: 55 push %ebp
8048591: 89 e5 mov %esp,%ebp
8048593: 83 ec 08 sub $0x8,%esp
8048596: e8 79 fe ff ff call 8048414 <_init+0x28>
804859b: e8 94 fe ff ff call 8048434 <_init+0x48>
80485a0: 83 ec 0c sub $0xc,%esp
80485a3: ff 35 48 97 04 08 pushl 0x8049748
80485a9: e8 b6 fe ff ff call 8048464 <_init+0x78>
80485ae: 83 c4 10 add $0x10,%esp
80485b1: b8 00 00 00 00 mov $0x0,%eax
80485b6: c9 leave
80485b7: c3 ret
80485b8: 90 nop
80485b9: 90 nop
80485ba: 90 nop
80485bb: 90 nop
80485bc: 90 nop
80485bd: 90 nop
80485be: 90 nop
80485bf: 90 nop
080485c0 <__do_global_ctors_aux>:
80485c0: 55 push %ebp
80485c1: 89 e5 mov %esp,%ebp
80485c3: 53 push %ebx
80485c4: 83 ec 04 sub $0x4,%esp
80485c7: a1 3c 96 04 08 mov 0x804963c,%eax
80485cc: bb 3c 96 04 08 mov $0x804963c,%ebx
80485d1: 83 f8 ff cmp $0xffffffff,%eax
80485d4: 74 16 je 80485ec <__do_global_ctors_aux+0x2c>
80485d6: 8d 76 00 lea 0x0(%esi),%esi
80485d9: 8d bc 27 00 00 00 00 lea 0x0(%edi,1),%edi
80485e0: 83 eb 04 sub $0x4,%ebx
80485e3: ff d0 call *%eax
80485e5: 8b 03 mov (%ebx),%eax
80485e7: 83 f8 ff cmp $0xffffffff,%eax
80485ea: 75 f4 jne 80485e0 <__do_global_ctors_aux+0x20>
80485ec: 58 pop %eax
80485ed: 5b pop %ebx
80485ee: 5d pop %ebp
80485ef: c3 ret
080485f0 <init_dummy>:
80485f0: 55 push %ebp
80485f1: 89 e5 mov %esp,%ebp
80485f3: 83 ec 08 sub $0x8,%esp
80485f6: 89 ec mov %ebp,%esp
80485f8: 5d pop %ebp
80485f9: c3 ret
80485fa: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
[root@proxy ~/3]# readelf -a 4
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048490
Start of program headers: 52 (bytes into file)
Start of section headers: 11028 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 27
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 080480f4 0000f4 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048108 000108 000020 00 A 0 0 4
[ 3] .hash HASH 08048128 000128 000054 04 A 4 0 4
[ 4] .dynsym DYNSYM 0804817c 00017c 000100 10 A 5 1 4
[ 5] .dynstr STRTAB 0804827c 00027c 0000d7 00 A 0 0 1
[ 6] .gnu.version VERSYM 08048354 000354 000020 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 08048374 000374 000030 00 A 5 1 4
[ 8] .rel.dyn REL 080483a4 0003a4 000010 08 A 4 0 4
[ 9] .rel.plt REL 080483b4 0003b4 000038 08 A 4 b 4
[10] .init PROGBITS 080483ec 0003ec 000018 00 AX 0 0 4
[11] .plt PROGBITS 08048404 000404 000080 04 AX 0 0 4
[12] .text PROGBITS 08048490 000490 000170 00 AX 0 0 16
[13] .fini PROGBITS 08048600 000600 00001e 00 AX 0 0 4
[14] .rodata PROGBITS 08048620 000620 000008 00 A 0 0 4
[15] .data PROGBITS 08049628 000628 000010 00 WA 0 0 4
[16] .eh_frame PROGBITS 08049638 000638 000004 00 WA 0 0 4
[17] .ctors PROGBITS 0804963c 00063c 000008 00 WA 0 0 4
[18] .dtors PROGBITS 08049644 000644 000008 00 WA 0 0 4
[19] .got PROGBITS 0804964c 00064c 00002c 04 WA 0 0 4
[20] .dynamic DYNAMIC 08049678 000678 0000d0 08 WA 5 0 4
[21] .sbss PROGBITS 08049748 000748 000000 00 W 0 0 1
[22] .bss NOBITS 08049748 000748 00001c 00 WA 0 0 4
[23] .stab PROGBITS 00000000 000748 0007a4 0c 24 0 4
[24] .stabstr STRTAB 00000000 000eec 001983 00 0 0 1
[25] .comment PROGBITS 00000000 00286f 000144 00 0 0 1
[26] .note NOTE 00000000 0029b3 000078 00 0 0 1
[27] .shstrtab STRTAB 00000000 002a2b 0000e9 00 0 0 1
[28] .symtab SYMTAB 00000000 002fc4 000510 10 29 3b 4
[29] .strtab STRTAB 00000000 0034d4 00022e 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4
INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00628 0x00628 R E 0x1000
LOAD 0x000628 0x08049628 0x08049628 0x00120 0x0013c RW 0x1000
DYNAMIC 0x000678 0x08049678 0x08049678 0x000d0 0x000d0 RW 0x4
NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata
03 .data .eh_frame .ctors .dtors .got .dynamic .bss
04 .dynamic
05 .note.ABI-tag
Dynamic segment at offset 0x678 contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [1.so]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x80483ec
0x0000000d (FINI) 0x8048600
0x00000004 (HASH) 0x8048128
0x00000005 (STRTAB) 0x804827c
0x00000006 (SYMTAB) 0x804817c
0x0000000a (STRSZ) 193 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x804964c
0x00000002 (PLTRELSZ) 56 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x80483b4
0x00000011 (REL) 0x80483a4
0x00000012 (RELSZ) 16 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x8048374
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x8048354
0x00000000 (NULL) 0x0
Relocation section '.rel.dyn' at offset 0x3a4 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name
08049674 00f06 R_386_GLOB_DAT 00000000 __gmon_start__
08049748 00105 R_386_COPY 08049748 t
Relocation section '.rel.plt' at offset 0x3b4 contains 7 entries:
Offset Info Type Symbol's Value Symbol's Name
08049658 00307 R_386_JUMP_SLOT 08048414 f
0804965c 00407 R_386_JUMP_SLOT 08048424 __register_frame_info
08049660 00507 R_386_JUMP_SLOT 08048434 g
08049664 00607 R_386_JUMP_SLOT 08048444 __deregister_frame_info
08049668 00807 R_386_JUMP_SLOT 08048454 __libc_start_main
0804966c 00907 R_386_JUMP_SLOT 08048464 printf
08049670 00a07 R_386_JUMP_SLOT 08048474 __cxa_finalize
There are no unwind sections in this file.
Symbol table '.dynsym' contains 16 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 08049748 4 OBJECT GLOBAL DEFAULT 22 t
2: 08049678 0 OBJECT GLOBAL DEFAULT ABS _DYNAMIC
3: 08048414 41 FUNC GLOBAL DEFAULT UND f
4: 08048424 129 FUNC WEAK DEFAULT UND __register_frame_info@GLIBC_2.0 (2)
5: 08048434 43 FUNC GLOBAL DEFAULT UND g
6: 08048444 172 FUNC WEAK DEFAULT UND __deregister_frame_info@GLIBC_2.0 (2)
7: 08049748 0 OBJECT GLOBAL DEFAULT ABS __bss_start
8: 08048454 202 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2)
9: 08048464 50 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.0 (2)
10: 08048474 157 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.1.3 (3)
11: 08049748 0 OBJECT GLOBAL DEFAULT ABS _edata
12: 0804964c 0 OBJECT GLOBAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
13: 08049764 0 OBJECT GLOBAL DEFAULT ABS _end
14: 08048624 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
15: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Symbol table '.symtab' contains 81 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 080480f4 0 SECTION LOCAL DEFAULT 1
2: 08048108 0 SECTION LOCAL DEFAULT 2
3: 08048128 0 SECTION LOCAL DEFAULT 3
4: 0804817c 0 SECTION LOCAL DEFAULT 4
5: 0804827c 0 SECTION LOCAL DEFAULT 5
6: 08048354 0 SECTION LOCAL DEFAULT 6
7: 08048374 0 SECTION LOCAL DEFAULT 7
8: 080483a4 0 SECTION LOCAL DEFAULT 8
9: 080483b4 0 SECTION LOCAL DEFAULT 9
10: 080483ec 0 SECTION LOCAL DEFAULT 10
11: 08048404 0 SECTION LOCAL DEFAULT 11
12: 08048490 0 SECTION LOCAL DEFAULT 12
13: 08048600 0 SECTION LOCAL DEFAULT 13
14: 08048620 0 SECTION LOCAL DEFAULT 14
15: 08049628 0 SECTION LOCAL DEFAULT 15
16: 08049638 0 SECTION LOCAL DEFAULT 16
17: 0804963c 0 SECTION LOCAL DEFAULT 17
18: 08049644 0 SECTION LOCAL DEFAULT 18
19: 0804964c 0 SECTION LOCAL DEFAULT 19
20: 08049678 0 SECTION LOCAL DEFAULT 20
21: 08049748 0 SECTION LOCAL DEFAULT 21
22: 08049748 0 SECTION LOCAL DEFAULT 22
23: 00000000 0 SECTION LOCAL DEFAULT 23
24: 00000000 0 SECTION LOCAL DEFAULT 24
25: 00000000 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 SECTION LOCAL DEFAULT 26
27: 00000000 0 SECTION LOCAL DEFAULT 27
28: 00000000 0 SECTION LOCAL DEFAULT 28
29: 00000000 0 SECTION LOCAL DEFAULT 29
30: 00000000 0 FILE LOCAL DEFAULT ABS initfini.c
31: 080484b4 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
32: 080484b4 0 FUNC LOCAL DEFAULT 12 call_gmon_start
33: 00000000 0 FILE LOCAL DEFAULT ABS init.c
34: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
35: 080484e0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
36: 08049630 0 OBJECT LOCAL DEFAULT 15 p.0
37: 08049644 0 OBJECT LOCAL DEFAULT 18 __DTOR_LIST__
38: 08049634 0 OBJECT LOCAL DEFAULT 15 completed.1
39: 080484e0 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
40: 08049638 0 OBJECT LOCAL DEFAULT 16 __EH_FRAME_BEGIN__
41: 08048540 0 FUNC LOCAL DEFAULT 12 fini_dummy
42: 0804974c 24 OBJECT LOCAL DEFAULT 22 object.2
43: 08048550 0 FUNC LOCAL DEFAULT 12 frame_dummy
44: 08048580 0 FUNC LOCAL DEFAULT 12 init_dummy
45: 08049638 0 OBJECT LOCAL DEFAULT 15 force_to_data
46: 0804963c 0 OBJECT LOCAL DEFAULT 17 __CTOR_LIST__
47: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
48: 080485c0 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
49: 080485c0 0 FUNC LOCAL DEFAULT 12 __do_global_ctors_aux
50: 08049640 0 OBJECT LOCAL DEFAULT 17 __CTOR_END__
51: 080485f0 0 FUNC LOCAL DEFAULT 12 init_dummy
52: 08049638 0 OBJECT LOCAL DEFAULT 15 force_to_data
53: 08049648 0 OBJECT LOCAL DEFAULT 18 __DTOR_END__
54: 08049638 0 OBJECT LOCAL DEFAULT 16 __FRAME_END__
55: 00000000 0 FILE LOCAL DEFAULT ABS initfini.c
56: 08048600 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
57: 00000000 0 FILE LOCAL DEFAULT ABS 2.c
58: 08048590 0 NOTYPE LOCAL DEFAULT 12 gcc2_compiled.
59: 08049748 4 OBJECT GLOBAL DEFAULT 22 t
60: 08049678 0 OBJECT GLOBAL DEFAULT ABS _DYNAMIC
61: 08048414 41 FUNC GLOBAL DEFAULT UND f
62: 08048424 129 FUNC WEAK DEFAULT UND __register_frame_info@@GLIBC_2.0
63: 08048620 4 NOTYPE GLOBAL DEFAULT 14 _fp_hw
64: 08048434 43 FUNC GLOBAL DEFAULT UND g
65: 080483ec 0 FUNC GLOBAL DEFAULT 10 _init
66: 08048444 172 FUNC WEAK DEFAULT UND __deregister_frame_info@@GLIBC_2.0
67: 08048490 0 FUNC GLOBAL DEFAULT 12 _start
68: 08049748 0 OBJECT GLOBAL DEFAULT ABS __bss_start
69: 08048590 40 FUNC GLOBAL DEFAULT 12 main
70: 08048454 202 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.0
71: 08049628 0 NOTYPE WEAK DEFAULT 15 data_start
72: 08048464 50 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.0
73: 08048600 0 FUNC GLOBAL DEFAULT 13 _fini
74: 08048474 157 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.1.3
75: 08049748 0 OBJECT GLOBAL DEFAULT ABS _edata
76: 0804964c 0 OBJECT GLOBAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
77: 08049764 0 OBJECT GLOBAL DEFAULT ABS _end
78: 08048624 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
79: 08049628 0 NOTYPE GLOBAL DEFAULT 15 __data_start
80: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Histogram for bucket list length (total of 3 buckets):
Length Number % of total Coverage
0 0 ( 0.0%)
1 0 ( 0.0%) 0.0%
2 0 ( 0.0%) 0.0%
3 1 ( 33.3%) 20.0%
4 0 ( 0.0%) 20.0%
5 0 ( 0.0%) 20.0%
6 2 ( 66.7%) 100.0%
Version symbols section '.gnu.version' contains 16 entries:
Addr: 0000000008048354 Offset: 0x000354 Link: 4 (.dynsym)
000: 0 (*local*) 0 (*local*) 1 (*global*) 0 (*local*)
004: 2 (GLIBC_2.0) 0 (*local*) 2 (GLIBC_2.0) 1 (*global*)
008: 2 (GLIBC_2.0) 2 (GLIBC_2.0) 3 (GLIBC_2.1.3) 1 (*global*)
00c: 1 (*global*) 1 (*global*) 1 (*global*) 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x0000000008048374 Offset: 0x000374 Link to section: 5 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 2
0x0010: Name: GLIBC_2.1.3 Flags: none Version: 3
0x0020: Name: GLIBC_2.0 Flags: none Version: 2
本节分析开始处:
R_386_RELATIVE 用于局部变量,执行时重定位
R_386_RELATIVE The link editor creates this relocation type for dynamic linking. Its offset member gives a location within a shared object that contains a value representing a relative address. The dynamic linker computes the corresponding virtual address by adding the virtual address at which the shared object was loaded to the relative address. Relocation entries for this type must specify 0 for the symbol table index.
查看1.c.txt生成的1.so的readelf
000013c8 00008 R_386_RELATIVE
000013cc 00008 R_386_RELATIVE
这两项在.rel.dyn中, offset 00013c8 是地址, 相对于1.so加载地址,显然是在.data节中, 没有符号名,那他们是什么呢?
[ 9] .data PROGBITS 000013c8 0003c8 000008 00 WA 0 0 4
[评]=>
猜想可知是动态加载so时, 相当于ModuleBase做重定位.
[root@proxy ~/3]# objdump -sj .data 1.so
1.so: file format elf32-i386
Contents of section .data:
13c8 b4030000 c2030000 ........
值分别是03b4和03c2,应该是位于.rodata中
[root@proxy ~/3]# objdump -sj .rodata 1.so
1.so: file format elf32-i386
Contents of section .rodata:
03b4 68656c6c 6f20576f 726c6421 0a006162 hello World!..ab
03c4 6300 c.
果然是的.
R_386_RELATIVE 8 word32 B + A,使用加载地址+Offset处值来重定位
验证:由于是执行时连接,需要启用gdb来调试看看
[root@proxy ~/3]# ldd 4
1.so => /usr/lib/1.so (0x4002a000)
libc.so.6 => /lib/i686/libc.so.6 (0x4002c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
因此
000013c8 00008 R_386_RELATIVE
000013cc 00008 R_386_RELATIVE
加载后的地址为0x4002b3c8,0x4002b3cc
[root@proxy ~/3]# cp 1.so /usr/lib
cp: overwrite `/usr/lib/1.so' y
[root@proxy ~/3]# gdb -q ./4
(gdb) b main
Breakpoint 1 at 0x8048596
(gdb) r
Starting program: /root/3/./4
Breakpoint 1, 0x08048596 in main ()
(gdb) x/w 0x4002b3c8
0x4002b3c8 <s>: 0x4002a3b4
(gdb) x/w 0x4002b3cc
0x4002b3cc <t>: 0x4002a3c2
(gdb)
Contents of section .data:
13c8 b4030000 c2030000 ........
分别加上0x4002a000就是上面的结果
R_386_GOTOFF 用于静态变量,链接是重定位
目标文件1.o中
00000018 00309 R_386_GOTOFF 00000000 .data
16: ff b3 00 00 00 00 pushl 0x0(%ebx)
pushl s@GOTOFF(%ebx)
生成1.so中
372: ff b3 f8 ff ff ff pushl 0xfffffff8(%ebx)
修正值为0xfffffff8,即-8,即got-8处.
[root@proxy ~/3]# objdump -sj .data 1.so
1.so: file format elf32-i386
Contents of section .data:
13c8 b4030000 c2030000 ........
即s的值为03b4,指向.rodata
[root@proxy ~/3]# objdump -sj .rodata 1.so
1.so: file format elf32-i386
Contents of section .rodata:
03b4 68656c6c 6f20576f 726c6421 0a006162 hello World!..ab
03c4 6300 c.
所以R_386_GOTOFF的修正方式是: 将符号地址和GOT地址差值加上Offset处的值存入Offset处. 即ELF文档中的S + A – GOT
[评]=>
由1.so的sections表可以看到, .got之前即为.data, got本身就放在.data中; .got-8就是s变量的地址, 所以使用GOT地址做负偏移寻址, 形成位置无关代码. 因为s是static的, 不导出, 所以在GOT中没有对应项.
R_386_COPY,用于全局变量,执行时重定位
R_386_COPY The link editor creates this relocation type for dynamic linking. Its offset member refers to a location in a writable segment. The symbol table index specifies a symbol that should exist both in the current object file and in a shared object. During execution, the dynamic linker copies data associated with the shared object’s symbol to the location specified by the offset.
因为在4.c中有声明:
extern char *t;
在可执行文件4中
08049748 00105 R_386_COPY 08049748 t
[22] .bss NOBITS 08049748 000748 00001c 00 WA 0 0 4
在1.so中
16: 000013cc 4 OBJECT GLOBAL DEFAULT 9 t
加载地址0x4002a00,所以t的值是0x4002b3cc
abcabc[root@proxy ~/3]# gdb -q ./4
(gdb) b main
Breakpoint 1 at 0x8048596
(gdb) r
Starting program: /root/3/./4
Breakpoint 1, 0x08048596 in main ()
(gdb) x /w 0x08049748 //查4中t的值
0x08049748 <t>: 0x4002a3c2
(gdb) x /w 0x4002b3cc //查1.so中t的值
0x4002b3cc <t>: 0x4002a3c2
(gdb)
两个值相等
所以R_386_COPY的修正方式是:将解析到的符号地址处的值(大小由size决定)复制到Offset处。
这实现了每个可执行文件都有独立的全局变量,而不互相干扰。
[评]=>
要求的是同一个地址,而不是不相互干扰; 见总结中纠正: 而同时so的GOT中该变量的地址值被改写成可执行文件中的地址
[评]=>
变量t在so中是有初始值的, 所以在.data section中; 而以extern引用时, 由于不知道其是否有初始值, 所以只能放在.bss中, 有初始值, 则再根据1.so中符号的st_value COPY一下相当于初始化.
可以发现
重定位目标文件有.symtab表, 这个表是必须的, 虽然可以用strip去掉, 但是最终连接时会出错; 而动态链接库文件和可执行文件有.dynsym和.symtab, .dynsym是必须的, 而.symtab不是,可以执行strip命令去掉.
重定位总结
总结
R_386_NONE 0 none none
1.ld时重定位
1.1位置相关
1.1.1 R_386_32
R_386_32 1 word32 S + A //数据,绝对地址
符号的值即变量的地址,因此变量都需要重定位
如果变量的值是普通值,则不需对值重定位
如果变量的值是地址,则需对值重定位,例如char *="abc";
Offset Info Type Symbol's Value Symbol's Name
0000000b 00301 R_386_32 00000000 .data
00000010 00e02 R_386_PC32 00000000 printf
9: ff 35 00 00 00 00 pushl 0x0 //ff 35 将立即数压栈
f: e8 fc ff ff ff call 10 <f+0x10> //e8 相对寻址
14: 83 c4 10 add $0x10,%esp
所以R_386_32都是对Offset处的地址值重定位
S即调整后的符号值(新的变量地址),A即原值(Offset处的地址值,需要重定位的地址)
1.1.2 R_386_PC32
R_386_PC32 2 word32 S + A - P//代码,相对地址
P即Offset
连接时,ld会合并相同的节,假设printf被安排的地址是x,1.o中.text节安排的地址是y
则x+(-4)-(y+10)=x-y-14,所以重定位的结果是x-y-14,
当cpu执行y+f:处的call指令时,ip指向y+14,则call的目标地址是ip+(x-y-14)=x
1.2 位置无关(PIC)
1.2.1 R_386_GOTPC
R_386_GOTPC 10 word32 GOT + A - P
GOT即GOT地址(符号_GLOBAL_OFFSET_TABLE_的值),A为Offset处值,P为Offset.
Offset Info Type Symbol's Value Symbol's Name
0000000f 00e0a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_
00000018 00309 R_386_GOTOFF 00000000 .data
0000001d 00f04 R_386_PLT32 00000000 printf
7: e8 00 00 00 00 call c <f+0xc>
c: 5b pop %ebx
d: 81 c3 03 00 00 00 add $0x3,%ebx
13: 83 ec 0c sub $0xc,%esp
16: ff b3 00 00 00 00 pushl 0x0(%ebx)
1c: e8 fc ff ff ff call 1d <f+0x1d>
call .L3
.L3:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L3], %ebx
subl $12, %esp
pushl s@GOTOFF(%ebx)
call printf@PLT
1.2.2 R_386_GOTOFF
R_386_GOTOFF 9 word32 S + A - GOT//静态(局部)变量
将符号地址和GOT地址差值加上Offset处值存入Offset处.
1.2.3 R_386_GOT32
R_386_GOT32 3 word32 G + A - P//外部(全局)变量
G为符号在GOT中地址,A为Offset处值,P为Offset
1.2.4 R_386_PLT32
R_386_PLT32 4 word32 L + A - P//代码
L为符号在plt中的地址,A为Offset处值,P为Offset
2.执行时重定位
2.1 位置相关
2.1.1 R_386_32
2.1.2 R_386_PC32
2.2 位置无关
2.2.1 R_386_RELATIVE
R_386_RELATIVE 8 word32 B + A//局部变量
使用加载地址+Offset处值来重定位
Relocation section '.rel.dyn' at offset 0x330 contains 3 entries:
Offset Info Type Symbol's Value Symbol's Name
000013e8 00008 R_386_RELATIVE //字符串地址
000013ec 00008 R_386_RELATIVE //字符串地址
00001408 01006 R_386_GLOB_DAT 000013ec t
2.2.2 R_386_GLOB_DAT
R_386_GLOB_DAT 6 word32 S //外部全局在PIC so间共享,或PIC so共享可执行文件中的变量
S为调整后的符号值写入Offset处
对于本地全局变量,直接把调整后的符号值写入本地GOT
3b6: 8b 83 10 00 00 00 mov 0x10(%ebx),%eax//%eax中地址值指向.data节
3bc: ff 30 pushl (%eax)//将.data节中的变量值入栈
对于外部全局变量,解析该符号值(即变量地址),写入本地GOT<<<<<
2.2.3 R_386_COPY
R_386_COPY 5 none none//外部全局变量
可执行文件共享PIC so中变量,
由于所有的可执行文件都不需要重定位,所以为可执行文件共享动态链接库中的全局变量单独设置这个属性,在本地的bss中分配空间,置R_386_COPY定位类型,而不使用R_386_32定位类型(那样需使代码段可写,且COW,耗费内存)
6.c
extern char * s;
extern int t;
1.c
char *s="abc";
int t=1;
6.o中
Relocation section '.rel.text' at offset 0x38c contains 5 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000b 00901 R_386_32 00000000 s
00000010 00a02 R_386_PC32 00000000 printf
00000019 00b01 R_386_32 00000000 t
0000001e 00c02 R_386_PC32 00000000 g
00000024 00d01 R_386_32 00000004 u
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND s
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
11: 00000000 0 NOTYPE GLOBAL DEFAULT UND t
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND g
13: 00000004 4 OBJECT GLOBAL DEFAULT COM u
gcc 1.so 6.o -o 6
而可执行文件6中就变成了
Relocation section '.rel.dyn' at offset 0x3f4 contains 3 entries:
Offset Info Type Symbol's Value Symbol's Name
080496b0 01006 R_386_GLOB_DAT 00000000 __gmon_start__
08049784 00105 R_386_COPY 08049784 t
08049788 00905 R_386_COPY 08049788 s
1: 08049784 4 OBJECT GLOBAL DEFAULT 22 t
9: 08049788 4 OBJECT GLOBAL DEFAULT 22 s
可见s,t的Ndx不是UND,而是位于.bss中
将解析到的符号地址处的值(大小由size决定)复制到Offset处。
而同时so的GOT中该变量的地址值被改写成可执行文件中的地址
R_386_COPY read a string of bytes from the "symbol" address and deposit a copy into this dword; the "symbol" object contains the length; this is used to copy initialized data
from a library to the main app data space
On i386 the most important ones are the R_386_COPY type, meaning "just copy the address of the symbol to that address"
2.2.4 R_386_JMP_SLOT
R_386_JMP_SLOT 7 word32 S//代码
其他:
1.如果文件使用了动态链接库,则该文件就有GOT
2.GOT中的信息
[root@proxy ~/3]# objdump -sj .got 6
6: file format elf32-i386
Contents of section .got:
804968c b4960408 00000000 00000000 6a840408 ............j...
804969c 7a840408 8a840408 9a840408 aa840408 z...............
80496ac ba840408 00000000
GOT[0]是.dynsym节的地址
[20] .dynamic DYNAMIC 080496b4 0006b4 0000d0 08 WA 5 0 4
GOT[1]是动态链接库自身的struct link_map*的指针
GOT[2]是_dl_runtime_resolve的地址
GOT[3]..,函数解析前指向.plt中,解析后执行真正的函数地址
变量加载时解析,指向全局变量地址
3.plt
位置相关:
08048454 <.plt>:
8048454: ff 35 90 96 04 08 pushl 0x8049690
804845a: ff 25 94 96 04 08 jmp *0x8049694
8048460: 00 00 add %al,(%eax)
8048462: 00 00 add %al,(%eax)
8048464: ff 25 98 96 04 08 jmp *0x8049698
804846a: 68 00 00 00 00 push $0x0
804846f: e9 e0 ff ff ff jmp 8048454 <_init+0x18>
8048474: ff 25 9c 96 04 08 jmp *0x804969c
804847a: 68 08 00 00 00 push $0x8
804847f: e9 d0 ff ff ff jmp 8048454 <_init+0x18>
8048484: ff 25 a0 96 04 08 jmp *0x80496a0
PIC:
00000370 <.plt>:
370: ff b3 04 00 00 00 pushl 0x4(%ebx)
376: ff a3 08 00 00 00 jmp *0x8(%ebx)
37c: 00 00 add %al,(%eax)
37e: 00 00 add %al,(%eax)
380: ff a3 0c 00 00 00 jmp *0xc(%ebx)
386: 68 00 00 00 00 push $0x0
38b: e9 e0 ff ff ff jmp 370 <f-0x20>
其中push $0x0是符号在rel节中的索引数0(字节偏移)