Compiling

執行檔在執行時在哪裡尋找共享對象?

  • September 26, 2020

我了解如何在連結/編譯時定義包含共享對象。但是,我仍然想知道執行檔*.so在執行時如何查找共享對象(庫)。

例如,我的應用a.out呼叫lib.so庫中定義的函式。編譯後,我移動lib.so到我的$HOME.

我怎麼能告訴a.out去那裡找呢?

共享庫 HOWTO解釋了所涉及的大部分機制,動態載入器手冊更詳細。每個 unix 變體都有自己的方式,但大多數使用相同的可執行格式 ( ELF ) 並具有相似的動態連結器¹(源自 Solaris)。下面我將以 Linux 為重點總結常見行為;檢查您的系統手冊以獲取完整的故事。

(術語說明:載入共享庫的系統部分通常稱為“動態連結器”,但有時更準確地說是“動態載入器”。“動態連結器”也可以指編譯時為動態載入器生成指令的工具一個程序,或者編譯時工具和執行時載入程序的組合。在這個答案中,“連結器”是指執行時部分。)

簡而言之,當它在尋找動態庫(.so文件)時,連結器會嘗試:

  • LD_LIBRARY_PATH環境變數中列出的目錄(DYLD_LIBRARY_PATH在 OSX 上);
  • 執行檔的rpath中列出的目錄;
  • 系統搜尋路徑上的目錄,其中(至少在 Linux 上)由/etc/ld.so.confplus/lib/usr/lib.

rpath 儲存在執行檔中(它是DT_RPATHorDT_RUNPATH動態屬性)。它可以包含絕對路徑或以 開頭$ORIGIN的路徑,以指示相對於執行檔位置的路徑(例如,如果執行檔在/opt/myapp/bin其中且其 rpath 為,$ORIGIN/../lib:$ORIGIN/../plugins則動態連結器將在/opt/myapp/liband中查找/opt/myapp/plugins)。rpath 通常在編譯執行檔時確定,使用-rpath選項ld,但您可以在之後使用chrpath.

在您描述的場景中,如果您是應用程序的開發人員或打包人員並打算將其安裝在…/bin,…/lib結構中,則使用-rpath='$ORIGIN/../lib'. 如果您要在系統上安裝預建構的二進製文件,請將庫放在搜尋路徑上的目錄中(/usr/local/lib如果您是系統管理員,否則是您添加到的目錄$LD_LIBRARY_PATH),或者嘗試chrpath.

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