不幸的是,權威性文檔是源代碼。 Linux的大多數發行版都使用glibc或其fork,eglibc。在兩者的源代碼,即應記錄dlopen()的文件的內容如下:
手動/ libdl.texi
@c FIXME these are undocumented:
@c dladdr
@c dladdr1
@c dlclose
@c dlerror
@c dlinfo
@c dlmopen
@c dlopen
@c dlsym
@c dlvsym
有可以從ELF specification和POSIX標準繪製什麼技術規範。 ELF規範是使弱符號有意義的原因。 POSIX本身就是實際的specification for dlopen()。
這是我發現的ELF規範中最相關的部分。
當鏈接編輯器搜索歸檔庫時,它將提取包含未定義全局符號定義的歸檔文件 。成員的定義可以是全局符號或弱符號。
ELF規範沒有提到動態加載,所以本段的其餘部分是我自己的解釋。我發現上述相關的原因是解析符號出現在一個單獨的「when」時。在您給出的示例中,當程序a
動態加載b.so
時,動態加載器將嘗試解析未定義的符號。它可能會以全局或弱符號結束。當程序動態加載c.so
時,動態加載程序再次嘗試解析未定義的符號。在你描述的場景中,b.so
中的符號用弱符號解決。一旦解決,這些符號不再未定義。使用全局或弱符號來定義它們並不重要。在加載c.so
時,它們已不再未定義。
ELF規範沒有提供關於鏈接編輯器或鏈接編輯器必須組合目標文件的準確定義。推測這是一個非問題,因爲該文件考慮了動態鏈接。
POSIX描述了一些dlopen()功能,但留下了許多實現,包括問題的實質。一般來說,POSIX不提及ELF格式或弱符號。對於實現dlopen()的系統,甚至不需要任何弱符號的概念。
http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html
POSIX標準是另一個標準,Linux標準庫的一部分。 Linux發行版可能會或可能不會選擇遵循這些標準,可能會或可能不會去認證的麻煩。例如,據我所知,Open Group的正式Unix認證非常昂貴 - 因此大量的「類Unix」系統。
關於dlopen()的標準符合性的一個有趣點在Wikipedia article for dynamic loading上進行。按照POSIX的規定,dlopen()返回一個void *,但是,如ISO所強制的那樣,C說void *是一個指向對象的指針,這樣的指針不一定與函數指針兼容。
的事實仍然是功能和對象 指針之間任意轉換必須被視爲(固有的非便攜式) 實現擴展,而對於直接 轉換沒有「正確」的方式存在,因爲在這方面POSIX和ISO標準 相互矛盾。
無論如何,確實存在的標準是矛盾的,哪些標準文件可能並不特別有意義。這裏是Ulrich Drepper寫的關於他對Open Group及其「規格」的蔑視。
http://udrepper.livejournal.com/8511.html
類似的情緒在由羅德里戈鏈接後表示。
我做了這個變化的原因是不是真的更符合的 (這是不錯的,但因爲沒有人沒有理由抱怨老 行爲)。
看過之後,我相信你問的問題的正確答案是dlopen()
在這方面沒有正確或錯誤的行爲。可以說,一旦搜索已經解決了一個符號,它就不再是未定義的,並且在隨後的搜索中動態加載器不會嘗試解析已定義的符號。
最後,正如您在評論中所述,您在原始帖子中描述的內容不正確。動態加載的共享庫可用於解析先前動態加載的共享庫中未定義的符號。實際上,這並不侷限於動態加載代碼中未定義的符號。下面是一個例子,其中可執行文件本身有一個通過動態加載解析的未定義符號。
的main.c
#include <dlfcn.h>
void say_hi(void);
int main(void) {
void* symbols_b = dlopen("./dyload.so", RTLD_NOW | RTLD_GLOBAL);
/* uh-oh, forgot to define this function */
/* better remember to define it in dyload.so */
say_hi();
return 0;
}
dyload。c
#include <stdio.h>
void say_hi(void) {
puts("dyload.so: hi");
}
編譯並運行。
gcc-4.8 main -fpic -ldl -Wl,--unresolved-symbols=ignore-all -o main
gcc-4.8 dyload.c -shared -fpic -o dyload.so
$ ./main
dyload.so: hi
請注意,主可執行文件本身被編譯爲PIC。
您有沒有看過[此PDF](http://refspecs.linuxbase.org/elf/elf.pdf)?很多有趣的數據,但不知道它是否包含你所尋找的。 – rodrigo
@rodrigo:不知道它是否是這個或類似的東西,但到目前爲止,我發現的所有ELF文檔只是描述了執行二進制文件之前的動態鏈接,而不是涉及動態加載對象的鏈接。這是一個很長的文件,我可能在錯誤的地方看過,但到目前爲止,它似乎不是我正在尋找的東西。 – MvG
那麼[Drepper的帖子](http://www.sourceware.org/ml/libc-hacker/2000-06/msg00029.html)及其或多或少的[相關文檔](http:// www。 akkadia.org/drepper/dsohowto.pdf)(見第1.5.2節)?按照我的理解,弱符號僅用於靜態鏈接。所以'dlopen()'不會對弱符號和強符號產生影響。 – rodrigo