2016-05-08 76 views
3

我正在使用dlsym在程序中查找符號,但它始終返回NULL,這並不是我期待的。根據手冊頁,如果出現錯誤,dlsym可能會返回NULL,或者符號確實爲NULL。在我的情況下,我收到一個錯誤。我會告訴你我今晚做的MCVE。即使符號存在,dlsym也會返回NULL

這裏是instr.c的內容:

#include <stdio.h> 

void * testing(int i) { 
    printf("You called testing(%d)\n", i); 
    return 0; 
} 

僅含有一個不起眼示例功能的非常簡單的事情。

這裏是test.c的內容:

#include <dlfcn.h> 
#include <stdlib.h> 
#include <stdio.h> 

typedef void * (*dltest)(int); 

int main(int argc, char ** argv) { 

    /* Declare and set a pointer to a function in the executable */ 
    void * handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); 
    dlerror(); 
    dltest fn = dlsym(handle, "testing"); 

    if(fn == NULL) { 
     printf("%s\n", dlerror()); 
     dlclose(handle); 
     return 1; 
    } 
    dlclose(handle); 
    return 0; 
} 

正如我通過與調試器的代碼步驟,我看到的dlopen返回一個句柄。根據手冊頁,If filename is NULL, then the returned handle is for the main program.因此,如果我將一個名爲testing的符號鏈接到主程序中,dlsym應該找到它,對不對?

這裏是我編譯和鏈接程序的方式:

all: test 

instr.o: instr.c 
    gcc -ggdb -Wall -c instr.c 

test.o: test.c 
    gcc -ggdb -Wall -c test.c 

test: test.o instr.o 
    gcc -ldl -o test test.o instr.o 

clean: 
    rm -f *.o test 

當我建立這個程序,然後做objdump -t test | grep testing,我看到符號testing確實存在:

08048632 g  F .text 00000020    testing 

然而,我的程序的輸出是錯誤:

./test: undefined symbol: testing 

我不知道我做錯了什麼。如果有人能夠解決這個問題,我將不勝感激。

+2

http://coliru.stacked-crooked.com/a/3048847bea8edb97添加:'-Wl, - export-dynamic'使您的程序可以正常工作。沒有它,你會得到錯誤'未定義的符號:'testing''。 – Brandon

回答

4

我不認爲你可以那樣做,dlsym適用於導出的符號。因爲你在做dlsymNULL(當前圖像),即使符號存在於可執行的ELF圖像中,它們也不會被導出(因爲它不是共享庫)。

爲什麼不直接調用它並讓鏈接器照顧它呢?使用dlsym從與您的dlsym呼叫相同的圖像中獲取符號沒有意義。如果您的testing符號位於您使用dlopen鏈接或加載的共享庫中,那麼您將能夠檢索它。

我相信當構建可執行文件時(-Wl,--export-dynamic,在Brandon的評論中提到),也有一種導出符號的方法,但我不確定爲什麼要這麼做。

+0

ELF程序和ELF共享庫幾乎沒有區別。實際上,一些共享庫包含'main()'函數,可以作爲程序運行。 ELF「程序」無法作爲共享庫加載的原因沒有特別的理由。儘管如此,我相信你是對的,問題是這個符號不會被導出。 –

相關問題