Debugging skills-how to analyze program exceptions using windbg + dump + map

Source: Internet
Author: User

I met a few friends in the Forum, saying that the program crashes from time to time and what xxoo cannot be read! If this memory address is used, you may lose your mind ~~

So let's share some basic debugging skills. The tools that need to be prepared include windbg + vc6.0,

Below is a self-organized copy of the source code that automatically generates the dump file. You only need to add it to the project. The source code is as follows:

Minidump. h

#include <windows.h>#include <tlhelp32.h>//#include "dbghelp.h"//#define DEBUG_DPRINTF1//allow d()//#include "wfun.h"#pragma optimize("y", off)//generate stack frame pointers for all functions - same as /Oy- in the project#pragma warning(disable: 4200)//nonstandard extension used : zero-sized array in struct/union#pragma warning(disable: 4100)//unreferenced formal parameter/*BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, PCHAR Module_Name, PBYTE & Module_Addr);int WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, PCHAR Str);int  WINAPI Get_Version_Str(PCHAR Str);PCHAR WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException);void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag);*/// In case you don't have dbghelp.h.#ifndef _DBGHELP_typedef struct _MINIDUMP_EXCEPTION_INFORMATION {DWORDThreadId;PEXCEPTION_POINTERSExceptionPointers;BOOLClientPointers;} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;typedef enum _MINIDUMP_TYPE {MiniDumpNormal =0x00000000,MiniDumpWithDataSegs =0x00000001,} MINIDUMP_TYPE;typedefBOOL (WINAPI * MINIDUMP_WRITE_DUMP)(IN HANDLEhProcess,IN DWORDProcessId,IN HANDLEhFile,IN MINIDUMP_TYPEDumpType,IN CONST PMINIDUMP_EXCEPTION_INFORMATIONExceptionParam, OPTIONALIN PVOIDUserStreamParam, OPTIONALIN PVOIDCallbackParam OPTIONAL);#elsetypedefBOOL (WINAPI * MINIDUMP_WRITE_DUMP)(IN HANDLEhProcess,IN DWORDProcessId,IN HANDLEhFile,IN MINIDUMP_TYPEDumpType,IN CONST PMINIDUMP_EXCEPTION_INFORMATIONExceptionParam, OPTIONALIN PMINIDUMP_USER_STREAM_INFORMATIONUserStreamParam, OPTIONALIN PMINIDUMP_CALLBACK_INFORMATIONCallbackParam OPTIONAL);#endif //#ifndef _DBGHELP_// Tool Help functions.typedefHANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);typedefBOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);typedefBOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);extern void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag);extern HMODULEhDbgHelp;extern MINIDUMP_WRITE_DUMPMiniDumpWriteDump_;extern CREATE_TOOL_HELP32_SNAPSHOTCreateToolhelp32Snapshot_;extern MODULE32_FIRSTModule32First_;extern MODULE32_NESTModule32Next_;

Minidump. cpp

/*Author:Vladimir Sedach.Purpose: demo of Call Stack creation by our own means,and with MiniDumpWriteDump() function of DbgHelp.dll.*/#include "StdAfx.h"#include "MiniDump.h"#include <Shlwapi.h>#pragma comment(lib,"shlwapi.lib")HMODULEhDbgHelp;MINIDUMP_WRITE_DUMPMiniDumpWriteDump_;CREATE_TOOL_HELP32_SNAPSHOTCreateToolhelp32Snapshot_;MODULE32_FIRSTModule32First_;MODULE32_NESTModule32Next_;#defineDUMP_SIZE_MAX8000//max size of our dump#defineCALL_TRACE_MAX((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40))//max number of traced calls#defineNL"\r\n"//new lineextern CString GetExePath();//****************************************************************************************BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, PCHAR Module_Name, PBYTE & Module_Addr)//****************************************************************************************// Find module by Ret_Addr (address in the module).// Return Module_Name (full path) and Module_Addr (start address).// Return TRUE if found.{MODULEENTRY32M = {sizeof(M)};HANDLEhSnapshot;Module_Name[0] = 0;if (CreateToolhelp32Snapshot_){hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0);if ((hSnapshot != INVALID_HANDLE_VALUE) &&Module32First_(hSnapshot, &M)){do{if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize){lstrcpyn(Module_Name, M.szExePath, MAX_PATH);Module_Addr = M.modBaseAddr;break;}} while (Module32Next_(hSnapshot, &M));}CloseHandle(hSnapshot);}return !!Module_Name[0];} //Get_Module_By_Ret_Addr//******************************************************************int WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, PCHAR Str)//******************************************************************// Fill Str with call stack info.// pException can be either GetExceptionInformation() or NULL.// If pException = NULL - get current call stack.{CHARModule_Name[MAX_PATH];PBYTEModule_Addr = 0;PBYTEModule_Addr_1;intStr_Len;typedef struct STACK{STACK *Ebp;PBYTERet_Addr;DWORDParam[0];} STACK, * PSTACK;STACKStack = {0, 0};PSTACKEbp;if (pException)//fake frame for exception address{Stack.Ebp = (PSTACK)pException->ContextRecord->Ebp;Stack.Ret_Addr = (PBYTE)pException->ExceptionRecord->ExceptionAddress;Ebp = &Stack;}else{Ebp = (PSTACK)&pException - 1;//frame addr of Get_Call_Stack()// Skip frame of Get_Call_Stack().if (!IsBadReadPtr(Ebp, sizeof(PSTACK)))Ebp = Ebp->Ebp;//caller ebp}Str[0] = 0;Str_Len = 0;// Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX.// Break trace on wrong stack frame.for (int Ret_Addr_I = 0;(Ret_Addr_I < CALL_TRACE_MAX) && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr));Ret_Addr_I++, Ebp = Ebp->Ebp){// If module with Ebp->Ret_Addr found.if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr_1)){if (Module_Addr_1 != Module_Addr)//new module{// Save module's address and full path.Module_Addr = Module_Addr_1;Str_Len += wsprintf(Str + Str_Len, NL "%08X  %s", Module_Addr, Module_Name);}// Save call offset.Str_Len += wsprintf(Str + Str_Len,NL "  +%08X", Ebp->Ret_Addr - Module_Addr);// Save 5 params of the call. We don't know the real number of params.if (pException && !Ret_Addr_I)//fake frame for exception addressStr_Len += wsprintf(Str + Str_Len, "  Exception Offset");else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))){Str_Len += wsprintf(Str + Str_Len, "  (%X, %X, %X, %X, %X)",Ebp->Param[0], Ebp->Param[1], Ebp->Param[2], Ebp->Param[3], Ebp->Param[4]);}}elseStr_Len += wsprintf(Str + Str_Len, NL "%08X", Ebp->Ret_Addr);}return Str_Len;} //Get_Call_Stack//***********************************int WINAPI Get_Version_Str(PCHAR Str)//***********************************// Fill Str with Windows version.{OSVERSIONINFOEXV = {sizeof(OSVERSIONINFOEX)};//EX for NT 5.0 and laterif (!GetVersionEx((POSVERSIONINFO)&V)){ZeroMemory(&V, sizeof(V));V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);GetVersionEx((POSVERSIONINFO)&V);}if (V.dwPlatformId != VER_PLATFORM_WIN32_NT)V.dwBuildNumber = LOWORD(V.dwBuildNumber);//for 9x HIWORD(dwBuildNumber) = 0x04xxreturn wsprintf(Str,NL "Windows:  %d.%d.%d, SP %d.%d, Product Type %d",//SP - service pack, Product Type - VER_NT_WORKSTATION,...V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor/*, V.wProductType*/);} //Get_Version_Str//*************************************************************PCHAR WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException)//*************************************************************// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str.{PCHARStr;intStr_Len;inti;CHARModule_Name[MAX_PATH];PBYTEModule_Addr;HANDLEhFile;FILETIMELast_Write_Time;FILETIMELocal_File_Time;SYSTEMTIMET;Str = new CHAR[DUMP_SIZE_MAX];if (!Str)return NULL;Str_Len = 0;Str_Len += Get_Version_Str(Str + Str_Len);Str_Len += wsprintf(Str + Str_Len, NL "Process:  ");GetModuleFileName(NULL, Str + Str_Len, MAX_PATH);Str_Len = lstrlen(Str);// If exception occurred.if (pException){EXCEPTION_RECORD &E = *pException->ExceptionRecord;CONTEXT &C = *pException->ContextRecord;// If module with E.ExceptionAddress found - save its path and date.if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)){Str_Len += wsprintf(Str + Str_Len,NL "Module:  %s", Module_Name);if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE){if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)){FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time);FileTimeToSystemTime(&Local_File_Time, &T);Str_Len += wsprintf(Str + Str_Len,NL "Date Modified:  %02d/%02d/%d",T.wMonth, T.wDay, T.wYear);}CloseHandle(hFile);}}else{Str_Len += wsprintf(Str + Str_Len,NL "Exception Addr:  %08X", E.ExceptionAddress);}Str_Len += wsprintf(Str + Str_Len,NL "Exception Code:  %08X", E.ExceptionCode);if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION){// Access violation type - Write/Read.Str_Len += wsprintf(Str + Str_Len,NL "%s Address:  %08X",(E.ExceptionInformation[0]) ? "Write" : "Read", E.ExceptionInformation[1]);}// Save instruction that caused exception.Str_Len += wsprintf(Str + Str_Len, NL "Instruction: ");for (i = 0; i < 16; i++)Str_Len += wsprintf(Str + Str_Len, " %02X", PBYTE(E.ExceptionAddress)[i]);// Save registers at exception.Str_Len += wsprintf(Str + Str_Len, NL "Registers:");Str_Len += wsprintf(Str + Str_Len, NL "EAX: %08X  EBX: %08X  ECX: %08X  EDX: %08X", C.Eax, C.Ebx, C.Ecx, C.Edx);Str_Len += wsprintf(Str + Str_Len, NL "ESI: %08X  EDI: %08X  ESP: %08X  EBP: %08X", C.Esi, C.Edi, C.Esp, C.Ebp);Str_Len += wsprintf(Str + Str_Len, NL "EIP: %08X  EFlags: %08X", C.Eip, C.EFlags);} //if (pException)// Save call stack info.Str_Len += wsprintf(Str + Str_Len, NL "Call Stack:");Get_Call_Stack(pException, Str + Str_Len);if (Str[0] == NL[0])lstrcpy(Str, Str + sizeof(NL) - 1);return Str;} //Get_Exception_Info//*************************************************************************************void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag)//*************************************************************************************// Create dump. // pException can be either GetExceptionInformation() or NULL.// If File_Flag = TRUE - write dump files (.dmz and .dmp) with the name of the current process.// If Show_Flag = TRUE - show message with Get_Exception_Info() dump.{HANDLEhDump_File;PCHARStr;DWORDBytes;DWORDnLen = 0;CString strDir,strTXTFile,strDMPFile;CString strDate,strTotal;CTimetm = CTime::GetCurrentTime();strDir.Format(_T("%s\\Log"),GetExePath());strTXTFile.Format(_T("%s\\Log\\%04d-%02d-%02d %02d%02d%02d.txt"),GetExePath(),tm.GetYear(),tm.GetMonth(),tm.GetDay(),tm.GetHour(),tm.GetMinute(),tm.GetSecond());strDMPFile.Format(_T("%s\\Log\\%04d-%02d-%02d %02d%02d%02d.dmp"),GetExePath(),tm.GetYear(),tm.GetMonth(),tm.GetDay(),tm.GetHour(),tm.GetMinute(),tm.GetSecond());if(!PathFileExists(strDir))CreateDirectory(strDir,NULL);Str = Get_Exception_Info(pException);//if (Show_Flag && Str)//MessageBox(NULL, Str, "MiniDump", MB_ICONHAND | MB_OK);if (File_Flag){if (Str){hDump_File = CreateFile(strTXTFile,GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);nLen = lstrlen(Str);Str[nLen] = '\0';WriteFile(hDump_File, Str, lstrlen(Str) + 1, &Bytes, NULL);CloseHandle(hDump_File);}// If MiniDumpWriteDump() of DbgHelp.dll available.if (MiniDumpWriteDump_){MINIDUMP_EXCEPTION_INFORMATIONM;M.ThreadId = GetCurrentThreadId();M.ExceptionPointers = pException;M.ClientPointers = 0;hDump_File = CreateFile(strDMPFile,GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);MiniDumpWriteDump_(GetCurrentProcess(), GetCurrentProcessId(), hDump_File,MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL);CloseHandle(hDump_File);}} //if (File_Flag)delete Str;} //Create_Dump

The specific reference method is as follows:

1. Add the following section to cxxdlg: oninitdialog:

SetUnhandledExceptionFilter(CrashReportEx);HMODULEhKernel32;// Try to get MiniDumpWriteDump() address.hDbgHelp = LoadLibrary("DBGHELP.DLL");MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");//d("hDbgHelp=%X, MiniDumpWriteDump_=%X", hDbgHelp, MiniDumpWriteDump_);// Try to get Tool Help library functions.hKernel32 = GetModuleHandle("KERNEL32");CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot");Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32First");Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32Next");

Test Project:

Http://download.csdn.net/source/3575167

For more information, go to the VC station: Use windbg to find the code line number of the program crash

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.