動機
之前不常用記錄一下
basic
- 印
- 變數val:
print(p) {var}
- 追蹤var(step每次都印):
display {var}
- 追蹤var(step每次都印):
- 變數type:
whatis {var}
- code:
list(l)
- 資訊:
info ??
- break
- 下面hook的list
- threads
thread {thread-id}
: 換到某個thread去
- forks
fork {fork-id}
: 換到某個proc去
- share
- locals
- args
- reg / all-regs
- break
- 變數val:
- 跑:
run
- 離開gdb:
quit(q)
- 設定gdb參數:
set {key} {val}
- kill:
kill [sig]
- 處理gdb收到的sig:
handle {sig} nostop noprint ...
hook
- breakpoint(b)
- 設定:
b {addr} or {funcname} or {filename:line-num}
- 條件成立才設:
b {pat} if expr
b main.cpp:255 if strA.compare(strB) != 0
- 條件成立才設:
- 設定:
- watchpoint
- 設定在??時中斷:
- 寫:
watch {expr}
- 讀:
rwatch {expr}
- 寫或讀:
awatch {expr}
- 寫:
- 設定在??時中斷:
- catchpoint
- 中斷一次就好:
tcatch {??}
- 設定在??發生時中斷:
catch {??}
- throw
- catch
- exec/fork/vfork
- load/unload libname
- 中斷一次就好:
- 操作hook
- 啟用/停用:
enable
/disable
- 刪br:
clear(delete)
- 繼續跑:
continue
- 先不要跑:
ignore {br_id} num
- 跑到br就做下面的事:
commands {br_id} ... end
一行一個指令command 1
print param2
print param3->member1
continue
end
- 啟用/停用:
對stack與function上下其手
- stack
- 現在整個stack:
bt
- 上一層:
up [num]
- 下一層:
down
- 現在這一層:
frame [num]
- 單行執行:
step
ornext
- 把loop跑完:
until
- 直接return:
return
- 把frame跑完:
finish
- 單行執行:
- 現在整個stack:
- 我就是要跳:
jump {addr} or {filename:line-num}
reg, addr, signal
- addr -> val
- examine(x):
x/{COUNT}{FMT}{SIZE} {ADDRESS}
- FMT: octal(o), hex(h), decimal(d) …
- SIZE: byte(b), word(w), giant(g)
- examine(x):
- 看reg:
${reg}
handle {SIG} {ACT}
- SIG: SIGHUP, SIGINT, …
- 可以看
shell kill -l
- 可以看
- ACT: 收到SIG時,做什麼,不要就是前面加no(
nostop
)- stop: 程式停下來
- print: 印出這個SIG
- pass: relay SIG到被觀察的程式 (選no就是會sig被擋掉,因為沒有relay過去)
- SIG: SIGHUP, SIGINT, …
core dump
生core dump
ulimit -c unlimited
cat /proc/sys/kernel/core_pattern
echo “1” > /proc/sys/kernel/core_uses_pid # 我不想打proc name
使用core dump
gdb {proc-path} {coredump}
gdb -c {coredump}
- 如果有開core_uses_pid
script
- 自訂function:
define {func-name} ... end
- 引入script:
source {path}
- 變數:
set ${var} = {val}
gdbserver
兩邊準備同一個與source code 之後就可以透過server在client的gdb做除錯
gdbserver localhost:8888 prog
target remote 192.168.81.173:8888 prog
複習asm與debug
Assembly And The Art Of Debugging
reverse debug的範例
假設有一個程式多跑幾次就會seg fault
- 讓他在gdb一直跑
b main # main的b
b _exit # 最後一行的b
command 1
record
continue
end
command 2
run
end
- 爆了,看pc現在指到哪
p $pc # 假設是 (void (*))0x5e4c5d00
p/x $*0x5e4c5d00 # 試著拿值看看,應該是不行
- 開始往後追
reverse-stepi # 往後
disassemble # 現在在跑什麼,假設發現,是最後的return發生問題
p $sp # (void *) 0x7fffffffdc98 出事的addr
watch *(long**)0x7fffffffdc98 # 有人動了就停下來
reverse-continue # 往後,等停下來就是出事的位置
Ref
How to get a core dump for a segfault on Linux How to Debug Programs on Remote Server using GDBServer Example Scripting GDB GDB實用教學:自動化你的debug