GDB
gdb調(diào)試中直接輸入回車是重復(fù)上一步命令
start:臨時斷點打在main函數(shù)處鳖擒,等候進一步指令
r(run):從main函數(shù)處開始運行程序,直至程序結(jié)束/出錯/到達斷點
shell ls / !ls:在gdb中執(zhí)行shell命令
set prompt (xxxx) :修改命令提示符前綴,默認是(gdb)狐肢,多gdb調(diào)試時用來區(qū)分
$gdb -args ./a.out a b c / (gdb) set args a b c:指定程序的命令行參數(shù)端辱,下次調(diào)用run時就會使用a b c參數(shù),也可以(gdb) run a b c / (gdb) start a b c
set logging on:將gdb調(diào)試的歷史保存到日志中怯晕;set logging file xx.file:指定gdb調(diào)試日志名字,默認是gdb.txt缸棵;set logging overwrite on:覆蓋之前的gdb調(diào)試日志舟茶,默認是追加寫gdb調(diào)試日志
函數(shù)
info functions:列出可執(zhí)行文件的所有函數(shù)名稱
info functions regex:指定函數(shù),使用正則表達式匹配
step(縮寫為s):可以進入函數(shù)(函數(shù)必須有調(diào)試信息)
next(縮寫為n):不進入函數(shù)堵第,gdb會等函數(shù)執(zhí)行完吧凉,再顯示下一行要執(zhí)行的程序代碼
set step-mode on:設(shè)置步進模式,進入沒有調(diào)試信息的函數(shù)
finish:執(zhí)行完當(dāng)前函數(shù)踏志,并且打印返回值
return (expression):當(dāng)前函數(shù)不會繼續(xù)執(zhí)行阀捅,而是直接返回,可以指定返回值
call/print:直接調(diào)用函數(shù)執(zhí)行
i frame:輸出當(dāng)前函數(shù)堆棧幀的地址针余,指令寄存器的值饲鄙,局部變量地址及值等信息
i registers:輸出當(dāng)前寄存器中的值
disassemble fun:輸出函數(shù)的匯編代碼
f(frame) n:選擇函數(shù)堆棧幀,n為層數(shù)圆雁,
f(frame) addr:選擇函數(shù)堆棧幀忍级,其中addr是堆棧地址
up n / down n:向上或向下選擇函數(shù)堆棧幀,n為層數(shù)
up-silently n / down-silently n:與上面指令的區(qū)別在于伪朽,切換堆棧幀后轴咱,不會打印信息
斷點
b Foo::foo / b (anonymous namespace):命名空間/匿名空間打斷點
b *address:當(dāng)調(diào)試匯編程序,或者沒有調(diào)試信息的程序時烈涮,在程序地址上打斷點
b:在當(dāng)前代碼行打上斷點
info b:輸出當(dāng)前所有斷點朴肺,它們各自的bnum以及所在的相對路徑文件與行號
disable <bnum>:關(guān)閉編號為bnum的斷點;enable <bnum>:打開編號為bnum的斷點跃脊;delete <bnum>:刪除編號為bnum的斷點
b 6:當(dāng)前文件第6行打斷點
b file.c:6:gdb會對所有匹配的文件(file.c)的第6行設(shè)置斷點
b a/file.c:6:通過指定(部分)路徑宇挫,來區(qū)分相同的文件名
b a/file.c:6 if i==100:設(shè)置條件斷點
condition <bnum> (<condition>):把bnum斷點的條件修改為condition
ignore <bnum> count:接下來count次編號為bnum的斷點觸發(fā)都不會讓程序中斷
tb(tbreak) a/file.c:6:設(shè)置臨時斷點苛吱,斷點只會生效一次酪术,然后就會刪除
rbreak regexp:在所有匹配regexp的函數(shù)名都設(shè)置斷點,regexp與grep相同
在程序入口處打斷點:當(dāng)調(diào)試沒有調(diào)試信息的程序時翠储,直接運行start命令是沒有效果的绘雁,如果不知道m(xù)ain在何處,那么可以在程序入口處打斷點援所,兩種方法:
# 方法一:從elf文件處獲得程序入口(entry point)
$ strip a.out
$ readelf -h a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
...
Entry point address: 0x400440
...
# 方法二:info files
$ gdb a.out
(gdb) info files
# -------------------------------------------------------- #
(gdb) b *0x400440
觀察點
watch(wa) a:當(dāng)變量a的值發(fā)生變化庐舟,程序暫停
watch (data type)address:當(dāng)類型為data type、地址為address的內(nèi)存發(fā)生變化住拭,程序暫停
info disable enable delete用法與斷點類似
set can-use-hw-watchpoints:禁止硬件觀察點挪略,如果系統(tǒng)支持硬件觀察點历帚,設(shè)置觀察點會有輸出Hardware watchpoint num: expr
,需要注意軟件觀察點會讓程序很慢
watch expr thread threadnum:設(shè)置觀察點只針對線程編號為threadnum的線程生效(只對硬件觀察點生效
rwatch(rw) a:當(dāng)讀取變量a時杠娱,程序就會暫停淄炖巍(只對硬件觀察點生效
awatch(aw) a:當(dāng)發(fā)生讀取變量a或改變變量a值的行為,程序就會暫停滋蟆(只對硬件觀察點生效
catchpoint
簡介:use catchpoints to cause the debugger to stop for certain kinds of program events, such as C++ exceptions or the loading of a shared library
catch fork:程序在調(diào)用fork系統(tǒng)調(diào)用時暫停
tcatch fork:程序只在第一次調(diào)用fork時暫停
catch syscall [name | number]:為指定的系統(tǒng)調(diào)用設(shè)定catchpoint禽拔,系統(tǒng)調(diào)用和編號的映射參考具體的xml文件,如果不指定具體的系統(tǒng)調(diào)用室叉,則會為所有的系統(tǒng)調(diào)用設(shè)置catchpoint
打印
set print elements number-of-elements:打印大數(shù)組的元素時缺省最多200個睹栖,該命令可以修改該限制
p array[index]@num:打印數(shù)組中任意連續(xù)元素的值
set print array-indexes on:設(shè)置打印數(shù)組時同時打印索引下標(biāo)
bt full:打印函數(shù)堆棧各自的局部變量
bt full n:從內(nèi)向外打印n個棧幀的局部變量
bt full -n:從外向內(nèi)打印n個棧幀的局部變量
info locals:打印當(dāng)前函數(shù)局部變量的值
p 'stataic-1.c'::var:打印指定文件的靜態(tài)變量的值
whatis he:打印變量he的類型
ptype he:打印變量he的類型的詳細信息
info variable ^he$
:查看定義變量he的文件,^he$
是正則完全匹配he茧痕,如果不完全匹配野来,可能會匹配到很多變量
x/s:打印ASCII字符串
x/nfu addr:以f格式打印從addr開始的n個長度單元為u的內(nèi)存值。n:輸出單元的個數(shù)踪旷。f:是輸出格式梁只。比如x是以16進制形式輸出,o是以8進制形式輸出埃脏。u:標(biāo)明一個單元的長度搪锣。b是一個byte,h是兩個byte(halfword)彩掐,w是四個byte(word)构舟,g是八個byte(giant word)。
l(list) [line_num / func_name]:打印源代碼以及行號堵幽,可以指定行號與函數(shù)名
l -/+:指定打印源代碼向前或向后打印
l 1,10:指定打印源代碼范圍
set print pretty on:設(shè)置打印的美化狗超,每行只會顯示結(jié)構(gòu)體的一名成員,默認打印結(jié)構(gòu)體是很緊湊的
set print object on:設(shè)置打印按照派生對象的類型朴下,設(shè)置后會修改p/whatis/ptype的輸出結(jié)果
p func_in_frame2::b:直接打印調(diào)用棧幀中的變量值努咐,不需要先切換到對應(yīng)棧幀再打印變量值
多進程/線程
$ gdb programe -p / --pid:調(diào)試已經(jīng)運行的進程
attach pid:gdb啟動后,調(diào)用該命令調(diào)試已經(jīng)運行的進程
detach:退出當(dāng)前正在調(diào)試的進程
set follow-fork-mode child:設(shè)置調(diào)試子進程殴胧,父進程退出后程序會自動調(diào)試子進程
set detach-on-fork off:gdb默認只會跟蹤父進程渗稍,子進程不受控制,該命令可以同時調(diào)試父子進程
info inferiors:查看進程狀態(tài)团滥,顯示*的是當(dāng)前正在調(diào)試的進程
info threads [threadnum]:查看所有線程信息竿屹,LWP是lightweight process(輕量級進程)
set schedule-multiple on:gdb默認不能同時運行父子進程,該命令可以同時執(zhí)行父子進程
thread <ID> 切換調(diào)試的線程為指定ID的線程灸姊。
break file.c:100 thread all 在file.c文件第100行處為所有經(jīng)過這里的線程設(shè)置斷點拱燃。
set scheduler-locking on:調(diào)試一個線程時,讓其他線程暫停(默認是off力惯,即不暫停碗誉,除了on/off召嘶,還有step模式:用step命令調(diào)試線程時,其他線程不會執(zhí)行哮缺,但是用其他命令(如next)調(diào)試線程時苍蔬,其他線程也許會執(zhí)行
add-inferior [ -copies n ] [ -exec executable ]:在gdb會話中調(diào)試另一個可執(zhí)行文件,可同時調(diào)試多個可執(zhí)行文件
為調(diào)試進程產(chǎn)生core dump文件
generate-core-file / gcore:為當(dāng)前調(diào)試的進程產(chǎn)生core dump文件蝴蜓,default name is 'core.<process_id>'
$ gdb path/to/the/executable path/to/the/coredump:加載core dump文件
file <excutive file>:讀取可執(zhí)行文件的符號表信息
core <core file>:指定core dump文件位置
匯編
disassemble <func name>:顯示函數(shù)的匯編指令
set disassembly-flavor intel:將匯編改為intel格式碟绑,gdb默認是AT&T,該命令只能用于intel x86處理器上
b *func:將斷點設(shè)置在匯編指令層次函數(shù)的開頭茎匠,如果僅用b func不會把斷點設(shè)在匯編指令層次函數(shù)的開頭
disassemble /m fun:將函數(shù)內(nèi)所有代碼與匯編指令映射起來
disassemble 0x4004e9, 0x40050c:只查看某條語句對應(yīng)的匯編代碼
i line 13:Line 13 of "foo.c" starts at address 0x4004e9 <main+37> and ends at 0x40050c <main+72>.
display /ni $pc:當(dāng)程序停止時格仲,該指令可以顯示將要執(zhí)行的n行匯編指令
i registers:查看寄存器的值,不包含浮點寄存器與向量寄存器
i all-registers:查看所有寄存器的值
disassemble /r:用16進制顯示程序的原始機器碼
改變程序的執(zhí)行
set main::p1="Jil":更改字符串的值诵冒,一定要注意內(nèi)存越界的問題
set {char [4] } 0x80477a4 = "Ace":更改指定內(nèi)存地址的字符串的值凯肋,更改字符串的值,一定要注意內(nèi)存越界的問題
set var variable=expr:設(shè)置變量的值
set {type}address=expr:給存儲地址在address汽馋、變量類型為type的變量賦值
set var $eax = 8:eax寄存器存儲著函數(shù)的返回值侮东,也可以通過這種方式修改函數(shù)的返回值
set var $pc=0x08050949:pc寄存器存儲著接下來要執(zhí)行的指令,可以通過這種方式更改程序的執(zhí)行流程
info line 7:Line 7 of "a.c" starts at address 0x8050949 <main+40> and ends at 0x805094e <main+45>.
jump [line_num]:調(diào)到第line_num行豹芯,該指令只改變pc的值悄雅,所以可能會出現(xiàn)不同的結(jié)果
command <break_num>(然后輸入多行命令最后以end行結(jié)尾):為斷點break_num設(shè)置指令組合,當(dāng)程序運行到斷點處铁蹈,會自動執(zhí)行command 1的指令組合宽闲,然后繼續(xù)執(zhí)行
set write on:允許gdb修改二進制文件
set variable (short)0x400651=0x0ceb:修改二進制代碼,注意大小端和指令長度
信號
info signals/handle:查看gdb如何處理進程收到的信號
handle SIGHUP nostop:設(shè)置當(dāng)SIGHUP信號發(fā)生時握牧,gdb不暫停程序容诬,handle signal stop/nostop
handle SIGHUP noprint:設(shè)置當(dāng)SIGHUP信號發(fā)生時,gdb不打印信號信息沿腰,handle signal print/noprint
handle SIGHUP nopass:設(shè)置當(dāng)SIGHUP信號發(fā)生時览徒,gdb不把信號丟給程序處理,handle signal pass(noignore)/nopass(ignore)
signal SIGHUP:gdb會直接將信號發(fā)送給程序處理颂龙,而且程序會繼續(xù)運行
與在shell中使用kill發(fā)送信號給程序的區(qū)別是:kill發(fā)送信號习蓬,gdb會決定是否把信號發(fā)送給進程,而signal指令是直接發(fā)送信號
signal 0:程序重新運行厘托,但不會收到SIGHUP信號
源文件
directory [path]:設(shè)置查找源文件的路徑友雳,有時gdb不能準(zhǔn)確地定位到源文件的位置(比如文件被移走了稿湿,等等)
$gdb a.out -d /search/code/some:在gdb啟動時指定搜索源文件的路徑
set substitute-path [from] [to]:查看源代碼時铅匹,用新的目錄代替舊的目錄
info source:顯示當(dāng)前源文件名
info sources:顯示加載的symbols涉及的源文件
圖形界面
$ gdb --tui / (gdb) (ctrl+X+A):進入圖形化調(diào)試界面
layout asm:進入圖形化界面后,該命令顯示匯編代碼窗口
layout split:進入圖形化潔面后饺藤,該命令同時顯示源代碼和匯編代碼
layout regs:顯示通用寄存器窗口
winheight <win_name> [+ | -] count:調(diào)整窗口大小包斑,winheight
縮寫為win
流礁。win_name
可以是src
、cmd
罗丰、asm
和regs神帅。count是變化值
Ctrl + L:刷新窗口
命令的縮寫
b -> break
c -> continue
d -> delete
f -> frame
i -> info
j -> jump
l -> list
n -> next
p -> print
r -> run
s -> step
u -> until
aw -> awatch
bt -> backtrace
dir -> directory
disas -> disassemble
fin -> finish
ig -> ignore
ni -> nexti
rw -> rwatch
si -> stepi
tb -> tbreak
wa -> watch
win -> winheight
另外,如果直接按回車鍵萌抵,會重復(fù)執(zhí)行上一次的命令找御。