Created
May 8, 2012 18:40
-
-
Save gabonator/2638372 to your computer and use it in GitHub Desktop.
Windows CE stack dumping
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void DeviceExceptionHandler( void *pep ) | |
{ | |
if ( !_DeviceExceptionHandler((LPEXCEPTION_POINTERS)pep) ) | |
{ | |
MessageBox(NULL, _T("Cannot generate dumpreport!"), _T("Illegal operation report"), MB_OK); | |
} | |
} | |
#include <Tlhelp32.h> | |
#include <vector> | |
using namespace std; | |
struct MyModuleInfo | |
{ | |
BYTE* Base; | |
HMODULE Handle; | |
DWORD Size; | |
enum { MaxNameLen = 36 }; | |
TCHAR Name[MaxNameLen]; | |
}; | |
#define IMPORTBEGIN(dll) \ | |
HINSTANCE hTL = LoadLibrary(_T(dll)); \ | |
if (!hTL) \ | |
{ \ | |
DbgPrint(_T("GetModuleList(): Cannot load library '%s'\n"), _T(#dll)); \ | |
return false; \ | |
} | |
#define IMPORTEND() \ | |
FreeLibrary(hTL); | |
#define IMPORTLIB(r, s, a) \ | |
typedef r (*_##s)a; \ | |
_##s s = (_##s)GetProcAddress(hTL, _T(#s)); \ | |
if (!s) { DbgPrint(_T("GetModuleList(): Cannot load %s\n"), _T(#s)); return false; } | |
bool GetModuleList(vector<MyModuleInfo>& moduleList) | |
{ | |
IMPORTBEGIN("toolhelp.dll") | |
IMPORTLIB(HANDLE, CreateToolhelp32Snapshot, (DWORD dwFlags, DWORD th32ProcessID)) | |
IMPORTLIB(BOOL32, CloseToolhelp32Snapshot, (HANDLE hSnapshot)) | |
IMPORTLIB(BOOL32, Process32Next, (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)) | |
IMPORTLIB(BOOL32, Process32First, (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)) | |
IMPORTLIB(BOOL32, Module32Next, (HANDLE hSnapshot, LPMODULEENTRY32 lpme)) | |
IMPORTLIB(BOOL32, Module32First, (HANDLE hSnapshot, LPMODULEENTRY32 lpme)) | |
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPMODULE | TH32CS_GETALLMODS, 0); | |
if (hSnapshot == INVALID_HANDLE_VALUE) | |
{ | |
DbgPrint(_T("GetModuleList(): hSnapshot = NULL\n")); | |
IMPORTEND(); | |
return false; | |
} | |
MODULEENTRY32 moduleInfo; | |
moduleInfo.dwSize = sizeof(moduleInfo); | |
if (Module32First(hSnapshot, &moduleInfo)) do { | |
MyModuleInfo myInfo; | |
myInfo.Handle = moduleInfo.hModule; | |
myInfo.Base = moduleInfo.modBaseAddr; | |
myInfo.Size = moduleInfo.modBaseSize; | |
memcpy(myInfo.Name, moduleInfo.szModule, min(sizeof(myInfo.Name), sizeof(moduleInfo.szModule))); | |
myInfo.Name[myInfo.MaxNameLen-1] = '\0'; | |
moduleList.push_back(myInfo); | |
} while (Module32Next(hSnapshot, &moduleInfo)); | |
// The module list obtained above only contains DLLs! To get the EXE files | |
// also, we must call Process32First and Process32Next in a loop. | |
PROCESSENTRY32 processInfo; | |
processInfo.dwSize = sizeof(processInfo); | |
if (Process32First(hSnapshot, &processInfo)) do { | |
MyModuleInfo myInfo; | |
myInfo.Handle = NULL; // No handle given | |
myInfo.Base = (BYTE*)processInfo.th32MemoryBase; | |
myInfo.Size = 0x800000; // No size provided! Allow max 8 MB | |
memcpy(myInfo.Name, processInfo.szExeFile, min(sizeof(myInfo.Name), sizeof(processInfo.szExeFile))); | |
myInfo.Name[myInfo.MaxNameLen-1] = '\0'; | |
moduleList.push_back(myInfo); | |
} while(Process32Next(hSnapshot, &processInfo)); | |
// Debug output | |
for (INT i = 0; i < (INT)moduleList.size(); i++) { | |
MyModuleInfo& m = moduleList[i]; | |
DbgPrint(_T("%-30s: 0x%08x - 0x%08x\n"), m.Name, (DWORD)m.Base, (DWORD)m.Base + m.Size); | |
} | |
CloseToolhelp32Snapshot(hSnapshot); | |
IMPORTEND(); | |
return true; | |
} | |
#define STACKSNAP_RETURN_FRAMES_ON_ERROR 8 | |
typedef struct _CallSnapshot { | |
DWORD dwReturnAddr; | |
} CallSnapshot; | |
extern "C" ULONG GetThreadCallStack (HANDLE hThrd, ULONG dwMaxFrames, LPVOID lpFrames, DWORD dwFlags, DWORD dwSkip); | |
bool GetCallStack(vector<MyModuleInfo>& moduleList) | |
{ | |
CallSnapshot frames[100]; | |
HANDLE hThread = GetCurrentThread(); | |
SetLastError(ERROR_SUCCESS); | |
INT funcCount = GetThreadCallStack(hThread, 100, frames, STACKSNAP_RETURN_FRAMES_ON_ERROR, 0); | |
INT nGLE = GetLastError(); | |
if ( nGLE != ERROR_SUCCESS ) | |
{ | |
DbgPrint(_T("GetCallStack(): GetLastError() = %d \n"), nGLE); | |
return false; | |
} | |
for (INT i=0; i<funcCount; i++) | |
{ | |
DWORD dwFrame = frames[i].dwReturnAddr; | |
DbgPrint(_T("Stack frame 0x%08x"), dwFrame); | |
for (INT j = 0; j < (INT)moduleList.size(); j++) | |
{ | |
MyModuleInfo& m = moduleList[j]; | |
if ( (DWORD)m.Base == 0x00010000 ) | |
{ | |
DbgPrint(_T(": %-16s @ 0x%08x"), _T("App"), dwFrame ); | |
break; | |
} | |
if ( dwFrame >= (DWORD)m.Base && dwFrame < (DWORD)(m.Base) + m.Size) | |
{ | |
DbgPrint(_T(": %-16s @ 0x%08x"), m.Name, (dwFrame - (DWORD)m.Base) | 0x10000000 ); | |
break; | |
} | |
} | |
DbgPrint(_T("\n")); | |
} | |
return true; | |
} | |
void Dump() | |
{ | |
vector<MyModuleInfo> moduleList; | |
bool bModuleList = GetModuleList(moduleList); | |
bool bCallStack = GetCallStack(moduleList); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__try | |
{ | |
// code | |
} | |
__except( DeviceExceptionHandler( GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER ) | |
{ | |
// show error message | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// stackdec.cpp : Defines the entry point for the console application. | |
// | |
/* | |
Inspirovane projektom "StackWalker" http://www.codeproject.com/KB/threads/StackWalker.aspx | |
Z naseho crash reportu (napr. 090101-042250-log.txt) vygeneruje vystup v citatelnom tvare, napr: | |
Module 'driver.dll' Loaded. | |
Module 'device.dll' Loaded. | |
Module 'library.dll' Loaded. | |
Module 'corenavi.dll' Loaded. | |
Module 'device.dll' Loaded. | |
Module 'Aura.exe' Loaded. | |
Stack: | |
0x42e1e974> GetCallStack (...ependent\wince\exceptions.cpp: 417) | |
0x42e1ff48> DumpManual (...ependent\wince\exceptions.cpp: 496) | |
0x42e20008> _DeviceExceptionHandler (...ependent\wince\exceptions.cpp: 311) | |
0x42e20094> CLowDevice::DeviceExceptionHandler (...ependent\wince\exceptions.cpp: 14) | |
0x00011bfc> WinMain (...\sources\aura\source\aura.cpp: 250) | |
0x400771bc> Unknown | |
0x400585ac> Unknown | |
0x4005277c> Unknown | |
0x4002a524> Unknown | |
0x4002a814> Unknown | |
0x4005287c> Unknown | |
0x432ebf70> _EasterEgg (...\overlays\ntoverlaylabels.cpp: 28) | |
0x432ec628> CNTOverlayEdit::_OnLabelClick (...\overlays\ntoverlaylabels.cpp: 169) | |
0x432e6390> CNTOverlayEdit::OnLButtonUp (...ui\overlays\ntoverlayedit.cpp: 477) | |
0x430062d8> Library::CWnd::WindowProc (...ibrary\source\wnd\wndproc.cpp: 348) | |
0x432e4954> CNTOverlayEdit::WindowProc (...ui\overlays\ntoverlayedit.cpp: 819) | |
0x43005538> Library::CWnd::SendMessage (...ibrary\source\wnd\wndproc.cpp: 98) | |
0x42f47308> Library::CTopWnd::WindowProc (...rary\source\app\container.cpp: 535) | |
0x43005538> Library::CWnd::SendMessage (...ibrary\source\wnd\wndproc.cpp: 98) | |
0x42f46e4c> Library::CContainer::SysDispatchMessage (...rary\source\app\container.cpp: 784) | |
0x42f4aa6c> CApp::Run (...pp\windows\app\windowsapp.cpp: 1241) | |
0x00011b40> HelperWinMain (...\sources\aura\source\aura.cpp: 221) | |
0x00011bc0> WinMain (...\sources\aura\source\aura.cpp: 248) | |
0x00147414> WinMainCRTStartup (...ibc\crtw32\startup\pegwmain.c: 21) | |
0x4003be54> Unknown | |
*/ | |
#include "stdafx.h" | |
#include <dbghelp.h> | |
#define IMPORTBEGIN(dll) \ | |
HINSTANCE hTL = LoadLibrary(_T(dll)); \ | |
if (!hTL) \ | |
{ \ | |
DbgPrint(_T("Cannot load library '%s'\n"), _T(#dll)); \ | |
return 1; \ | |
} | |
#define IMPORTEND() \ | |
FreeLibrary(hTL); | |
#define IMPORTLIB(r, s, a) \ | |
typedef r (__stdcall *_##s)a; \ | |
_##s s = (_##s)GetProcAddress(hTL, #s); \ | |
if (!s) { DbgPrint(_T("Cannot load %s\n"), _T(#s)); return 1; } | |
#define DbgPrint printf | |
class MAXLEN | |
{ | |
public: | |
CHAR *pStr; | |
MAXLEN( CHAR* pInStr, int nMaxLen ) | |
{ | |
int nLen = pInStr ? (int) strlen( pInStr ) : 0; | |
if ( nLen <= nMaxLen ) | |
{ | |
pStr = _strdup( pInStr ); | |
return; | |
} | |
pStr = new CHAR[nMaxLen+1]; | |
strcpy(pStr, "..."); | |
strcat(pStr, pInStr + nLen - nMaxLen + 3); | |
} | |
~MAXLEN() | |
{ | |
delete pStr; | |
} | |
operator const LPSTR&() const { return pStr; } | |
}; | |
void Trim( CHAR* pszStr ) | |
{ | |
int i = (int)strlen(pszStr)-1; | |
while ( i > 0 && pszStr[i] == ' ' ) | |
pszStr[i--] = 0; | |
} | |
BOOL Exist( CHAR* pszPath ) | |
{ | |
DWORD fileAttr = GetFileAttributesA( pszPath ); | |
if ( fileAttr == (DWORD)-1 ) | |
return FALSE; | |
return TRUE; | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
if ( argc != 2 ) | |
{ | |
DbgPrint(_T("Crash logfile analyser - 2011 Sygic/gv\n")); | |
DbgPrint(_T("\n")); | |
DbgPrint(_T("Specify dumpfile as parameter!\n")); | |
return 1; | |
} | |
IMPORTBEGIN("dbghelp.dll"); | |
IMPORTLIB( BOOL, SymInitialize, ( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess ) ); | |
IMPORTLIB( BOOL, SymCleanup, ( IN HANDLE hProcess ) ); | |
IMPORTLIB( DWORD64, SymLoadModule64, ( IN HANDLE hProcess, IN HANDLE hFile, | |
IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll ) ); | |
IMPORTLIB( BOOL, SymGetSymFromAddr64, ( IN HANDLE hProcess, IN DWORD64 dwAddr, | |
OUT PDWORD64 pdwDisplacement, /*OUT*/ PIMAGEHLP_SYMBOL64 Symbol ) ); | |
IMPORTLIB( BOOL, SymGetLineFromAddr64, ( IN HANDLE hProcess, IN DWORD64 dwAddr, | |
OUT PDWORD pdwDisplacement, /*OUT*/ PIMAGEHLP_LINE64 Line ) ); | |
IMPORTLIB( DWORD64, SymGetModuleBase64, (HANDLE hProcess, __in DWORD64 dwAddr) ); | |
IMPORTLIB( BOOL, SymGetModuleInfo64, ( HANDLE hProcess, DWORD64 dwAddr, PIMAGEHLP_MODULE64 ModuleInfo ) ); | |
HANDLE hProcess = (HANDLE)-1; | |
BOOL bFrame = FALSE; | |
struct SModuleInfo { | |
CHAR strModuleName[128]; | |
DWORD dwBeginAddr; | |
DWORD dwEndAddr; | |
BOOL bLoaded; | |
} arrModules[1024]; | |
int nModules = 0; | |
if ( SymInitialize( hProcess, "", FALSE ) ) | |
{ | |
FILE *f = fopen(argv[1], "r"); | |
if (!f) | |
{ | |
DbgPrint(_T("Cannot open log file!\n")); | |
return 1; | |
} | |
BYTE pSymbolData[sizeof(IMAGEHLP_SYMBOL64) + 1024]; | |
IMAGEHLP_SYMBOL64 *pSym = (IMAGEHLP_SYMBOL64 *)pSymbolData; | |
pSym->SizeOfStruct = sizeof( IMAGEHLP_SYMBOL64 ); | |
pSym->MaxNameLength = 1023; | |
IMAGEHLP_LINE64 Line = {0}; | |
Line.SizeOfStruct = sizeof(Line); | |
while ( !feof(f) ) | |
{ | |
CHAR strLine[1024] = {0}; | |
fgets(strLine, 1024, f); | |
if ( strlen(strLine) == 56 && strLine[30] == ':' && strLine[43] == '-' ) | |
{ | |
DWORD dwBegin, dwEnd; | |
CHAR strModule[128] = {0}; | |
if ( sscanf( strLine, "%30c: 0x%08x - 0x%10x", strModule, &dwBegin, &dwEnd ) == 3 ) | |
{ | |
Trim( strModule ); | |
//dwBegin &= 0x00ffffff; | |
//dwEnd &= 0x00ffffff; | |
strcpy( arrModules[nModules].strModuleName, strModule ); | |
arrModules[nModules].dwBeginAddr = dwBegin; | |
arrModules[nModules].dwEndAddr = dwEnd; | |
arrModules[nModules].bLoaded = FALSE; | |
CHAR strModPath[MAX_PATH]; | |
strcpy( strModPath, strModule ); | |
if ( !Exist( strModPath ) ) | |
{ | |
strcpy( strModPath, "drivers\\default\\" ); | |
strcat( strModPath, strModule ); | |
} | |
if ( !Exist( strModPath ) ) | |
{ | |
strcpy( strModPath, "..\\" ); | |
strcat( strModPath, strModule ); | |
} | |
if ( !Exist( strModPath ) ) | |
{ | |
strcpy( strModPath, "..\\drivers\\default\\" ); | |
strcat( strModPath, strModule ); | |
} | |
if ( !Exist( strModPath ) ) | |
{ | |
nModules++; | |
continue; | |
} | |
if (! SymLoadModule64( hProcess, 0, strModPath, strModule, | |
dwBegin, dwEnd - dwBegin ) ) | |
{ | |
DbgPrint( _T("SymLoadModule64 ('%s') failed!\n"), strModule); | |
} else | |
{ | |
DbgPrint( _T("Module '%s' Loaded. "), strModule); | |
IMAGEHLP_MODULE64 moduleInfo = {0}; | |
moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); | |
if ( SymGetModuleInfo64( hProcess, dwBegin, &moduleInfo ) ) | |
{ | |
if ( moduleInfo.SymType == SymPdb ) | |
DbgPrint( _T("PDB(%s)"), moduleInfo.LoadedPdbName ); | |
if ( moduleInfo.SymType == SymNone ) | |
DbgPrint( _T("NONE") ); | |
if ( moduleInfo.SymType == SymExport ) | |
DbgPrint( _T("EXPORT") ); | |
} | |
DbgPrint( _T("\n") ); | |
arrModules[nModules].bLoaded = TRUE; | |
} | |
} | |
nModules++; | |
} | |
if ( ( strlen(strLine) == 54 || strlen(strLine) == 23 ) && strncmp(strLine, "Stack frame", 11) == 0 ) | |
{ | |
if ( !bFrame ) | |
{ | |
bFrame = TRUE; | |
DbgPrint( _T("\nStack:\n")); | |
} | |
DWORD dwFrame; | |
if ( sscanf( strLine, "Stack frame 0x%08x", &dwFrame ) == 1 ) | |
{ | |
//dwFrame &= 0x00ffffff; | |
DWORD64 dwDisplacement; | |
DbgPrint( _T("0x%08x> "), dwFrame ); | |
BYTE bBank = (BYTE)(dwFrame >> 24); | |
SModuleInfo *pModule = NULL; | |
SModuleInfo *pModuleLoaded = NULL; | |
int nCollisions = 0; | |
for (int i=0; i<nModules; i++) | |
{ | |
if ( dwFrame >= arrModules[i].dwBeginAddr && | |
dwFrame < arrModules[i].dwEndAddr ) | |
{ | |
if ( arrModules[i].bLoaded ) | |
pModuleLoaded = arrModules + i; | |
pModule = arrModules + i; | |
nCollisions++; | |
} | |
} | |
if ( bBank != 0 && !pModuleLoaded) // current app - aura.exe | |
{ | |
for (int i=0; i<nModules; i++) | |
{ | |
if ( dwFrame >= arrModules[i].dwBeginAddr && | |
dwFrame < arrModules[i].dwEndAddr ) | |
{ | |
DbgPrint( _T("[%s]+0x%x "), arrModules[i].strModuleName, dwFrame - arrModules[i].dwBeginAddr ); | |
} | |
} | |
} else | |
{ | |
IMAGEHLP_MODULE64 moduleInfo = {0}; | |
moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); | |
if ( SymGetModuleInfo64( hProcess, dwFrame, &moduleInfo ) ) | |
DbgPrint( _T("[%s]\t "), moduleInfo.ImageName ); | |
if ( !SymGetSymFromAddr64( hProcess, dwFrame, &dwDisplacement, pSym ) ) | |
{ | |
DbgPrint( _T("Unknown")); | |
} else | |
{ | |
DbgPrint( _T("%s"), pSym->Name ); | |
DWORD dwDisplacement; | |
if ( SymGetLineFromAddr64( hProcess, dwFrame, &dwDisplacement, &Line ) ) | |
{ | |
if ( Line.FileName || Line.LineNumber ) | |
{ | |
DbgPrint( _T(" (%s: %d)"), MAXLEN(Line.FileName, 40), Line.LineNumber ); | |
} | |
} | |
} | |
} | |
DbgPrint( _T("\n")); | |
} | |
} | |
} | |
fclose(f); | |
} else | |
{ | |
DbgPrint( _T("SymInitialize failed\n") ); | |
return 1; | |
} | |
SymCleanup( hProcess ); | |
IMPORTEND(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment