- 论坛徽章:
- 0
|
因为有人讨论起linux的共享库的函数调用地址的问题,为了能简单的进行探讨,特就两段简单的代码进行比较来说明linux下plt的一写简单特点:
testdll.c
#include
#include
#include
char buffer[100];
int main()
{
int handle;
handle=open("myfile",O_RDONLY);
close(handle);
return(0);
}
testdll2.c
#include
#include
#include
char buffer[100];
int main()
{
int handle;
printf("hello! world");
handle=open("myfile",O_RDONLY);
close(handle);
return(0);
}
[root@localhost test]# gdb testdll
GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/i686/nosegneg/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x80483c5: file testdll.c, line 12.
(gdb) r
Starting program: /test/testdll
Breakpoint 1, main () at testdll.c:12
12 handle=open("myfile",O_RDONLY);
(gdb) disass main
Dump of assembler code for function main:
0x080483b4 : lea 0x4(%esp),%ecx
0x080483b8 : and $0xfffffff0,%esp
0x080483bb : pushl 0xfffffffc(%ecx)
0x080483be : push %ebp
0x080483bf : mov %esp,%ebp
0x080483c1 : push %ecx
0x080483c2 : sub $0x24,%esp
0x080483c5 : movl $0x0,0x4(%esp)
0x080483cd : movl $0x80484d0,(%esp)
0x080483d4 : call 0x8048294
0x080483d9 : mov %eax,0xfffffff8(%ebp)
0x080483dc : mov 0xfffffff8(%ebp),%eax
0x080483df : mov %eax,(%esp)
0x080483e2 : call 0x80482c4
0x080483e7 : mov $0x0,%eax
0x080483ec : add $0x24,%esp
0x080483ef : pop %ecx
0x080483f0 : pop %ebp
0x080483f1 : lea 0xfffffffc(%ecx),%esp
0x080483f4 : ret
End of assembler dump.
(gdb) n
13 close(handle);
(gdb) disass main
Dump of assembler code for function main:
0x080483b4 : lea 0x4(%esp),%ecx
0x080483b8 : and $0xfffffff0,%esp
0x080483bb : pushl 0xfffffffc(%ecx)
0x080483be : push %ebp
0x080483bf : mov %esp,%ebp
0x080483c1 : push %ecx
0x080483c2 : sub $0x24,%esp
0x080483c5 : movl $0x0,0x4(%esp)
0x080483cd : movl $0x80484d0,(%esp)
0x080483d4 : call 0x8048294 //调用open,这个地址不是真正的open地址
0x080483d9 : mov %eax,0xfffffff8(%ebp)
0x080483dc : mov 0xfffffff8(%ebp),%eax
0x080483df : mov %eax,(%esp)
0x080483e2 : call 0x80482c4
0x080483e7 : mov $0x0,%eax
0x080483ec : add $0x24,%esp
0x080483ef : pop %ecx
0x080483f0 : pop %ebp
0x080483f1 : lea 0xfffffffc(%ecx),%esp
0x080483f4 : ret
End of assembler dump.
(gdb) disass 0x8048294
Dump of assembler code for function open@plt:
0x08048294 : jmp *0x80495c8
0x0804829a : push $0x0
0x0804829f : jmp 0x8048284
End of assembler dump.
(gdb) x 0x80495c8
0x80495c8 : 0x0090cf20 //open函数的地址
(gdb)
gdb testdll2
GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/i686/nosegneg/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x80483f5: file testdll.c, line 10.
(gdb) r
Starting program: /testdll2
Breakpoint 1, main () at testdll.c:10
10 printf("hello! world");
(gdb) disass main
Dump of assembler code for function main:
0x080483e4 : lea 0x4(%esp),%ecx
0x080483e8 : and $0xfffffff0,%esp
0x080483eb : pushl 0xfffffffc(%ecx)
0x080483ee : push %ebp
0x080483ef : mov %esp,%ebp
0x080483f1 : push %ecx
0x080483f2 : sub $0x24,%esp
0x080483f5 : movl $0x8048510,(%esp)
0x080483fc : call 0x80482e8
0x08048401 : movl $0x0,0x4(%esp)
0x08048409 : movl $0x804851d,(%esp)
0x08048410 : call 0x80482b8 //调用open,这个地址不是真正的open地址
0x08048415 : mov %eax,0xfffffff8(%ebp)
0x08048418 : mov 0xfffffff8(%ebp),%eax
0x0804841b : mov %eax,(%esp)
0x0804841e : call 0x80482f8
0x08048423 : mov $0x0,%eax
0x08048428 : add $0x24,%esp
0x0804842b : pop %ecx
0x0804842c : pop %ebp
0x0804842d : lea 0xfffffffc(%ecx),%esp
0x08048430 : ret
---Type to continue, or q to quit---
End of assembler dump.
(gdb) n
12 handle=open("myfile",O_RDONLY);
(gdb) n
13 close(handle);
(gdb) disass main
Dump of assembler code for function main:
0x080483e4 : lea 0x4(%esp),%ecx
0x080483e8 : and $0xfffffff0,%esp
0x080483eb : pushl 0xfffffffc(%ecx)
0x080483ee : push %ebp
0x080483ef : mov %esp,%ebp
0x080483f1 : push %ecx
0x080483f2 : sub $0x24,%esp
0x080483f5 : movl $0x8048510,(%esp)
0x080483fc : call 0x80482e8
0x08048401 : movl $0x0,0x4(%esp)
0x08048409 : movl $0x804851d,(%esp)
0x08048410 : call 0x80482b8
0x08048415 : mov %eax,0xfffffff8(%ebp)
0x08048418 : mov 0xfffffff8(%ebp),%eax
0x0804841b : mov %eax,(%esp)
0x0804841e : call 0x80482f8
0x08048423 : mov $0x0,%eax
0x08048428 : add $0x24,%esp
0x0804842b : pop %ecx
0x0804842c : pop %ebp
0x0804842d : lea 0xfffffffc(%ecx),%esp
0x08048430 : ret
---Type to continue, or q to quit---disass 80482b8
End of assembler dump.
(gdb) disass 0x80482b8
Dump of assembler code for function open@plt:
0x080482b8 : jmp *0x8049614
0x080482be : push $0x0
0x080482c3 : jmp 0x80482a8
End of assembler dump.
(gdb) x 0x8049614
0x8049614 : 0x0090cf20 //open函数的地址
(gdb)
在testdll.c中
0x080483d4 : call 0x8048294
0x08048294 : jmp *0x80495c8
0x0804829a : push $0x0
0x0804829f : jmp 0x8048284
(gdb) x 0x80495c8
0x80495c8 : 0x0090cf20
open@plt在0x080483d4地址处,而真正的open地址在0x80495c8处(从jmp *0x80495c8可以的出), 可以看到0x080495c8地址处的是0x0090cf20这是指向了真正open的映射.
在testdll2.c中
0x08048410 : call 0x80482b8
0x080482b8 : jmp *0x8049614
0x080482be : push $0x0
0x080482c3 : jmp 0x80482a8
(gdb) x 0x8049614
0x8049614 : 0x0090cf20
open@plt在0x080482b8地址处,而真正的open地址在0x8049614处(从jmp *0x8049614可以的出), 可以看到0x8049614地址处的是0x0090cf20这是指向了真正open的映射.
需要说明的是0x8049614处的值在程序(这里是testdll2)运行第一此调用open的时候由stub程序修改为实际指向open的地址. 而stub程序就是
0x080482b8 : jmp *0x8049614
0x080482be : push $0x0
0x080482c3 : jmp 0x80482a8
开始的这段代码,当第一此修改0x8049614的值后,以后由于jmp *0x8049614直接可以访问到open函数,因此加快了访问速度.
为了证实stub程序是否修改jmp *xxxx中xxxx处的值,我们继续看没有运行到的close@plt
0x0804841e : call 0x80482f8
(gdb) disass 0x80482f8
Dump of assembler code for function close@plt:
0x080482f8 : jmp *0x8049624
0x080482fe : push $0x20
0x08048303 : jmp 0x80482a8
End of assembler dump.
(gdb) x 0x8049624
0x8049624 : 0x080482fe
(gdb)
如上看到的jmp *0x8049624 中 *0x8049624实际上就是0x080482fe,也就是一个没有指向close的地址,这个地址需要stub程序去填写.
当call 0x80482f8 完成后
(gdb) x 0x8049624
0x8049624 : 0x0090d5a0
(gdb)
此处的值已经被修改了。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/86872/showart_1848976.html |
|