2011-11-30 158 views
7

我想創建可在兩種不同的方式加載到目標共享庫:動態加載Linux共享庫?

  1. LD_PRELOAD通過dlsym

我的共享庫

  • 動態加載看起來是這樣的:

    #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. 使用相同的方法,即使dlopen返回非空,爲什麼dlsym始終返回nil?同樣,nm不會列出my_loadsomeFunc作爲.so的符號。
    3. 是否可以使用LD_PRELOAD加載庫?我試圖將.so複製到與目標相同的目錄中,然後調用LD_PRELOAD="./MyLib.so.1.0.1" ./TestProg,但似乎還沒有調用my_load
  • 回答

    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 
    

    更新:只是tryed本地的命令(不任何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 [email protected]@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 
    

    它是一個空的動態庫。

    +0

    完美地工作。它按照LR_PRELOAD以及動態的方式加載。在這兩種情況下也調用my_load。謝謝! –

    +1

    其實它不是空的,它包含一些libc的東西。如果你沒有指定'-lc',鏈接將失敗。 :) – ninjalj