動機

之前不常用記錄一下

basic

    • 變數val: print(p) {var}
      • 追蹤var(step每次都印): display {var}
    • 變數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
  • 跑: 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 or next
      • 把loop跑完: until
      • 直接return: return
      • 把frame跑完: finish
  • 我就是要跳: 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)
  • 看reg: ${reg}
  • handle {SIG} {ACT}
    • SIG: SIGHUP, SIGINT, …
      • 可以看shell kill -l
    • ACT: 收到SIG時,做什麼,不要就是前面加no(nostop)
      • stop: 程式停下來
      • print: 印出這個SIG
      • pass: relay SIG到被觀察的程式 (選no就是會sig被擋掉,因為沒有relay過去)

core dump

生core dump

ulimit -c unlimited
cat /proc/sys/kernel/core_pattern
echo   “1” > /proc/sys/kernel/core_uses_pid # 我不想打proc name

man core

使用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

  1. 讓他在gdb一直跑
b main # main的b
b _exit # 最後一行的b

command 1
record
continue
end

command 2
run
end
  1. 爆了,看pc現在指到哪
p $pc # 假設是 (void (*))0x5e4c5d00
p/x $*0x5e4c5d00 # 試著拿值看看,應該是不行
  1. 開始往後追
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