Windows 2000對(duì)調(diào)試技術(shù)的支持
盡管本書(shū)中的很多內(nèi)容都稱(chēng)之為“ Undocumented ”,但其中的一些內(nèi)容只能通過(guò)挖掘操作系統(tǒng)的代碼才能獲取。 Windows 2000 DDK ( Device Driver Kit )提供了一個(gè)強(qiáng)大的調(diào)試器可以出色的完成這方面的工作。本章將從建立一個(gè)完善的調(diào)試環(huán)境開(kāi)始介紹。在閱讀隨后的章節(jié)時(shí),你會(huì)經(jīng)常的使用內(nèi)核調(diào)試器來(lái)挖掘操作系統(tǒng)內(nèi)部的各種特性。如果你對(duì)內(nèi)核調(diào)試器很是厭煩,或許你需要制作一個(gè)自己的調(diào)試工具了。因此,本章還將介紹有關(guān) Windows 2000 調(diào)試接口的文檔化和未文檔化的資料,包括微軟符號(hào)文件( Symbol File )的詳細(xì)信息。 It features two sample librarIEs with companion applications that list processes, process and system modules, and various kinds of symbol information buried inside the Windows 2000 symbol files 。做為一個(gè)特殊收獲,在本章結(jié)束時(shí),你將得到首份有關(guān) PDB ( Microsoft Program Database )的公開(kāi)文檔。
建立一個(gè)調(diào)試環(huán)境
“嗨,我不想調(diào)試 Windows 2000 程 序。在此之前,我想自己寫(xiě)一個(gè)先!”當(dāng)你讀到這個(gè)標(biāo)題時(shí)你可能會(huì)這樣大喊出來(lái)。“很對(duì)!”我說(shuō)“這就是你該去做的!”但是為什么你要以建立一個(gè)調(diào)試環(huán)境開(kāi) 始這次旅行呢?答案很簡(jiǎn)單:調(diào)試器是進(jìn)入系統(tǒng)的后門(mén)。當(dāng)然,這并不是調(diào)試器開(kāi)發(fā)人員的主要目的。然而,當(dāng)你跟蹤代碼的執(zhí)行過(guò)程或者你的程序意外的玩完時(shí), 任何優(yōu)秀的調(diào)試器都須能夠告訴你一些有用的系統(tǒng)信息。僅僅報(bào)告一個(gè)指向 4GB 地址空間某處的 8 位 崩潰地址,然后讓你獨(dú)自一人去尋找到底發(fā)生了什么,真是無(wú)法讓人接受。調(diào)試器至少應(yīng)該告訴你最后執(zhí)行的引發(fā)錯(cuò)誤的代碼是哪個(gè)模塊中的代碼,而且,在理想情 況下,它還應(yīng)該告訴你讓你的程序玩完的那個(gè)函數(shù)的名稱(chēng)。因此,調(diào)試器通常必須知道比編程手冊(cè)還要多的系統(tǒng)信息,你可以利用這些信息來(lái)研究系統(tǒng)的內(nèi)部情況。
Windows 2000 提供了兩個(gè)調(diào)試器: WinDbg.exe (發(fā)音很像“ WindBag ”,譯注: WindBag 在俚語(yǔ)中指空話連篇的人)一個(gè) Win32 GUI 程序和 i386kd.exe 一個(gè)提供與之等價(jià)功能的命令行模式程序。我曾經(jīng)同時(shí)使用過(guò)這兩個(gè)程序,最后確定 i386kd.exe 是最好的一個(gè),因?yàn)樗幸唤M非常強(qiáng)大的選項(xiàng)。不過(guò),最近看來(lái) WinDbg.exe 似乎有所改進(jìn)。不過(guò),本書(shū)中的所有例子都是與 i386kd.exe 相關(guān)的。就像你猜想的那樣, i386 前綴表示目標(biāo)平臺(tái)( Intel 386 處理器家族,也包括 Pentium ) kd 是 Kernel Debugger (內(nèi)核調(diào)試器)的縮寫(xiě)。 Windows 2000 內(nèi)核調(diào)試器是一個(gè)非常強(qiáng)大的工具。比如,他知道如何使用 Windows 2000 安裝光盤(pán)中的符號(hào)文件( Symbol files ),因此,可以給出系統(tǒng)內(nèi)存中幾乎任何地址的相關(guān)符號(hào)信息(這非常有價(jià)值)。而且,它還可以反編譯二進(jìn)制代碼、將內(nèi)存信息的 16 進(jìn)制轉(zhuǎn)儲(chǔ)數(shù)據(jù)以多種格式顯示,甚至還能顯示一些內(nèi)核關(guān)鍵結(jié)構(gòu)的布局。在調(diào)試器的在線幫助中有其命令行接口的詳細(xì)文檔。
準(zhǔn)備一次崩潰轉(zhuǎn)儲(chǔ)( Crash Dump )
這 些都是好消息。壞消息是你在內(nèi)核調(diào)試器順從你之前,必須做一些準(zhǔn)備工作。第一個(gè)障礙是調(diào)試通常涉及兩臺(tái)獨(dú)立的計(jì)算機(jī)(通過(guò)線路連接在一起),其中一臺(tái)運(yùn)行 調(diào)試器,另一臺(tái)用于被調(diào)試。然而,如果并不需要實(shí)時(shí)調(diào)試,那么有一個(gè)簡(jiǎn)單的方法,可以不需要第二臺(tái)機(jī)器。例如,如果一個(gè)有錯(cuò)誤的程序拋出了一個(gè)未處理的異 常而引發(fā)了聲名狼藉的 NT 藍(lán)屏死機(jī)( Blue Screen Of Death, BSOD ),你可以選擇保存崩潰前的內(nèi)存映像到一個(gè)文件中,在重新啟動(dòng)后,檢查這個(gè)崩潰轉(zhuǎn)儲(chǔ)( Crash Dump )文件。這項(xiàng)技術(shù)通常被叫做 post mortem (事后檢查)在拉丁文中, post mortem 意思是“ after death ”。這種方式是本書(shū)首選方法之一。在這里,我們的主要任務(wù)是研究系統(tǒng)內(nèi)存,在大多數(shù)情況下,內(nèi)存數(shù)據(jù)是來(lái)自還在工作的系統(tǒng)或者來(lái)自系統(tǒng)崩潰前內(nèi)存的一個(gè)快照( snapshot )都并不重要。然而,一些有趣的信息則需要通過(guò)內(nèi)核模式的驅(qū)動(dòng)程序深入正在工作的系統(tǒng)的內(nèi)部才能觀察到,這一主題被保留在后面的章節(jié)中。
一個(gè)崩潰轉(zhuǎn)儲(chǔ)( Crash Dump )只是簡(jiǎn)單將當(dāng)前內(nèi)存數(shù)據(jù)寫(xiě)入一個(gè)磁盤(pán)文件而已。因此,一個(gè)完整的崩潰轉(zhuǎn)儲(chǔ)( crash dump )文件的大小通常與系統(tǒng)物理內(nèi)存一樣大(事實(shí)上,會(huì)略微小些)。崩潰轉(zhuǎn)儲(chǔ)( Crash dump )是由內(nèi)核中的一個(gè)特殊程序在處理致命錯(cuò)誤過(guò)程中生成的。然而,這個(gè)例程( handler )并不是立即將內(nèi)存數(shù)據(jù)寫(xiě)入目標(biāo)文件中。這是個(gè)不錯(cuò)的處理方式,因?yàn)樵谙到y(tǒng)崩潰后,磁盤(pán)文件系統(tǒng)可能也不能正常工作。因此,內(nèi)存映像首先被復(fù)制到頁(yè)面文件存儲(chǔ)器( page file storage ),這是系統(tǒng)內(nèi)存管理器的一部分。因此,你應(yīng)該將你的頁(yè)面文件大小增加到至少兩倍于物理內(nèi)存。兩倍?一樣大還不夠嗎?當(dāng)然 — 那只夠存放崩潰轉(zhuǎn)儲(chǔ)( crash dump )。要知道,在啟動(dòng)時(shí),系統(tǒng)會(huì)嘗試將崩潰轉(zhuǎn)儲(chǔ)( crash dump ) 映像復(fù)制到實(shí)際的磁盤(pán)文件,這意味著,如果系統(tǒng)不能及時(shí)的釋放映像數(shù)據(jù)占用的頁(yè)面文件,它就可能用盡所有的虛擬內(nèi)存。通常,系統(tǒng)會(huì)處理這種情況,它會(huì)瘋狂 的讀寫(xiě)磁盤(pán)并向你拋出一個(gè)惹人厭的“虛擬內(nèi)存不足”的警告。只要你預(yù)料藍(lán)屏的概率會(huì)增大時(shí),將頁(yè)面文件設(shè)置的足夠大,這將會(huì)為你節(jié)省很多時(shí)間。
到這兒,你應(yīng)該打開(kāi) Windows 2000 的控制面板,改變?nèi)缦碌脑O(shè)置:
l 增加頁(yè)面文件到至少兩倍物理內(nèi)存的大小。
l 接下來(lái),配置系統(tǒng)以便當(dāng)藍(lán)屏發(fā)生時(shí)生成一個(gè) 崩潰轉(zhuǎn)儲(chǔ)( crash dump )文件。在系統(tǒng)屬性對(duì)話框里,選擇高級(jí)頁(yè),然后單擊啟動(dòng)和恢復(fù)按鈕,檢查寫(xiě)入調(diào)試信息選項(xiàng)。你應(yīng)該在下拉列表中選擇完成內(nèi)存轉(zhuǎn)儲(chǔ)選項(xiàng)。在轉(zhuǎn)儲(chǔ)文件對(duì)話框中輸入一個(gè)文件名和路徑,轉(zhuǎn)儲(chǔ)文件將會(huì)從頁(yè)面文件中復(fù)制到你指定的這個(gè)文件中。 %SystemRoot%MEMORY.DMP 是默認(rèn)設(shè)置。
讓系統(tǒng)崩潰
當(dāng)設(shè)置好系統(tǒng)準(zhǔn)備一次 crash dump 后,是時(shí)候做在 Windows 2000 系統(tǒng)程序員一生中最厭惡的事了:開(kāi)始讓系統(tǒng)崩潰!通常,只要達(dá)摩克利斯的劍掛在了你的頭頂上(通常是在離產(chǎn)品截止時(shí)間還有幾個(gè)小時(shí)的時(shí)候)你就會(huì)看到恐怖的藍(lán)屏。現(xiàn)在,是你自愿讓系統(tǒng)崩潰,但你可能無(wú)法找到有問(wèn)題的軟件來(lái)完成這項(xiàng)“工作”。來(lái)試試 David Solomon 在他的《 Inside Windows NT 第二版》中提到的那個(gè)優(yōu)雅的訣竅:
“如何能可靠的產(chǎn)生一個(gè)崩潰轉(zhuǎn)儲(chǔ)( crash dump )文件?只需要使用 Windows NT 資源工具中的 kill.exe 工具, kill 掉 Win32 子系統(tǒng)進(jìn)程( csRSS.exe )或者 Windows NT 登陸進(jìn)程( winlogon.exe ),你必須有管理員權(quán)限”( Solomon [1998],p.23. )
神奇,太神奇了!這個(gè)竅門(mén)不能在 Windows 2000 上工作!第一感覺(jué),很不走運(yùn),但是從另一個(gè)角度看,這是個(gè)好消息。當(dāng)你知道使用微軟自己正式發(fā)布的一個(gè)小工具就能如此輕松的破壞系統(tǒng),你會(huì)怎樣想?事實(shí)上,微軟關(guān)閉這個(gè)安全漏洞非常對(duì)。可是,我們現(xiàn)在需要一種方法來(lái)使系統(tǒng)崩潰啊。在這一點(diǎn)上,想想那個(gè)古老而簡(jiǎn)單的 NT 規(guī)則:“ If anything seems to be impossible in the Win32 Word, just write a kernel-mode driver, and it will work out all right! ” Windows 2000 非常謹(jǐn)慎的管理 Win32 程序。它在應(yīng)用程序和內(nèi)核之間構(gòu)建了一堵墻,任何企圖跨越此邊界者都會(huì)被毫不留情的解決掉。這對(duì)于系統(tǒng)的穩(wěn)定性是個(gè)好消息,但是對(duì)于編寫(xiě)需要直接與硬件打交道的程序的人來(lái)說(shuō)并不是個(gè)好消息。想想 Dos ,在那兒任何程序都可以直接觸及硬件,在這方面 Windows 2000 有些過(guò)分講究。但這并不意味著在 Windows 2000 中訪問(wèn)硬件是不可能的。不同的是,這種訪問(wèn)被限制到一個(gè)特殊類(lèi)型的模塊 — 內(nèi)核模式的驅(qū)動(dòng)程序( Kernel-mode driver )。
我可以告訴你,現(xiàn)在我將簡(jiǎn)要的介紹一下 Kernel-mode driver 編程技術(shù)(這本是第三章的內(nèi)容)。眼下,這已經(jīng)足夠說(shuō)明 kernel-mode driver 讓系統(tǒng)崩潰是非常容易的事。當(dāng)驅(qū)動(dòng)程序出錯(cuò)時(shí), Windows 2000 沒(méi)有提供一種錯(cuò)誤恢復(fù)機(jī)制,這就導(dǎo)致即使無(wú)意中試圖執(zhí)行一個(gè)不合法的操作也會(huì)招來(lái)藍(lán)屏。當(dāng)然,最簡(jiǎn)單而且危險(xiǎn)最小的違規(guī)動(dòng)作就是讀取一個(gè)無(wú)效的內(nèi)存地址。由于系統(tǒng)顯示捕獲所有通過(guò)空指針進(jìn)行的內(nèi)存訪問(wèn),這是 C 編程中一個(gè)常見(jiàn)的錯(cuò)誤,讀取一個(gè)空指針是讓系統(tǒng)崩潰的理想動(dòng)作。示例代碼中的 w2k_kill.sys driver 就是這么做的。這是一個(gè)非常簡(jiǎn)單的程序,同時(shí)也是出現(xiàn)在本書(shū)中的第一個(gè) kernel-mode driver 。
列表 1-1 是 w2k_kill.c 的引用部分,展示了引發(fā)藍(lán)屏的錯(cuò)誤代碼。當(dāng)編寫(xiě)這樣無(wú)意義的代碼時(shí),需要注意內(nèi)建于 Visual C/C++ 的優(yōu)化器可能會(huì)抵消你的努力,它會(huì)跟蹤所有的代碼并試圖消除其中任何有副作用的部分。在下面的例子中,優(yōu)化器并未起作用,因?yàn)?DriverEntry() 堅(jiān)持將在 0 地址發(fā)現(xiàn)的東西作為其返回值。這意味著這個(gè)數(shù)值將會(huì)被存放到 CPU 的 EAX 寄存器中,最簡(jiǎn)單的方法就是 MOV EAX, [0] 指令,這個(gè)指令將會(huì)拋出我們期待的異常。
NTSTATUS DriverEntry ( PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING puRegistryPath )
{
return *((NTSTATUS*)0); // read through NULL pointer
}
列表 1-1 A NULL Pointer Read Operation in Kernel-Mode Crashes the System
w2k_load.exe 程序出現(xiàn)在第三章,用來(lái)用來(lái)載入并啟動(dòng) w2k_kill.sys 驅(qū)動(dòng)程序。如果你在精神上做好了 kill 掉你的 Windows 2000 系統(tǒng),請(qǐng)按照下面的步驟來(lái)做:
l 關(guān)閉所有應(yīng)用程序
l 插入本書(shū)的附帶光盤(pán)
l 在開(kāi)始菜單中選擇運(yùn)行
l 輸入 d:binw2k_load w2k_kill.sys ,用你 CD-ROM 的盤(pán)符替換 d: ,然后單擊確定
當(dāng)單擊后, w2k_load.exe 將試圖加載 w2k_kill.sys 文件(位于光盤(pán)的 bin 目錄下)。隨后 DriverEntry() 開(kāi)始執(zhí)行,藍(lán)屏出現(xiàn)了,如圖 1-3 所示,你會(huì)看到當(dāng)內(nèi)存數(shù)據(jù)被轉(zhuǎn)儲(chǔ)到頁(yè)面文件存儲(chǔ)器時(shí),屏幕上會(huì)有一個(gè)計(jì)數(shù)器從 0 逐漸增加到 100 。 如果你在啟動(dòng)和恢復(fù)對(duì)話框中選中了自動(dòng)重起,當(dāng)崩潰轉(zhuǎn)儲(chǔ)完成后,系統(tǒng)會(huì)立即重新啟動(dòng)。當(dāng)系統(tǒng)進(jìn)入等待登陸狀態(tài)后,稍等一會(huì)直到硬盤(pán)燈不再閃爍。這是因?yàn)閷?崩潰轉(zhuǎn)儲(chǔ)數(shù)據(jù)從頁(yè)面文件復(fù)制到磁盤(pán)文件需要一定的時(shí)間,特別是你的物理內(nèi)存很大時(shí)。在此時(shí)干擾系統(tǒng),例如,將系統(tǒng)過(guò)早的關(guān)閉,可能會(huì)產(chǎn)生一個(gè)無(wú)效的崩潰轉(zhuǎn) 儲(chǔ)文件。
在圖 1-3 中,可以看出系統(tǒng)會(huì)顯示包含出錯(cuò)代碼的模塊的名稱(chēng)( w2k_kill.sys ),以及引發(fā)異常的指令地址( 0xBECC3000 )。這個(gè)地址或許和你的系統(tǒng)的不同,因?yàn)樗请S硬件配置而變化的。驅(qū)動(dòng)程序的加載地址通常都不確定,和 DLL 的加載地址類(lèi)似。請(qǐng)記下顯示的地址 ---- 稍后在安裝和配置內(nèi)核調(diào)試器是你還需要它。
一點(diǎn)小的提示:故意讓系統(tǒng)崩潰不該是你每天都作的事。盡管有問(wèn)題的 w2k_kill.sys 本 身是無(wú)害的,但在它執(zhí)行的那一刻可能并不那么走運(yùn)。如果度去空指針發(fā)生時(shí)另一個(gè)線程正在做某些重要的事情,系統(tǒng)可能會(huì)在該線程有機(jī)會(huì)做清理工作之前關(guān)閉。 比如,在重起之后,活動(dòng)桌面往往會(huì)抱怨發(fā)生了一些可惡的事情,它需要進(jìn)行恢復(fù)。因此,在你使系統(tǒng)崩潰之前,應(yīng)該仔細(xì)的檢察系統(tǒng)是否影響了重要數(shù)據(jù)并且保證 所有 cache 中的數(shù)據(jù)都被寫(xiě)入了磁盤(pán)。注意,作者和出版商不會(huì)對(duì) w2k_kill.sys 驅(qū)動(dòng)程序造成的破壞負(fù)責(zé)。
譯注: 達(dá)摩克利斯希臘傳說(shuō)中的敘拉古國(guó)王狄?jiàn)W尼西奧斯的朝臣,據(jù)傳說(shuō)其被迫坐在上懸寶劍的餐桌旁,寶劍由一根頭發(fā)系住 , 以此來(lái)暗示君王命運(yùn)的多危
安裝符號(hào)文件
重新啟動(dòng)后,你就有了一個(gè) Windows 2000 系統(tǒng)的快照( snapshot ),包括一個(gè)有問(wèn)題的 Kernel-mode Driver (讀取空指針時(shí)被捕獲)。觀察此快照文件和察看實(shí)際系統(tǒng)內(nèi)存是一樣的。當(dāng)然,這個(gè)快照文件和動(dòng)物死尸一樣 --- 不再對(duì)外界刺激有所反應(yīng),但是你現(xiàn)在不需要擔(dān)心這些。接下來(lái)你需要安裝內(nèi)核調(diào)試器需要的符號(hào)文件( symbol files ),當(dāng)你分析崩潰文件時(shí),你就會(huì)用到了。
MSDN 用戶(hù)可以在 Windows 2000 Customer Suuport – Diagnostic Tools 光盤(pán)上找到這些符號(hào)文件。插入光盤(pán),用 IE 打開(kāi)光盤(pán)上的 DBG.HTM 文件,你會(huì)看到很多安裝選項(xiàng)。如果你運(yùn)行的是 free build 的 Windows 2000 ,你最好安裝 retail symbols 。對(duì)于 checked build 版,可以選擇安裝 debug symbols 。安裝程序會(huì)從 SYMBOLS.CAB 中復(fù)制一些 .dbg 和 .pdb 文件到系統(tǒng)符號(hào)文件目錄中。默認(rèn)的系統(tǒng)符號(hào)文件目錄為: %SystemRoot%Symbols 。 %SystemRoot% 環(huán)境變量代表 Windows 2000 的安裝目錄。
在起動(dòng)時(shí), Windows 2000 內(nèi)核調(diào)試器會(huì)嘗試通過(guò)環(huán)境變量 _NT_SYMBOL_PATH 指示的路徑來(lái)尋找符號(hào)文件,所以最好正確的定義該變量。
譯注:
現(xiàn)在可以通過(guò) Symchk.exe 工具來(lái)檢查和下載最新的符號(hào)文件,該工具隨 Debugging Tools for Windows 軟件包安裝。
微軟的文檔中對(duì)于 _NT_SYMBOL_PATH 應(yīng)該指向哪里的說(shuō)明有些模糊不清。在 DDK 的內(nèi)核調(diào)試一節(jié)里提到必須包含符號(hào)子目錄,即 C:WINNTSymbols 或等價(jià)目錄。而在 SDK 關(guān)于 dbghelp.dll 庫(kù)的文檔中,有關(guān)符號(hào)路徑的描述又稍微有些區(qū)別:
“該庫(kù)需要使用符號(hào)搜索路徑來(lái)定位 .dll 、 .exe 或 .sys 對(duì)應(yīng)的調(diào)試符號(hào)( .dbg 文件)。它會(huì)在路徑后添加 dll 、 exe 或 sys 。例如, .dll 符號(hào)文件位于: C:WINNTSymbolsdll , .exe 文件的路徑則為: C:WINNTSymbolsexe ”
。。。。。。
“如果你設(shè)置了 _NT_SYMBOL_PATH 環(huán)境變量,符號(hào)管理器按照如下順序搜索符號(hào)文件:
1. 應(yīng)用程序的當(dāng)前工作目錄
2. _NT_SYMBOL_PATH 指示的目錄
3. _NT_ALT_SYMBOL_PATH 指示的目錄
4. SYSTMEROOT 指示的目錄
”
這樣看來(lái)把 _NT_SYMBOL_PATH 設(shè)定為 C:WINNT 似乎要好于 C:WINNTSymbols ,為了確定哪種說(shuō)法是正確的。我試驗(yàn)了這兩種方法,很高興它們都能正常的工作。
配置內(nèi)核調(diào)試器
構(gòu)建調(diào)試環(huán)境的最后一步就是安裝和配置內(nèi)核調(diào)試器。如果你已經(jīng)安裝了 Windows 2000 DDK ,那你可以在 NTDDKbin 目錄中找到調(diào)試器。內(nèi)核調(diào)試器的可執(zhí)行文件名為 i386kd.exe 。另一種方法是從 Windows 2000 Customer Support---Diagnostic Tools 光盤(pán)中安裝。
為了使用前面我們得到的崩潰轉(zhuǎn)儲(chǔ)文件,你需要使用 i368kd 的 –Z 選項(xiàng)。示例如下:
i386kd –z C:WINNTMEMORY.DMF
成功打開(kāi)我們的 crash dump 后,你會(huì)看到類(lèi)似圖 1-7 所示的東東, kd> 提示符會(huì)出現(xiàn),這表示內(nèi)核調(diào)試器已經(jīng)準(zhǔn)備接受命令了。在開(kāi)始之前,請(qǐng)檢查符號(hào)搜索路徑是否正確。列出的啟動(dòng)信息,表示調(diào)試器已經(jīng)加載了三個(gè)擴(kuò)展 DLL 。 i386kd.exe 一個(gè)強(qiáng)大的特性就是其擴(kuò)展機(jī)制,這允許第三方采用獨(dú)立的 DLL 來(lái)擴(kuò)展其基本功能。對(duì)于這些擴(kuò)展的命令,要在其前面加上!號(hào)以區(qū)分內(nèi)建的命令。
如圖 1-7 所示,我輸入了一個(gè)內(nèi)建命令: u becc3000 , u 的含義是“反編譯( unassembel )”, becc3000 是開(kāi)始反編譯的 16 進(jìn)制地址。默認(rèn)情況下,均采用 16 進(jìn)制,但你也可也通過(guò)命令來(lái)改變此默認(rèn)值。命令為: n 10 ,此后默認(rèn)所有數(shù)字都是 10 進(jìn)制表示。你可以使用 0x 前綴來(lái)表示這是一個(gè) 16 進(jìn)制數(shù)。地址 becc3000 就是 w2k_kill.sys 引起系統(tǒng)崩潰的地方。請(qǐng)使用你在藍(lán)屏?xí)r看到的地址。如果一切正確的話,你會(huì)看到 mov eax, [00000000] 指令,如上圖所示。如果沒(méi)有看到的話,你可能沒(méi)有使用正確的崩潰轉(zhuǎn)儲(chǔ)文件。 mov eax, [00000000] 指令表示從虛擬地址(也可稱(chēng)作線性地址) 0x00000000 讀取一個(gè) 32 位的數(shù)值到 CPU 寄存器 EAX 中,這明顯是列表 1-1 中 *(NTSTATUS*)0) 表達(dá)式的實(shí)現(xiàn),等同于讀取空指針的操作。沒(méi)有針對(duì)此類(lèi)錯(cuò)誤的異常處理例程,因此,系統(tǒng)在藍(lán)屏上會(huì)顯示 KMODE_EXCEPTION_NOT_HANDLED ,如圖 1-3 所示。如果你想知道有關(guān)此錯(cuò)誤信息更多的東西請(qǐng)參考《 The NT Insider 》( Open Systems Resources 1999b )。
