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