如何讀取動態連結庫中的符號表,並呼叫
阿新 • • 發佈:2019-02-06
dlopen函式開啟一個函式庫然後為後面的使用做準備。C語言原形是:
void * dlopen(const char *filename, int flag);
如果檔名filename是以“/”開頭,也就是使用絕對路徑,那麼dlopne就直接使用它,而不去查詢某些環境變數或者系統設定的函式庫所在的目錄了。否則dlopen()就會按照下面的次序查詢函式庫檔案:
1. 環境變數LD_LIBRARY指明的路徑。
2. /etc/ld.so.cache中的函式庫列表。
3. /lib目錄,然後/usr/lib。不過一些很老的a.out的loader則是採用相反的次序,也就是 先查/usr/lib,然後是/lib。
Dlopen()函式中,引數flag的值必須是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolv e undefined symbols as code from the dynamic library is executed,而RTLD_NOW的含 義是resolve all undefined symbols before dlopen() returns and fail if this canno t be done'。
如果有好幾個函式庫,它們之間有一些依賴關係的話,例如X依賴Y,那麼你就要先載入那些被依賴的函式。例如先載入Y,然後載入X。
dlopen()函式的返回值是一個控制代碼,然後後面的函式就通過使用這個控制代碼來做進一步的操 作。如果開啟失敗dlopen()就返回一個NULL。如果一個函式庫被多次開啟,它會返回同樣的控制代碼。
如果一個函式庫裡面有一個輸出的函式名字為_init,那麼_init就會在dlopen()這個函式返回前被執行。我們可以利用這個函式在我的函式庫裡面做一些初始化的工作。我們後面會繼續討論這個問題的。
2) dlerror()
通過呼叫dlerror()函式,我們可以獲得最後一次呼叫dlopen(),dlsym(),或者dlclose( )的錯誤資訊。
3) dlsym()
如果你載入了一個DL函式庫而不去使用當然是不可能的了,使用一個DL函式庫的最主要的一 個函式就是dlsym(),這個函式在一個已經開啟的函式庫裡面查詢給定的符號。這個函式如 下定義:
void * dlsym(void *handle, char *symbol);
函式中的引數handle就是由dlopen開啟後返回的控制代碼,symbol是一個以NIL結尾的字串。
如果dlsym()函式沒有找到需要查詢的symbol,則返回NULL。如果你知道某個symbol的值不 可能是NULL或者0,那麼就很好,你就可以根據這個返回結果判斷查詢的symbol是否存在了 ;不過,如果某個symbol的值就是NULL,那麼這個判斷就有問題了。標準的判斷方法是先調 用dlerror(),清 除以前可能存在的錯誤,然後呼叫dlsym()來訪問一個symbol,然後再呼叫dlerror()來 判斷是否出現了錯誤。一個典型的過程如下:
dlerror(); /* clear error code */
s = (actual_type) dlsym(handle, symbol_being_searched_for);
if ((err = dlerror()) != NULL)
{
/* handle error, the symbol wasn't found */
}
else
{
/* symbol found, its value is in s */
}
void * dlopen(const char *filename, int flag);
如果檔名filename是以“/”開頭,也就是使用絕對路徑,那麼dlopne就直接使用它,而不去查詢某些環境變數或者系統設定的函式庫所在的目錄了。否則dlopen()就會按照下面的次序查詢函式庫檔案:
1. 環境變數LD_LIBRARY指明的路徑。
2. /etc/ld.so.cache中的函式庫列表。
3. /lib目錄,然後/usr/lib。不過一些很老的a.out的loader則是採用相反的次序,也就是 先查/usr/lib,然後是/lib。
Dlopen()函式中,引數flag的值必須是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolv e undefined symbols as code from the dynamic library is executed,而RTLD_NOW的含 義是resolve all undefined symbols before dlopen() returns and fail if this canno t be done'。
如果有好幾個函式庫,它們之間有一些依賴關係的話,例如X依賴Y,那麼你就要先載入那些被依賴的函式。例如先載入Y,然後載入X。
dlopen()函式的返回值是一個控制代碼,然後後面的函式就通過使用這個控制代碼來做進一步的操
如果一個函式庫裡面有一個輸出的函式名字為_init,那麼_init就會在dlopen()這個函式返回前被執行。我們可以利用這個函式在我的函式庫裡面做一些初始化的工作。我們後面會繼續討論這個問題的。
2) dlerror()
通過呼叫dlerror()函式,我們可以獲得最後一次呼叫dlopen(),dlsym(),或者dlclose( )的錯誤資訊。
3) dlsym()
如果你載入了一個DL函式庫而不去使用當然是不可能的了,使用一個DL函式庫的最主要的一 個函式就是dlsym(),這個函式在一個已經開啟的函式庫裡面查詢給定的符號。這個函式如
void * dlsym(void *handle, char *symbol);
函式中的引數handle就是由dlopen開啟後返回的控制代碼,symbol是一個以NIL結尾的字串。
如果dlsym()函式沒有找到需要查詢的symbol,則返回NULL。如果你知道某個symbol的值不 可能是NULL或者0,那麼就很好,你就可以根據這個返回結果判斷查詢的symbol是否存在了 ;不過,如果某個symbol的值就是NULL,那麼這個判斷就有問題了。標準的判斷方法是先調 用dlerror(),清 除以前可能存在的錯誤,然後呼叫dlsym()來訪問一個symbol,然後再呼叫dlerror()來 判斷是否出現了錯誤。一個典型的過程如下:
dlerror(); /* clear error code */
s = (actual_type) dlsym(handle, symbol_being_searched_for);
if ((err = dlerror()) != NULL)
{
/* handle error, the symbol wasn't found */
}
else
{
/* symbol found, its value is in s */
}