--hash-style兼容性問題


本文記錄瞭解決 --hash-style 兼容性問題的過程。


問題

dlopen failed: empty/missing DT_HASH in "libxxx.so" (built with --hash-style=gnu?)

最近,穩定性監控平臺,被這一行錯誤日誌霸榜,剛看到時也一臉懵逼,下面我們來逐步分析。

名詞解釋

首先需要查閱一下相關文檔,瞭解一下其中的”新朋友”。

  • DT_HASH
ELF 中的一個 Sections,保存了一個用於查找符號的散列表,用於支持符號表的訪問,能夠提高符號搜索速度。
  • --hash-style=style(以下解釋摘自 man ld)
Set the type of linker's hash table(s). style can be either "sysv" for classic ELF ".hash" section, "gnu" for new style GNU ".gnu.hash" section or "both" for both the classic ELF ".hash" and new style GNU ".gnu.hash" hash tables. The default is "sysv".

實驗

通過查閱 --hash-style=style 參數,發現 style 支持三種配置:sysvgnuboth,廢話不多說,先試一把。

  • gcc -Wl,--hash-style=sysv
$ readelf -S libxxx.so  | grep "hash"
[ 4] .hash             HASH             0000000000003120  00003120
  • gcc -Wl,--hash-style=gnu
$ readelf -S libxxx.so  | grep "hash"
[ 4] .gnu.hash         GNU_HASH         0000000000003120  00003120
  • gcc -Wl,--hash-style=both
$ readelf -S libxxx.so  | grep "hash"
  [ 4] .gnu.hash         GNU_HASH         0000000000003120  00003120
  [ 5] .hash             HASH             00000000000035f8  000035f8

-Wl 用於編譯器向鏈接器傳遞參數。

如上,發現使用不同的配置,Sections Name 不同。

.gnu.hash 段​,提​供了​與 hash 段​相​同​的​功​能​;但​是與 hash 相比,增加了某些限制(附加規則),​導致了不兼容,帶​來​了​ 50% 的​動​態​鏈​接​性​能​提​升​,具體參見 https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2

分析

結合實驗結果,我先翻譯一下問題中的那一行錯誤日誌:

動態庫加載失敗,libxxx.so 中 DT_HASH 爲空或者丟失,是不是用了 --hash-style=gnu 編譯?

結合上表,若 --hash-style=gnu,那麼 Section Name 就是 .gnu.hash 了,當然找不到.hash 了。

再查閱一下 Makefile 配置,發現並沒有相關配置,懷疑是編譯器的默認配置:

$ gcc -dumpspecs | grep "hash"
... --hash-style=gnu ...

-dumpspecs 參數可以打印編譯器的內置規範。

果不其然,默認的 --hash-style 配置爲了 gnu

結論

輸出的動態庫的 --hash-stylegnu,而目標系統並不能正確讀取 --hash-stylegnu 的動態庫,導致瞭如上的錯誤。

解決方案

配置 --hash-styleboth

LDFLAGS += -Wl,--hash-style=both

參考


微信公衆號同步更新,微信搜索"AnSwEr不是答案"或者掃描二維碼,即可訂閱。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章