cc682/NetRoc
http://netroc682.spaces.live.com/
調試器操作(用戶模式)
本節包含以下主題:
被創建的進程行為
控制進程和線程
重新附加到目標進程
調試托管代碼
被創建進程的行為
由調試器創建的進程(也稱為產生的進程)的行為和不是調試器創建的進程有輕微不同。
調試器創建的進程使用特殊的調試堆,而不是使用標準的堆API。在Microsoft Windows XP和之后版本Windows中,可以通過_NO_DEBUG_HEAP 環境變量或 -hd命令行選項強制子進程使用標準堆。
同樣,由于子目標程序是調試器的子進程,所以繼承了調試器的權限。這種權限可能使得目標進程能做一些通常情況下不能進行的操作。例如,目標進程可能可以影響其它被保護的進程。
控制進程和線程
當進行用戶模式調試時,可以激活、顯示、凍結、解凍、掛起、恢復進程和線程。
當前正被調試的進程稱為當前活動進程。類似的,當前調試器正在控制的線程稱為當前線程或活動線程。很多調試器命令的行為由當前進程和當前線程決定。
調試開始時,當前進程是調試器附加到的進程或因為異常中斷到調試器的進程。同樣,當前線程是當調試器附加到進程時的線程或產生異常的線程。但是,可以利用調試器改變當前線程和進程,也可以分別凍結或解凍線程。
在內核模式調試下,不使用本節描述的方法來控制線程和進程。關于在內核模式下操作進程和線程的更多信息,查看改變上下文。
顯示進程和線程
使用如下方法顯示進程和線程信息:
設置當前進程和當前線程
使用如下方法改變當前進程和線程:
凍結和掛起線程
調試器可以通過掛起或凍結線程來改變它的執行。這兩種操作有一些不同的地方。
每個線程都有一個關聯的掛起計數(suspend count)。如果這個數字是大于等于1,則系統不會運行該線程。如果計數小于等于0,系統會在適當的時機運行該線程。
一般來說,每個線程的掛起計數都是0。當調試器附加到進程時,會將它的所有線程的掛起計數加1。如果調試器停止對進程的附加,會將所有掛起計數減1。當調試器執行進程時,會臨時將所有的掛起計數減少1。
使用下面一些方法可以用調試器控制任何一個線程的掛起計數:
一般用這些命令來將指定線程的掛起計數從1加到2。當調試器執行或停止附加進程時,該線程由于掛起計數為1,即使進程中其他線程都開始執行,該線程仍然保持掛起。
在進行非侵入式調試時也可以掛起線程。
調試器也可以凍結線程。該行為和以某些方式掛起線程類似。但是,"凍結"僅僅是一種調試器設置。Windows系統不會知道該線程有任何不同點。
默認情況下,所有線程都是非凍結的。當調試器運行進程時,被凍結的線程不會運行。但是,當調試器停止對該進程的附加時,所有線程都會變為非凍結狀態。
使用下面一些方法來凍結和解凍各個線程:
在任何情況下,當調試器中斷目標時,該進程中的所有線程永遠不會被執行。線程的掛起計數僅在調試器運行進程或者停止進程附加時有效。凍結狀態僅在調試器運行進程時有效。
其他命令中的線程和進程
在很多其他命令中也可以指定進程或線程。更多信息,查看各個命令的主題。
在很多命令和擴展命令前都可以加上~e?(Thread-Specific Command) 限定詞。該限定詞使得命令對指定線程起作用。在想對一個以上線程使用某個命令時它非常有用。例如,下面的命令對被調使得所有線程使用!gle 擴展命令。
~*e?!gle?
多系統
調試器可以同一時刻附加到多個目標。當這些處理包含不止一臺計算機上的dump文件或活動目標時,調試器的每個行為都以一個系統、進程和線程為基準。關于這類調試的更多信息,查看調試多個目標。
重新附加到目標程序
如果調試器在用戶模式調試時凍結了,或因為其他原因停止響應(即崩潰),可以將一個新調試器附加到已存在的進程上。
注意??該方法僅在Microsoft Windows XP和之后版本Windows中支持。該方法不管進程是調試器創建的還是附加上去的,也不管是否使用了-pd選項。
使用以下步驟來重新將調試器附加到目標程序:
- 對目標程序確認進程ID。
-
打開一個新的CDB或WinDbg。使用-pe命令行選項。
Debugger?-pe?-p?PID?
也可以使用其他命令行選項。
可以在一個靜止的調試器中使用.attach?(Attach to Process) 命令和-e選項。
- 附加完成后,結束原來的調試器進程。
- 如果進程沒有正常響應,可能是因為掛起計數太高。可以使用~m?(Resume Thread) 命令來減少掛起計數。關于掛起計數的更多信息,查看控制進程和線程。
如果原來的調試器還在正常工作,該方法可能無效。兩個調試器會競爭調試事件,并且Windows操作系統沒有必要將所有調試事件都通知新調試器。
如果原來的調試器在附加新調試器之前就已經結束,目標程序也會被結束掉。 (但是,如果調試器以-pd選項附加上去并正常結束,目標程序會繼續運行。這種情況下,第二個調試器可以不使用-pe選項附加到目標程序。)
如果已經在調試一個進程并想停止附加,但保持進程在調試狀態凍結,可以使用.abandon?(Abandon Process) 命令。該命令之后,任何Windows調試器都可以用本主題描述的方法重新附加到進程上。
調試托管代碼
WinDbg、CDB和NTSD也可以對包含托管代碼的目標程序進行有限制的調試。
介紹托管代碼
托管代碼是和Microsoft .NET 公用語言運行時(CLR)一同執行的代碼。.NET CLR 管理程序的原始代碼和數據,并且提供類似垃圾回收和平臺無關代碼這樣的高級支持。
需要該運行時的編譯后代碼稱為托管代碼。不需要該運行時的代碼成為非托管代碼。只包含托管代碼的應用程序稱為托管應用程序。
托管的.NET應用程序可以在支持.NET CLR 的任何平臺上運行,因為編譯器生成的二進制代碼是平臺無關的。托管程序中的二進制代碼是Microsoft中間語言(Microsoft intermediate language (MSIL))。這種二進制代碼還包含對象信息和其他引用(稱為元數據)。
托管應用程序和傳統的應用程序有所不同,因為很多程序執行的細節是在運行時決定的,例如數據結構如何分布和本地代碼如何生成和使用。當這種程序執行的時候,運行時決定程序運行的數據使用和代碼使用,生成和平臺相關的本地代碼。從MSIL產生本地代碼的過程稱為托管或just-in-time (JIT) 編譯(有時也稱JITting)。運行時用來進行這種翻譯的組件成為JIT編譯器。
當JIT編譯器為某個方法編譯了MSIL后,該方法的存根被編譯后代碼的地址取代。不管之后這個方法什么時候被調用,執行的都是本地代碼,而JIT編譯器不需要再重復這個步驟。
構建托管代碼
可以使用各個軟件廠商提供的各個編譯器來構建托管代碼。特別是,Microsoft Visual Studio .NET可以使用4種不同語言來生成托管代碼:
- 帶托管擴展的C++
- C#
- Visual Basic
- JScript
默認的,Microsoft Visual C++ .NET不會構建托管應用程序。必須通過圖形界面或命令行開關來指定這樣的構建。
調試托管代碼
可以使用Sos.dll 擴展來調試托管代碼。該擴展在Windows調試工具包安裝目錄的\clr10 子目錄下。
要使用該擴展,可以加載它之后輸入!clr10\sos.help。
該命令會列出所有可用的擴展命令和它們的參數。