2012-02-06 23 views
4
nm -D /lib32/libc.so.6 | grep '\<fopen\>' 
0005d0c0 T fopen 
00109750 T fopen 

readelf -s /lib32/libc.so.6 | egrep '0005d0c0|00109750' 
181: 0005d0c0 50 FUNC GLOBAL DEFAULT 12 [email protected]@GLIBC_2.1 
182: 00109750 136 FUNC GLOBAL DEFAULT 12 [email protected]_2.0 
679: 0005d0c0 50 FUNC GLOBAL DEFAULT 12 [email protected]@GLIBC_2.1 
680: 00109750 136 FUNC GLOBAL DEFAULT 12 [email protected]_2.0 

這裏是我的問題:爲什麼/lib32/libc.so.6中有兩個「fopen」符號?

  1. 爲什麼/lib32/libc.so.6有兩份的fopen符號?應該禁止在同一個目標文件中使用相同的符號,對吧?

  2. 爲什麼readelf -s轉儲fopen @@ GLIBC_2.1和[email protected]_2.0而不是fopen?

感謝

回答

3

的相同符號其實多個定義是罰款,可以通過多種方式發生。其中一個(這裏不是這種情況)是弱符號。

這裏發生的事情是,glibc動態鏈接器支持符號版本控制,而glibc使用它。它從glibc 2.1導出版本爲fopen,而從glibc 2.0導出具有不同接口的向後兼容版本。

在動態鏈接時,應用程序可以選擇特定版本或默認版本。

+0

感謝gby,你能舉個例子,謝謝:) – camino 2012-02-06 06:57:31

+1

關於共享庫的任何事情,這個星球上最好的資源是Ulrich Drepper的「如何編寫共享庫」:http://people.redhat.com/ drepper/dsohowto.pdf – gby 2012-02-06 15:39:46

+0

非常感謝! :) – camino 2012-02-07 09:10:28

9

爲了理解這裏發生了什麼,您首先需要了解傳統上如何處理二進制兼容性。

該機制曾經是「外部版本控制」。您從libfoo.so.1開始,當您需要更改現有功能的ABI時,您不得不介紹libfoo.so.2

libfoo.so.2之前鏈接的應用程序繼續使用libfoo.so.1與舊的ABI,並且新的應用程序使用libfoo.so.2與新的ABI。

這全部在一些細節here中描述。

但是,然後glibc引入了一個extension,其中不是引入一個全新的庫(與前一版本共享99%的代碼),而是在現有的庫中引入一個新的符號。

該擴展是允許libc.so.6停留在版本6的,同時允許舊的二進制文件工作,並使ABI進化。

fopen的特定情況下,一個不相容變化struct FILE在glibc的2.1版製備。在glibc-2.0系統上鍊接的二進制文件繼續使用舊的struct FILE(當時唯一可用的),並繼續調用_IO_old_fopen(其中[email protected]_2.0是別名)。與glibc-2.1及更新版本鏈接的二進制文件使用新的struct FILE,並調用_IO_new_fopen(其中[email protected]_2.1是別名)。

@@只是一個表示當前默認符號版本的符號。

相關問題