c语言学习笔记十六

共享库
  
命名规范:
 通常带有符号链接 ls -l /lib 
...
  libipq_pic.so.0                       libulockmgr.so.1
libipq_pic.so.0.0.0                   libulockmgr.so.1.0.1
libipq.so.0                           libusb-0.1.so.4
libipq.so.0.0.0                       libusb-0.1.so.4.4.4
 ...
共享库文件名的组成:
  real name 库文件
  soname    符号链接的名字,共享库的主版本号
        
     示例代码:
       /*soname:libstack.so.1
        *real name: libstack.so.1.0
        */
       gcc -shared -Wl,-soname,libstack.so.1 -o libstack.so.1.0 test20.o 


test21.o test22.o test23.o
  linker name  gcc的-L选项指定linker name所在的目录
     创建linker name 的符号链接
        ln -s libstack.so.1.0 libstack.so
        gcc test24.c -L. -lstack -Istack -o main


 


共享库在编译时要加-fPIC选项,
 1 编译目标文件命令为:
 gcc -c -fPIC stack/test20.c stack/test21.c stack/test22.c stack/test23.c
  反汇编结果为:
   test21.o:     file format elf32-i386




Disassembly of section .text:


00000000 <push>:
   0: 55                   push   %ebp
   1: 89 e5                 mov    %esp,%ebp
   3: 53                   push   %ebx
   4: 83 ec 04             sub    $0x4,%esp
   7: e8 fc ff ff ff       call   8 <push+0x8>
   c: 81 c3 02 00 00 00     add    $0x2,%ebx
  12: 8b 45 08             mov    0x8(%ebp),%eax
  15: 88 45 f8             mov    %al,-0x8(%ebp)
  /* top的地址为:0x0(%ebx)*/
  18: 8b 83 00 00 00 00     mov    0x0(%ebx),%eax
  1e: 8b 00                 mov    (%eax),%eax
  20: 8d 50 01             lea    0x1(%eax),%edx
  23: 8b 83 00 00 00 00     mov    0x0(%ebx),%eax
  29: 89 10                 mov    %edx,(%eax)
  2b: 8b 83 00 00 00 00     mov    0x0(%ebx),%eax
  31: 8b 00                 mov    (%eax),%eax
  33: 8b 93 00 00 00 00     mov    0x0(%ebx),%edx
  39: 0f b6 4d f8           movzbl -0x8(%ebp),%ecx
  3d: 88 0c 02             mov    %cl,(%edx,%eax,1)
  40: 83 c4 04             add    $0x4,%esp
  43: 5b                   pop    %ebx
  44: 5d                   pop    %ebp
  45: c3                   ret  


  查看符号表:readelf -a test21.o
  Relocation section '.rel.text' at offset 0x42c contains 6 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000008  00000a02 R_386_PC32        00000000   __i686.get_pc_thunk.bx
0000000e  00000b0a R_386_GOTPC       00000000   _GLOBAL_OFFSET_TABLE_
/*top和stack对应的记录不是R_386_32,而是R_386_GOT32*/
0000001a  00000c03 R_386_GOT32       00000000   top
00000025  00000c03 R_386_GOT32       00000000   top
0000002d  00000c03 R_386_GOT32       00000000   top
00000035  00000d03 R_386_GOT32       00000000   stack












  不加-fPIC进行编译,反汇编结果为:


   test21.o:     file format elf32-i386




Disassembly of section .text:


00000000 <push>:
   0: 55                   push   %ebp
   1: 89 e5                 mov    %esp,%ebp
   3: 83 ec 04             sub    $0x4,%esp
   6: 8b 45 08             mov    0x8(%ebp),%eax
   9: 88 45 fc             mov    %al,-0x4(%ebp)
   /*top地址为0x0,准备在重定位时修改 */
   c: a1 00 00 00 00       mov    0x0,%eax
  11: 83 c0 01             add    $0x1,%eax
  14: a3 00 00 00 00       mov    %eax,0x0
  19: a1 00 00 00 00       mov    0x0,%eax
  1e: 0f b6 55 fc           movzbl -0x4(%ebp),%edx
  22: 88 90 00 00 00 00     mov    %dl,0x0(%eax)
  28: c9                   leave  
  29: c3                   ret
  


  使用readelf -a test21.o 查看符号表
  Relocation section '.rel.text' at offset 0x324 contains 4 entries:
/*标出指令中有四处需要重定位修改*/
 Offset     Info    Type            Sym.Value  Sym. Name
0000000d  00000801 R_386_32          00000000   top
00000015  00000801 R_386_32          00000000   top
0000001a  00000801 R_386_32          00000000   top
00000024  00000901 R_386_32          00000000   stack
  
  编译链接生成可发执行文件:
   gcc -g test24.c test20.o test21.o test22.o test23.o -Istack -o test24
  
 反汇编结果为:
 080483d0 <push>:
 80483d0: 55                   push   %ebp
 80483d1: 89 e5                 mov    %esp,%ebp
 80483d3: 83 ec 04             sub    $0x4,%esp
 80483d6: 8b 45 08             mov    0x8(%ebp),%eax
 80483d9: 88 45 fc             mov    %al,-0x4(%ebp)
 80483dc: a1 10 a0 04 08       mov    0x804a010,%eax 
 80483e1: 83 c0 01             add    $0x1,%eax
/*0x0被修改为0x804a010*/
 80483e4: a3 10 a0 04 08       mov    %eax,0x804a010
 80483e9: a1 10 a0 04 08       mov    0x804a010,%eax
 80483ee: 0f b6 55 fc           movzbl -0x4(%ebp),%edx
