使用-rpath和$ORIGIN動態設置鏈接庫路徑

前言

本文主要介紹瞭如何在Linux環境下使用-rpath和$ORIGIN動態設置鏈接庫路徑。

一般開發過程中,我們是通過LD_LIBRARY_PATH來設置程序依賴的動態庫路徑,但是我們也可以通過-rpath和$ORIGIN來動態設置鏈接庫路徑。rpath是gcc/g++的一個參數。rpath添加一個目錄,當程序被加載時搜尋此目錄。ORIGIN變量標識了程序自身所在目錄。

$ORIGIN詳細介紹:https://www.technovelty.org/linux/exploring-origin.html

正文

  • 創建庫文件與主函數代碼
  • sum.h

    <code>#include <cstdio>
    int Sum(int &a, int &b);/<cstdio>/<code>

    sum.cpp

    <code>#include "sum.h"
    int Sum(int &a, int &b)
    {
    \treturn (a+b);
    }/<code>

    main.cpp

    <code>#include <cstdio>
    #include "sum.h"
    int main()
    {
    \tint a = 1024;
    \tint b = 996;
    \t
    \tprintf("%d+%d=%d.\\n",a,b,Sum(a,b));
    return 0;
    }/<cstdio>/<code>
  • 創建Makefile文件
  • <code>main:main.cpp lib/libSum.so
    \tg++ -L${shell pwd}/lib -g -Wall -o test -Wl,-rpath,'$$ORIGIN/lib' -I./lib main.cpp -lSum

    lib/libSum.so:lib/sum.cpp
    \tg++ -g -Wall -fPIC -shared -o lib/libSum.so lib/sum.cpp -I./lib/<code>
  • 編譯
  • <code>[test@root test_rpath]$ make
    g++ -g -Wall -fPIC -shared -o lib/libSum.so lib/sum.cpp -I./lib
    g++ -L/opt/test/test_rpath/lib -g -Wall -o test -Wl,-rpath,'$ORIGIN/lib' -I./lib main.cpp -lSum/<code>
  • 執行
  • <code>[test@root test_rpath]$ ./test 
    1024+996=2020./<code>
  • 查看文件信息
  • 輸入命令:readelf -d test查看文件信息,如下rpath則為動態庫路徑

    0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]

    <code>[test@root test_rpath]$ readelf -d test 
    Dynamic section at offset 0xdd8 contains 29 entries:
    Tag Type Name/Value
    0x0000000000000001 (NEEDED) Shared library: [libSum.so]
    0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
    0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
    0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
    0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
    0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]
    0x000000000000000c (INIT) 0x4005b0
    0x000000000000000d (FINI) 0x4007d4
    0x0000000000000019 (INIT_ARRAY) 0x600dc0
    0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
    0x000000000000001a (FINI_ARRAY) 0x600dc8
    0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
    0x000000006ffffef5 (GNU_HASH) 0x400298
    0x0000000000000005 (STRTAB) 0x400408
    0x0000000000000006 (SYMTAB) 0x4002d0
    0x000000000000000a (STRSZ) 245 (bytes)
    0x000000000000000b (SYMENT) 24 (bytes)
    0x0000000000000015 (DEBUG) 0x0
    0x0000000000000003 (PLTGOT) 0x601000
    0x0000000000000002 (PLTRELSZ) 96 (bytes)
    0x0000000000000014 (PLTREL) RELA
    0x0000000000000017 (JMPREL) 0x400550
    0x0000000000000007 (RELA) 0x400538
    0x0000000000000008 (RELASZ) 24 (bytes)

    0x0000000000000009 (RELAENT) 24 (bytes)
    0x000000006ffffffe (VERNEED) 0x400518
    0x000000006fffffff (VERNEEDNUM) 1
    0x000000006ffffff0 (VERSYM) 0x4004fe
    0x0000000000000000 (NULL) 0x0/<code>

    輸入命令:ldd -r test查看文件所需共享庫,可以看到依賴的庫路徑

    <code>[test@root test_rpath]$ ldd -r test 
    \tlinux-vdso.so.1 => (0x00007ffc1036e000)
    \tlibSum.so => /opt/test/test_rpath/./lib/libSum.so (0x00007f697e2d9000)
    \tlibstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f697dfc8000)
    \tlibm.so.6 => /lib64/libm.so.6 (0x00007f697dcc6000)
    \tlibgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f697dab0000)
    \tlibc.so.6 => /lib64/libc.so.6 (0x00007f697d6ee000)
    \t/lib64/ld-linux-x86-64.so.2 (0x000055f4137dd000)/<code>
  • 改變庫路徑
  • 將依賴的libSum.so拷貝到可執行文件路徑下,再次執行,報錯!

    <code>(base) [root@root test_rpath]# ./test 
    ./test: error while loading shared libraries: libSum.so: cannot open shared object file: No such file or directory/<code>

    輸入命令修改rpath路徑: chrpath -r"\\$ORIGIN" test

    <code>(base) [root@root test_rpath]# chrpath -r"\\$ORIGIN" test 
    test: RPATH=$ORIGIN/lib
    test: new RPATH: $ORIGIN/<code>
  • 再次查看文件信息
  • <code>(base) [root@roottest_rpath]# readelf -d test 
    Dynamic section at offset 0xdd8 contains 29 entries:
    Tag Type Name/Value
    0x0000000000000001 (NEEDED) Shared library: [libSum.so]
    0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
    0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
    0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
    0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
    0x000000000000000f (RPATH) Library rpath: [$ORIGIN]
    0x000000000000000c (INIT) 0x4005b0
    0x000000000000000d (FINI) 0x4007d4
    0x0000000000000019 (INIT_ARRAY) 0x600dc0

    0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
    0x000000000000001a (FINI_ARRAY) 0x600dc8
    0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
    0x000000006ffffef5 (GNU_HASH) 0x400298
    0x0000000000000005 (STRTAB) 0x400408
    0x0000000000000006 (SYMTAB) 0x4002d0
    0x000000000000000a (STRSZ) 245 (bytes)
    0x000000000000000b (SYMENT) 24 (bytes)
    0x0000000000000015 (DEBUG) 0x0
    0x0000000000000003 (PLTGOT) 0x601000
    0x0000000000000002 (PLTRELSZ) 96 (bytes)
    0x0000000000000014 (PLTREL) RELA
    0x0000000000000017 (JMPREL) 0x400550
    0x0000000000000007 (RELA) 0x400538
    0x0000000000000008 (RELASZ) 24 (bytes)
    0x0000000000000009 (RELAENT) 24 (bytes)
    0x000000006ffffffe (VERNEED) 0x400518
    0x000000006fffffff (VERNEEDNUM) 1
    0x000000006ffffff0 (VERSYM) 0x4004fe
    0x0000000000000000 (NULL) 0x0/<code>
    <code>(base) [root@root test_rpath]# ldd -r test 
    \tlinux-vdso.so.1 => (0x00007ffd75bee000)
    \tlibSum.so => /opt/test/test_rpath/./libSum.so (0x00007f3b223a1000)
    \tlibstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f3b22090000)
    \tlibm.so.6 => /lib64/libm.so.6 (0x00007f3b21d8e000)
    \tlibgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f3b21b78000)
    \tlibc.so.6 => /lib64/libc.so.6 (0x00007f3b217b6000)
    \t/lib64/ld-linux-x86-64.so.2 (0x0000563d2141a000)/<code>

    發現可執行文件依賴的動態庫路徑已經修改,再次執行OK

    <code>[test@root test_rpath]$ ./test 
    1024+996=2020./<code>

    本文完。


    分享到:


    相關文章: