通過使用windbg提供DbgHelp庫中的MiniDumpWriteDump函式在程式崩潰時寫dump檔案記錄程式當時狀態,為後續分析問題提供現場。
該函式提供了DumpType引數,讓程式設計師根據具體情況來生成包含不同詳細程度內容的dump檔案。
例如:QQ崩潰後,會詢問玩家是否要傳送崩潰到伺服器,以幫助開發解決該問題,這個時候建立的dump就不宜過大。
typedef enum _MINIDUMP_TYPE { MiniDumpNormal = 0x00000000, MiniDumpWithDataSegs = 0x00000001, MiniDumpWithFullMemory = 0x00000002, MiniDumpWithHandleData = 0x00000004, MiniDumpFilterMemory = 0x00000008, MiniDumpScanMemory = 0x00000010, MiniDumpWithUnloadedModules = 0x00000020, MiniDumpWithIndirectlyReferencedMemory = 0x00000040, MiniDumpFilterModulePaths = 0x00000080, MiniDumpWithProcessThreadData = 0x00000100, MiniDumpWithPrivateReadWriteMemory = 0x00000200, MiniDumpWithoutOptionalData = 0x00000400, MiniDumpWithFullMemoryInfo = 0x00000800, MiniDumpWithThreadInfo = 0x00001000, MiniDumpWithCodeSegs = 0x00002000, MiniDumpWithoutManagedState = 0x00004000, } MINIDUMP_TYPE;
這些列舉可以組合,以生成包含自己想要的dump檔案。
如:DUMP_TYPE_MINI = MiniDumpWithUnloadedModules
如:DUMP_TYPE_MIDD = MiniDumpWithUnloadedModules | MiniDumpWithIndirectlyReferencedMemory
如:DUMP_TYPE_FULL = MiniDumpNormal | MiniDumpWithFullMemory | MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData
組合的列舉越多,生成出來的dump檔案資訊就越豐富。下面依次對各個列舉的dump包含的資訊進行說明:
MiniDumpNormal -- 包含最基礎的資料 預設
資料型別 | 說明 | 命令 |
系統資訊 |
發生崩潰機器的os版本號 cpu個數與型號 |
vertarget !cpuid |
程式資訊 |
程式ID 程式建立時間、執行使用者態程式碼與核心態程式碼的時間 |
| .time |
模組資訊 |
每一個被程式載入的模組,資訊包括:載入地址、大小、檔名(包含路徑)、版本、 模組元資訊(checksum, timestamp, debug information record; -- 用於偵錯程式匹配與載入該模組的除錯資訊) |
lm |
執行緒資訊 | 當前跑的每一個執行緒,資訊包括:執行緒ID、優先順序、執行緒上下文、暫停次數、TEB地址(不包括TEB具體內容) | ~ |
執行緒棧 | 所有執行緒的完整stack內容(stack中存放著:函式呼叫堆疊、區域性變數、引數變數) | |
IP資訊 | 儲存每個執行緒IP暫存器所指向地址周圍的256個位元組的記憶體,使得在沒有可執行模組情況下也能檢視崩潰點周圍的彙編指令 | |
異常資訊 |
通過MiniDumpWriteDump第5個引數傳入的 內容包括:EXCEPTION_RECORD結構體資料、當前異常執行緒上下文、當前異常執行緒的IP資訊 |
.ecxr |
(1) 通過檢視各個執行緒的函式呼叫堆疊來看它們在等待什麼,來確認程式是否發生了死鎖
(2) 可檢視各個執行緒函式棧幀的區域性變數以及引數變數的值,不能檢視全域性變數及malloc、new出來的堆記憶體中的內容
(3) Dump檔案大小主要取決於執行緒棧的大小,一般小於20KB
MiniDumpWithFullMemory -- 包含所有資料
(1) 包含程式地址空間內所有可讀頁的內容
(2) 可檢視各個模組、執行緒環境塊(PEB)、程式環境塊(TEB)在棧或堆上的值
(3) 包含各個模組程式碼段的頁(冗餘 如果有各個模組可執行檔案的話,windbg能從這些檔案中獲取到)
(4) 可檢視各個模組資料段內容(全域性變數)
(5) Dump檔案很大,與程式佔用的實體記憶體工作集(Working Set)大小相當
MiniDumpWithPrivateReadWriteMemory
(1) 包括程式地址空間內所有可讀可寫的私有記憶體頁(實體記憶體私有工作集Working Set Private,即主模組exe的記憶體頁)
(2) 可檢視主模組exe、執行緒區域性儲存(TLS)、執行緒環境塊(PEB)、程式環境塊(TEB)在棧或堆上的值
(3) 不能檢視共享模組及記憶體對映檔案中的內容
(4) 不包括各個模組的程式碼段
(5) 不能檢視各個模組的資料段(全域性變數)
MiniDumpWithIndirectlyReferencedMemory
(1) 掃描各個執行緒棧中的指向可讀記憶體頁的指標(由於MiniDumpWriteDump在掃描時無法訪問除錯資訊,無法區分指標與整型變數,因此整型變數也會被當做指標處理),
將指標指向的記憶體地址前256B+後768B的內容(共1KB)儲存到Dump檔案中
(2) 不包括指向資料段的指標(無法檢視全域性變數的值)
MiniDumpWithDataSegs
(1) 包含各個模組所有可寫資料段, 可檢視資料段內容(非常量的全域性變數)
(2) Dump檔案較大,哪怕只使用了dll的一個函式,該dll的所有可寫資料段都會被寫入Dump
MiniDumpWithCodeSegs
(1) 包含各個已載入模組程式碼段(使得windbg中不用配置Image Path)
MiniDumpWithHandleData
(1) 發生崩潰時,將程式控制程式碼表中所有控制程式碼資訊寫入Dump中
(2) windbg中通過!handle命令來檢視控制程式碼
MiniDumpWithThreadInfo
(1) 各個執行緒的額外資訊:時間(建立時間、分別執行使用者和核心程式碼的時間)、執行緒函式地址(Start Address)、
關聯性(Affinity -- 在那些cpu上執行當前執行緒,若TheadAffinity為fd,表示可以在0、2-7編號的cpu上執行;TheadAffinity的值首先會受到程式的Affinity的限制)
(2) .ttime檢視當前執行緒的時間資訊,~.檢視當前執行緒的執行緒函式地址及關聯性
!runaway檢視所有執行緒的時間資訊,~*檢視所有執行緒的執行緒函式地址及關聯性
MiniDumpWithProcessThreadData
(1) 包含執行緒環境塊(PEB)、程式環境塊(TEB)的記憶體頁
(2) PEB及TEB引用的記憶體頁(如:環境變數、程式引數、通過TlsAlloc分配的位標誌所在的記憶體頁)
(3) 不包括TLS資料(執行緒區域性變數,可通過__declspec(thread)關鍵字來定義)
MiniDumpWithFullMemoryInfo
(1) 程式的整個虛擬記憶體佈局資訊(各個記憶體頁的基址、大小、狀態和型別)
(2) .vadump檢視程式的整個虛擬記憶體佈局
MiniDumpWithoutOptionalData -- 只包含MiniDumpNormal的資料 如:MiniDumpWithFullMemory | MiniDumpWithoutOptionalData等價於MiniDumpNormal
MiniDumpFilterMemory -- 執行緒棧結構完好,但會將棧上的資料(如區域性變數、引數變數)設定成0,堆記憶體不受影響;另外對MiniDumpWithFullMemory不起作用
MiniDumpFilterModulePaths -- 去除模組路徑,只保留模組名稱
MiniDumpScanMemory -- 從Dump檔案中排除某些模組(通過MiniDumpCallback函式),以減少Dump檔案的大小
----------------------------------------------------------------------------------------------------
MiniDumpCallback可以實現如下使用者自定義行為:
① 整個或部分排除某個模組的資訊
② 整個或部分排除某個執行緒的資訊
③ 加入使用者指定記憶體內容到Dump中
----------------------------------------------------------------------------------------------------
MiniDumpWithUnloadedModules -- 包含未載入模組資訊(windows server 2003 sp1, windows xp sp2及以上系統能獲取到這塊資訊)
參考: