GDB动态库搜索路径
筆記:
當(dāng)GDB無法顯示so動態(tài)庫的信息或者顯示信息有誤時,通常是由于庫搜索路徑錯誤導(dǎo)致的,可使用set sysroot、set solib-absolute-prefix、set solib-search-path來指定庫搜索路徑。
1. set sysroot 與 set solib-absolute-prefix 是同一條命令,實際上,set sysroot是set solib-absolute-prefix 的別名。
2. set solib-search-path設(shè)置動態(tài)庫的搜索路徑,該命令可設(shè)置多個搜索路徑,路徑之間使用“:”隔開(在linux中為冒號,DOS和Win32中為分號)。
3. set solib-absolute-prefix 與 set solib-search-path 的區(qū)別:
? 總體上來說solib-absolute-prefix設(shè)置庫的絕對路徑前綴,只對絕對路徑有效;而solib-search-path設(shè)置庫的搜索路徑,對絕對路徑和相對路徑均起作用。(編譯器自動鏈接的so庫多采用絕對路徑)。
? 詳細規(guī)則有:
? set solib-search-path由于是路徑前綴,所以只能設(shè)置一個路徑,而solib-search-path可以設(shè)置多個搜索路徑。
? 在載入動態(tài)庫信息時Coredump會碰到兩種路徑:絕對路徑和相對路徑。編譯時鏈接的庫通常是絕對路徑,例如"/lib/libc.so.6"、"/lib/libdl.so.2"等,此時在Coredump文件中也同樣保存為絕對路徑;而程序用dlopen函數(shù)載入的so庫可能使用相對路徑,例如"./libddd.so",此時Coredump文件原封不動地保存相同的路徑。
? 為便于表述,用A表示set solib-absolute-prefix設(shè)置的路徑,R(A)表示A去掉根前綴后的路徑(即去掉前綴“/”符號),用Bn表示set solib-search-path設(shè)置的每一條路徑,用X表示Coredump中保存的庫路徑,即待搜索的庫文件路徑,F(X)表示X中去掉目錄后的文件名(路徑最后“/”符號后的字符串)。
? 對絕對路徑,搜索順序是:
? 1)?A / X???????????????????????// 先添加solib-absolute-prefix前綴進行搜索,成功則不再繼續(xù),否則繼續(xù)2)
? 2)?R(A) / X?????????????????// 再把1)的根前綴去掉后進行搜索,成功則不再繼續(xù),否則繼續(xù)3)
? 3)?Bn / R(A) / X?????????// 再在2)的基礎(chǔ)上逐一添加solib-search-path中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)4)
? 4) Bn / F(X)?????????????? // 再只使用2)中的文件名(去掉目錄段),并逐一添加solib-search-path中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)5)
? 5) $PATH / R(A) / X??????????????????????????????????? // 在2)的基礎(chǔ)上使用環(huán)境變量$PATH中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)6)
? 6) $LD_LIBRARY_PATH / R(A) / X???????? // 在2)的基礎(chǔ)上使用環(huán)境變量$LD_LIBRARY_PATH中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)7)
? 7) 返回失敗
? 對相對路徑,搜索順序是:
? 1)?X????????????????????????????// 直接使用原始路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)2)
? 2)?Bn /?X???????????????? ???// 再逐一添加solib-search-path中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)3)
? 3) Bn / F(X)?????????????? // 再只使用文件名(去掉目錄段),并逐一添加solib-search-path中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)4)
? 4) $PATH / X??????????????????????????????????? // 再使用環(huán)境變量$PATH中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)5)
? 5) $LD_LIBRARY_PATH / X???????? // 再使用環(huán)境變量$LD_LIBRARY_PATH中的每條路徑進行搜索,成功則不再繼續(xù),否則繼續(xù)6)
? 6) 返回失敗
? ===================================
? 舉例說明:
? set solib-absolute-prefix /root/temp
? set solib-search-path /home/evan:/home/peter
? $PATH is /usr/sbin:/usr/bin
? $LD_LIBRARY_PATH is /opt:/usr/games
? 那么對絕對路徑"/lib/libc.so.6"的搜索順序是:
? 1) A / X
??????/root/temp/lib/libc.so.6
? 2) R(A) / X
????? root/temp/lib/libc.so.6
? 3) Bn / R(A) / X
????? /home/evan/root/temp/lib/libc.so.6
????? /home/peter/root/temp/lib/lic.so.6
??4) Bn / F(X)
????? /home/evan/libc.so.6
????? /home/peter/libc.so.6
? 5) $PATH / R(A) / X
????? /usr/sbin/root/temp/lib/libc.so.6
????? /usr/bin/roo/temp/lib/lic.so.6
? 6) $LD_LIBRARY_PATH / R(A) / X
????? /opt/root/temp/lib/libc.so.6
????? /usr/games/root/temp/lib/libc.so.6
? 對相對路徑"./libddd.so"的搜索順序是
? 1) X
????? ./libddd.so
? 2) Bn /?X
????? /home/evan/./libddd.so
????? /home/peter/./libddd.so
? 3) Bn / F(X)
????? /home/evan/libddd.so
????? /home/peter/libddd.so
? 4) $PATH / X
????? /usr/sbin/./libddd.so
????? /usr/bin/./libddd.so
? 5) $LD_LIBRARY_PATH / X
????? /opt/./libddd.so
????? /usr/games/./libddd.so
? 從上面看到,對絕對路徑和相對路徑都有一步是采用文件名和solib-search-path拼接來查找(絕對路徑的第4步和相對路徑的第3步),所以只要用set solib-search-path設(shè)置了每一個庫文件所在的直接目錄,那么就能保證每一個庫都能被找到。
?
4. 查看so庫的加載路徑是否正確可使用info sharedlibrary命令,如果已找到對應(yīng)的文件則其From和To的加載地址會有值,并且右邊路徑顯示的就是加載文件所在的地址,這個時候,如果so庫文件含符號信息,則syms Read的值為Yes,否則為No,如果未找到對應(yīng)的文件則From和To的地址為空,syms Read的值為No,此時右邊路徑顯示的是Coredump文件中庫文件路徑。
?
5. 如果在Coredump文件載入過程中,或者info sharedlibrary命令時,出現(xiàn)" Cannot access memory at address 0x87000069 "這樣的錯誤,這通常是由于所使用的主執(zhí)行文件("file"命令或"exec-file"命令)與Coredump文件("core"命令或"core-file"命令)兩者不匹配導(dǎo)致的。這個時候應(yīng)檢查主執(zhí)行文件是否是生成Coredump時所用的主執(zhí)行文件,只要差一點,就可能導(dǎo)致動態(tài)庫信息讀取錯誤。
?
6. 如果載入過程中有" warning: .dynamic section for "/lib/librt.so.1" is not at the expected address (wrong library or version mismatch?) "這樣的提示,這通常是庫搜索路徑設(shè)置錯誤,GDB載入了錯誤的庫文件導(dǎo)致的。這時,應(yīng)使用info sharedlibrary命令查看相應(yīng)庫的載入路徑,并使用set sysroot或set solib-search-path修改搜索路徑來將錯誤的庫修正到正確的路徑上。
?
7. 在設(shè)置了搜索路路徑后,最好先用file命令載入主執(zhí)行文件,再用core命令載入Coredump文件,這樣才能保證正確載入庫的符號表。否則,如果先用core命令載入Coredump文件,再用file命令載入主執(zhí)行文件,那么會造成庫只是被搜索但并不載入符號(使用info sharedlibrary命令可以看到),這時再重新執(zhí)行一次core命令就可以了。
?
8. 一個實際的搜索例子:
當(dāng)前目錄為/home
主執(zhí)行文件在/home/evan/gdbso/mips/gdbso
Core文件在/home/evan/gdbso/mips/Coredump
所用動態(tài)庫與拷貝到主執(zhí)行文件同一目錄下
編譯主執(zhí)行文件所用的標(biāo)準(zhǔn)庫被拷貝到主執(zhí)行文件的lib目錄下/home/evan/gdbso/mips/lib/libxxx.so
進入GDB,用file命令載入主執(zhí)行文件:
evan@ubunu:/home$ mips-linux-gnu-gdb
...
(gdb) file evan/gdbso/mips/gdbso
Reading symbols from /home/evan/gdbso/mips/gdbso...done.
(gdb) info sharedlibrary?
No shared libraries loaded at this time.
可以看到只載入了主執(zhí)行文件時,是無法得到動態(tài)庫信息的。
再用core命令載入Coredump文件:
(gdb) core evan/gdbso/mips/Coredump
...
warning: .dynamic section for "/lib/libc.so.6" is not at the expected address (wrong library or version mismatch?)
...
(gdb) info sharedlibrary?
From??????? To????????? Syms Read?? Shared Object Library
0x2aad98c0? 0x2aadd6d8? Yes???????? /lib/librt.so.1
0x2aaf3460? 0x2ab0db98? Yes???????? /lib/libm.so.6
0x2ab7e2e0? 0x2ab89b28? Yes???????? /lib/libpthread.so.0
0x2abba9a0? 0x2acb2bd8? Yes???????? /lib/libc.so.6
0x2ad06a40? 0x2ad07988? Yes???????? /lib/libdl.so.2
??????????????????????? No????????? /lib/ld.so.1
??????????????????????? No????????? ./libddd.so
(gdb)?
在同時有了主執(zhí)行文件和Coredump文件后,用info sharedlibrary就可以看到動態(tài)庫信息了。但在載入過程中有庫版本不匹配的提示。通過info sharedlibrary也看到GDB錯誤地載入了系統(tǒng)中自帶的標(biāo)準(zhǔn)庫。
我們將絕對路徑設(shè)置到一個不存在的目錄來看看Coredump中保存的原始路徑名:
(gdb) set sysroot /noexist
...
(gdb) info sharedlibrary?
From??????? To????????? Syms Read?? Shared Object Library
??????????????????????? No????????? /lib/librt.so.1
??????????????????????? No????????? /lib/libm.so.6
??????????????????????? No????????? /lib/libpthread.so.0
??????????????????????? No????????? /lib/libc.so.6
??????????????????????? No????????? /lib/libdl.so.2
??????????????????????? No????????? /lib/ld.so.1
??????????????????????? No????????? ./libddd.so
(gdb)?
Coredump中保存的原始路徑名為/lib/librt.so.1,為了讓GDB使用正確的庫/home/evan/gdbso/mips/lib/librt.so.1,只需要將絕對路徑前綴設(shè)置為/home/evan/gdbso/mips即可,這里設(shè)置為evan/gdbso/mips來演示效果:
(gdb) set sysroot evan/gdbso/mips
...
(gdb) info sharedlibrary?
From??????? To????????? Syms Read?? Shared Object Library
0x2aad98c0? 0x2aade270? Yes???????? evan/gdbso/mips/lib/librt.so.1
0x2aaf3110? 0x2ab31b70? Yes???????? evan/gdbso/mips/lib/libm.so.6
0x2ab7e320? 0x2ab8e620? Yes???????? evan/gdbso/mips/lib/libpthread.so.0
0x2abba6a0? 0x2accc3f0? Yes???????? evan/gdbso/mips/lib/libc.so.6
0x2ad06b50? 0x2ad07c70? Yes???????? evan/gdbso/mips/lib/libdl.so.2
0x2aaa8810? 0x2aac2e40? Yes???????? evan/gdbso/mips/lib/ld.so.1
??????????????????????? No????????? ./libddd.so
(gdb)?
可以看到,GDB已經(jīng)正確地載入了絕對路徑。但相對路徑"./libddd.so"還沒有找到,為了使用/home/evan/gdbso/mips/libddd.so,設(shè)置庫搜索路徑包含/home/evan/gdbso/mips即可。為了查看效果,這里還添加了一個不存在的搜索路徑:
(gdb) set solib-search-path /noexist:/home/evan/gdbso/mips
...
(gdb) info sharedlibrary?
From??????? To????????? Syms Read?? Shared Object Library
0x2aad98c0? 0x2aade270? Yes???????? evan/gdbso/mips/lib/librt.so.1
0x2aaf3110? 0x2ab31b70? Yes???????? evan/gdbso/mips/lib/libm.so.6
0x2ab7e320? 0x2ab8e620? Yes???????? evan/gdbso/mips/lib/libpthread.so.0
0x2abba6a0? 0x2accc3f0? Yes???????? evan/gdbso/mips/lib/libc.so.6
0x2ad06b50? 0x2ad07c70? Yes???????? evan/gdbso/mips/lib/libdl.so.2
0x2aaa8810? 0x2aac2e40? Yes???????? evan/gdbso/mips/lib/ld.so.1
0x2ad1a590? 0x2ad1a770? Yes???????? /home/evan/gdbso/mips/libddd.so
(gdb)?
可以看到,所有的庫都找到正確的路徑了,Syms也被正確地載入。
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的GDB动态库搜索路径的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【团队项目】2.0
- 下一篇: 类中赋值运算符重载函数