Linux系統調用--ptrace函數詳解
說明:整理轉載
轉載地址:http://hi.baidu.com/lisuo/blog/item/05b70a248be7662fd50742c1.html
【ptrace系統調用】
1. 功能描述:
提供父進程觀察和控制另一個進程執行的機制,同時提供查詢和修改另一進程的核心影像與寄存器的能力。主要用於執行斷點調試和系統調用跟蹤。父進程可通過調用 fork ,接著指定所產生的子進程的 PTRACE_TRACEME 行為,最後使用 exec 等操作來初始化一個進程跟蹤。可替代的做法是,父進程通過 PTRACE_ATTACH 請求跟蹤一個現存進程的執行。
當子進程被跟蹤時,每次接收到訊號都會停止執行,即使不對訊號進行處理( SIGKILL 訊號除外)。父進程下次執行 wait 調用時,會接收到核心的通告,並可能檢查和修改已停止的子進程。父進程使子進程繼續執行,並有可能忽略接收到的訊號。
2. 用法:
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
參數:
request:請求執行的行為,可能選擇有:
PTRACE_TRACEME //指示父進程跟蹤某個子進程的執行。任何傳給子進程的訊號將導致其停止執行,同時父進程調用 wait() 時會得到通告。之後,子進程調用 exec() 時,核心會給它傳送 SIGTRAP 訊號,在新程式開始執行前,給予父進程式控制制的機會。pid, addr, 和 data參數被忽略。
以上是唯一由子進程使用的請求,剩下部分將由父進程使用的請求。
PTRACE_PEEKTEXT, PTRACE_PEEKDATA //從子進程記憶體空間 addr 指向的位置讀取一個字,並作為調用的結果返回。Linux 內部對文本段和資料區段不加區分,所以目前這兩個請求相等。data 參數被忽略。
PTRACE_PEEKUSR //從子進程的使用者區 addr 指向的位置讀取一個字,並作為調用的結果返回。
PTRACE_POKETEXT, PTRACE_POKEDATA //將 data 指向的字拷貝到子進程記憶體空間由 addr 指向的位置。
PTRACE_POKEUSR //將 data 指向的字拷貝到子進程使用者區由 addr 指向的位置。
PTRACE_GETREGS, PTRACE_GETFPREGS //將子進程通用和浮點寄存器的值拷貝到父進程內由 data 指向的位置。addr 參數被忽略。
PTRACE_GETSIGINFO //擷取導致子進程停止執行的訊號資訊,並將其存放在父進程內由 data 指向的位置。addr 參數被忽略。
PTRACE_SETREGS, PTRACE_SETFPREGS //從父進程內將 data 指向的資料拷貝到子進程的通用和浮點寄存器。addr 參數被忽略。
PTRACE_SETSIGINFO //將父進程內由 data 指向的資料作為 siginfo_t 結構體拷貝到子進程。addr 參數被忽略。
PTRACE_SETOPTIONS //將父進程內由 data 指向的值設定為 ptrace 選項,data 作為位元遮罩來解釋,由下面的標誌指定。
PTRACE_O_TRACESYSGOOD //當轉寄 syscall 陷阱 (traps) 時,在訊號編碼中設定位7,即第一個位元組的最高位。例如:SIGTRAP | 0x80。這有利於追蹤者識別一般的陷阱和那些由 syscall 引起的陷阱。
PTRACE_O_TRACEFORK //通過 (SIGTRAP | PTRACE_EVENT_FORK << 8) 使子進程下次調用 fork() 時停止其執行,並自動跟蹤開始執行時就已設定 SIGSTOP 訊號的新進程。新進程的 PID 可以通過 PTRACE_GETEVENTMSG 擷取。
PTRACE_O_TRACEVFORK //通過 (SIGTRAP | PTRACE_EVENT_VFORK << 8) 使子進程下次調用 vfork() 時停止其執行,並自動跟蹤開始執行時就已設定 SIGSTOP 訊號的新進程。新進程的 PID 可以通過 PTRACE_GETEVENTMSG 擷取。
PTRACE_O_TRACECLONE //通過 (SIGTRAP | PTRACE_EVENT_CLONE << 8) 使子進程下次調用 clone() 時停止其執行,並自動跟蹤開始執行時就已設定 SIGSTOP 訊號的新進程。新進程的 PID 可以通過 PTRACE_GETEVENTMSG 擷取。
PTRACE_O_TRACEEXEC //通過 (IGTRAP | PTRACE_EVENT_EXEC << 8) 使子進程下次調用 exec() 時停止其執行。
PTRACE_O_TRACEVFORKDONE //通過 (SIGTRAP | PTRACE_EVENT_VFORK_DONE << 8) 使子進程下次調用 exec() 並完成時停止其執行。
PTRACE_O_TRACEEXIT //通過 (SIGTRAP | PTRACE_EVENT_EXIT << 8) 使子進程退出時停止其執行。子進程的退出狀態可通過 PTRACE_GETEVENTMSG 。
PTRACE_GETEVENTMSG //擷取剛發生的 ptrace 事件訊息,並存放在父進程內由 data 指向的位置。addr參數被忽略。
PTRACE_CONT //重啟動已停止的進程。如果 data 指向的資料並非0,同時也不是 SIGSTOP 訊號,將會作為傳遞給子進程的訊號來解釋。那樣,父進程可以控制是否將一個訊號發送給子進程。addr 參數被忽略。
PTRACE_SYSCALL, PTRACE_SINGLESTEP //如同 PTRACE_CONT 一樣重啟子進程的執行,但指定子進程在下個入口或從系統調用退出時,或者執行單個指令後停止執行,這可用於實現單步調試。addr 參數被忽略。
PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP //用於使用者模式的程式模擬子進程的所有系統調用。
PTRACE_KILL //給子進程發送 SIGKILL 訊號,從而終止其執行。data,addr 參數被忽略。
PTRACE_ATTACH //銜接到pid指定的進程,從而使其成為當前進程的追蹤目標。
PTRACE_DETACH // PTRACE_ATTACH 的反向操作。
pid:目標進程標識。
addr:執行 peek 和 poke 操作的目標地址。
data:對於 poke 操作,存放資料的地方。對於 peek 操作,擷取資料的地方。
返回說明:
成功執行時,PTRACE_PEEK* 請求返回所請求的資料,其它返回0。失敗返回-1,errno 被設為以下的某個值。由於一個成功的 PTRACE_PEEK* 請求可能返回-1,決定錯誤是否發生前,調用者應檢查 errno 。
EBUSY:分配和釋放調試寄存器時出錯
EFAULT:讀寫不可訪問的記憶體空間
EINVAL:嘗試設定無效選項
EIO:請求無效,或者嘗試讀寫父子進程不可訪問的空間
EPERM:沒有許可權追蹤指定的進程
ESRCH:指定的子進程不存在,或者當前正由調用者追蹤