gdb工作原理和核心實現
gdb主要功能的實現依賴於一個系統函式ptrace,通過man手冊可以瞭解到,ptrace可以讓父程序觀察和控制其子程序的檢查、執行,改變其暫存器和記憶體的內容,主要應用於打斷點(也是gdb的主要功能)和列印系統呼叫軌跡。
一、ptrace函式
函式原型如下:
1 2 3 | #include <sys/ptrace.h> longptrace(enum__ptrace_request request,pid_t pid, void*addr,void*data); |
ptrace系統呼叫的request主要選項
PTRACE_TRACEME
表示本程序將被其父程序跟蹤,交付給這個程序的所有訊號(除SIGKILL之外),都將使其停止,父程序將通過wait()獲知這一情況。
PTRACE_ATTACH
attach到一個指定的程序,使其成為當前程序跟蹤的子程序,子程序的行為等同於它進行了一次PTRACE_TRACEME操作。
PTRACE_CONT
繼續執行之前停止的子程序。可同時向子程序交付指定的訊號。
更多引數請man ptrace
二、gdb使用ptrace的基本流程
- gdb除錯一個新程序:通過fork函式建立一個新程序,在子程序中執行ptrace(PTRACE_TRACEME, 0, 0, 0)函式,然後通過execv()呼叫準備除錯的程式。
- attach到已執行程序:將pid傳遞給gdb,然後執行ptrace(PTRACE_ATTACH, pid, 0, 0)。
在使用引數為PTRACE_TRACEME或PTRACE_ATTACH的ptrace系統呼叫建立除錯關係之後,交付給目標程式的任何訊號(除SIGKILL之外)都將被gdb先行截獲,gdb因此有機會對訊號進行相應處理,並根據訊號的屬性決定在繼續目標程式執行時是否將之前截獲的訊號實際交付給目標程式。
三、gdb使用的核心機制
斷點的功能是通過核心訊號實現的,以x86為例,核心向某個地址打入斷點,實際上就是往該地址寫入斷點指令INT 3,即0xCC。目標程式執行到這條指令之後就會觸發SIGTRAP訊號,gdb捕獲到這個訊號,根據目標程式當前停止位置查詢gdb維護的斷點連結串列,若發現在該地址確實存在斷點,則可判定為斷點命中。
核心是通過如下呼叫進入核心態的:
SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data)
根據不同的request呼叫不同函式,基本都是判斷當前程序task中ptrace選項,走security_ptrace函式,在linux security模組中,然後彙編。待續
—————————————
參考內容:
—結束—