<?xml version="1.0" encoding="gbk"?> <rss version="2.0"><channel> <title>定阅帖子更新</title> <link>http://www.broadkey.com.cn/XML.ASP</link><description>TEAM Board - 意得法电子</description> <copyright>TEAM 2.0.5 Release</copyright><generator>TEAM Board by TEAM5.Cn Studio</generator> <ttl>30</ttl><item><link>http://www.broadkey.com.cn/Thread.asp?tid=48 </link><title>x86&amp;nbsp;下动态链接库机制</title><author>east</author><pubDate>2009-11-25 23:33:24</pubDate><description><![CDATA[考虑以下简单的程序：<br />
<br />
<font color="#808080">int</font> <font color="#009900"><strong>main</strong></font>()<br />
{<br />
<font color="#808080">&nbsp;&nbsp;&nbsp; printf(</font><font color="#808080">&quot;f[0] = </font><font color="#808080">%d\n</font><font color="#808080">&quot;, 0x0);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; printf(</font><font color="#808080">&quot;f[0] = </font><font color="#808080">%d\n</font><font color="#808080">&quot;, 0x8);&nbsp;&nbsp;&nbsp;</font> <br />
&nbsp;&nbsp;&nbsp; <font color="#ff9900">return</font> 0;<br />
}<br />
<br />
[root@comcat]$ gdb ./test <br />
<br />
(gdb) disass main<br />
Dump of assembler code for function main:<br />
0x08048374 &lt;main+0&gt;:&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp; 0x4(%esp),%ecx<br />
0x08048378 &lt;main+4&gt;:&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp; $0xfffffff0,%esp<br />
0x0804837b &lt;main+7&gt;:&nbsp;&nbsp;&nbsp; pushl -0x4(%ecx)<br />
0x0804837e &lt;main+10&gt;:&nbsp;&nbsp; push&nbsp;&nbsp; %ebp<br />
0x0804837f &lt;main+11&gt;:&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; %esp,%ebp<br />
0x08048381 &lt;main+13&gt;:&nbsp;&nbsp; push&nbsp;&nbsp; %ecx<br />
0x08048382 &lt;main+14&gt;:&nbsp;&nbsp; sub&nbsp;&nbsp;&nbsp; $0x14,%esp<br />
0x08048385 &lt;main+17&gt;:&nbsp;&nbsp; movl&nbsp;&nbsp; $0x0,0x4(%esp)<br />
0x0804838d &lt;main+25&gt;:&nbsp;&nbsp; movl&nbsp;&nbsp; $0x8048480,(%esp)<br />
0x08048394 &lt;main+32&gt;:&nbsp;&nbsp; call&nbsp;&nbsp; 0x80482d8 &lt;printf@plt&gt;<br />
0x08048399 &lt;main+37&gt;:&nbsp;&nbsp; movl&nbsp;&nbsp; $0x8,0x4(%esp)<br />
0x080483a1 &lt;main+45&gt;:&nbsp;&nbsp; movl&nbsp;&nbsp; $0x8048480,(%esp)<br />
0x080483a8 &lt;main+52&gt;:&nbsp;&nbsp; call&nbsp;&nbsp; 0x80482d8 &lt;printf@plt&gt;<br />
0x080483ad &lt;main+57&gt;:&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; $0x0,%eax<br />
0x080483b2 &lt;main+62&gt;:&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; $0x14,%esp<br />
0x080483b5 &lt;main+65&gt;:&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp; %ecx<br />
0x080483b6 &lt;main+66&gt;:&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp; %ebp<br />
0x080483b7 &lt;main+67&gt;:&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp; -0x4(%ecx),%esp<br />
0x080483ba &lt;main+70&gt;:&nbsp;&nbsp; ret&nbsp;&nbsp;&nbsp; <br />
End of assembler dump.<br />
(gdb) x /8i 0x80482d8<br />
0x80482d8 &lt;printf@plt&gt;: <strong>jmp&nbsp;&nbsp;&nbsp; *<font color="#99cc00">0x804958c</font></strong><font color="#99cc00">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#3366ff">----&gt; 0x804958c 处的值为 0x80482de，则其实际上跳到了下一条指令处。</font></font><br />
<font color="#ff6600">0x80482de</font> &lt;printf@plt+6&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp; $0x10<br />
0x80482e3 &lt;printf@plt+11&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp; 0x80482a8 &lt;_init+48&gt;<br />
0x80482e8:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cannot access memory at address 0x80482e8<br />
(gdb) x /4x <strong><font color="#99cc00">0x804958c</font></strong><br />
0x804958c &lt;_GLOBAL_OFFSET_TABLE_+20&gt;:&nbsp;&nbsp; <font color="#ff6600">0x080482de</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0804949c<br />
(gdb) b *0x0804838d<br />
Breakpoint 1 at 0x804838d: file test.c, line 3.<br />
(gdb) r<br />
Starting program: /home/comcat/develop/test/dl/test <br />
<br />
Breakpoint 1, 0x0804838d in main () at test.c:3<br />
3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;f[0] = %d\n&quot;, 0);<br />
(gdb) si<br />
0x08048394&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;f[0] = %d\n&quot;, 0);<br />
(gdb) <br />
0x080482d8 in printf@plt ()<br />
(gdb) <br />
0x080482de in printf@plt ()<br />
(gdb) <br />
0x080482e3 in printf@plt ()<br />
<br />
(gdb) x /4i 0x80482a8<br />
0x80482a8 &lt;_init+48&gt;:&nbsp;&nbsp; pushl 0x804957c<br />
0x80482ae &lt;_init+54&gt;:&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp; *<font color="#009900">0x8049580</font><br />
0x80482b4 &lt;_init+60&gt;:&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; %al,(%eax)<br />
0x80482b6 &lt;_init+62&gt;:&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; %al,(%eax)<br />
(gdb) x /4x <font color="#009900">0x8049580</font><br />
0x8049580 &lt;_GLOBAL_OFFSET_TABLE_+8&gt;:&nbsp;&nbsp;&nbsp; <strong>0xb7fc02d0</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x080482be&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0xb7e6e370&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x080482de&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&gt; 0xb7fc02d0 处为动态链接器的解析函数 _dl_runtime_resolve()<br />
<br />
(gdb) si<br />
0x080482a8 in ?? ()<br />
(gdb) si<br />
0x080482ae in ?? ()<br />
(gdb) si<br />
0xb7fc02d0 in _dl_runtime_resolve () from /lib/ld-linux.so.2<br />
<br />
(gdb) b *0x080483a1<br />
Breakpoint 2 at 0x80483a1: file test.c, line 4.<br />
(gdb) c<br />
Continuing.<br />
f[0] = 0<br />
<br />
Breakpoint 2, 0x080483a1 in main () at test.c:4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&gt; 第一次 printf 调用已经完，动态链接器已经修改 GOT 的相应项为 printf 的地址<br />
4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;f[0] = %d\n&quot;, 8);<br />
<br />
(gdb) x /8i 0x80482d8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&gt; PLT 没有变化，但原 GOT 入口 <strong><font color="#99cc00">0x804958c<font color="#808080"> </font></font></strong><font color="#808080">处的值已经被改写为 printf 的地址</font><br />
0x80482d8 &lt;printf@plt&gt;: jmp&nbsp;&nbsp;&nbsp; *<strong><font color="#99cc00">0x804958c</font></strong><br />
0x80482de &lt;printf@plt+6&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp; $0x10<br />
0x80482e3 &lt;printf@plt+11&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp; 0x80482a8 &lt;_init+48&gt;<br />
0x80482e8:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; %al,(%eax)<br />
0x80482ea:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; %al,(%eax)<br />
0x80482ec:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; %al,(%eax)<br />
0x80482ee:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp; %al,(%eax)<br />
0x80482f0 &lt;printf@plt+24&gt;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp; %ebp,%ebp<br />
(gdb) x /4x <font color="#99cc00"><strong>0x804958c</strong></font><br />
0x804958c &lt;_GLOBAL_OFFSET_TABLE_+20&gt;:&nbsp;&nbsp; <font color="#ff9900"><strong>0xb7e9f170</strong></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0804949c<br />
(gdb) x /4i <font color="#ff00ff">0xb7e9f170</font><br />
0xb7e9f170 &lt;printf&gt;:&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp; %ebp<br />
0xb7e9f171 &lt;printf+1&gt;: mov&nbsp;&nbsp;&nbsp; %esp,%ebp<br />
0xb7e9f173 &lt;printf+3&gt;: push&nbsp;&nbsp; %ebx<br />
0xb7e9f174 &lt;printf+4&gt;: call&nbsp;&nbsp; 0xb7e6e28f &lt;__i686.get_pc_thunk.bx&gt;<br />
<br />
x86 下动态链接机制，动态链接器不会更改 PLT，只会在用到相应链接函数时，才会去解析符号，然后将对应的地址更新到 GOT 的相应项，GOT 里亦没有代码，不需要执行。<br />
<br />]]></description></item></channel></rss>