一究履、替換源碼路徑
1. 找到可執(zhí)行文件原來的路徑
readelf a.out -p .debug_str
2. 替換路徑path為to
set substitute-path? From? To
3. 取消替換
unset substitute-path [path]
二、查看源碼
命令? ? ? ? ? ? 縮寫? ? ? ? ? ? ? ? 用法1? ? ? ? ? ? 用法2? ? ? ? ? ? ? ? 用法3? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 用法4
list? ? ? ? ? ? ? ? ? l? ? ? ? ? ? ? ? ? ? l + 行號? ? ? ? l + 函數(shù)名? ? ? ? ? l 行號 搏存, 行號(指定范圍)? ? ? l + 文件名:行號
disassemble? ? ? ? ? ? ? ? ? ? ? 默認(rèn)(反匯編$pc)? ? ? ? ? ? ? ? +? 函數(shù)名? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + 內(nèi)存地址
三秫舌、編輯源碼
????為了避免已經(jīng)啟動了調(diào)試之后的妖,需要編輯源碼,又不想退出足陨,可以直接在gdb模式下編輯源碼嫂粟。
? ? 默認(rèn)使用的編輯器是/bin/ex
? ? 想使用自己熟悉的編輯器,那么可以通過下面的方式進(jìn)行設(shè)置
EDITOR=/usr/bin/vim
export EDITOR
如果你不知道你的編輯器在什么位置墨缘,可借助whereis命令或者which命令查看
whereis vim
?which vim
編輯完保存后星虹,別忘了重新編譯程序
(gdb) shell gcc -g -o main main.c
這里要注意,為了在gdb調(diào)試模式下執(zhí)行shell命令镊讼,需要在命令之前加上shell宽涌,表明這是一條shell命令。
這樣就能在不用退出GDB調(diào)試模式的情況下編譯程序了蝶棋。
四卸亮、堆棧跟蹤
程序“調(diào)用堆棧”是當(dāng)前函數(shù)之前的所有已調(diào)用函數(shù)的列表(包括當(dāng)前函數(shù))玩裙。
每個函數(shù)及其變量都被分配了一個“幀”兼贸,最近調(diào)用的函數(shù)在 0 號幀中(“底部”幀)段直。
命令? ? ? ? ? ? ? ? ????縮寫? ? ? ? ? ? ? ? ? ? ? ?用法1? ? ? ? ? ? ? ? ? ? 用法2
backtrace? ? ? ? ? ? ?bt? ? ? ? ? ? ? ? ? ? ? ? ? bt + n? ? ? ? ? ? ? ? ? ? bt? ?full(打印包括所有局部變量)
函數(shù)幀
執(zhí)行 'info locals' 命令時,gdb 會打印出當(dāng)前幀中的局部變量寝受。
缺省情況下坷牛,這個幀中的函數(shù)就是被中斷的函數(shù)(0 號幀)罕偎。
切換后很澄,再使用?'info locals' 可查看對應(yīng)幀中的變量。
命令? ? ? ? ? ? ? ? 縮寫? ? ? ? ? ? ? ? 用法1? ? ? ? ? ? ? ? ? ? ? ? ? ? 用法2? ? ? ? ? ? ? ? ? ? ? ??
frame? ? ? ? ? ? ? ? f? ? ? ? ? ? ? ? f(打印當(dāng)前函數(shù)幀)? ? ? ? f + 函數(shù)幀號(切換到指定幀)
up? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 移動至調(diào)用此函數(shù)的上一個函數(shù)幀
down? ? ? ? ? ? ? ? ? ? ? ? ?移動至將調(diào)用函數(shù)的下一個函數(shù)幀
五颜及、連接到其它進(jìn)程
gdb 還可以連接到已經(jīng)運(yùn)行的進(jìn)程(它的程序已經(jīng)過編譯甩苛,并加入了調(diào)試信息),并中斷該進(jìn)程俏站。
在啟動該程序時使其返回進(jìn)程pid讯蒲。
./程序名 &
啟動 gdb 并指定進(jìn)程標(biāo)識
sudo gdb 程序名 pid
此時進(jìn)程會中斷等待,進(jìn)程已經(jīng)運(yùn)行一段時間肄扎,無需執(zhí)行‘run’墨林,可直接設(shè)置斷點。但是‘watch’和‘info local’還無法找到對應(yīng)標(biāo)號犯祠,執(zhí)行一次‘next’即可正常設(shè)置旭等。
如果已經(jīng)完成了對程序的查看
(gdb)detach? ? ? ? # 釋放連接,使進(jìn)程繼續(xù)執(zhí)行
(gdb)kill? ? ? ? ? ? ? ?# 殺死進(jìn)程
GDB動態(tài)鏈接到進(jìn)程
file eg2 ????????????????#? 裝入文件
attach pid? ? ? ? ? ? ?# 連接到進(jìn)程標(biāo)識下的 eg2
六衡载、運(yùn)行 shell 命令
調(diào)用形式
shell [commandline]
修改變量的值
在程序運(yùn)行時搔耕,可以使用 'set ' 命令設(shè)置變量值。
set 變量名=值
七痰娱、源碼界面
啟動時弃榨,帶上tui(Text User Interface)參數(shù),將源碼以文本窗口呈現(xiàn)梨睁。
gdb 程序名 -tui? ? ? ? ? ? ? ? ? ? ? ? # 以tui方式打開
或者快捷鍵 “ctrl x a” 打開關(guān)閉tui
(gdb)tui enable? ? ? ? ? ? ? ? # 打開tui
(gdb)tui disable? ? ? ? ? ? ? ? # 關(guān)閉tui
(gdb)tui reg all? ? ? ? ? ? ? ? ?# 顯示所有寄存器
上方是源代碼窗口鲸睛,下面是 gdb 終端,窗口管理快捷鍵模仿 emacs坡贺。
窗口切換
啟動gdb之后官辈,上面是src窗口,下面是cmd窗口拴念,默認(rèn)focus在src窗口钧萍。
上下鍵以及pagedown,pageup? 移動顯示代碼政鼠,不顯示上下的調(diào)試命令风瘦。
info win? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? 查看當(dāng)前focus及窗口
命令? ? ? ? ? ????? 縮寫? ? ? ? ? ? ? ? ? ? 用法1????????????????????????????????????????用法2
focus? ? ? ? ? ? ? ? fs? ? ? ? ? ? ? ? ? ?fs next [prev]? 切換focus? ? ? ? ? ? fs? 窗口名
窗口布局
(gdb)layout src? ? ? ? ? ? ? ? ? ? # 顯示源碼 同 tui? enable
(gdb)layout asm? ? ? ? ? ? ? ? ?# 顯示反匯編碼
(gdb)layout reg? ? ? ? ? ? ? ? ? ?# 顯示寄存器
(gdb)layout split? ? ? ? ? ? ? ? ?# 顯示源碼、匯編
單步的時候上面的源代碼窗口會跟著滾動公般,比之前不停的 list 方便万搔。
若 up/down 切換棧幀后胡桨,上面的代碼來不及更新。
?update? ? ? ? ? ? ? ? ? ? ? ? ?#? 代碼窗口定位到最新的執(zhí)行位置瞬雹。
?CTRL-L? ? ? ? ? ? ? ? ? ? ? ? # 重繪整個界面昧谊。
九、程序中斷
中斷循環(huán)
程序運(yùn)行至死循環(huán)后酗捌,無法結(jié)束呢诬,為了讓程序停下來,我們可以發(fā)送一個中斷信號(ctrl + c)胖缤,GDB捕捉到該信號后會掛起被調(diào)試進(jìn)程尚镰。
ctrl + c? ? ? ? ? ? ? ? ? ? ? ? # 使正在運(yùn)行的程序中斷
掛起程序
通過Linux的作業(yè)管理機(jī)制,通過ctrl + z把當(dāng)前任務(wù)掛起哪廓,返回終端做其他事情狗唉。通過jobs命令可以查看當(dāng)前shell有哪些任務(wù)。
ctrl + z? ? ? ? ? ? ? ? ? ? ? ? # 掛起當(dāng)前程序
jobs? ? ? ? ? ? ? ? ? ? ? ? ? ? # 查看當(dāng)前掛起的程序
fg? ? %掛起號? ? ? ? ? ? ? # 恢復(fù)掛起的進(jìn)程
使用實例
ctrl + z? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????# 掛起GDB
jobs? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????#? 查看VIM對應(yīng)的作業(yè)號涡真,假設(shè)為1
fg %1? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????# 恢復(fù)VIM
ctrl + z? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????#? 修改完后掛起VIM
gcc -g -Wall -o insert_sort a.cpp? ? ?# 重新編譯程序
fg %2? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 恢復(fù)GDB
(gdb)r? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 重新加載文件執(zhí)行分俯,原有的斷點和信息不變?
十、 使用腳本
在使用gdb調(diào)試程序的時候哆料,有時候需要設(shè)定多個斷點缸剪,重復(fù)執(zhí)行某些操作。
10.1 自定義命令
gdb支持用戶自定義命令
define commandName?
? ? statement?
? ? ......?
end?
其中statement可以是任意gdb命令剧劝。
此外自定義命令還支持最多10個輸入?yún)?shù):$arg0橄登,$arg1……$arg9,$argc標(biāo)明參數(shù)個數(shù)讥此。
示例 自定義 myassign 命令
define myassign
? ? set var $arg0 = $arg1
end
自定義命令的help
document myassign
? ? 其中的文字會被直接顯示
end
10.2 編寫腳本
任意編寫一個腳本文件
#filename: .gdbinit? ? ? ? ? #注釋
file test_gdbscript? ? ? ? ? ?# 加載文件
set args hello? ? ? ? ? ? ? ? ? # 設(shè)置參數(shù)?
b? main? ? ? ? ? ? ? ? ? ? ? ? ? ? # 設(shè)置斷點
r? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 運(yùn)行
10.3 加載腳本
gdb 程序名? -x 腳本
或者
gdb 程序名 -command=腳本
或者
(gdb)source 腳本