除錯小技巧: 在程式中直接中斷及偵測是否被 gdb 監控中

在程式中直接中斷

《Binary Hack》 #92 所言, 在 gdb 監控 process 的情況, 使用下列程式碼會進入中斷:

raise(SIGTRAP);

對 x86 環境, 下列作法也許會更好, 少了一層 function call

__asm__ __volatile__("int3");

Scott 有個 debugbreak 有處理 x86 以外的情況, 有需要時再來參考看看。

偵測是否被 gdb 監控中

比起在程式中直接中斷, 我比較需要知道目前程式是否被 gdb 監控 (attach) 中。以下是兩個實用的情境:

  • 原本已有 log 錯誤訊息, 在 log 極為嚴重錯誤訊息 (如 severity = FATAL) 時, 檢查看看是否有 gdb 在監控, 有的話不如順便進入中斷, 提前察看錯誤點。
  • 寫 multi-thread 時, 有時會有特定 thread 負責特定的事, 像是 UI 或 IO。有時會監控這個 thread 是否正常運作。或是有網路連線時, 有時會想監控另一端連線是否仍然正常運作。其中一種監控 thread 或網路連線的方式是週期性察看有無更新資料, 超過一定時間沒更新, 就中止程序或關掉連線重連。在使用 gdb 除錯時, 有可能在中斷點待太久而觸發前述安全防護機制, 反而無法長時間除錯。這時自動關閉防護措施會比較方便。

《Binary Hack》 #92 的作法利用設 gdb 會覆寫 SIGTRAP 的 signal handler 做檢查, 這個作法可以跨比較多平台, 但可用時機太窄。我偏好 Chromium 的作法, 直接讀 /proc/PID/status, 由 "TracerPid" 的值得知目前是否有 process 控控自己。程式執行中的任何時間都可用這方法得知正確的結果, 不過只適用於 Linux 和 Android。以下是參考 Chromium 實作稍作修改的版本:

留言

這個網誌中的熱門文章

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

virtualbox 使用 USB 裝置

熟悉系統工具好處多多