亚洲狠狠干,亚洲国产福利精品一区二区,国产八区,激情文学亚洲色图

一種調(diào)試器及其調(diào)試方法

文檔序號:6607016閱讀:261來源:國知局
專利名稱:一種調(diào)試器及其調(diào)試方法
技術(shù)領(lǐng)域
本發(fā)明涉及計算機(jī)技術(shù)領(lǐng)域,尤其涉及一種調(diào)試器及其調(diào)試方法。
背景技術(shù)
在類UNIX操作系統(tǒng)中,提供了一種標(biāo)準(zhǔn)的服務(wù)使得用戶態(tài)程序能夠?qū)崿F(xiàn)對底層硬件和服務(wù)的控制(如對文件系統(tǒng)的控制),這種服務(wù)稱為系統(tǒng)調(diào)用(system calls)。而連接用戶態(tài)程序和系統(tǒng)調(diào)用的橋梁稱為庫函數(shù)。當(dāng)一個程序需要作系統(tǒng)調(diào)用的時候,它首先調(diào)用與之對應(yīng)的庫函數(shù),通過庫函數(shù)找到系統(tǒng)調(diào)用表和對應(yīng)的系統(tǒng)調(diào)用號,再將相關(guān)參數(shù)放進(jìn)與系統(tǒng)調(diào)用相關(guān)的寄存器中,然后調(diào)用軟中斷。這個中斷就像一個讓用戶態(tài)程序得以接觸到內(nèi)核模式的窗口,使得庫函數(shù)能夠?qū)?shù)和系統(tǒng)調(diào)用號交給內(nèi)核,最后由內(nèi)核完成系統(tǒng)調(diào)用的執(zhí)行。用戶態(tài)程序和庫函數(shù)都是運(yùn)行在用戶地址空間,而系統(tǒng)調(diào)用則是運(yùn)行在內(nèi)核地址空間。在嵌入式軟件開發(fā)過程中,往往需要修改內(nèi)核的相關(guān)接口,再由用戶態(tài)程序通過庫函數(shù)調(diào)用到這些內(nèi)核接口。要對這類程序進(jìn)行調(diào)試,就需要調(diào)試器具有從用戶地址空間跟蹤調(diào)試進(jìn)內(nèi)核地址空間的功能。因此,如何能夠同時對被調(diào)試任務(wù)的用戶地址空間和內(nèi)核地址空間進(jìn)行調(diào)試,成為調(diào)試器設(shè)計的一種需要。調(diào)試器是用來幫助開發(fā)人員分析和定位程序故障的一種工具。按照調(diào)試的地址空間范圍進(jìn)行劃分,目前的調(diào)試器可以分為內(nèi)核級調(diào)試器和用戶態(tài)調(diào)試器。內(nèi)核級調(diào)試器能夠跟蹤和調(diào)試運(yùn)行在內(nèi)核態(tài)的任務(wù)。而用戶態(tài)調(diào)試器只能對運(yùn)行在用戶態(tài)的任務(wù)進(jìn)行跟蹤和調(diào)試。類UNIX操作系統(tǒng)已經(jīng)提供了一套完整的機(jī)制用于用戶態(tài)任務(wù)的跟蹤和調(diào)試,即 Ptrace系統(tǒng)調(diào)用。ptrace系統(tǒng)調(diào)用提供了一種使得父進(jìn)程得以監(jiān)視和控制其他進(jìn)程的方式,它能夠改變子進(jìn)程中的寄存器和內(nèi)存信息,從而可以實(shí)現(xiàn)斷點(diǎn)調(diào)試和系統(tǒng)調(diào)用的跟蹤。 目前已有的用戶態(tài)調(diào)試器大多采用Ptrace系統(tǒng)調(diào)用進(jìn)行跟蹤調(diào)試。雖然ptrace系統(tǒng)調(diào)用能夠跟蹤和調(diào)試子進(jìn)程的運(yùn)行,但Ptrace系統(tǒng)調(diào)用只能對被調(diào)試任務(wù)的用戶地址空間進(jìn)行跟蹤和調(diào)試,最多跟蹤到庫函數(shù)一級,無法通過庫函數(shù)跟蹤進(jìn)內(nèi)核。內(nèi)核級調(diào)試器是運(yùn)行在內(nèi)核態(tài)的,它能夠?qū)?nèi)核任務(wù)進(jìn)行跟蹤和調(diào)試。以 WindRiver公司的Vxworks ( 一種嵌入式實(shí)時操作系統(tǒng))為例,它提供了一種shell調(diào)試器, 這種shell調(diào)試器就屬于內(nèi)核級調(diào)試器。而目前已有的內(nèi)核級調(diào)試器只針對內(nèi)核任務(wù)進(jìn)行調(diào)試,不能對用戶態(tài)任務(wù)進(jìn)行調(diào)試,更不能從用戶地址空間跟蹤調(diào)試進(jìn)內(nèi)核地址空間。在目前已有的各種調(diào)試器中,還沒有實(shí)現(xiàn)能夠同時對用戶地址空間和內(nèi)核地址空間進(jìn)行調(diào)試的功能。

發(fā)明內(nèi)容
本發(fā)明提供一種調(diào)試器及其調(diào)試方法,用以解決現(xiàn)有技術(shù)中的調(diào)試器不能同時對用戶地址空間和內(nèi)核地址空間進(jìn)行跟蹤調(diào)試的問題。
具體的,本發(fā)明提供一種調(diào)試方法,包括調(diào)試器在調(diào)試關(guān)系建立后,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);調(diào)試器判斷是否停止所述被調(diào)試任務(wù),若是,在所述被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,停止所述被調(diào)試任務(wù)的運(yùn)行后進(jìn)行任務(wù)訪問;所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或寄存器信息;其中,所述調(diào)制器對于因中斷或異常停止的被調(diào)試任務(wù),從內(nèi)核堆棧上訪問寄存器信息;對于非中斷或非異常停止的內(nèi)核態(tài)被調(diào)試任務(wù),以及停止在用戶地址空間的用戶態(tài)被調(diào)試任務(wù),通過調(diào)用Ptrace系統(tǒng)調(diào)用,在threacLstruct結(jié)構(gòu)體中訪問寄存器信息。進(jìn)一步地,本發(fā)明所述方法中,所述調(diào)試器在所述被調(diào)試任務(wù)為內(nèi)核態(tài)任務(wù)時,直接對內(nèi)核地址空間進(jìn)行內(nèi)存信息訪問;在所述被調(diào)試任務(wù)為用戶態(tài)任務(wù)時,調(diào)用Ptrace系統(tǒng)調(diào)用對用戶地址空間進(jìn)行內(nèi)存信息訪問。本發(fā)明所述方法進(jìn)一步具有以下特點(diǎn)本發(fā)明所述方法中,調(diào)試器判斷所述被調(diào)試任務(wù)是否停止的判斷條件包括所述調(diào)試器接收到上層發(fā)送的停止指令;或者,所述調(diào)試器在調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件;或者,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,捕獲到關(guān)心的信號消息。其中,所述調(diào)試器調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件的處理過程包括所述調(diào)試器調(diào)用相應(yīng)的異常處理函數(shù)進(jìn)行異常處理,并在檢測出當(dāng)前異常事件為有效異常事件時,上報當(dāng)前異常事件,并停止所述被調(diào)試任務(wù)的運(yùn)行;所述異常事件至少包括斷點(diǎn)異常事件和單步異常事件。其中,所述斷點(diǎn)異常事件中斷點(diǎn)的設(shè)置方式包括所述調(diào)試器獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若為用戶地址空間斷點(diǎn),直接將內(nèi)存指令替換為斷點(diǎn)指令;若為內(nèi)核地址空間斷點(diǎn),待所述被調(diào)試任務(wù)被調(diào)度時,將內(nèi)存指令替換為斷點(diǎn)指令,并在所述被調(diào)試任務(wù)完成調(diào)度時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原內(nèi)存指令。進(jìn)一步地,本發(fā)明所述方法中,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,檢測是否存在未處理的信號消息,若是,獲取待處理信號消息的信號值,上報信號處理事件,并基于獲取的所述信號值得到所關(guān)心的信號消息時,停止所述被調(diào)試任務(wù)。本發(fā)明還提供一種調(diào)試器,包括調(diào)試開啟模塊,用于建立調(diào)試關(guān)系,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);任務(wù)運(yùn)行控制模塊,用于在判斷出需要停止所述被調(diào)試任務(wù)時,在所述被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,停止所述被調(diào)試任務(wù)的運(yùn)行;任務(wù)訪問模塊,用于在所述任務(wù)運(yùn)行控制模塊停止運(yùn)行所述被調(diào)試任務(wù)時,進(jìn)行任務(wù)訪問,所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或寄存器信息;其中,所述任務(wù)訪問模塊對于因中斷或異常停止的被調(diào)試任務(wù),從內(nèi)核堆棧上獲取寄存器信肩、ο
其中,所述任務(wù)運(yùn)行控制模塊判斷所述被調(diào)試任務(wù)是否停止的判斷條件包括所述調(diào)試器接收到上層發(fā)送的停止指令;或者,所述調(diào)試器在調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件;或者,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,捕獲到關(guān)心的信號消息。進(jìn)一步地,本發(fā)明所述的調(diào)試器還包括異常處理模塊,用于調(diào)用相應(yīng)的異常處理函數(shù)進(jìn)行異常處理,并在檢測出當(dāng)前異常事件為有效異常事件時,上報當(dāng)前異常事件,并觸發(fā)所述任務(wù)運(yùn)行控制模塊,停止所述被調(diào)試任務(wù)的運(yùn)行;所述異常事件至少包括斷點(diǎn)異常事件和單步異常事件。進(jìn)一步地,所述調(diào)試器還包括斷點(diǎn)設(shè)置模塊,用于獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若為用戶地址空間斷點(diǎn),直接將內(nèi)存指令替換為斷點(diǎn)指令;若為內(nèi)核地址空間斷點(diǎn),待所述被調(diào)試任務(wù)被調(diào)度時,將內(nèi)存指令替換為斷點(diǎn)指令,并在所述被調(diào)試任務(wù)完成調(diào)度時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原內(nèi)存指令。進(jìn)一步地,所述調(diào)試器還包括信號處理模塊,用于在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,檢測是否存在未處理的信號消息,若是,獲取待處理信號消息的信號值,上報信號處理事件,并基于獲取的所述信號值得到所關(guān)心的信號消息時,觸發(fā)所述任務(wù)運(yùn)行控制模塊,停止所述被調(diào)試任務(wù)。與現(xiàn)有技術(shù)相比,本發(fā)明有益效果如下本發(fā)明提供的調(diào)試方法和調(diào)試器,克服了現(xiàn)有的各種調(diào)試器不能同時支持對用戶地址空間和內(nèi)核地址空間進(jìn)行調(diào)試功能的問題,達(dá)到了能夠?qū)Ρ徽{(diào)試任務(wù)在用戶地址空間和內(nèi)核地址空間的運(yùn)行進(jìn)行跟蹤和調(diào)試的目的。


為了更清楚地說明本發(fā)明實(shí)施例或現(xiàn)有技術(shù)中的技術(shù)方案,下面將對實(shí)施例或現(xiàn)有技術(shù)描述中所需要使用的附圖作一簡單地介紹,顯而易見地,下面描述中的附圖僅僅是本發(fā)明的一些實(shí)施例,對于本領(lǐng)域普通技術(shù)人員來講,在不付出創(chuàng)造性勞動性的前提下,還可以根據(jù)這些附圖獲得其他的附圖。圖1為本發(fā)明提供的一種調(diào)試方法流程圖;圖2為本發(fā)明提供的一種調(diào)試器的結(jié)構(gòu)圖;圖3為本發(fā)明實(shí)施例提供的一種調(diào)試器的結(jié)構(gòu)圖;圖4為本發(fā)明中調(diào)試器停止被調(diào)試任務(wù)運(yùn)行流程圖;圖5為本發(fā)明中調(diào)試器恢復(fù)被調(diào)試任務(wù)運(yùn)行流程圖;圖6為本發(fā)明中調(diào)試器訪問被調(diào)試任務(wù)內(nèi)存流程圖;圖7為本發(fā)明中調(diào)試器訪問被調(diào)試任務(wù)寄存器流程圖;圖8為本發(fā)明中調(diào)試器斷點(diǎn)設(shè)置流程圖;圖9為本發(fā)明中調(diào)試器斷點(diǎn)異常處理流程圖;圖10為本發(fā)明中調(diào)試器單步異常處理流程圖;圖11為本發(fā)明中調(diào)試器信號處理流程圖。
具體實(shí)施例方式下面將結(jié)合本發(fā)明實(shí)施例中的附圖,對本發(fā)明實(shí)施例中的技術(shù)方案進(jìn)行清楚、完整地描述,顯然,所描述的實(shí)施例僅僅是本發(fā)明一部分實(shí)施例,而不是全部的實(shí)施例?;诒景l(fā)明中的實(shí)施例,本領(lǐng)域普通技術(shù)人員在沒有做出創(chuàng)造性勞動前提下所獲得的所有其他實(shí)施例,都屬于本發(fā)明保護(hù)的范圍。為了解決現(xiàn)有技術(shù)中存在的各種調(diào)試器不能夠同時支持對用戶地址空間和內(nèi)核地址空間進(jìn)行跟蹤調(diào)試的問題,本發(fā)明提供一種調(diào)試器及其調(diào)試方法。該調(diào)試器實(shí)現(xiàn)了對被調(diào)試程序在用戶地址空間和內(nèi)核地址空間的運(yùn)行進(jìn)行跟蹤和調(diào)試的目的。該支持雙態(tài)調(diào)試的調(diào)試器不僅支持對用戶態(tài)任務(wù)的調(diào)試,同時也支持對內(nèi)核態(tài)任務(wù)的調(diào)試;所述支持雙態(tài)調(diào)試的調(diào)試器是一種內(nèi)核級調(diào)試器。如圖1所示,為本發(fā)明提供的一種調(diào)試方法流程圖,該方法具體包括步驟S101、調(diào)試器在調(diào)試關(guān)系建立后,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài)。步驟S102、調(diào)試器判斷是否停止所述被調(diào)試任務(wù),若是,在所述被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,停止所述被調(diào)試任務(wù)的運(yùn)行。該步驟中,所述調(diào)試器判斷所述被調(diào)試任務(wù)是否停止的判斷條件包括所述調(diào)試器接收到上層發(fā)送的停止指令;或者,所述調(diào)試器在調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件;或者,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,捕獲到關(guān)心的信號消息。其中,所述調(diào)試器調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件的處理過程包括所述調(diào)試器調(diào)用相應(yīng)的異常處理函數(shù)進(jìn)行異常處理,并在檢測出當(dāng)前異常事件為有效異常事件時,上報當(dāng)前異常事件,并停止所述被調(diào)試任務(wù)的運(yùn)行;所述異常事件至少包括斷點(diǎn)異常事件和單步異常事件。其中,所述斷點(diǎn)異常事件中斷點(diǎn)的設(shè)置方式包括所述調(diào)試器獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若為用戶地址空間斷點(diǎn),直接將內(nèi)存指令替換為斷點(diǎn)指令;若為內(nèi)核地址空間斷點(diǎn),待所述被調(diào)試任務(wù)被調(diào)度時,將內(nèi)存指令替換為斷點(diǎn)指令,并在所述被調(diào)試任務(wù)完成調(diào)度時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原內(nèi)存指令。進(jìn)一步的,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,檢測是否存在未處理的信號消息,若是,獲取待處理信號消息的信號值,上報信號處理事件,并基于獲取的所述信號值得到所關(guān)心的信號消息時,停止所述被調(diào)試任務(wù)。其中,所述調(diào)試器根據(jù)獲取的信號值,查找預(yù)先配置的信號列表,根據(jù)信號列表中記錄的信息,判斷該信號值所對應(yīng)的信號消息是否為所關(guān)心的信號消息。其中,信號列表是用戶根據(jù)具體需求所配置的。步驟S103、調(diào)試器在所述被調(diào)試任務(wù)停止運(yùn)行后進(jìn)行任務(wù)訪問,所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或寄存器信息;其中,所述調(diào)制器對于因中斷或異常停止的被調(diào)試任務(wù),從內(nèi)核堆棧上訪問寄存器信息。進(jìn)一步的,調(diào)試器在進(jìn)行任務(wù)訪問后,恢復(fù)被調(diào)試任務(wù)的運(yùn)行;其中,恢復(fù)方式為將所述被調(diào)試任務(wù)中設(shè)置的停止標(biāo)志位刪除。如圖2所示,為本發(fā)明提供的一種調(diào)試器,該調(diào)試器包括調(diào)試開啟模塊210,用于建立調(diào)試關(guān)系,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);任務(wù)運(yùn)行控制模塊220,用于在判斷出需要停止所述被調(diào)試任務(wù)時,在所述被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,停止所述被調(diào)試任務(wù)的運(yùn)行;任務(wù)訪問模塊230,用于在任務(wù)運(yùn)行控制模塊220停止運(yùn)行所述被調(diào)試任務(wù)時,進(jìn)行任務(wù)訪問;所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或寄存器信息;其中,對于寄存器信息訪問,任務(wù)訪問模塊230對于因中斷或異常停止的被調(diào)試任務(wù),從內(nèi)核堆棧上獲取寄存器信息;對于非中斷或異常停止的內(nèi)核態(tài)被調(diào)試任務(wù),以及停止在用戶地址空間的用戶態(tài)被調(diào)試任務(wù),通過調(diào)用Ptrace系統(tǒng)調(diào)用,在threacLstruct結(jié)構(gòu)體中獲取寄存器信息。進(jìn)一步地,對于內(nèi)存信息訪問,所述任務(wù)訪問模塊230在所述被調(diào)試任務(wù)為內(nèi)核態(tài)任務(wù)時,直接對內(nèi)核地址空間進(jìn)行內(nèi)存信息訪問;在所述被調(diào)試任務(wù)為用戶態(tài)任務(wù)時,調(diào)用ptrace系統(tǒng)調(diào)用對用戶地址空間進(jìn)行內(nèi)存信息訪問。進(jìn)一步地,所述任務(wù)運(yùn)行控制模塊220判斷被調(diào)試任務(wù)是否停止的判斷條件包括調(diào)試器接收到上層發(fā)送的停止指令;或者,調(diào)試器在調(diào)試被調(diào)試任務(wù)時發(fā)生異常事件;或者,調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,捕獲到關(guān)心的信號消息?;谏鲜鎏卣?,本發(fā)明所提供的調(diào)試器進(jìn)一步包括異常處理模塊M0,用于調(diào)用相應(yīng)的異常處理函數(shù)進(jìn)行異常處理,并在檢測出當(dāng)前異常事件為有效異常事件時,上報當(dāng)前異常事件,并觸發(fā)所述任務(wù)運(yùn)行控制模塊220,停止所述被調(diào)試任務(wù)的運(yùn)行;所述異常事件至少包括斷點(diǎn)異常事件和單步異常事件。斷點(diǎn)設(shè)置模塊250,用于獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若為用戶地址空間斷點(diǎn),直接將內(nèi)存指令替換為斷點(diǎn)指令;若為內(nèi)核地址空間斷點(diǎn),待所述被調(diào)試任務(wù)被調(diào)度時,將內(nèi)存指令替換為斷點(diǎn)指令,并在所述被調(diào)試任務(wù)完成調(diào)度時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原指令。以及,信號處理模塊沈0,用于在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,檢測是否存在未處理的信號消息,若是,獲取待處理信號消息的信號值,上報信號處理事件,并基于獲取的所述信號值得到所關(guān)心的信號消息時,觸發(fā)所述任務(wù)運(yùn)行控制模塊220,停止所述被調(diào)試任務(wù)。下面根據(jù)圖3 圖11給出本發(fā)明一個較佳的實(shí)施例,并結(jié)合對實(shí)施例的描述,進(jìn)一步給出本發(fā)明的技術(shù)細(xì)節(jié),使其能夠更好地說明本發(fā)明的具體實(shí)現(xiàn)過程。如圖3所示,本發(fā)明還提供一種調(diào)試器,該調(diào)試器包括調(diào)試開啟模塊300、任務(wù)運(yùn)行控制模塊310、內(nèi)存訪問控制模塊320、寄存器訪問控制模塊330、斷點(diǎn)設(shè)置模塊340、異常處理模塊350、信號處理模塊360 ;具體的調(diào)試開啟模塊300,用于建立調(diào)試關(guān)系,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);
具體的,調(diào)試開啟模塊300通過執(zhí)行attach操作,建立調(diào)試關(guān)系。其中,attach被調(diào)試任務(wù)是支持雙態(tài)調(diào)試的調(diào)試器進(jìn)行調(diào)試的第一個操作,在實(shí)現(xiàn)了控制被調(diào)試任務(wù)運(yùn)行的基礎(chǔ)上,attach被調(diào)試任務(wù)操作除了執(zhí)行設(shè)置被調(diào)試任務(wù)的 Ptrace屬性,建立調(diào)試器與被調(diào)試任務(wù)父子關(guān)系外,還需要調(diào)用kertSk_irmer_SuSpend_ tsk()接口停止被調(diào)試任務(wù)的運(yùn)行。需要修改的是linux/kernel/ptrace. c文件中的 ptrace_attach()函數(shù)接口,其關(guān)鍵偽代碼如下所示int ptrace_attach (struct task_struct氺task){......task- > ptrace | = PT_PTRACED ; /* 設(shè)置被調(diào)試任務(wù) attach 屬性 */_ptrace_l ink (task, current) ; /氺建立父子進(jìn)程關(guān)系氺/kertsk_inner_suspend_tsk (task) ;/* 停止被調(diào)試任務(wù) */......}與attach任務(wù)對應(yīng)的,還存在detach任務(wù);detach被調(diào)試任務(wù)是支持雙態(tài)調(diào)試的調(diào)試器進(jìn)行調(diào)試的最后一個操作。與 attach任務(wù)相對應(yīng),支持雙態(tài)調(diào)試的調(diào)試器detach任務(wù)調(diào)用的是SyS_ptraCe ()函數(shù)接口,執(zhí)行PTRACE_DETACH操作。detach被調(diào)試任務(wù)除了刪除調(diào)試器與被調(diào)試任務(wù)父子關(guān)系外,還需要調(diào)用kertSk_irmer_reSume_tSk()接口恢復(fù)被調(diào)試任務(wù)的運(yùn)行。需要修改的是 linux/kernel/ptrace. c文件中的—ptrace_detach ()函數(shù)接口,其關(guān)鍵偽代碼如下所示static inline void—ptrace_detach(struct task_struct氺child, unsigned int data){......}任務(wù)運(yùn)行控制模塊310,控制被調(diào)試任務(wù)的運(yùn)行,是調(diào)試器各種調(diào)試功能的基礎(chǔ), 用于在判斷出需要停止被調(diào)試任務(wù)時,在相應(yīng)的被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,使得對應(yīng)被調(diào)試任務(wù)被停止調(diào)用。該任務(wù)運(yùn)行控制模塊通過設(shè)置停止標(biāo)志位的方式,控制被調(diào)試任務(wù)是否能夠被內(nèi)核調(diào)度,從而達(dá)到控制被調(diào)試任務(wù)運(yùn)行的目的。為了清楚的說明該任務(wù)運(yùn)行控制模塊310的具體控制過程,下面結(jié)合圖4給出停止被調(diào)試任務(wù)運(yùn)行的基本流程,具體包括步驟401、開始;步驟402、任務(wù)運(yùn)行控制模塊310在相應(yīng)被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位;步驟403、判斷上述被調(diào)試任務(wù)是否正在CPU上運(yùn)行,若是,執(zhí)行步驟404 ;否則,執(zhí)行步驟410 ;步驟404、CPU停止當(dāng)前運(yùn)行的被調(diào)試任務(wù),重新選擇一個任務(wù)進(jìn)行調(diào)度;步驟405、內(nèi)核調(diào)度到被調(diào)試任務(wù);
_ptrace_unlink (child) ;/* 取消被調(diào)試關(guān)系 */ kertsk_inner_resume_tsk(child) ;/* 恢復(fù)被調(diào)試任務(wù)運(yùn)行 */
步驟406、檢測是否設(shè)置了停止標(biāo)志位,若是,執(zhí)行步驟407 ;否則,執(zhí)行步驟409。步驟407、將被調(diào)試任務(wù)從任務(wù)隊列中刪除。步驟408、重新選擇一個任務(wù)調(diào)度,執(zhí)行步驟412 ;步驟409、執(zhí)行被調(diào)試任務(wù)相關(guān)代碼,執(zhí)行步驟412 ;步驟410、判斷被調(diào)試任務(wù)是否在任務(wù)隊列中,若是,執(zhí)行步驟411 ;否則,執(zhí)行步驟 405 ;步驟411、將被調(diào)試任務(wù)從任務(wù)隊列中刪除,執(zhí)行步驟405 ;步驟412、結(jié)束。進(jìn)一步地,任務(wù)運(yùn)行控制模塊310,還用于基于上層指令或任務(wù)訪問完成后,撤銷相應(yīng)被調(diào)試任務(wù)中設(shè)置的停止標(biāo)志位,使得對應(yīng)被調(diào)試任務(wù)重新被喚醒接受調(diào)用。如圖5所示,為恢復(fù)被調(diào)試任務(wù)運(yùn)行的基本流程,包括步驟501、開始;步驟502、刪除被調(diào)試任務(wù)停止標(biāo)志位;步驟503、喚醒被調(diào)試任務(wù);步驟504、內(nèi)核調(diào)度到被調(diào)試任務(wù);步驟505、判斷是否設(shè)置了停止標(biāo)志位,若是,執(zhí)行步驟507 ;否則,執(zhí)行步驟506 ;步驟506、執(zhí)行被調(diào)試任務(wù)相關(guān)代碼,執(zhí)行步驟509 ;步驟507、將被調(diào)試任務(wù)從任務(wù)隊列中刪除;步驟508、重新選擇一個任務(wù)調(diào)度;步驟509、結(jié)束。上述任務(wù)運(yùn)行控制模塊310從Iinux系統(tǒng)方面的改進(jìn),主要體現(xiàn)在以下幾個方面(1)定義被調(diào)試任務(wù)停止標(biāo)志位在linux/include/sched. h文件的task_struct結(jié)構(gòu)體中,增加被調(diào)試任務(wù)停止標(biāo)志掩碼值和相應(yīng)的成員變量,如下所示struct task_struct {......#define KERTSK_SUSPEND 0x100 /* 定義停止標(biāo)志掩碼值 */int kertask_special_flags ;/氺標(biāo)志位成員變量氺/......}(2)定義停止被調(diào)試任務(wù)運(yùn)行接口在linux/kernel/sched. c文件中,增加停止被調(diào)試任務(wù)函數(shù)接口 kertsk_inner_ suspencLtskO,其關(guān)鍵偽代碼如下所示int kertsk_inner_suspend_tsk(struct task—struct氺tsk){......tsk- > kertask_special_flags | = KERTSK_SUSPEND ;/* 設(shè)置停止標(biāo)志位 */tsk- > state = TASK_ST0PPED ;/* 設(shè)置任務(wù)停止?fàn)顟B(tài) */schedule () ;/* 重新調(diào)度任務(wù) */
......}(3)定義恢復(fù)被調(diào)試任務(wù)運(yùn)行接口在linux/kernel/sched. c文件中,增加停止被調(diào)試任務(wù)函數(shù)接口 kertsk_inner_ resumejskO,其關(guān)鍵偽代碼如下所示int kertsk_inner_resume_tsk(struct task—struct氺tsk){......tsk- > kertask_special_flags& = KERTASK_SUSPEND ;wake_up_state (tsk, TASK_ST0PPED | TASK_TRACED);____}(4)修改內(nèi)核任務(wù)調(diào)度流程在內(nèi)核任務(wù)調(diào)度流程中,當(dāng)調(diào)度出來的任務(wù)判斷被置了 KERTSK_SUSPEND標(biāo)志,則重新調(diào)度一個新的任務(wù)。以上操作需要對linux/kemel/sched. c文件中的schedule ()函數(shù)進(jìn)行相應(yīng)的修改,其關(guān)鍵偽代碼如下所示asmlinkage void_sched schedule(void){......reselect_next_kertsk next = pick_next_task (rq, prev) ;/* 選擇下一個被調(diào)度的任務(wù) *//*被調(diào)度的任務(wù)被設(shè)置了停止標(biāo)志位*/if (unlikely (next- > ketask_special_flags & KERTASK_SUSPEND)){next- > state = TASK_ST0P ; /* 設(shè)置任務(wù)停止?fàn)顟B(tài) */deactivate_task(rq, next, 1) ;/* 從任務(wù)隊列中刪除 */goto reselect_next_kertsk ; /*重新選擇下一個被調(diào)度的任務(wù)*/}......}內(nèi)存訪問控制模塊320 ;內(nèi)存訪問控制模塊,用于在被調(diào)試任務(wù)停止運(yùn)行后,獲取待訪問的內(nèi)存地址,在所述內(nèi)存地址為用戶態(tài)地址時,調(diào)用Ptrace系統(tǒng)調(diào)用進(jìn)行內(nèi)存訪問操作;在所述內(nèi)存地址為內(nèi)核態(tài)地址時,直接進(jìn)行內(nèi)存訪問操作。本發(fā)明所述調(diào)試器對被調(diào)試任務(wù)的內(nèi)存訪問主要分為用戶地址空間的內(nèi)存訪問和內(nèi)核地址空間的內(nèi)存訪問。由于支持雙態(tài)調(diào)試的調(diào)試器是一種內(nèi)核級調(diào)試器,運(yùn)行在內(nèi)核地址空間,因此,支持雙態(tài)調(diào)試的調(diào)試器可以直接對被調(diào)試任務(wù)的內(nèi)核地址空間進(jìn)行讀寫操作,不需要進(jìn)行任何地址轉(zhuǎn)換操作。當(dāng)支持雙態(tài)調(diào)試的調(diào)試器對被調(diào)試任務(wù)的用戶地址空間進(jìn)行訪問時,由于用戶態(tài)地址是一個虛擬地址,需要通過地址轉(zhuǎn)換才能進(jìn)行訪問。對于用戶地址空間的訪問,類UNIX 操作系統(tǒng)已經(jīng)提供了相關(guān)接口,如access_pr0cess_vm()函數(shù)等。因此,訪問被調(diào)試任務(wù)的用戶地址空間,支持雙態(tài)調(diào)試的調(diào)試器可以調(diào)用ptrace系統(tǒng)調(diào)用,執(zhí)行PTRACE_PEEKTEXT 或者PTRACE_POKETEXT操作,來實(shí)現(xiàn)對被調(diào)試任務(wù)用戶地址空間的讀寫操作。如圖6所示,為內(nèi)存訪問控制模塊320對被調(diào)試任務(wù)的內(nèi)存訪問流程,包括步驟601、開始;步驟602、獲取待訪問的內(nèi)存地址;步驟603、判斷待訪問的內(nèi)存地址是否為用戶態(tài)地址,若是,執(zhí)行步驟605 ;否則, 執(zhí)行步驟604 ;步驟604、直接對內(nèi)核地址空間進(jìn)行讀寫操作,執(zhí)行步驟607 ;步驟605、調(diào)用ptrace系統(tǒng)調(diào)用;步驟606、執(zhí)行PTRACE_PEEKTEXT或者PTRACE_POKETEXT操作,對用戶地址空間進(jìn)行讀寫操作;步驟607、結(jié)束。根據(jù)圖6的流程,支持雙態(tài)調(diào)試的調(diào)試器調(diào)用sys_ptrace O函數(shù)接口,執(zhí)行 PTRACE_PEEKTEXT或者PTRACE_POKETEXT操作,實(shí)現(xiàn)對被調(diào)試任務(wù)的內(nèi)存訪問。內(nèi)存訪問主要分為用戶地址空間的內(nèi)存訪問和內(nèi)核地址空間的內(nèi)存訪問,需要修改的是linux/mm/ memory, c文件中的access_process_vmQ函數(shù)接口,其關(guān)鍵偽代碼如下所示int access_process_vm(struct task—struct氺tsk,unsigned long addr, void^buf, intlen, int write) {......if (IS_VALID_KADD(addr)) {/* 訪問內(nèi)核地址空間內(nèi)存 */if (write) {/* 寫內(nèi)存 */*addr = *buf ;/*直接修改目標(biāo)地址的值*/}else {/* 讀內(nèi)存 */*buf = *addr ;/*直接讀取目標(biāo)地址的值*/}}else{ /*訪問用戶地址空間內(nèi)存*/if (write) {/* 寫內(nèi)存 */copy_to_user_page () ;/*修改用戶地址空間內(nèi)存接口 */}else {/* 讀內(nèi)存 */copy_from_user_page () ;/*讀取用記地址空間內(nèi)存接口 */}}......} 寄存器訪問控制模塊330 ;
寄存器訪問控制模塊,用于在被調(diào)試任務(wù)停止運(yùn)行后,獲取被調(diào)試任務(wù)信息,若該被調(diào)試任務(wù)為內(nèi)核態(tài)任務(wù)且為中斷或異常停止,從內(nèi)核堆棧上訪問被調(diào)試任務(wù)的寄存器信息;否則,通過調(diào)用Ptrace系統(tǒng)調(diào)用進(jìn)行寄存器訪問;若被調(diào)試任務(wù)為用戶態(tài)任務(wù),則在所述被調(diào)試任務(wù)停止在用戶地址空間時,通過調(diào)用Ptrace系統(tǒng)調(diào)用進(jìn)行寄存器訪問;在所述被調(diào)試任務(wù)停止在內(nèi)核地址空間時(此時用戶態(tài)被調(diào)試任務(wù)肯定發(fā)生了中斷或異常),從內(nèi)核堆棧上訪問被調(diào)試任務(wù)的寄存器信息。其中,寄存器訪問控制模塊330在內(nèi)核堆棧上訪問被調(diào)試任務(wù)的寄存器信息時, 記錄下被調(diào)試任務(wù)發(fā)生中斷或異常時的棧幀信息,根據(jù)棧幀信息和對應(yīng)的CPU類型的pt_ regs結(jié)構(gòu)體信息,從內(nèi)核堆棧上相應(yīng)位置訪問pt_regs結(jié)構(gòu)體大小的內(nèi)存值,這段內(nèi)存值就對應(yīng)著被調(diào)試任務(wù)發(fā)生中斷或者異常時的寄存器信息。本發(fā)明所述調(diào)試器對被調(diào)試任務(wù)的寄存器訪問主要分為兩種,一種是對內(nèi)核態(tài)被調(diào)試任務(wù)的寄存器訪問,另一種是對用戶態(tài)被調(diào)試任務(wù)的寄存器訪問。在類UNIX操作系統(tǒng)中,不論是用戶態(tài)任務(wù)還是內(nèi)核態(tài)任務(wù),都在內(nèi)核中對應(yīng)著一個taSk_Struct結(jié)構(gòu)體,用于保存與任務(wù)相關(guān)的一些信息。在taSk_Struct結(jié)構(gòu)體中,還存在一個threacLstruct結(jié)構(gòu)體,用于保存與任務(wù)相關(guān)的寄存器信息。當(dāng)內(nèi)核態(tài)任務(wù)發(fā)生調(diào)度時,內(nèi)核會將一些主要的寄存器信息(包括指令寄存器、 堆棧寄存器、通用寄存器、返回地址寄存器以及參數(shù)寄存器)保存到threacLstruct結(jié)構(gòu)體中。當(dāng)內(nèi)核態(tài)任務(wù)發(fā)生中斷或者異常時,內(nèi)核會將內(nèi)核態(tài)任務(wù)的所有寄存器信息保存到內(nèi)核堆棧上。因此,支持雙態(tài)調(diào)試的調(diào)試器訪問內(nèi)核態(tài)被調(diào)試任務(wù)的寄存器時,首先判斷內(nèi)核態(tài)被調(diào)試任務(wù)是否發(fā)生中斷或者異常,如果內(nèi)核態(tài)被調(diào)試任務(wù)發(fā)生了中斷或者異常,調(diào)試器就從內(nèi)核堆棧上訪問被調(diào)試任務(wù)的寄存器信息;如果被調(diào)試任務(wù)發(fā)生了調(diào)度,就可以通過ptrace系統(tǒng)調(diào)用,執(zhí)行PTRACE_PEEKUSER或者PTRACE_POKEUSER操作,來實(shí)現(xiàn)對內(nèi)核態(tài)被調(diào)試任務(wù)的寄存器訪問。對于用戶態(tài)被調(diào)試任務(wù)的寄存器訪問,支持雙態(tài)調(diào)試的調(diào)試器首先判斷用戶態(tài)被調(diào)試任務(wù)停止的地址空間。如果用戶態(tài)被調(diào)試任務(wù)停止在用戶地址空間,此時內(nèi)核會將一些主要的寄存器信息保存到threacLstruct結(jié)構(gòu)體中,支持雙態(tài)調(diào)試的調(diào)試器就可以通過 ptrace系統(tǒng)調(diào)用,執(zhí)行PTRACE_PEEKUSER或者PTRACE_POKEUSER操作,來實(shí)現(xiàn)對用戶態(tài)被調(diào)試任務(wù)的寄存器訪問;如果用戶態(tài)被調(diào)試任務(wù)停止在內(nèi)核地址空間,此時用戶態(tài)被調(diào)試任務(wù)肯定發(fā)生了中斷或者異常,內(nèi)核會將被調(diào)試任務(wù)的所有寄存器信息保存到內(nèi)核堆棧上, 支持雙態(tài)調(diào)試的調(diào)試器從內(nèi)核堆棧上訪問用戶態(tài)被調(diào)試任務(wù)的寄存器信息即可。支持雙態(tài)調(diào)試的調(diào)試器訪問被調(diào)試任務(wù)的寄存器流程,如圖7所示,包括以下步驟步驟701、開始;步驟702、獲取被調(diào)試任務(wù)信息;步驟703、判斷是否是內(nèi)核態(tài)被調(diào)試任務(wù),若是,執(zhí)行步驟704,否則,執(zhí)行步驟 709 ;步驟704、判斷被調(diào)試任務(wù)停止是否是發(fā)生中斷或者異常,若是,執(zhí)行步驟707 ;否則,執(zhí)行步驟705;
步驟705、調(diào)用ptrace系統(tǒng)調(diào)用;步驟706、執(zhí)行PTRACE_PEEKUSER或者PTRACE_POKEUSER操作,進(jìn)行寄存器訪問后, 執(zhí)行步驟714;步驟707、獲取棧幀地址;步驟708、從內(nèi)核堆棧上相應(yīng)位置訪問pt_regs結(jié)構(gòu)體大小的內(nèi)存值,執(zhí)行步驟 714 ;步驟709、判斷被調(diào)試任務(wù)是否停止在用戶地址空間,若是,執(zhí)行步驟710 ;否則, 執(zhí)行步驟712;步驟710、調(diào)用ptrace系統(tǒng)調(diào)用;步驟711、執(zhí)行PTRACE_PEEKUSER或者PTRACE_POKEUSER操作,進(jìn)行寄存器訪問后, 執(zhí)行步驟714;步驟712、獲取棧幀地址;步驟713、從內(nèi)核堆棧上相應(yīng)位置訪問pt_regs結(jié)構(gòu)體大小的內(nèi)存值,執(zhí)行步驟 714 ;步驟714、結(jié)束。根據(jù)圖7的流程,支持雙態(tài)調(diào)試的調(diào)試器調(diào)用sys_ptraCe O函數(shù)接口,執(zhí)行 PTRACE_PEEKUSR或者PTRACE_POKEUSR操作,實(shí)現(xiàn)對被調(diào)試任務(wù)的寄存器訪問。寄存器訪問主要分為內(nèi)核態(tài)被調(diào)試任務(wù)的寄存器訪問和用戶態(tài)被調(diào)試任務(wù)的寄存器訪問,每種類型又可以分為從堆棧上訪問和從寄存器結(jié)構(gòu)體上訪問兩種。需要修改的是linuX/arch/i386/ kernel/ptrace. c文件中的getregO和putregO函數(shù)接口,其關(guān)鍵偽代碼如下所示static unsigned long getreg(struct task—struct氺child,unsigned long regno){......if (child- > mm) { /*用戶態(tài)被調(diào)試任務(wù)*/if( ! IS_STOPPED_IN_KERNEL_SPACE(child)) { /* 停止在用戶地址空間*/retval = get_usr_reg (chiId, regno) ;/氺從寄存器結(jié)構(gòu)體上獲取寄存器信息*/}else {/*停止在內(nèi)核地址空間*/retval = get_reg_from_stack(child,regno) ;/氺從堆豐曳上獲取寄存器信息*/}}else/*內(nèi)核態(tài)被調(diào)試任務(wù)*/{
if( ! IS_INTERRUPTED(child)) {/* 發(fā)生調(diào)度 */retval = get_usr_reg(child, regno) ;/氺從寄存器結(jié)構(gòu)體上獲取寄存器信息*/}else{/*發(fā)生中斷或者異常*/retval = get_reg_from_stack(child, regno) ;/氺從堆豐曳上獲取寄存器信息*/}}......}static int putreg(struct task—struct氺child, unsigned long regno, unsigned longvalue) {......if (child- > mm) {/*用戶態(tài)被調(diào)試任務(wù)*/if( ! IS_STOPPED_IN_KERNEL_SPACE(child)) {/* 停止在用戶地址空間*/put_usr_reg(child, regno, value) ;/氺從寄存器結(jié)構(gòu)體上修改寄存器信息*/}else {/*停止在內(nèi)核地址空間*/put_reg_to_stack(chiId,regno,value) ;/氺從堆棧上修改寄存器信息*/}}else/*內(nèi)核態(tài)被調(diào)試任務(wù)*/{if( ! IS_INTERRUPTED(child)) {/* 發(fā)生調(diào)度 */put_usr_reg(chiId,regno,value) ;/氺從寄存器結(jié)構(gòu)體上修改寄存器信息*/}else{/*發(fā)生中斷或者異常*/put_reg_to_stack(chiId,regno,value) ;/氺從堆棧上修改寄存
斷點(diǎn)設(shè)置模塊;340 ;在調(diào)試器需要設(shè)置斷點(diǎn)時,斷點(diǎn)設(shè)置模塊,獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若斷點(diǎn)為用戶地址空間斷點(diǎn),直接修改用戶地址空間內(nèi)存,將內(nèi)存指令替換為斷點(diǎn)指令;若斷點(diǎn)為內(nèi)核地址空間斷點(diǎn),在被調(diào)試任務(wù)被調(diào)度時,修改用戶地址空間內(nèi)存,將內(nèi)存指令替換為斷點(diǎn)指令;并在被調(diào)試任務(wù)被內(nèi)核調(diào)度出CPU時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原內(nèi)存指令。調(diào)試器通常是通過將內(nèi)存中的指令替換成斷點(diǎn)指令進(jìn)行斷點(diǎn)設(shè)置的。當(dāng)被調(diào)試任務(wù)運(yùn)行到斷點(diǎn)指令時,就會產(chǎn)生斷點(diǎn)異常停止下來,并上報事件給調(diào)試器,此時調(diào)試器就可以查看被調(diào)試任務(wù)的信息。當(dāng)被調(diào)試任務(wù)恢復(fù)運(yùn)行以后,調(diào)試器再將原指令恢復(fù)回來。支持雙態(tài)調(diào)試的調(diào)試器的斷點(diǎn)設(shè)置主要分為兩種,一種是用戶地址空間的斷點(diǎn)設(shè)置,另一種是內(nèi)核地址空間的斷點(diǎn)設(shè)置。由于被調(diào)試任務(wù)的用戶地址空間是獨(dú)立于其他任務(wù),不會被其他任務(wù)所訪問。因此,處于用戶地址空間的斷點(diǎn)不會被其他任務(wù)所遇到。而被調(diào)試任務(wù)的內(nèi)核地址空間是與其他任務(wù)所共用的,如果在內(nèi)核地址空間設(shè)置斷點(diǎn),就有可能被其他任務(wù)所遇到,造成非法的斷點(diǎn)異常。因此,對于支持雙態(tài)調(diào)試的調(diào)試器進(jìn)行斷點(diǎn)設(shè)置時,如果斷點(diǎn)是用戶地址空間的斷點(diǎn),可以直接修改用戶地址空間的內(nèi)存,將內(nèi)存指令替換為斷點(diǎn)指令。如果斷點(diǎn)是內(nèi)核地址空間的斷點(diǎn),只有當(dāng)被調(diào)試任務(wù)被內(nèi)核調(diào)度進(jìn)CPU時,才修改內(nèi)核地址空間的內(nèi)存,將內(nèi)存指令替換為斷點(diǎn)指令;當(dāng)被調(diào)試任務(wù)被內(nèi)核調(diào)度出CPU時,就將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原指令。支持雙態(tài)調(diào)試的調(diào)試器的斷點(diǎn)設(shè)置流程,如圖8所示,包括以下步驟步驟801、開始;步驟802、獲取斷點(diǎn)設(shè)置的內(nèi)存地址;步驟803、判斷是否是用戶地址空間斷點(diǎn),若是,執(zhí)行步驟804;否則,執(zhí)行步驟 805 ;步驟804、直接修改用戶地址空間內(nèi)存,將內(nèi)存指令替換為斷點(diǎn)指令,執(zhí)行步驟 807 ;步驟805、判斷被調(diào)試任務(wù)是否被調(diào)度,若是,執(zhí)行步驟806 ;否則,執(zhí)行步驟807 ;步驟806、修改內(nèi)核地址空間內(nèi)存,將內(nèi)存指令替換為斷點(diǎn)指令,執(zhí)行步驟807 ;步驟807、結(jié)束。異常處理模塊;350 ;異常處理模塊,用于在被調(diào)試任務(wù)被調(diào)度時,若發(fā)生異常事件,則基于異常類型, 調(diào)用異常處理函數(shù)執(zhí)行異常處理,并在上報當(dāng)前的異常事件,并在當(dāng)前異常事件為有效事
16件時,觸發(fā)任務(wù)運(yùn)行控制模塊310,停止被調(diào)試任務(wù)的運(yùn)行。支持雙態(tài)調(diào)試的調(diào)試器涉及到異常處理主要分為斷點(diǎn)異常處理和單步異常處理。在類UNIX操作系統(tǒng)中,當(dāng)用戶態(tài)任務(wù)運(yùn)行遇到斷點(diǎn)指令時,會停止下來進(jìn)行斷點(diǎn)異常處理,并發(fā)送SIGTRAP信號給調(diào)試器。而內(nèi)核態(tài)任務(wù)運(yùn)行遇到斷點(diǎn)指令時,也會進(jìn)入斷點(diǎn)異常處理函數(shù)中進(jìn)行相關(guān)的處理操作。同時,在類UNIX操作系統(tǒng)中,ptrace系統(tǒng)調(diào)用也已經(jīng)提供了對被調(diào)試任務(wù)進(jìn)行單步操作的功能。ptrace (PTRACE_SINGLESTEP,...)會使內(nèi)核在被調(diào)試任務(wù)的每一條指令執(zhí)行前先將其阻塞,然后發(fā)送信號給調(diào)試器,并將控制權(quán)交給調(diào)試器。由于支持雙態(tài)調(diào)試的調(diào)試器是一種內(nèi)核級調(diào)試器,不支持對信號的處理。并且不論是用戶態(tài)被調(diào)試任務(wù)還是內(nèi)核態(tài)被調(diào)試任務(wù),當(dāng)被調(diào)試任務(wù)運(yùn)行遇到斷點(diǎn)指令或者執(zhí)行單步操作時,都會進(jìn)入到內(nèi)核的斷點(diǎn)異常處理函數(shù)或者單步異常處理函數(shù)中。因此,可以通過修改內(nèi)核的斷點(diǎn)異常處理函數(shù)的方式來實(shí)現(xiàn)對被調(diào)試任務(wù)命中斷點(diǎn)操作的處理。在內(nèi)核的斷點(diǎn)異常處理函數(shù)和單步異常處理函數(shù)中,支持雙態(tài)調(diào)試的調(diào)試器除了執(zhí)行異常處理的相關(guān)操作外,還需要執(zhí)行上報斷點(diǎn)命中事件和停止被調(diào)試任務(wù)運(yùn)行的操作,其流程如圖9和圖10所示。如圖9所示,為支持雙態(tài)調(diào)試的調(diào)試器斷點(diǎn)異常處理流程,具體包括步驟901、開始;步驟902、被調(diào)試任務(wù)命中斷點(diǎn);步驟903、進(jìn)入內(nèi)核的斷點(diǎn)異常處理函數(shù);步驟904、斷點(diǎn)命中相關(guān)處理;步驟905、判斷是否是有效斷點(diǎn),若是,執(zhí)行步驟906,否則,執(zhí)行步驟910;步驟906、上報斷點(diǎn)命中事件;步驟907、刪除內(nèi)核地址空間中的斷點(diǎn);步驟908、設(shè)置被調(diào)試任務(wù)的停止標(biāo)志位;步驟909、將被調(diào)試任務(wù)從任務(wù)運(yùn)行隊列中刪除;步驟910、結(jié)束。根據(jù)圖9所述的流程,支持雙態(tài)調(diào)試的調(diào)試器的斷點(diǎn)設(shè)置實(shí)際上是將內(nèi)存中的指令修改為斷點(diǎn)指令,其操作流程屬于內(nèi)存訪問范疇,修改方法可以是在支持雙態(tài)調(diào)試的調(diào)試器的代碼中調(diào)用內(nèi)存訪問的相關(guān)接口進(jìn)行斷點(diǎn)指令的設(shè)置。不論是用戶態(tài)被調(diào)試任務(wù)還是內(nèi)核態(tài)被調(diào)試任務(wù),當(dāng)遇到斷點(diǎn)指令時,都會進(jìn)入到內(nèi)核的斷點(diǎn)異常處理函數(shù)。在內(nèi)核的斷點(diǎn)異常處理函數(shù)中,支持雙態(tài)調(diào)試的調(diào)試器除了執(zhí)行斷點(diǎn)異常處理的相關(guān)操作外,還需要執(zhí)行上報斷點(diǎn)命中事件和停止被調(diào)試任務(wù)運(yùn)行的操作。需要修改的是linux/arch/i386/kernel/traps. c文件中的do_trap ()函數(shù)接口,其關(guān)鍵偽代碼如下所示 vm86,static void_kprobes do_trap(int trapnr, int signr, char氺str, intstruct pt_regs氺regs, long error_code, siginfo_t*info) {......
bp = lookup_breakpoint(regs_ > eip) ;/* 根據(jù)斷點(diǎn)異常地址查找斷點(diǎn)*/if (bp) {/*命中有效斷點(diǎn)*/report_hit_breakpoint () ;/* 上報命中斷點(diǎn)事件 */kertsk_inner_suspend_task (current) ;/氺停止被i周i式任務(wù)運(yùn)行*/regs- > eflags | = TF_MASK ;/* 設(shè)置單步標(biāo)志 */current- > kertask_special_f lags | = DBG_STEP_0VER ;/* 設(shè)置跨斷點(diǎn)標(biāo)志*/return;/*從斷點(diǎn)異常中返回*/}......}如圖10所示,為支持雙態(tài)調(diào)試的調(diào)試器單步異常處理流程,具體包括步驟1001、開始;步驟1002、調(diào)用ptrace系統(tǒng)調(diào)用設(shè)置被調(diào)試任務(wù)單步標(biāo)志;步驟1003、進(jìn)入內(nèi)核的單步異常處理函數(shù);步驟1004、單步異常相關(guān)處理;步驟1005、判斷是否是有效單步,若是,執(zhí)行步驟1006 ;否則,執(zhí)行步驟1009 ;步驟1006、上報單步異常事件;步驟1007、設(shè)置被調(diào)試任務(wù)的停止標(biāo)志位;步驟1008、將被調(diào)試任務(wù)從任務(wù)運(yùn)行隊列中刪除,執(zhí)行步驟1009 ;步驟1009、結(jié)束。根據(jù)圖10的流程,對于單步異常處理,支持雙態(tài)調(diào)試的調(diào)試器可以調(diào)用sys— ptrace ()函數(shù)接口,執(zhí)行PTRACE_SINGLESTEP操作,實(shí)現(xiàn)被調(diào)試任務(wù)的單步操作。為了實(shí)現(xiàn)這一功能,需要對內(nèi)核實(shí)現(xiàn)以下幾方面的修改。(1)設(shè)置單步標(biāo)志由于支持雙態(tài)調(diào)試的調(diào)試器采用設(shè)置停止標(biāo)志位的方式來控制被調(diào)試任務(wù)的運(yùn)行,因此,在設(shè)置被調(diào)試任務(wù)的單步標(biāo)志后,還需要取消停止標(biāo)志位,恢復(fù)被調(diào)試任務(wù)的運(yùn) ^f0 需要修改的是 linux/arch/i386/kernel/ptrace· c 中的 arch—ptrace () 01 Π, 其關(guān)鍵偽代碼如下long arch_ptrace(struct task—struct氺child,long request, long addr,long data){......case PTRACE_SINGLESTEP :/* 設(shè)置單步標(biāo)志操作 */......set_singlestep (child) ;/* 設(shè)置單步標(biāo)志 */kertsk_inner_resume_tsk(child) ;/* 恢復(fù)被調(diào)試任務(wù)運(yùn)行 */
......break ;/*設(shè)置單步標(biāo)志操作結(jié)束*/......}(2)單步異常事件處理當(dāng)被調(diào)試任務(wù)進(jìn)入單步異常函數(shù)時,支持雙態(tài)調(diào)試的調(diào)試器除了執(zhí)行單步異常處理的相關(guān)操作外,還需要執(zhí)行上報單步異常事件和停止被調(diào)試任務(wù)運(yùn)行的操作。需要修改的是linux/arch/i386/kernel/traps. c文件中的do_debug()函數(shù)接口,其關(guān)鍵偽代碼如下所示fastcall void_kprobes do—debug(struct pt_regs氺regs, long error— code){......regs- > eflags& = TF_MASK ;/* 取消單步標(biāo)志 */if (is_valid_singstep (regs- > eip)) {/氺有效單步氺/report_singlestep_exception () ;/* 上報單步異常事件 */kertsk_inner_suspend_task (current) ;/氺停止被調(diào)試任務(wù)運(yùn)行*/return ;/*從單步異常中返回*/}else if (current- > kertask_special_flags & DBG_STEP_ OVER){/*跨斷點(diǎn)操作*/insert_all_breakpoint () ;/* 回插所有的斷點(diǎn) */return ;/*從單步異常中返回*/}......}信號處理模塊360 ;信號處理模塊,用于在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間
時,若用戶態(tài)被調(diào)試任務(wù)的信號隊列不為空,則調(diào)用信號處理函數(shù),逐一獲取信號隊列中待處理信號,上報信號處理事件,并根據(jù)信號對應(yīng)的信號值判定為關(guān)心的信號消息時,觸發(fā)任務(wù)運(yùn)行控制模塊310,停止相應(yīng)被調(diào)試任務(wù)的運(yùn)行;若判定為不關(guān)心的信號消息時,不做處理,獲取下一個信號。在類UNIX操作系統(tǒng)中,當(dāng)用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,需要判斷用戶態(tài)被調(diào)試任務(wù)的信號隊列是否為空。如果存在未處理的信號,需要對信號隊列中的信號進(jìn)行提取并進(jìn)行相應(yīng)的處理,同時上報給父進(jìn)程。由于支持雙態(tài)調(diào)試的調(diào)試器是一種內(nèi)核級調(diào)試器,雖然同用戶態(tài)被調(diào)試任務(wù)存在父子進(jìn)程關(guān)系,但對用戶態(tài)被調(diào)試任務(wù)上報的信號不會進(jìn)行處理。因此,支持雙態(tài)調(diào)試的調(diào)試器要想獲取用戶態(tài)被調(diào)試任務(wù)信號處理的狀態(tài),就必須對內(nèi)核中信號處理函數(shù)進(jìn)行相應(yīng)的修改。 當(dāng)用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,如果存在未處理的信號,就會進(jìn)入內(nèi)核的信號處理函數(shù)。在該函數(shù)中,支持雙態(tài)調(diào)試的調(diào)試器首先獲取用戶態(tài)被調(diào)試任務(wù)待處理的信號值,再根據(jù)該信號值在預(yù)先配置的信號列表中查找相關(guān)設(shè)置,決定用戶態(tài)被調(diào)試任務(wù)對該信號的處理流程,該處理流程具體包括停止被調(diào)試任務(wù)的運(yùn)行, 或者當(dāng)前信號為不關(guān)心的信號,不做處理。
支持雙態(tài)調(diào)試的調(diào)試器信號處理流程,如圖11所示,包括以下步驟 步驟1101、開始;
步驟1102、用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間; 步驟1103、判斷是否存在未處理的信號,若是,執(zhí)行步驟1104;否則,執(zhí)行步驟
步驟1104、獲取待處理信號值; 步驟1105、上報信號處理事件;
步驟1106、根據(jù)信號列表設(shè)置決定用戶態(tài)被調(diào)試任務(wù)處理流程; 步驟1107、結(jié)束。
根據(jù)圖11所述的流程,當(dāng)用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,如果存在未處理的信號,就會進(jìn)入內(nèi)核的信號處理函數(shù)。在該函數(shù)中,支持雙態(tài)調(diào)試的調(diào)試器首先獲取用戶態(tài)被調(diào)試任務(wù)待處理的信號值,再根據(jù)信號列表中的相關(guān)設(shè)置,決定用戶態(tài)被調(diào)試任務(wù)對該信號的處理流程。需要修改的是linux/kernel/signal. c文件中的get_Signal_t0_deliver()函數(shù)接口,其關(guān)鍵偽代碼如下所示 ;/氺從 言號隊列中獲取一個信號*/
確定信號處理流程*/else if (ret = = HANDL_SIG_ST0P) {/*信號處理需要停止被調(diào)試任務(wù)*/kertsk_inner_suspend_task (current) ;/氺停止被i周i式任務(wù)運(yùn)
if ( ! signr)
break ;/*沒有待處理的信號則退出*/ ret = report_debug_signal (signr) ;/* 上 艮獲取信號事件,
if (ret == HANDLE_SIG_IGN) {/* 忽略信號處理 */ continue ;/*獲取下一個信號*/
本發(fā)明提供的調(diào)試方法和調(diào)試器,克服了現(xiàn)有的各種調(diào)試器不能同時支持對用戶地址空間和內(nèi)核地址空間進(jìn)行調(diào)試功能的問題,達(dá)到了能夠?qū)Ρ徽{(diào)試程序在用戶地址空間和內(nèi)核地址空間的運(yùn)行進(jìn)行跟蹤和調(diào)試的目的。顯然,本領(lǐng)域的技術(shù)人員可以對本發(fā)明進(jìn)行各種改動和變型而不脫離本發(fā)明的精神和范圍。這樣,倘若本發(fā)明的這些修改和變型屬于本發(fā)明權(quán)利要求及其等同技術(shù)的范圍之內(nèi),則本發(fā)明也意圖包含這些改動和變型在內(nèi)。
權(quán)利要求
1.一種調(diào)試方法,其特征在于,包括調(diào)試器在調(diào)試關(guān)系建立后,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);調(diào)試器判斷是否停止所述被調(diào)試任務(wù),若是,在所述被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,停止所述被調(diào)試任務(wù)的運(yùn)行后進(jìn)行任務(wù)訪問;所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或寄存器信息;其中,所述調(diào)制器對于因中斷或異常停止的被調(diào)試任務(wù),從內(nèi)核堆棧上訪問寄存器信息ο
2.如權(quán)利要求1所述的方法,其特征在于,所述調(diào)試器判斷所述被調(diào)試任務(wù)是否停止的判斷條件包括所述調(diào)試器接收到上層發(fā)送的停止指令;或者,所述調(diào)試器在調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件;或者,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,捕獲到關(guān)心的信號消息。
3.如權(quán)利要求2所述的方法,其特征在于,所述調(diào)試器調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件的處理過程包括所述調(diào)試器調(diào)用相應(yīng)的異常處理函數(shù)進(jìn)行異常處理,并在檢測出當(dāng)前異常事件為有效異常事件時,上報當(dāng)前異常事件,并停止所述被調(diào)試任務(wù)的運(yùn)行;所述異常事件至少包括斷點(diǎn)異常事件和單步異常事件。
4.如權(quán)利要求3所述的方法,其特征在于,所述斷點(diǎn)異常事件中斷點(diǎn)的設(shè)置方式包括 所述調(diào)試器獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若為用戶地址空間斷點(diǎn),直接將內(nèi)存指令替換為斷點(diǎn)指令;若為內(nèi)核地址空間斷點(diǎn),待所述被調(diào)試任務(wù)被調(diào)度時,將內(nèi)存指令替換為斷點(diǎn)指令,并在所述被調(diào)試任務(wù)完成調(diào)度時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原內(nèi)存指令。
5.如權(quán)利要求2所述的方法,其特征在于,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,檢測是否存在未處理的信號消息,若是,獲取待處理信號消息的信號值,上報信號處理事件,并基于獲取的所述信號值得到所關(guān)心的信號消息時,停止所述被調(diào)試任務(wù)。
6.一種調(diào)試器,其特征在于,包括調(diào)試開啟模塊,用于建立調(diào)試關(guān)系,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);任務(wù)運(yùn)行控制模塊,用于在判斷出需要停止所述被調(diào)試任務(wù)時,在所述被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位,停止所述被調(diào)試任務(wù)的運(yùn)行;任務(wù)訪問模塊,用于在所述任務(wù)運(yùn)行控制模塊停止運(yùn)行所述被調(diào)試任務(wù)時,進(jìn)行任務(wù)訪問,所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或寄存器信息;其中,所述任務(wù)訪問模塊對于因中斷或異常停止的被調(diào)試任務(wù),從內(nèi)核堆棧上獲取寄存器信息。
7.如權(quán)利要求6所述的調(diào)試器,其特征在于,所述任務(wù)運(yùn)行控制模塊判斷所述被調(diào)試任務(wù)是否停止的判斷條件包括所述調(diào)試器接收到上層發(fā)送的停止指令;或者,所述調(diào)試器在調(diào)試所述被調(diào)試任務(wù)時發(fā)生異常事件;或者,所述調(diào)試器在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,捕獲到關(guān)心的信號消息。
8.如權(quán)利要求7所述的調(diào)試器,其特征在于,所述調(diào)試器還包括異常處理模塊,用于調(diào)用相應(yīng)的異常處理函數(shù)進(jìn)行異常處理,并在檢測出當(dāng)前異常事件為有效異常事件時,上報當(dāng)前異常事件,并觸發(fā)所述任務(wù)運(yùn)行控制模塊,停止所述被調(diào)試任務(wù)的運(yùn)行;所述異常事件至少包括斷點(diǎn)異常事件和單步異常事件。
9.如權(quán)利要求6或8所述的調(diào)試器,其特征在于,所述調(diào)試器還包括斷點(diǎn)設(shè)置模塊,用于獲取斷點(diǎn)設(shè)置的內(nèi)存地址,若為用戶地址空間斷點(diǎn),直接將內(nèi)存指令替換為斷點(diǎn)指令;若為內(nèi)核地址空間斷點(diǎn),待所述被調(diào)試任務(wù)被調(diào)度時,將內(nèi)存指令替換為斷點(diǎn)指令,并在所述被調(diào)試任務(wù)完成調(diào)度時,將內(nèi)核地址空間中的斷點(diǎn)指令恢復(fù)成原內(nèi)存指令。
10.如權(quán)利要求7所述的調(diào)試器,其特征在于,所述調(diào)試器還包括信號處理模塊,用于在用戶態(tài)被調(diào)試任務(wù)從內(nèi)核地址空間切換到用戶地址空間時,檢測是否存在未處理的信號消息,若是,獲取待處理信號消息的信號值,上報信號處理事件, 并基于獲取的所述信號值得到所關(guān)心的信號消息時,觸發(fā)所述任務(wù)運(yùn)行控制模塊,停止所述被調(diào)試任務(wù)。
全文摘要
本發(fā)明公開了一種調(diào)試器及其調(diào)試方法,所述方法包括調(diào)試器在調(diào)試關(guān)系建立后,運(yùn)行被調(diào)試任務(wù),所述被調(diào)試任務(wù)運(yùn)行在內(nèi)核態(tài)或用戶態(tài);調(diào)試器在接收到上層發(fā)送的停止指令,或者在調(diào)試所述被調(diào)試任務(wù)時命中異常事件,或者在調(diào)試用戶態(tài)被調(diào)試任務(wù)時捕獲到關(guān)心的信號消息,停止運(yùn)行所述被調(diào)試任務(wù),所述停止的方式包括在被調(diào)試任務(wù)中設(shè)置停止標(biāo)志位;調(diào)試器在所述被調(diào)試任務(wù)停止運(yùn)行后進(jìn)行任務(wù)訪問,所述任務(wù)訪問類型包括訪問所述被調(diào)試任務(wù)的內(nèi)存信息和/或訪問寄存器信息。本發(fā)明所述方法實(shí)現(xiàn)了對被調(diào)試任務(wù)在用戶地址空間和內(nèi)核地址空間的運(yùn)行進(jìn)行跟蹤和調(diào)試的目的。
文檔編號G06F11/36GK102346708SQ20101024347
公開日2012年2月8日 申請日期2010年8月3日 優(yōu)先權(quán)日2010年8月3日
發(fā)明者吳春江 申請人:中興通訊股份有限公司
網(wǎng)友詢問留言 已有0條留言
  • 還沒有人留言評論。精彩留言會獲得點(diǎn)贊!
1