Libraries

為什麼某些工作封包件對於 ldd 的某些輸出庫返回“未找到”?

  • November 10, 2014

我發現一堆東西,其中工作包包含 ldd 為某些庫返回“未找到”的文件。例如…

/usr/lib64/thunderbird/libprldap60.so
   libldap60.so => not found

/usr/lib64/libreoffice/program/libofficebean.so
   libjawt.so => not found

我們有數百名使用者使用 Thunderbird 和 Libre Office,沒有人報告任何問題。這些文件存在於系統中:

/usr/lib64/thunderbird/libldap60.so
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.33.x86_64/jre/lib/amd64/libjawt.so
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/libjawt.so

對於這個例子,/usr/bin/thunderbird 和 /usr/bin/libreoffice 都是用於啟動各自程序的包裝腳本,我希望這些腳本會設置環境,以便這些庫變得可見,但事實並非如此看起來在這些腳本中會發生這種情況。

在我們的系統中還有數百個這樣的例子,我只是選擇這兩個作為例子。誰能解釋發生了什麼?

直接(可能很明顯)的答案是您正在查看的庫的搜尋路徑ldd不包括庫自身依賴項所在的目錄。通常,除非在系統範圍的標準位置中找到庫的依賴項,否則應該使用指定的執行路徑建構庫(通過使用環境變數$LD_RUN_PATH或適當的連結器選項)。否則,稍後在執行時將無法找到這些庫,就像您使用ldd.

那麼,儘管有這個“問題”,為什麼 Thunderbird 仍然可以工作?

儘管缺少執行路徑,但仍有幾種方法可以找到必要的庫:

  • 環境變數$LD_LIBRARY_PATH在執行時設置並提供要搜尋的其他目錄列表。
  • 必要的目錄可能已包含在搜尋路徑中,因為它是在其他一些不相關庫的執行路徑中找到的,而這些庫恰好在目前庫之前載入。順便說一句,如果標準指定了它,我不確定這是否是實施的意外。無論哪種方式,它都是脆弱的,因為它關鍵取決於載入庫的確切順序。
  • 該庫可能已由應用程序使用dlopen()給定完整路徑名的函式手動載入。

Thunderbird 似乎正在使用最後一種技術。我查看strace了它在啟動時所做的輸出,它似乎是這樣做的:

  • 找到它自己的二進製文件所在的目錄。這總是可能的,因為啟動 Thunderbird 的 shell 腳本助手使用完整的路徑名。
  • 打開dependentlibs.list在該目錄中找到的文本文件。
  • 對於此文本文件中的每個文件名,按順序在相同目錄前面添加完整路徑名,然後使用dlopen().
  • 現在您提到的所有那些依賴庫libldap60.so都是“預載入的”,其他需要它們的庫不需要再次找到它們。

請注意,其中列出的順序或文件dependentlibs.list很重要。

Thunderbird 這樣做的原因是它所在的目錄不必硬編碼到應用程序或其任何內部庫的執行路徑中。

我不知道 Java 做了什麼,但毫無疑問它是類似的。

引用自:https://unix.stackexchange.com/questions/167193