如果您可以分析程式代碼的來源,而不是反組譯二進位檔,偵錯應用程式會比較容易。
如果來源語言為 C、C++或元件,則 WinDbg、CDB 和 KD 可以在偵錯中使用原始程式碼。
編譯需求
若要使用來源偵錯,您必須在建置二進位檔時,讓編譯程式或鏈接器建立符號檔 (.pdb 檔案)。 這些符號檔會顯示調試程式二進位指令如何對應至來源行。
此外,調試程式必須能夠存取實際的原始程式檔,因為符號檔不包含實際的來源文字。
如果可能的話,編譯程式和連結器不應該優化您的程序代碼。 如果程式代碼已優化,來源偵錯和本機變數的存取會比較困難,有時幾乎是不可能的。 如果您使用 Build 公用程式作為編譯程式和連結器,請將MSC_OPTIMIZATION巨集設定為 /Od /Oi 以避免優化。
尋找符號檔和原始程序檔
若要在來源模式中偵錯,調試程式必須能夠尋找來源檔案和符號檔。 如需詳細資訊,請參閱 來源路徑。
開始來源偵錯
每當調試程式有正在偵錯之線程的適當符號和來源檔案時,調試程式就可以顯示來源資訊。
如果您使用調試程序啟動新的使用者模式應用程式,Ntdll.dll 載入應用程式時,就會發生初始中斷。 因為調試程式無法存取 Ntdll.dll 來源檔案,所以此時無法存取應用程式的來源資訊。
若要將程式計數器移至應用程式的開頭,請在您的二進位檔的進入點新增斷點。 在 [調試程式命令] 視窗中,輸入下列命令。
bp main
g
然後載入應用程式,並在輸入 main 函式時停止。 當然,您可以使用任何進入點,而不僅限於 main 。
如果應用程式擲回例外狀況,它會進入偵錯工具。 此時可取得來源資訊。 不過,如果您使用 CTRL+C、CTRL+BREAK 或偵錯工具的中斷命令,偵錯工具會建立新的執行緒,因此您無法看到原始程式碼。
到達來源檔案的線程之後,您可以使用 [調試程式命令] 視窗來執行來源偵錯命令。 如果您使用 WinDbg, [來源] 視窗 隨即出現。 如果您已按下 [檔案] 選單上的 [開放原始碼檔案] 來開啟 [來源] 視窗,WinDbg 通常會為來源建立新的視窗。 您可以關閉上一個視窗,而不會影響偵錯程式。
WinDbg GUI 中的來源偵錯
如果您使用 WinDbg,只要程式計數器位於調試程式具有來源資訊的程式代碼中,就會立即顯示 [來源] 視窗。
WinDbg 會顯示您或 WinDbg 開啟之每個來源檔案的一個 [來源] 視窗。 如需此視窗文字屬性的詳細資訊,請參閱 來源 Windows。
然後,您可以逐步檢查您的應用程式,或執行直到斷點或游標位置。 如需有關逐步執行和追蹤命令的詳細資訊,請參閱控制目標。
如果您處於原始碼模式,當您逐步執行應用程式時,相應的原始碼視窗會移至前景。 由於在應用程式執行期間也會呼叫Microsoft Windows 例程,因此調試程式可能會在發生這種呼叫時,將 反組譯碼視窗 移至前景(因為調試程式無法存取這些函式的來源)。 當程式計數器返回已知的來源檔案時,適當的 [來源] 視窗會變成作用中。
當您瀏覽應用程式時,WinDbg 會在 [來源] 視窗和 [反組譯碼] 視窗中醒目提示您的位置。 設定斷點的行也會反白顯示。 原始碼會根據語言的剖析來著色。 如果已選取 [來源] 視窗,您可以使用滑鼠將滑鼠停留在符號上來評估它。 如需這些功能以及如何控制這些功能的詳細資訊,請參閱 來源 Windows。
若要在 WinDbg 中啟動來源模式,請使用 l+t 命令,在偵錯功能表中點擊 來源模式,或點擊 來源模式開啟 按鈕。 當來源模式處於使用中狀態時, ASM 指標會出現在狀態列上無法使用。
當您逐步執行來源模式中的函式時,您可以檢視或變更任何局部變數的值。 如需詳細資訊,請參閱 讀取和寫入記憶體。
調試程式命令視窗中的來源偵錯
如果您使用CDB,則沒有個別的 [來源] 視窗。 不過,當您逐步執行來源時,您仍然可以檢視進度。
在CDB中執行來源偵錯之前,您必須發出 .lines (切換原始程式行支援) 命令或啟動調試程式搭配 -lines 命令行選項來載入來源行符號。
如果您執行 l+t 命令,所有程式將逐行執行原始碼。 使用 l-t 逐步執行組合語言指令。 如果您使用 WinDbg,此命令的效果與選取或清除 [偵錯] 功能表上的 [來源模式] 或使用工具列按鈕相同。
l+s 命令會在提示符中顯示當前的源程式碼行和行號。 如果您想要只看到行號,請改用 l+l 。
如果您使用 l+o 和 l+s,當您逐步執行程式時,只會顯示來源行。 程式計數器、反組譯碼和緩存器資訊會隱藏。 這種顯示可讓您快速逐步執行程式碼,只檢視原始碼。
您可以使用 lsp (設定來源行數目) 命令來指定當您逐步執行或執行應用程式時所顯示的來源行數目。
下列命令序列是逐步執行原始程序檔的有效方法。
.lines enable source line information
bp main set initial breakpoint
l+t stepping will be done by source line
l+s source lines will be displayed at prompt
g run program until "main" is entered
pr execute one source line, and toggle register display off
p execute one source line
因為 ENTER 會重複最後一個命令,您現在可以使用 ENTER 鍵逐步執行應用程式。 每個步驟都會導致來源行、記憶體位移和元件程式代碼出現。
如需如何解譯反組譯顯示的詳細資訊,請參閱 元件模式中的偵錯。
當顯示組合語言程式碼時,正在存取的任何記憶體位置會顯示在行的右端。 您可以使用 d* (顯示記憶體) 和 e* (輸入值) 命令來檢視或變更這些位置中的值。
如果您必須檢視每個組合指令以判斷位移或記憶體資訊,請使用 l-t 逐步執行組合指令,而非原始碼行。 源行資訊仍可顯示。 每個原始碼行都會對應至一或多個組合語言指令。
所有這些命令都可在 WinDbg 和 CDB 中使用。 您可以使用 命令,從 WinDbg 的 [調試程式命令] 視窗 檢視源程式行資訊,而不是從 [來源] 視窗檢視。
來源行和位移
您也可以使用表達式評估工具來判斷對應至特定來源行的位移,以執行來源偵錯。
下列命令會顯示記憶體位移。
? `[[module!]filename][:linenumber]`
如果您省略 檔名,調試程式會搜尋對應至目前程式計數器的來源檔案。
調試程式會將 linenumber 讀為十進位數,除非您在它之前新增 0x ,而不論目前的預設基數為何。 如果您省略 linenumber,表達式會評估為對應至原始程式檔之可執行檔的初始位址。
只有在 .lines 命令或 -lines 命令行選項已載入源行符號時,CDB 才會瞭解此語法。
這項技術非常多才多藝,因為不論程式計數器指向何處,您都可以使用它。 例如,這項技術可讓您使用下列命令來事先設定斷點。
bp `source.c:31`
在來源模式中逐步執行和追蹤
當您在來源模式中偵錯時,單一來源行上可能會有多個函式呼叫。 您無法使用 p 和 t 命令來分隔這些函數呼叫。
例如,在下列命令中, t 命令會逐步執行 GetTickCount 和 printf,而 p 命令會逐步執行這兩個函式呼叫。
printf( "%x\n", GetTickCount() );
如果您想要在追蹤其他呼叫時跳過特定呼叫,請使用 .step_filter (設定步驟篩選) 來指出要跳過哪些呼叫。
您可以使用 _step_filter 來篩選出架構函式(例如,Microsoft基礎類別 (MFC) 或 Active Template Library (ATL) 呼叫)。