調試器原理之ptrace調用學習

        其實很早以前就對調試器技術感興趣了。以前玩板子的時候用了JTAG,當時我覺得這東西好神奇。前面我下載了一份GDB源碼,可惜弄了幾天都沒有看出門道。昨天瞄了一眼《開源應用程序架構》,不出意外的看到了GDB。裏面說在Linux下面調試器的功能主要都是靠ptrace調用實現的。我突然覺得有戲,感覺找到了點希望(不得不說,網上真心沒找到GDB實現方面的資料,頂多是使用教程)。然後我就和ptrace幹上了。後來就查到了一份名爲《Linux源碼分析-PTRACE》的文檔,大致看了一遍後解決了我的不少疑問。下面是我摘抄的總結和自己的一點理解。
       調試進程的控制
       1) 終止進程運行
       在使用調試器調試程序時,被調試程序被中斷的條件有:: 
       1. 調試器設置的斷點(指令斷點和數據斷點)滿足條件。
       2. 進程收到一個信號(SIGKILL除外)。 
       3. 單步調用完成。 
       4. 系統調用調試下,進入或離開系統調用。

                A. 斷點  設置斷點是調試器中的一個重要功能。80386提供了兩種方式,INT3和利用調試寄存器。  如果使用INT3方式設置斷點,則調試器通過ptrace的PTRACE_POKETEXT功能在斷點處插入INT3單字節指令。當進程運行到斷點時(INT3處),則系統進入異常3的處理。 若使用調試寄存器,則調試器通過調用ptrace(PTRACE_POKEUSR,pid,0,data)在DR0-DR3寄存器設置與四個斷點條件的每一個相聯繫的線性地址在DR7中設置斷點條件。被跟蹤進程運行到斷點處時,CPU產生異常 1,從而轉至函數do_debug處理。由於子進程在調試狀態下屬於正常調試異常,所以do_debug函數處理中產生SIGTRAP信號,爲處理這個信號,進入do_signal,使被調試進程停止,並通知調試器(父進程),此時得到子進程終止原因爲SIGTRAP。
                B. 信號  在有些情況之下,要求調試器調試某進程時,當進程收到某一信號的時候中斷進程運行。如:被調試進程在某處運算錯誤,進程會接收到SIGFPE信號,在正常運行狀況下,會Coredump,而調試的情況下則希望在產生錯誤代碼處停止運行,可以讓用戶調試錯誤原因。  對於已經被調試的進程(PF_PTRACED標誌置位),當受到任何信號(SIGKILL除外)會中止其運行,並通知調試器(父進程)。(詳見do_signal分析)
                C. 單步執行  單步執行也是一種使進程中止的情況。當用戶調用ptrace的PTRACE_SINGLESTEP功能時,ptrace處理中,將用戶態標誌寄存器EFLAG中TF標誌爲置位,並讓進程繼續運行(具體分析見ptrace函數分析)。當進程回到用戶態運行了一條指令後,CPU產生異常 1,從而轉至函數do_debug處理。由於子進程在調試狀態下屬於正常調試異常,所以do_debug函數處理中產生SIGTRAP信號,爲處理這個信號,進入do_signal,使被調試進程停止,並通知調試器(父進程),此時得到子進程終止原因爲SIGTRAP。 
                D. 系統調用調試  對程序的調試,有時希望對系統調用進程跟蹤。當程序進行系統調用時中斷其運行。ptrace提供PTRACE_SYSCALL功能完成此功能。在ptrace調用中設置了進程標誌PF_TRACESYS,表示進程對系統調用進行跟蹤,並繼續執行進程(具體分析見ptrace函數分析)。直到進程調用系統調用時,則中止其運行,並通知調試器(父進程)。(詳見syscall_trace分析)
       2) 繼續進程執行 
       讓中斷的進程繼續執行,ptrace提供三種功能 
       1. 繼續執行(PTRACE_CONT) 
       2. 系統調用調試(PTRACE_SYSCALL) 
       3. 單步執行(PTRACE_SINGLESTEP) 
        三種功能的區別在於PTRACE_CONT功能讓進程繼續執行直到下一個斷點或收到一個信號會中止進程運行。PTRACE_SYSCALL功能讓進程繼續執行增加了一箇中止條件,進程調用系統調用。PTRACE_SINGLESTEP功能讓進程繼續執行,只執行一個機器指令,則就中止其運行。 當被調試進程因爲受到一個信號而中止時,這個信號並沒有被處理。如果希望繼續運行進程時繼續處理這個信號,則在上述三個ptrace功能調用時,最後一個參數data設置要繼續處理的信號。這種情況出現在,如:中止進程運行的信號爲用戶自定義信號,用戶想繼續運行進程,而不要忽略用戶信號處理。有時,用戶希望忽略其信號處理,這時則參數data設置爲0,這種情況出現在,如:由於算術錯誤接收到SIGFPE信號使進程中止,而用戶發現了錯誤,重新設置了正確的值,然後希望其繼續執行,這時SIGFPE信號則需要忽略。
        根據ptrace的具體工作原理,我們知道控制被調試進程的關鍵在於兩點。第一、按照我們的需要產生異常使被調試程序停下來,無論是使用INT3還是調試寄存器。然後在異常處理函數中發出信號,這些信號可以被調試器接收。第二、使用內存映射的方法讀取被調試程序的數據空間,實現對被調試程序的信息監控。
        還有一個值得注意的問題是信號處理函數執行的時機。信號函數會在執行流從內核空間返回用戶空間前夕判斷並執行。一個被調試程序執行完異常處理後,它必須返回用戶空間繼續執行。這可以保證信號處理一定會優先於用戶空間的代碼運行。在通常的情況下,這個信號處理函數會導致被調試程序停止,同時父進程(調試器)也會收到這一信號。
發佈了49 篇原創文章 · 獲贊 11 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章