歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> 學習Linux

linux下共享庫的注意點之-fpic,linux共享庫-fpic

linux下共享庫的注意點之-fpic,linux共享庫-fpic


linux下共享庫的注意點之-fpic,linux共享庫-fpic


在編譯共享庫必須加上-fpic。這是為什麼呢?

首先看一個簡單的例子:

#include <stdio.h>

int fun1()
{
        printf("fun1\n");
}

先不加-fpic的情況下生成庫,反匯編查看fun1的機器碼

0000044c <fun1>:
 44c:   55                      push   %ebp
 44d:   89 e5                   mov    %esp,%ebp
 44f:   83 ec 18                sub    $0x18,%esp
 452:   c7 04 24 b2 04 00 00    movl   $0x4b2,(%esp)
 459:   e8 fc ff ff ff          call   45a <fun1+0xe>
 45e:   c9                      leave  
 45f:   c3                      ret  

可以看出調用printf的位置是那個唯一的一個call,並不是跳轉到plt表,有關plt表的內容可以查看我前面的博文。也就是說在該庫被加載時需要修改代碼段來達到重定位的效果。那麼每一個加載這個共享庫的程序都要有這個庫的一份拷貝,這樣實際上就沒有達到共享庫的效果。

看下運行時的機器碼

   0xb771d44c <+0>:     55      push   %ebp
   0xb771d44d <+1>:     89 e5   mov    %esp,%ebp
   0xb771d44f <+3>:     83 ec 18        sub    $0x18,%esp
   0xb771d452 <+6>:     c7 04 24 b2 d4 71 b7    movl   $0xb771d4b2,(%esp)
   0xb771d459 <+13>:    e8 42 b2 ea ff  call   0xb75c86a0 <puts>
   0xb771d45e <+18>:    c9      leave  
   0xb771d45f <+19>:    c3      ret 

顯然代碼段被修改了。

再看一下再加了-fpic的情況下生成的庫,反匯編看下fun1的機器碼

0000045c <fun1>:
 45c:   55                      push   %ebp
 45d:   89 e5                   mov    %esp,%ebp
 45f:   53                      push   %ebx
 460:   83 ec 14                sub    $0x14,%esp
 463:   e8 ef ff ff ff          call   457 <__i686.get_pc_thunk.bx>
 468:   81 c3 8c 1b 00 00       add    $0x1b8c,%ebx
 46e:   8d 83 ee e4 ff ff       lea    -0x1b12(%ebx),%eax
 474:   89 04 24                mov    %eax,(%esp)
 477:   e8 04 ff ff ff          call   380 <puts@plt>
 47c:   83 c4 14                add    $0x14,%esp
 47f:   5b                      pop    %ebx
 480:   5d                      pop    %ebp
 481:   c3                      ret    
 482:   90                      nop
 483:   90                      nop
 484:   90                      nop
 485:   90                      nop
 486:   90                      nop
 487:   90                      nop
 488:   90                      nop

看過很多匯編代碼的人知道printf有時候是puts,所以這段機器碼中printf就對應第二個call,也就是跳轉到plt表中去查找puts符號,那麼這樣就達到了共享庫的效果,此時每一個需要該庫的程序只是有一個plt表的拷貝,而代碼段所有應用程序是共享的。

再看下運行時機器碼

   0xb773045c <+0>:     55      push   %ebp
   0xb773045d <+1>:     89 e5   mov    %esp,%ebp
   0xb773045f <+3>:     53      push   %ebx
   0xb7730460 <+4>:     83 ec 14        sub    $0x14,%esp
   0xb7730463 <+7>:     e8 ef ff ff ff  call   0xb7730457 <__i686.get_pc_thunk.bx>
   0xb7730468 <+12>:    81 c3 8c 1b 00 00       add    $0x1b8c,%ebx
   0xb773046e <+18>:    8d 83 ee e4 ff ff       lea    -0x1b12(%ebx),%eax
   0xb7730474 <+24>:    89 04 24        mov    %eax,(%esp)
   0xb7730477 <+27>:    e8 04 ff ff ff  call   0xb7730380 <puts@plt>
   0xb773047c <+32>:    83 c4 14        add    $0x14,%esp
   0xb773047f <+35>:    5b      pop    %ebx
   0xb7730480 <+36>:    5d      pop    %ebp
   0xb7730481 <+37>:    c3      ret 

顯然是一致的。

所以,在編譯共享庫時是必須加上-fpic的選項的,否則共享庫剩下的僅僅是硬盤上的空間,而沒有剩下內存。

http://xxxxxx/Linuxjc/1143291.html TechArticle

Copyright © Linux教程網 All Rights Reserved