423f308350 2010-11-07 kinaba: /************************************************************* 423f308350 2010-11-07 kinaba: Copyright (c) 2010 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Benjamin Thaut. All rights reserved. 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Redistribution and use in source and binary forms, with or without modification, are permitted 423f308350 2010-11-07 kinaba: provided that the following conditions are met: 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: 1. Redistributions of source code must retain the above copyright notice, this list of conditions 423f308350 2010-11-07 kinaba: and the following disclaimer. 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 423f308350 2010-11-07 kinaba: and the following disclaimer in the documentation and/or other materials provided with the distribution. 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 423f308350 2010-11-07 kinaba: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 423f308350 2010-11-07 kinaba: IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 423f308350 2010-11-07 kinaba: OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 423f308350 2010-11-07 kinaba: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 423f308350 2010-11-07 kinaba: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 423f308350 2010-11-07 kinaba: EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: web: http://3d.benjamin-thaut.de 423f308350 2010-11-07 kinaba: *************************************************************/ 423f308350 2010-11-07 kinaba: module stacktrace; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: import std.c.windows.windows; 423f308350 2010-11-07 kinaba: import std.c.string; 423f308350 2010-11-07 kinaba: import std.string; 423f308350 2010-11-07 kinaba: import dbghelp; 423f308350 2010-11-07 kinaba: import core.runtime; 423f308350 2010-11-07 kinaba: import std.stdio; 423f308350 2010-11-07 kinaba: import std.c.stdlib; 423f308350 2010-11-07 kinaba: import std.demangle; 423f308350 2010-11-07 kinaba: import std.conv; 5afe8e3f26 2010-11-13 kinaba: import std.path; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: extern(Windows){ 423f308350 2010-11-07 kinaba: DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWORD nSize); 423f308350 2010-11-07 kinaba: void RtlCaptureContext(CONTEXT* ContextRecord); 423f308350 2010-11-07 kinaba: typedef LONG function(void*) UnhandeledExceptionFilterFunc; 423f308350 2010-11-07 kinaba: void* SetUnhandledExceptionFilter(void* handler); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: class StackTrace { 423f308350 2010-11-07 kinaba: private: 423f308350 2010-11-07 kinaba: enum : uint { 423f308350 2010-11-07 kinaba: MAX_MODULE_NAME32 = 255, 423f308350 2010-11-07 kinaba: TH32CS_SNAPMODULE = 0x00000008, 423f308350 2010-11-07 kinaba: MAX_NAMELEN = 1024 423f308350 2010-11-07 kinaba: }; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: struct MODULEENTRY32 { 423f308350 2010-11-07 kinaba: DWORD dwSize; 423f308350 2010-11-07 kinaba: DWORD th32ModuleID; 423f308350 2010-11-07 kinaba: DWORD th32ProcessID; 423f308350 2010-11-07 kinaba: DWORD GlblcntUsage; 423f308350 2010-11-07 kinaba: DWORD ProccntUsage; 423f308350 2010-11-07 kinaba: BYTE* modBaseAddr; 423f308350 2010-11-07 kinaba: DWORD modBaseSize; 423f308350 2010-11-07 kinaba: HMODULE hModule; 423f308350 2010-11-07 kinaba: CHAR[MAX_MODULE_NAME32 + 1] szModule; 423f308350 2010-11-07 kinaba: CHAR[MAX_PATH] szExePath; 423f308350 2010-11-07 kinaba: }; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: string m_UserSymPath; 423f308350 2010-11-07 kinaba: static bool isInit = false; 423f308350 2010-11-07 kinaba: static bool modulesLoaded = false; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: extern(System){ 423f308350 2010-11-07 kinaba: typedef HANDLE function(DWORD dwFlags, DWORD th32ProcessID) CreateToolhelp32SnapshotFunc; 423f308350 2010-11-07 kinaba: typedef BOOL function(HANDLE hSnapshot, MODULEENTRY32 *lpme) Module32FirstFunc; 423f308350 2010-11-07 kinaba: typedef BOOL function(HANDLE hSnapshot, MODULEENTRY32 *lpme) Module32NextFunc; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: extern(Windows) static LONG UnhandeledExceptionFilterHandler(void* info){ 423f308350 2010-11-07 kinaba: printStackTrace(); 423f308350 2010-11-07 kinaba: return 0; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: static void printStackTrace(){ 423f308350 2010-11-07 kinaba: auto stack = TraceHandler(null); 423f308350 2010-11-07 kinaba: foreach(char[] s;stack){ 423f308350 2010-11-07 kinaba: writefln("%s",s); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: bool LoadModules(HANDLE hProcess, DWORD pid){ 423f308350 2010-11-07 kinaba: if(modulesLoaded) 423f308350 2010-11-07 kinaba: return true; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: CreateToolhelp32SnapshotFunc CreateToolhelp32Snapshot = null; 423f308350 2010-11-07 kinaba: Module32FirstFunc Module32First = null; 423f308350 2010-11-07 kinaba: Module32NextFunc Module32Next = null; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: HMODULE hDll = null; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: string[] searchDlls = [ "kernel32.dll", "tlhelp32.dll" ]; 423f308350 2010-11-07 kinaba: foreach(dll;searchDlls){ 423f308350 2010-11-07 kinaba: hDll = cast(HMODULE)Runtime.loadLibrary(dll); 423f308350 2010-11-07 kinaba: if(hDll == null) 423f308350 2010-11-07 kinaba: break; 423f308350 2010-11-07 kinaba: CreateToolhelp32Snapshot = cast(CreateToolhelp32SnapshotFunc) GetProcAddress(hDll,"CreateToolhelp32Snapshot"); 423f308350 2010-11-07 kinaba: Module32First = cast(Module32FirstFunc) GetProcAddress(hDll,"Module32First"); 423f308350 2010-11-07 kinaba: Module32Next = cast(Module32NextFunc) GetProcAddress(hDll,"Module32Next"); 423f308350 2010-11-07 kinaba: if(CreateToolhelp32Snapshot != null && Module32First != null && Module32Next != null) 423f308350 2010-11-07 kinaba: break; 423f308350 2010-11-07 kinaba: Runtime.unloadLibrary(hDll); 423f308350 2010-11-07 kinaba: hDll = null; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: if(hDll == null){ 423f308350 2010-11-07 kinaba: return false; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); 423f308350 2010-11-07 kinaba: if(hSnap == cast(HANDLE) -1) 423f308350 2010-11-07 kinaba: return false; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: MODULEENTRY32 ModuleEntry; 423f308350 2010-11-07 kinaba: memset(&ModuleEntry,0,MODULEENTRY32.sizeof); 423f308350 2010-11-07 kinaba: ModuleEntry.dwSize = MODULEENTRY32.sizeof; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: bool more = cast(bool)Module32First(hSnap,&ModuleEntry); 423f308350 2010-11-07 kinaba: int count = 0; 423f308350 2010-11-07 kinaba: while(more){ 423f308350 2010-11-07 kinaba: LoadModule(hProcess, ModuleEntry.szExePath.ptr, ModuleEntry.szModule.ptr, cast(Dbghelp.DWORD64)ModuleEntry.modBaseAddr, ModuleEntry.modBaseSize); 423f308350 2010-11-07 kinaba: count++; 423f308350 2010-11-07 kinaba: more = cast(bool)Module32Next(hSnap,&ModuleEntry); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: CloseHandle(hSnap); 423f308350 2010-11-07 kinaba: Runtime.unloadLibrary(hDll); 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: if(count <= 0) 423f308350 2010-11-07 kinaba: return false; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: modulesLoaded = true; 423f308350 2010-11-07 kinaba: return true; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: void LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, Dbghelp.DWORD64 baseAddr, DWORD size){ 423f308350 2010-11-07 kinaba: char[] szImg = new char[strlen(img)]; 423f308350 2010-11-07 kinaba: char[] szMod = new char[strlen(mod)]; 423f308350 2010-11-07 kinaba: szImg[0..szImg.length] = img[0..(strlen(img))]; 423f308350 2010-11-07 kinaba: szMod[0..szMod.length] = mod[0..(strlen(mod))]; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Dbghelp.DWORD64 moduleAddr = Dbghelp.SymLoadModule64(hProcess,HANDLE.init,cast(Dbghelp.PCSTR)toStringz(szImg),cast(Dbghelp.PCSTR)toStringz(szMod),baseAddr,size); 423f308350 2010-11-07 kinaba: if(moduleAddr == 0) 423f308350 2010-11-07 kinaba: return; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Dbghelp.IMAGEHLP_MODULE64 ModuleInfo; 423f308350 2010-11-07 kinaba: memset(&ModuleInfo,0,typeof(ModuleInfo).sizeof); 423f308350 2010-11-07 kinaba: ModuleInfo.SizeOfStruct = typeof(ModuleInfo).sizeof; 423f308350 2010-11-07 kinaba: if(Dbghelp.SymGetModuleInfo64(hProcess,moduleAddr,&ModuleInfo) == TRUE){ 423f308350 2010-11-07 kinaba: if(ModuleInfo.SymType == Dbghelp.SYM_TYPE.SymNone){ 423f308350 2010-11-07 kinaba: Dbghelp.SymUnloadModule64(hProcess,moduleAddr); 423f308350 2010-11-07 kinaba: moduleAddr = Dbghelp.SymLoadModule64(hProcess,HANDLE.init,cast(Dbghelp.PCSTR)toStringz(szImg),null,cast(Dbghelp.DWORD64)0,0); 423f308350 2010-11-07 kinaba: if(moduleAddr == 0) 423f308350 2010-11-07 kinaba: return; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: //writefln("Successfully loaded module %s",szImg); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: string GenereateSearchPath(){ 423f308350 2010-11-07 kinaba: string path; 423f308350 2010-11-07 kinaba: if(m_UserSymPath.length){ 423f308350 2010-11-07 kinaba: path = m_UserSymPath ~ ";"; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: char[1024] temp; 423f308350 2010-11-07 kinaba: if(GetCurrentDirectoryA(temp.length,temp.ptr) > 0){ 423f308350 2010-11-07 kinaba: temp[temp.length-1] = 0; 423f308350 2010-11-07 kinaba: path ~= temp ~ ";"; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: if(GetModuleFileNameA(null,temp.ptr,temp.length) > 0){ 423f308350 2010-11-07 kinaba: temp[temp.length-1] = 0; 423f308350 2010-11-07 kinaba: foreach_reverse(ref char e;temp){ 423f308350 2010-11-07 kinaba: if(e == '\\' || e == '/' || e == ':'){ 423f308350 2010-11-07 kinaba: e = 0; 423f308350 2010-11-07 kinaba: break; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: if(strlen(temp.ptr) > 0){ 423f308350 2010-11-07 kinaba: path ~= temp ~ ";"; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: string[] systemVars = [ "_NT_SYMBOL_PATH", "_NT_ALTERNATE_SYMBOL_PATH", "SYSTEMROOT" ]; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: foreach(e;systemVars){ 423f308350 2010-11-07 kinaba: if(GetEnvironmentVariableA(toStringz(e),temp.ptr,temp.length) > 0){ 423f308350 2010-11-07 kinaba: temp[temp.length-1] = 0; 423f308350 2010-11-07 kinaba: path ~= temp ~ ";"; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: return path; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: static class Callstack : Throwable.TraceInfo { 423f308350 2010-11-07 kinaba: private: 423f308350 2010-11-07 kinaba: string[] info = null; 423f308350 2010-11-07 kinaba: public: 423f308350 2010-11-07 kinaba: int opApply(scope int delegate(ref char[]) dg){ 423f308350 2010-11-07 kinaba: int result = 0; 423f308350 2010-11-07 kinaba: foreach(e;info){ 423f308350 2010-11-07 kinaba: char[] temp = to!(char[])(e); 423f308350 2010-11-07 kinaba: result = dg(temp); 423f308350 2010-11-07 kinaba: if(result) 423f308350 2010-11-07 kinaba: break; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: return result; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: override string toString(){ 423f308350 2010-11-07 kinaba: string result = ""; 423f308350 2010-11-07 kinaba: foreach(e;info){ 423f308350 2010-11-07 kinaba: result ~= e ~ "\n"; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: return result; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: void append(string str){ 423f308350 2010-11-07 kinaba: if(info is null){ 423f308350 2010-11-07 kinaba: info = new string[1]; 423f308350 2010-11-07 kinaba: info[0] = str; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: else { 423f308350 2010-11-07 kinaba: info.length = info.length + 1; 423f308350 2010-11-07 kinaba: info[info.length-1] = str; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: static Throwable.TraceInfo TraceHandler(void* ptr){ 0569f7b8c2 2010-11-07 kinaba: // modified by k.inaba to avoid a throw inside std.demangle.demangle 0569f7b8c2 2010-11-07 kinaba: // not quite thread safe 0569f7b8c2 2010-11-07 kinaba: Runtime.traceHandler(&core.runtime.defaultTraceHandler); 0569f7b8c2 2010-11-07 kinaba: scope(exit) Runtime.traceHandler(&TraceHandler); 0569f7b8c2 2010-11-07 kinaba: 0569f7b8c2 2010-11-07 kinaba: StackTrace trace = new StackTrace(); 0569f7b8c2 2010-11-07 kinaba: return trace.GetCallstack(); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: public: 423f308350 2010-11-07 kinaba: static this(){ 423f308350 2010-11-07 kinaba: Runtime.traceHandler(&TraceHandler); 423f308350 2010-11-07 kinaba: SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: this(){ 423f308350 2010-11-07 kinaba: if(isInit) 423f308350 2010-11-07 kinaba: return; 423f308350 2010-11-07 kinaba: HANDLE hProcess = GetCurrentProcess(); 423f308350 2010-11-07 kinaba: DWORD pid = GetCurrentProcessId(); 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Dbghelp.Init(); 423f308350 2010-11-07 kinaba: string symPath = GenereateSearchPath(); 423f308350 2010-11-07 kinaba: if(Dbghelp.SymInitialize(hProcess,cast(Dbghelp.PCSTR)toStringz(symPath),FALSE) != FALSE){ 423f308350 2010-11-07 kinaba: isInit = true; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: DWORD symOptions = Dbghelp.SymGetOptions(); 423f308350 2010-11-07 kinaba: symOptions |= Dbghelp.SYMOPT_LOAD_LINES; 423f308350 2010-11-07 kinaba: symOptions |= Dbghelp.SYMOPT_FAIL_CRITICAL_ERRORS; 423f308350 2010-11-07 kinaba: symOptions = Dbghelp.SymSetOptions(symOptions); 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: LoadModules(hProcess,pid); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Throwable.TraceInfo GetCallstack(){ 423f308350 2010-11-07 kinaba: if(!isInit){ 423f308350 2010-11-07 kinaba: writefln("Is not init!"); 423f308350 2010-11-07 kinaba: return null; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: HANDLE hThread = GetCurrentThread(); 423f308350 2010-11-07 kinaba: HANDLE hProcess = GetCurrentProcess(); 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: //Capture the current context 423f308350 2010-11-07 kinaba: CONTEXT c; 423f308350 2010-11-07 kinaba: memset(&c, 0, CONTEXT.sizeof); 423f308350 2010-11-07 kinaba: c.ContextFlags = CONTEXT_FULL; 423f308350 2010-11-07 kinaba: RtlCaptureContext(&c); 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Dbghelp.STACKFRAME64 stackframe; 423f308350 2010-11-07 kinaba: memset(&stackframe,0,typeof(stackframe).sizeof); 423f308350 2010-11-07 kinaba: DWORD imageType; 423f308350 2010-11-07 kinaba: //x86 423f308350 2010-11-07 kinaba: imageType = Dbghelp.IMAGE_FILE_MACHINE_I386; 423f308350 2010-11-07 kinaba: stackframe.AddrPC.Offset = cast(Dbghelp.DWORD64)c.Eip; 423f308350 2010-11-07 kinaba: stackframe.AddrPC.Mode = Dbghelp.ADDRESS_MODE.AddrModeFlat; 423f308350 2010-11-07 kinaba: stackframe.AddrFrame.Offset = cast(Dbghelp.DWORD64)c.Ebp; 423f308350 2010-11-07 kinaba: stackframe.AddrFrame.Mode = Dbghelp.ADDRESS_MODE.AddrModeFlat; 423f308350 2010-11-07 kinaba: stackframe.AddrStack.Offset = cast(Dbghelp.DWORD64)c.Esp; 423f308350 2010-11-07 kinaba: stackframe.AddrStack.Mode = Dbghelp.ADDRESS_MODE.AddrModeFlat; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: size_t SymbolSize = Dbghelp.IMAGEHLP_SYMBOL64.sizeof + MAX_NAMELEN; 423f308350 2010-11-07 kinaba: Dbghelp.IMAGEHLP_SYMBOL64 *Symbol = cast(Dbghelp.IMAGEHLP_SYMBOL64*) malloc(SymbolSize); 423f308350 2010-11-07 kinaba: memset(Symbol,0,SymbolSize); 423f308350 2010-11-07 kinaba: Symbol.SizeOfStruct = SymbolSize; 423f308350 2010-11-07 kinaba: Symbol.MaxNameLength = MAX_NAMELEN; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Dbghelp.IMAGEHLP_LINE64 Line; 423f308350 2010-11-07 kinaba: memset(&Line,0,typeof(Line).sizeof); 423f308350 2010-11-07 kinaba: Line.SizeOfStruct = typeof(Line).sizeof; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: Dbghelp.IMAGEHLP_MODULE64 Module; 423f308350 2010-11-07 kinaba: memset(&Module,0,typeof(Module).sizeof); 423f308350 2010-11-07 kinaba: Module.SizeOfStruct = typeof(Module).sizeof; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: auto stack = new Callstack(); 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: //writefln("Callstack:"); 423f308350 2010-11-07 kinaba: for(int frameNum=0;;frameNum++){ 423f308350 2010-11-07 kinaba: if(Dbghelp.StackWalk64(imageType, hProcess, hThread, 423f308350 2010-11-07 kinaba: &stackframe, &c, 423f308350 2010-11-07 kinaba: null, 423f308350 2010-11-07 kinaba: cast(Dbghelp.FunctionTableAccessProc64)Dbghelp.SymFunctionTableAccess64, 423f308350 2010-11-07 kinaba: cast(Dbghelp.GetModuleBaseProc64)Dbghelp.SymGetModuleBase64, 423f308350 2010-11-07 kinaba: null) != TRUE ) 423f308350 2010-11-07 kinaba: { 423f308350 2010-11-07 kinaba: //writefln("End of Callstack"); 423f308350 2010-11-07 kinaba: break; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: if(stackframe.AddrPC.Offset == stackframe.AddrReturn.Offset){ 423f308350 2010-11-07 kinaba: //writefln("Endless callstack"); 423f308350 2010-11-07 kinaba: stack.append("Endless callstack"); 423f308350 2010-11-07 kinaba: break; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: if(stackframe.AddrPC.Offset != 0){ 423f308350 2010-11-07 kinaba: string lineStr = ""; 423f308350 2010-11-07 kinaba: Dbghelp.DWORD64 offsetFromSymbol = cast(Dbghelp.DWORD64)0; 423f308350 2010-11-07 kinaba: if( Dbghelp.SymGetSymFromAddr64(hProcess,stackframe.AddrPC.Offset,&offsetFromSymbol,Symbol) == TRUE){ 5afe8e3f26 2010-11-13 kinaba: char[] symName = new char[strlen(cast(const(char)*)Symbol.Name.ptr)]; 423f308350 2010-11-07 kinaba: memcpy(symName.ptr,Symbol.Name.ptr,symName.length); 423f308350 2010-11-07 kinaba: string symString = ""; 423f308350 2010-11-07 kinaba: if(symName[0] == 'D') 423f308350 2010-11-07 kinaba: symString = "_"; 423f308350 2010-11-07 kinaba: symString ~= symName; 423f308350 2010-11-07 kinaba: 5afe8e3f26 2010-11-13 kinaba: string demangledName = demangle(symString); 5afe8e3f26 2010-11-13 kinaba: bool isOK = true; 5afe8e3f26 2010-11-13 kinaba: for(int i=0; i<demangledName.length; ++i) 5afe8e3f26 2010-11-13 kinaba: if( demangledName[i] >= 0x80 ) 5afe8e3f26 2010-11-13 kinaba: isOK = false; 5afe8e3f26 2010-11-13 kinaba: if(isOK) 5afe8e3f26 2010-11-13 kinaba: lineStr ~= demangledName; 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: DWORD zeichen = 0; 423f308350 2010-11-07 kinaba: if(Dbghelp.SymGetLineFromAddr64(hProcess,stackframe.AddrPC.Offset,&zeichen,&Line) == TRUE){ 423f308350 2010-11-07 kinaba: char[] fileName = new char[strlen(Line.FileName)]; 5afe8e3f26 2010-11-13 kinaba: fileName = std.path.basename( Line.FileName[0..fileName.length] ); 423f308350 2010-11-07 kinaba: lineStr = to!string(fileName ~ "::" ~ to!string(Line.LineNumber) ~ "(" ~ to!string(zeichen) ~ ") " ~ lineStr); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: else { 423f308350 2010-11-07 kinaba: lineStr = to!string(cast(ulong)stackframe.AddrPC.Offset); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: lineStr = to!string(frameNum-2) ~ " " ~ lineStr; 423f308350 2010-11-07 kinaba: if(frameNum-2 < 10) 423f308350 2010-11-07 kinaba: lineStr = "0" ~ lineStr; 423f308350 2010-11-07 kinaba: if(frameNum >= 2) 423f308350 2010-11-07 kinaba: stack.append(lineStr); 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: 423f308350 2010-11-07 kinaba: free(Symbol); 423f308350 2010-11-07 kinaba: return stack; 423f308350 2010-11-07 kinaba: } 423f308350 2010-11-07 kinaba: }; 0569f7b8c2 2010-11-07 kinaba: