免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1323 | 回复: 0

关于linux共享库内部的plt调用的说法 [复制链接]

论坛徽章:
0
发表于 2009-03-02 18:38 |显示全部楼层

                               
因为有人讨论起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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP