静态连接2-hello.o
2011-08-04 17:31
176 查看
看一下hello.o的符号表
[root@localhost mhello]# readelf -S hello.o
There are 11 section headers, starting at offset 0x144:
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 000068 00 AX 0 0 4
[ 2] .rel.text REL 00000000 000448 000048 08 9 1 4
[ 3] .data PROGBITS 00000000 00009c 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 00009c 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 00009c 000029 00 A 0 0 1
[ 6] .comment PROGBITS 00000000 0000c5 00002d 00 0 0 1
[ 7] .note.GNU-stack PROGBITS 00000000 0000f2 000000 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 0000f2 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 0002fc 0000f0 10 10 8 4
[10] .strtab STRTAB 00000000 0003ec 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)
[root@localhost mhello]# readelf -s hello.o
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 hello.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 20 FUNC GLOBAL DEFAULT 1 func_hello
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
10: 00000014 84 FUNC GLOBAL DEFAULT 1 main
11: 00000000 0 NOTYPE GLOBAL DEFAULT UND func_file_a
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND func_file_b
13: 00000004 4 OBJECT GLOBAL DEFAULT COM var_public_file_a
14: 00000004 4 OBJECT GLOBAL DEFAULT COM var_public_file_b
//func_hello,main都是在本模块hello.o内部定义的,所以符号位置在1段,即代码段
//func_file_a,func_file_b是外部符号,前者是一个来自另外一个.o的符号,后者是来自另外一个.so的符号,
//但对于hello.o而言二者都是外部符号,hello.o无力判断他们的出身,将他们视为und--undefined
//var_public_file_a,var_public_file_b放在common块中,在hello.o中还不确定他们到底是不是
//在本模块定义的,因为没有初始化,也没有加extern,现将其是为弱符号,留校观察
看一下hello.o的重定位表
[root@localhost mhello]# readelf -r hello.o
Relocation section '.rel.text' at offset 0x424 contains 9 entries:
Offset Info Type Sym.Value Sym. Name
00000009 00000501 R_386_32 00000000 .rodata
0000000e 00000902 R_386_PC32 00000000 puts
00000028 00000501 R_386_32 00000000 .rodata
0000002d 00000902 R_386_PC32 00000000 puts
00000032 00000802 R_386_PC32 00000000 func_hello
0000003e 00000b02 R_386_PC32 00000000 func_file_a
0000004a 00000c02 R_386_PC32 00000000 func_file_b
00000051 00000501 R_386_32 00000000 .rodata
00000056 00000902 R_386_PC32 00000000 puts
//看来不管内部符号,还是外部.o的符号,还是外部.so的符号都是需要重定位的,所以才叫重定位文件嘛
//内部符号和外部.o的符号在链接时由链接器重定位
//外部.so的符号由...........
//虽此时没能定位,但是所有符号在.text(和.data)section的位置--offset已定|
//这个表的作用是指示链接器,你需要在代码段中的这些Offset处重新塞进一些数据,
//这个新的数据却不是外部符号已确定的虚拟地址,而是一个偏移量
//通过这个偏移量可以找到想要的符号的虚拟地址,见后面-------
看一下hello.o的反汇编
[root@localhost mhello]# objdump -S hello.o
hello.o: file format elf32-i386
Disassembly of section .text:
00000000 <func_hello>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: c7 04 24 00 00 00 00 movl $0x0,(%esp)
d: e8 fc ff ff ff call e <func_hello+0xe>
12: c9 leave
13: c3 ret
00000014 <main>:
14: 8d 4c 24 04 lea 0x4(%esp),%ecx
18: 83 e4 f0 and $0xfffffff0,%esp
1b: ff 71 fc pushl -0x4(%ecx)
1e: 55 push %ebp
1f: 89 e5 mov %esp,%ebp
21: 51 push %ecx
22: 83 ec 04 sub $0x4,%esp
25: c7 04 24 15 00 00 00 movl $0x15,(%esp)
2c: e8 fc ff ff ff call 2d <main+0x19>
31: e8 fc ff ff ff call 32 <main+0x1e>
36: c7 04 24 06 00 00 00 movl $0x6,(%esp)
3d: e8 fc ff ff ff call 3e <main+0x2a>
42: c7 04 24 06 00 00 00 movl $0x6,(%esp)
49: e8 fc ff ff ff call 4a <main+0x36>
4e: c7 04 24 20 00 00 00 movl $0x20,(%esp)
55: e8 fc ff ff ff call 56 <main+0x42>
5a: b8 00 00 00 00 mov $0x0,%eax
5f: 83 c4 04 add $0x4,%esp
62: 59 pop %ecx
63: 5d pop %ebp
64: 8d 61 fc lea -0x4(%ecx),%esp
67: c3 ret
出现了几个call 3e <main+0x2a>之类的代码,3e是相对本段即text段的偏移,2a是相对main符号的偏移,main:14,3e=2a+14
他们的二进制是清一色的e8 fc ff ff ff ,e8是近地址相对位移调用指令,fc ff ff ff (=-4) 是被调用函数的相对于调用指令的下一条指定的偏移量
此时,即
2c: e8 fc ff ff ff // 地址为-4+31=2d,所以其汇编为 call 2d
31: e8 fc ff ff ff
36: c7 04 24 06 00 00 00
3d: e8 fc ff ff ff //3e 3f 40 41保存的是一个相对于42的偏移量X,而42+X便是要cpu去拜访的符号的地址
//,X现在暂定为-4
//所以地址为-4+42=3e,所以其汇编为 call 3e,(3e是目标地址,即跳转到地址3e去执行)-
//----巧的是本指令地址后面就是地址3e,
//这个巧合,却让我误以为3e里面以后会放一些虚拟地址之类的东东,现在知道额错了,
//3e-3f-40-41里面放的仅仅是偏移---
3e fc //在hello.o中3e处的值没有意义,因为hello.o不能执行,所以管你是
3f ff //多少呢,我又不去你那玩
40 ff //为什么是偏偏是-4(fc ff ff ff )呢?或许用100便不会引起我之前的误会了,
41 ff //便是cpu跳到42+100处执行任务
42: c7 04 24 06 00 00 00
49: e8 fc ff ff ff
4e: c7 04 24 20 00 00 00
55: e8 fc ff ff ff
[root@localhost mhello]# readelf -S hello.o
There are 11 section headers, starting at offset 0x144:
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 000068 00 AX 0 0 4
[ 2] .rel.text REL 00000000 000448 000048 08 9 1 4
[ 3] .data PROGBITS 00000000 00009c 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 00009c 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 00009c 000029 00 A 0 0 1
[ 6] .comment PROGBITS 00000000 0000c5 00002d 00 0 0 1
[ 7] .note.GNU-stack PROGBITS 00000000 0000f2 000000 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 0000f2 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 0002fc 0000f0 10 10 8 4
[10] .strtab STRTAB 00000000 0003ec 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)
[root@localhost mhello]# readelf -s hello.o
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 hello.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 20 FUNC GLOBAL DEFAULT 1 func_hello
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
10: 00000014 84 FUNC GLOBAL DEFAULT 1 main
11: 00000000 0 NOTYPE GLOBAL DEFAULT UND func_file_a
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND func_file_b
13: 00000004 4 OBJECT GLOBAL DEFAULT COM var_public_file_a
14: 00000004 4 OBJECT GLOBAL DEFAULT COM var_public_file_b
//func_hello,main都是在本模块hello.o内部定义的,所以符号位置在1段,即代码段
//func_file_a,func_file_b是外部符号,前者是一个来自另外一个.o的符号,后者是来自另外一个.so的符号,
//但对于hello.o而言二者都是外部符号,hello.o无力判断他们的出身,将他们视为und--undefined
//var_public_file_a,var_public_file_b放在common块中,在hello.o中还不确定他们到底是不是
//在本模块定义的,因为没有初始化,也没有加extern,现将其是为弱符号,留校观察
看一下hello.o的重定位表
[root@localhost mhello]# readelf -r hello.o
Relocation section '.rel.text' at offset 0x424 contains 9 entries:
Offset Info Type Sym.Value Sym. Name
00000009 00000501 R_386_32 00000000 .rodata
0000000e 00000902 R_386_PC32 00000000 puts
00000028 00000501 R_386_32 00000000 .rodata
0000002d 00000902 R_386_PC32 00000000 puts
00000032 00000802 R_386_PC32 00000000 func_hello
0000003e 00000b02 R_386_PC32 00000000 func_file_a
0000004a 00000c02 R_386_PC32 00000000 func_file_b
00000051 00000501 R_386_32 00000000 .rodata
00000056 00000902 R_386_PC32 00000000 puts
//看来不管内部符号,还是外部.o的符号,还是外部.so的符号都是需要重定位的,所以才叫重定位文件嘛
//内部符号和外部.o的符号在链接时由链接器重定位
//外部.so的符号由...........
//虽此时没能定位,但是所有符号在.text(和.data)section的位置--offset已定|
//这个表的作用是指示链接器,你需要在代码段中的这些Offset处重新塞进一些数据,
//这个新的数据却不是外部符号已确定的虚拟地址,而是一个偏移量
//通过这个偏移量可以找到想要的符号的虚拟地址,见后面-------
看一下hello.o的反汇编
[root@localhost mhello]# objdump -S hello.o
hello.o: file format elf32-i386
Disassembly of section .text:
00000000 <func_hello>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: c7 04 24 00 00 00 00 movl $0x0,(%esp)
d: e8 fc ff ff ff call e <func_hello+0xe>
12: c9 leave
13: c3 ret
00000014 <main>:
14: 8d 4c 24 04 lea 0x4(%esp),%ecx
18: 83 e4 f0 and $0xfffffff0,%esp
1b: ff 71 fc pushl -0x4(%ecx)
1e: 55 push %ebp
1f: 89 e5 mov %esp,%ebp
21: 51 push %ecx
22: 83 ec 04 sub $0x4,%esp
25: c7 04 24 15 00 00 00 movl $0x15,(%esp)
2c: e8 fc ff ff ff call 2d <main+0x19>
31: e8 fc ff ff ff call 32 <main+0x1e>
36: c7 04 24 06 00 00 00 movl $0x6,(%esp)
3d: e8 fc ff ff ff call 3e <main+0x2a>
42: c7 04 24 06 00 00 00 movl $0x6,(%esp)
49: e8 fc ff ff ff call 4a <main+0x36>
4e: c7 04 24 20 00 00 00 movl $0x20,(%esp)
55: e8 fc ff ff ff call 56 <main+0x42>
5a: b8 00 00 00 00 mov $0x0,%eax
5f: 83 c4 04 add $0x4,%esp
62: 59 pop %ecx
63: 5d pop %ebp
64: 8d 61 fc lea -0x4(%ecx),%esp
67: c3 ret
出现了几个call 3e <main+0x2a>之类的代码,3e是相对本段即text段的偏移,2a是相对main符号的偏移,main:14,3e=2a+14
他们的二进制是清一色的e8 fc ff ff ff ,e8是近地址相对位移调用指令,fc ff ff ff (=-4) 是被调用函数的相对于调用指令的下一条指定的偏移量
此时,即
2c: e8 fc ff ff ff // 地址为-4+31=2d,所以其汇编为 call 2d
31: e8 fc ff ff ff
36: c7 04 24 06 00 00 00
3d: e8 fc ff ff ff //3e 3f 40 41保存的是一个相对于42的偏移量X,而42+X便是要cpu去拜访的符号的地址
//,X现在暂定为-4
//所以地址为-4+42=3e,所以其汇编为 call 3e,(3e是目标地址,即跳转到地址3e去执行)-
//----巧的是本指令地址后面就是地址3e,
//这个巧合,却让我误以为3e里面以后会放一些虚拟地址之类的东东,现在知道额错了,
//3e-3f-40-41里面放的仅仅是偏移---
3e fc //在hello.o中3e处的值没有意义,因为hello.o不能执行,所以管你是
3f ff //多少呢,我又不去你那玩
40 ff //为什么是偏偏是-4(fc ff ff ff )呢?或许用100便不会引起我之前的误会了,
41 ff //便是cpu跳到42+100处执行任务
42: c7 04 24 06 00 00 00
49: e8 fc ff ff ff
4e: c7 04 24 20 00 00 00
55: e8 fc ff ff ff
相关文章推荐
- 静态连接1-hello hello.o file_a.o file_b.so
- 静态连接4-hello
- 静态连接5-hello
- Apache 下通过 .htaccess 文件实现伪静态连接
- 静态连接库
- 一篇很不错的介绍静态连接和动态链接的文章
- MySQL 数据库连接 静态语句块
- 静态使用DLL动态连接库
- 动态连接库和静态连接库有什么区别?
- 树莓派3连接WIFI及静态配置IP地址
- 关于PHP程序使用file_get_content()函数进行抓取PHP程序与smarty结合编译过程中产生的静态文件,抓取不了?连接超时?(地址映射)
- VS中使用sqlite静态连接
- 7天hadoop学习(一)之虚拟机的网络连接方式及linux的静态ip设置
- asp.net 生成静态网页并加连接
- 【虚拟机-网络IP】虚拟机配置静态 IP 以后无法连接的解决办法
- 更改静态ip导致无法连接网络
- 静态连接时undefindereference错误原因及解决方法
- 使用静态库 静态连接和动态连接
- 静态连接库和动态链接库的区别
- Dev-Cpp/Mingw32环境下使用静态连接库和做自己的静态库