Notes for shared libraries in linux-fpic, linux shared library-fpic
-Fpic must be added to the compilation shared library. Why?
First, let's look at a simple example:
#include <stdio.h>int fun1(){ printf("fun1\n");}
Generate a library without adding-fpic first, and disassemble it to view the machine code of 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
We can see that the position where printf is called is the only call, not to jump to the plt table. You can view the content of the plt table in the previous blog. That is to say, when the library is loaded, you need to modify the code segment to achieve the relocation effect. Therefore, each program that loads the shared library must have a copy of the database, which does not actually achieve the shared library effect.
Check the running machine code.
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
Obviously, the code segment has been modified.
Let's take a look at the library generated with the added-fpic, and disassemble the machine code of 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
Many people who have read the assembly code know that printf is sometimes puts, so the printf in this machine code corresponds to the second call, that is, jump to the plt table to find the puts symbol, in this way, the effect of the shared database is achieved. At this time, each program that requires the database only has a copy of the plt table, and all the applications in the code segment are shared.
Check the running machine code again.
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
Obviously, they are consistent.
Therefore, you must add the-fpic option when compiling the shared library. Otherwise, the shared library only has space on the hard disk, but no memory.