前言
本文主要介紹瞭如何在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>
<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>
本文完。
閱讀更多 青檸biu說 的文章