/*0x0被修改为0x804a040*/
 80483f2: 88 90 40 a0 04 08     mov    %dl,0x804a040(%eax)
 80483f8: c9                   leave  
 80483f9: c3                   ret    
 80483fa: 90                   nop
 80483fb: 90                   nop


 2 生成共享库:
 gcc -shared -o libstack.so test20.o test21.o test22.o test23.o  
 查看反汇编结果:objdump -dS libstack.so
  0000048c <push>:
 48c: 55                   push   %ebp
 48d: 89 e5                 mov    %esp,%ebp
 48f: 53                   push   %ebx
 490: 83 ec 04             sub    $0x4,%esp
 493: e8 ef ff ff ff       call   487 <__i686.get_pc_thunk.bx>
 498: 81 c3 5c 1b 00 00     add    $0x1b5c,%ebx
 49e: 8b 45 08             mov    0x8(%ebp),%eax
 4a1: 88 45 f8             mov    %al,-0x8(%ebp)
 /*oxo(%ebx)被修改成-0xc(%ebx) 和0x8(%ebp),不是绝对地址*/
 4a4: 8b 83 f4 ff ff ff     mov    -0xc(%ebx),%eax
 4aa: 8b 00                 mov    (%eax),%eax
 4ac: 8d 50 01             lea    0x1(%eax),%edx
 4af: 8b 83 f4 ff ff ff     mov    -0xc(%ebx),%eax
 4b5: 89 10                 mov    %edx,(%eax)
 /*top和stack的绝对地址保存在一个地址列表中*/
 4b7: 8b 83 f4 ff ff ff     mov    -0xc(%ebx),%eax
 4bd: 8b 00                 mov    (%eax),%eax
 4bf: 8b 93 fc ff ff ff     mov    -0x4(%ebx),%edx
 4c5: 0f b6 4d f8           movzbl -0x8(%ebp),%ecx
 4c9: 88 0c 02             mov    %cl,(%edx,%eax,1)
 4cc: 83 c4 04             add    $0x4,%esp
 4cf: 5b                   pop    %ebx
 4d0: 5d                   pop    %ebp
 4d1: c3                   ret    
 4d2: 90                   nop
 4d3: 90                   nop
 
 3 与共离享库编编链接在一起
  gcc test24.c -g -L. -lstack -Istack -o test24
 4 运行可执行文件
  yuezhenhua@ubuntu:/opt/sdk/tc$ ./test24
./test24: error while loading shared libraries: libstack.so: cannot open 


shared object file: No such file or directory
 
  运行时找不到依赖共享库
 


  查看该程序所依赖的共享库:
   ldd test24
   返回结果为:
        /*没有存在于文件系统中,由内核虚拟出来,负责处理系统调用*/
    linux-gate.so.1 =>  (0x00b89000)
        /*?路径没有找到*/
libstack.so => not found
        /*路径是由ld-linux.so.2在作动态链接时搜索到的*/
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00c04000) 
         /*动态链接器,路径在编译链接时指定*/
/lib/ld-linux.so.2 (0x008ea000)
 


  解决办法1 :
  将libstack.so的绝对路径添加到/etc/ld.so.conf中
  然后执行:sudo ldconfig -v
  


  方法2:
  将libstack.so复制到/usr/lib或是/lib 目录下
  复制文件:sudo cp libstack.so /lib
 
  方法3:(不推荐)
  在编译可执行文件的时候,将libstack.so的路径写死在可执行文件中
   gcc test24.c -g -L. -lstack -Istack -o test24 -Wl,-


rpath,/home/opt/sdk/tc
  查看符号表:readlf -a test24
  Dynamic section at offset 0xf18 contains 22 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libstack.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000f (RPATH)                      Library rpath: [/home/opt/sdk/tc]


   
  动态链接的过程:
  
  查看反汇编结果:  objdump -dS test24


   080484a4 <main>:
#include <stdio.h>
#include "test18.h"
   
   int main(void){
 80484a4: 55                   push   %ebp
 80484a5: 89 e5                 mov    %esp,%ebp
 80484a7: 83 e4 f0             and    $0xfffffff0,%esp
 80484aa: 83 ec 10             sub    $0x10,%esp
 /*push函数没有链接到可执行文件中*/
  push('a');
 80484ad: c7 04 24 61 00 00 00 movl   $0x61,(%esp)
 /*通过间接寻址来找到push函数的地址*/
 80484b4: e8 27 ff ff ff       call   80483e0 <push@plt>
        return 0;
 80484b9: b8 00 00 00 00       mov    $0x0,%eax
   }
 80484be: c9                   leave  
 80484bf: c3                   ret  


 
  用gdb跟踪结果:gdb test24
 /* 开始: start*/
  
   (gdb) start
Temporary breakpoint 1 at 0x80484ad: file test24.c, line 5.
Starting program: /opt/sdk/tc/test24 


Temporary breakpoint 1, main () at test24.c:5
5 push('a');
  
  /*执行下一条:si*/
(gdb) si
0x080484b4 5 push('a');


  
  /*执行下一条:si*/
  (gdb) si
0x080483e0 in push@plt ()
 
  /*查看地址0x080483e0 存放的数据*/
  (gdb) x 0x080483e0
0x80483e0 <push@plt>: 0xa00825ff
 
(gdb) si
0x080483e6 in push@plt ()
(gdb) si
0x080483eb in push@plt ()
(gdb) si
0x080483b0 in ?? ()
(gdb) si
0x080483b6 in ?? ()
/*进入动态链接器*/
(gdb) si
0x00123c00 in ?? () from /lib/ld-linux.so.2

你可能感兴趣的:(c语言学习笔记十六)