rpath和patchelf


rpath全稱是run-time search path。Linux下所有elf格式的文件都包含它,特別是可執行文件。它規定了可執行文件在尋找.so文件時的第一優先位置。
另外,elf文件中還規定了runpath。它與rpath相同,只是優先級低一些。

搜索.so的優先級順序

  • 編譯目標代碼時指定的動態庫搜索路徑; 如果在編譯程序時增加參數-Wl,-rpath='.' , 這時生成程序的Dynamic section會新加一個RPATH段
  • 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑; ( 可用export LD_LIBRARY_PATH="NEWDIRS" 命令添加臨時環境變量 )
  • RUNPATH: 寫在elf文件中
  • ldconfig的緩存:配置文件/etc/ld.so.conf中指定的動態庫搜索路徑;(系統默認情況下未設置)
  • 默認的動態庫搜索路徑/lib;
  • 默認的動態庫搜索路徑/usr/lib;

RPATH與RUNPATH中間隔着LD_LIBRARY_PATH,可以通過修改LD_LIBRARY_PATH來指定.so文件,大多數編譯器都將輸出的RPATH留空,並用RUNPATH代替RPATH。

查看RPATH

對於任意的elf文件,可以使用$ readelf -d filename | grep PATH 來查看。
0x000000000000001d (RUNPATH) Library runpath: [$ORIGIN/]

結果有兩類,一個是RPATH,另一個是RUNPATH。一般情況下,RPATH為空,而RUNPATH不為空。

RPATH中有個特殊的標識符$ORIGIN。這個標識符代表elf文件自身所在的目錄。

當希望使用相對位置尋找.so文件,就需要利用$ORIGIN設置RPATH。多個路徑之間使用冒號:隔開。

設置RPATH

在gcc中,設置RPATH的辦法很簡單,就是設置linker的rpath選項:

gcc -L. -larith main.c -Wl,-rpath='.' -o main

(-Wl參數意思是把rpath選項傳遞到鏈接階段)

如果需要設置$ORIGIN:$ gcc -Wl,-rpath,'$ORIGIN/lib' test.cpp。

注意,雖然選項里寫着RPATH,但它設置的還是RUNPATH。原因在前文有交代。

在CMake中,使用變量來控制RPATH:INSTALL_RPATH和BUILD_RPATH。
設置的辦法是:SET_TARGET_PROPERTIES(target PROPERTIES INSTALL_RPATH "$ORIGIN;/another/run/path")

(cmake中多個RPATH使用分號隔開)

patchelf

patchelf 是一個用來修改elf格式的動態庫和可執行程序的小工具,可以修改動態鏈接庫的庫名字,以及鏈接庫的RPATH。

  • 打印出動態庫的soname

    patchelf --print-soname xxx.so

  • 修改動態庫的soname

    patchelf --set-soname oldxxx.so newxxx.so

  • 查看並修改第三方依賴庫

    patchelf --print-needed xxx.so

    patchelf --replace-needed oldxxx.so newxxx.so this.so

  • 修改rpath

    patchelf --set-rpath '$ORIGIN/' main


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM