File Annotation
Not logged in
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] );
515502e8d1 2010-11-20        kinaba: 						lineStr = text(fileName ~ "::" ~ text(Line.LineNumber) ~ "(" ~ text(zeichen) ~ ") " ~ lineStr);
423f308350 2010-11-07        kinaba: 					}
423f308350 2010-11-07        kinaba: 				}
423f308350 2010-11-07        kinaba: 				else {
515502e8d1 2010-11-20        kinaba: 					lineStr = text(cast(ulong)stackframe.AddrPC.Offset);
423f308350 2010-11-07        kinaba: 				}
515502e8d1 2010-11-20        kinaba: 				lineStr = text(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: