本文共 96903 字,大约阅读时间需要 323 分钟。
|
|
/*st_info*/ #define ELF32_ST_BIND(x) ((x) >> 4) #define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) |
/* The following are used with relocations */ #define ELF32_R_SYM(x) ((x) >> 8) #define ELF32_R_TYPE(x) ((x) & 0xff)
|
名称 | 数值 | 字段 | 计算 | 说明 |
R_386_NONE | 0 | (无) | (无) | |
R_386_32 | 1 | word32 | S+A | |
R_386_PC32 | 2 | word32 | S+A-P | |
R_386_GOT32 | 3 | word32 | G+A-P |
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执行逻辑之前都是位置无关代码.
原文链接:
重定位目标文件:位置相关 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 (2) 2: 0804831c 172 FUNC WEAK DEFAULT UND (2) 3: 0804832c 202 FUNC GLOBAL DEFAULT UND (2) 4: 0804833c 50 FUNC GLOBAL DEFAULT UND (2) 5: 0804834c 157 FUNC WEAK DEFAULT UND (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
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 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 73: 0804952c 0 NOTYPE WEAK DEFAULT 15 data_start 74: 0804833c 50 FUNC GLOBAL DEFAULT UND 75: 080484f0 0 FUNC GLOBAL DEFAULT 13 _fini 76: 0804953c 4 OBJECT GLOBAL DEFAULT 15 s 77: 0804834c 157 FUNC WEAK DEFAULT UND 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,见下节。
本节分析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 (2) 3: 0804835c 172 FUNC WEAK DEFAULT UND (2) 4: 0804836c 202 FUNC GLOBAL DEFAULT UND (2) 5: 0804837c 50 FUNC GLOBAL DEFAULT UND (2) 6: 0804959c 4 OBJECT GLOBAL DEFAULT 15 s 7: 0804838c 157 FUNC WEAK DEFAULT UND (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
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 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 73: 0804958c 0 NOTYPE WEAK DEFAULT 15 data_start 74: 0804837c 50 FUNC GLOBAL DEFAULT UND 75: 08048550 0 FUNC GLOBAL DEFAULT 13 _fini 76: 0804959c 4 OBJECT GLOBAL DEFAULT 15 s 77: 0804838c 157 FUNC WEAK DEFAULT UND 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_PLT32R_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 ) is a trampoline to _dl_fixup (in Glibc's source file ). _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
本文分析剩下的四种类型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 ) call
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 ), %eax pushl (%eax) call 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.o1.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 (2) 5: 08048434 43 FUNC GLOBAL DEFAULT UND g 6: 08048444 172 FUNC WEAK DEFAULT UND (2) 7: 08049748 0 OBJECT GLOBAL DEFAULT ABS __bss_start 8: 08048454 202 FUNC GLOBAL DEFAULT UND (2) 9: 08048464 50 FUNC GLOBAL DEFAULT UND (2) 10: 08048474 157 FUNC WEAK DEFAULT UND (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
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 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 71: 08049628 0 NOTYPE WEAK DEFAULT 15 data_start 72: 08048464 50 FUNC GLOBAL DEFAULT UND 73: 08048600 0 FUNC GLOBAL DEFAULT 13 _fini 74: 08048474 157 FUNC WEAK DEFAULT UND 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 ) 生成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 ) call
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(字节偏移)
转载地址:http://sbhvi.baihongyu.com/