查看GNU/Linux 库机制笔记的源代码
←
GNU/Linux 库机制笔记
跳转到:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
== x86 下动态链接库机制 == 以下内容原记载于个人百度空间 http://hi.baidu.com/comcat/item/4166ef00ab975ad11ef04683 时间:2008-07-19 20:47 考虑以下简单的程序: <source lang=bash> int main() { printf("f[0] = %d\n", 0x0); printf("f[0] = %d\n", 0x8); return 0; } [root@comcat]$ gdb ./test (gdb) disass main Dump of assembler code for function main: 0x08048374 <main+0>: lea 0x4(%esp),%ecx 0x08048378 <main+4>: and $0xfffffff0,%esp 0x0804837b <main+7>: pushl -0x4(%ecx) 0x0804837e <main+10>: push %ebp 0x0804837f <main+11>: mov %esp,%ebp 0x08048381 <main+13>: push %ecx 0x08048382 <main+14>: sub $0x14,%esp 0x08048385 <main+17>: movl $0x0,0x4(%esp) 0x0804838d <main+25>: movl $0x8048480,(%esp) 0x08048394 <main+32>: call 0x80482d8 <printf@plt> 0x08048399 <main+37>: movl $0x8,0x4(%esp) 0x080483a1 <main+45>: movl $0x8048480,(%esp) 0x080483a8 <main+52>: call 0x80482d8 <printf@plt> 0x080483ad <main+57>: mov $0x0,%eax 0x080483b2 <main+62>: add $0x14,%esp 0x080483b5 <main+65>: pop %ecx 0x080483b6 <main+66>: pop %ebp 0x080483b7 <main+67>: lea -0x4(%ecx),%esp 0x080483ba <main+70>: ret End of assembler dump. (gdb) x /8i 0x80482d8 0x80482d8 <printf@plt>: jmp *0x804958c ----> 0x804958c 处的值为 0x80482de,则其实际上跳到了下一条指令处。 0x80482de <printf@plt+6>: push $0x10 0x80482e3 <printf@plt+11>: jmp 0x80482a8 <_init+48> 0x80482e8: Cannot access memory at address 0x80482e8 (gdb) x /4x 0x804958c 0x804958c <_GLOBAL_OFFSET_TABLE_+20>: 0x080482de 0x00000000 0x00000000 0x0804949c (gdb) b *0x0804838d Breakpoint 1 at 0x804838d: file test.c, line 3. (gdb) r Starting program: /home/comcat/develop/test/dl/test Breakpoint 1, 0x0804838d in main () at test.c:3 3 printf("f[0] = %d\n", 0); (gdb) si 0x08048394 3 printf("f[0] = %d\n", 0); (gdb) 0x080482d8 in printf@plt () (gdb) 0x080482de in printf@plt () (gdb) 0x080482e3 in printf@plt () (gdb) x /4i 0x80482a8 0x80482a8 <_init+48>: pushl 0x804957c 0x80482ae <_init+54>: jmp *0x8049580 0x80482b4 <_init+60>: add %al,(%eax) 0x80482b6 <_init+62>: add %al,(%eax) (gdb) x /4x 0x8049580 0x8049580 <_GLOBAL_OFFSET_TABLE_+8>: 0xb7fc02d0 0x080482be 0xb7e6e370 0x080482de ----> 0xb7fc02d0 处为动态链接器的解析函数 _dl_runtime_resolve() (gdb) si 0x080482a8 in ?? () (gdb) si 0x080482ae in ?? () (gdb) si 0xb7fc02d0 in _dl_runtime_resolve () from /lib/ld-linux.so.2 (gdb) b *0x080483a1 Breakpoint 2 at 0x80483a1: file test.c, line 4. (gdb) c Continuing. f[0] = 0 Breakpoint 2, 0x080483a1 in main () at test.c:4 ----> 第一次 printf 调用已经完,动态链接器已经修改 GOT 的相应项为 printf 的地址 4 printf("f[0] = %d\n", 8); (gdb) x /8i 0x80482d8 ----> PLT 没有变化,但原 GOT 入口 0x804958c 处的值已经被改写为 printf 的地址 0x80482d8 <printf@plt>: jmp *0x804958c 0x80482de <printf@plt+6>: push $0x10 0x80482e3 <printf@plt+11>: jmp 0x80482a8 <_init+48> 0x80482e8: add %al,(%eax) 0x80482ea: add %al,(%eax) 0x80482ec: add %al,(%eax) 0x80482ee: add %al,(%eax) 0x80482f0 <printf@plt+24>: xor %ebp,%ebp (gdb) x /4x 0x804958c 0x804958c <_GLOBAL_OFFSET_TABLE_+20>: 0xb7e9f170 0x00000000 0x00000000 0x0804949c (gdb) x /4i 0xb7e9f170 0xb7e9f170 <printf>: push %ebp 0xb7e9f171 <printf+1>: mov %esp,%ebp 0xb7e9f173 <printf+3>: push %ebx 0xb7e9f174 <printf+4>: call 0xb7e6e28f <__i686.get_pc_thunk.bx> </source> x86 下动态链接机制,动态链接器不会更改 PLT,只会在用到相应链接函数时,才会去解析符号,然后将对应的地址更新到 GOT 的相应项,GOT 里亦没有代码,不需要执行。 <br><br>
返回到
GNU/Linux 库机制笔记
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面