动态加载Linux共享库?

时间:2011-11-30 17:43:18

标签: linux shared

我想创建一个共享库,可以通过两种不同的方式加载到目标中:

  1. LD_PRELOAD
  2. 通过dlsym
  3. 动态加载

    我的共享库如下所示:

    #include "stdio.h"
    
    void __attribute__ ((constructor)) my_load(void);
    
    void my_load(void) {
      printf("asdf");
    }
    
    void someFunc(void) {
      printf("someFunc called");
    }
    

    我正在编译它:

    all:
        gcc -fPIC -g -c -Wall MyLib.c
        gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
    

    我不希望用ldconfig等安装它。目标进程如下所示:

    #include <stdio.h>
    #include <dlfcn.h>
    
    void func1() {
      printf("%d\n", 1);
    }
    
    void func2() {
      printf("%d\n", 2);
    }
    
    void func3() {
      printf("%d\n", 3);
    }
    
    int main() {
      void* lib_handle = dlopen("/home/mike/Desktop/TargetProcess/MyLib.so.1.0.1",
                             RTLD_NOW|RTLD_GLOBAL);
    
      if(lib_handle == NULL) {
        printf("Failed loading lib\n");
      } else {
        printf("Loaded lib successfully\n");
    
        void (*some_func)() = dlsym(lib_handle, "someFunc");
        printf("%p\n", some_func);
    
        dlclose(lib_handle);
      }
    
      func1();
      func2();
      func3();
    
      return 0;
    }
    

    目标编译如下:

    all:
        gcc TestProg.c -ldl -o TestProg
    

    我的问题是:

    1. 如上所述使用dlopen进行动态加载,为什么my_load似乎没有被调用?
    2. 使用相同的方法,为什么dlsym总是返回nil,即使dlopen返回非空?同样,nm也不会将my_loadsomeFunc列为.so的符号。
    3. 是否可以使用LD_PRELOAD加载库?我尝试将.so复制到与目标相同的目录中,然后调用LD_PRELOAD="./MyLib.so.1.0.1" ./TestProg但是再次my_load似乎没有被调用。

1 个答案:

答案 0 :(得分:6)

您的目标文件未链接到您的库中:

gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc

将其更改为包含您的目标文件MyLib.o:

gcc  MyLib.o -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc

更新:只在本地尝试你的命令(没有任何MyLib.c或MyLib.o):

$ gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc && echo ok
ok
$ nm MyLib.so.1.0.1
xxxxxxxx a _DYNAMIC
xxxxxxxx a _GLOBAL_OFFSET_TABLE_
         w _Jv_RegisterClasses
xxxxxxxx A __bss_start
         w __cxa_finalize@@xxxxxxxxxxx
xxxxxxxx d __dso_handle
         w __gmon_start__
xxxxxxxx t __i686.get_pc_thunk.bx
xxxxxxxx A _edata
xxxxxxxx A _end
xxxxxxxx T _fini
xxxxxxxx T _init

这是一个动态库。