GDB Python Integration === ###### tags: `gdb` `python` `elf` `mingnus` contributed by <`mingnus`> ## Basics * One-line Python code in gdb breakpoint command * 案例: 計算 breakpoint hit 次數 (雖說 gdb 本身就會計算 breakpoint hit count) ``` (gdb) command 1 >silent >python global i; i=0 >cont >end (gdb) command 2 >silent >python global i; i+=1 >cont >end (gdb) command 3 >silent >python global i; print("counter={}".format(i)) >cont >end ``` ## GDB Python API 應用案例 ### Print function call graph * [supertrace.py](http://rickey-nctu.blogspot.com/2013/11/gdb.html) 以 gdb Python API 提供的 stack frame 功能追踪程式執行時的 call stack, 進而印出 call graph, 對於追踪單一執行緒滿有幫助。程式存在以下缺失: * `supertrace.py` 載入方式: supertrace.{gdb|py} 必須和 debuggee 置於相同目錄 * Shared lib symbols 讀取方式及 file list 取得方式的缺陷: 為了讀取 shared lib symbols, supertrace 的做法是執行 debuggee, 讓程式自動載入 shared libs 後才使用 rbreak 設定 breakpoints。副作用是其他非相關 symbols 也會被設立 breakpoints,例如 debug 版 libc, 導致 supertrace.gdb 準備時間變很長 * 無法控制哪些 symbol 要設定 breakpoint, 也難以有效增減 breakpoints * 輸出格式可再加強, 例如增加 function parameters * Stack 追踪方式無法處理迴圈呼叫 * Breakpoint commands 可改用 Python API gdb.Breakpoint 實作 * [callgraph on GitHub](https://github.com/jmbr/callgraph) 本專案未使用 gdb Python API, 而是用 awk 後製 gdb output, 所以速度差了一截。另外它僅印出 caller 及 callee, 而非像 supertrace 那樣追踪整個 call stack ### Print backtrace context * [用 python gdb 客製化 backtrace 的結果](http://fcamel-life.blogspot.com/2013/08/python-gdb-backtrace-2.html) ## 改善 supertrace [source code](https://gist.github.com/mingnus/ac16334fc579cba96912af2c0e3c1ec1) 使用方法: gdb 直接載入 supertrace.py 即可 ```shell (gdb) python sys.path.insert(0, '<path_to_supertrace.py>'); import supertrace or (gdb) set script-extension soft (gdb) source supertrace.py ``` ### 改善項目 * 加強程式獨立性, 不需依賴 supertrace.gdb * 新增 tracepoint 設定指令 * breakfile: 追踪單一檔案內的所有 fucntion * breaksymbol: 追踪特定 function * 以 gdb.Breakpoint 取代 breakpoint commands ### 問題 * 如何用 gdb Python API 取得一個 source file 裡的所有 symbols rbreak 使用 search_symbols() (in `gdb/symtab.c`) 取得 symbols, 但 gdb Python API 僅提供 gdb.lookup_symbol() (對應 lookup_symbol() in `gdb/symtab.c`), 必須提供明確 symbol name。似乎要用 gdb.Block iteration 解決, 但這功能似乎還沒完成... > gdb provides a method to get a block's superblock, but there is currently no way to examine the sub-blocks of a block, or to iterate over all the blocks in a symbol table