1 /*************************************************************
2 Copyright (c) 2010
3
4 Benjamin Thaut. All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification, are permitted
7 provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
13 and the following disclaimer in the documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
18 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
20 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
21 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23 web: http://3d.benjamin-thaut.de
24 *************************************************************/
25 module dbghelp;
26
27 version (Windows){
28
29 import std.c.windows.windows;
30 import core.runtime;
31
32 class Dbghelp {
33 public:
34 typedef char TCHAR;
35 typedef ulong DWORD64;
36 typedef char* CTSTR;
37 typedef char* PTSTR;
38 typedef const(char)* PCSTR;
39
40 enum ADDRESS_MODE : DWORD {
41 AddrMode1616 = 0,
42 AddrMode1632 = 1,
43 AddrModeReal = 2,
44 AddrModeFlat = 3
45 };
46
47 enum : DWORD {
48 SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200,
49 SYMOPT_LOAD_LINES = 0x00000010
50 };
51
52 struct GUID {
53 uint Data1;
54 ushort Data2;
55 ushort Data3;
56 ubyte[8] Data4;
57 };
58
59 struct ADDRESS64 {
60 DWORD64 Offset;
61 WORD Segment;
62 ADDRESS_MODE Mode;
63 };
64
65 struct KDHELP64 {
66 DWORD64 Thread;
67 DWORD ThCallbackStack;
68 DWORD ThCallbackBStore;
69 DWORD NextCallback;
70 DWORD FramePointer;
71 DWORD64 KiCallUserMode;
72 DWORD64 KeUserCallbackDispatcher;
73 DWORD64 SystemRangeStart;
74 DWORD64 KiUserExceptionDispatcher;
75 DWORD64[7] Reserved;
76 };
77
78 struct STACKFRAME64 {
79 ADDRESS64 AddrPC;
80 ADDRESS64 AddrReturn;
81 ADDRESS64 AddrFrame;
82 ADDRESS64 AddrStack;
83 ADDRESS64 AddrBStore;
84 PVOID FuncTableEntry;
85 DWORD64[4] Params;
86 BOOL Far;
87 BOOL Virtual;
88 DWORD64[3] Reserved;
89 KDHELP64 KdHelp;
90 };
91
92 enum : DWORD {
93 IMAGE_FILE_MACHINE_I386 = 0x014c,
94 IMGAE_FILE_MACHINE_IA64 = 0x0200,
95 IMAGE_FILE_MACHINE_AMD64 = 0x8664
96 };
97
98 struct IMAGEHLP_LINE64 {
99 DWORD SizeOfStruct;
100 PVOID Key;
101 DWORD LineNumber;
102 PTSTR FileName;
103 DWORD64 Address;
104 };
105
106 enum SYM_TYPE : int {
107 SymNone = 0,
108 SymCoff,
109 SymCv,
110 SymPdb,
111 SymExport,
112 SymDeferred,
113 SymSym,
114 SymDia,
115 SymVirtual,
116 NumSymTypes
117 };
118
119 struct IMAGEHLP_MODULE64 {
120 DWORD SizeOfStruct;
121 DWORD64 BaseOfImage;
122 DWORD ImageSize;
123 DWORD TimeDateStamp;
124 DWORD CheckSum;
125 DWORD NumSyms;
126 SYM_TYPE SymType;
127 TCHAR[32] ModuleName;
128 TCHAR[256] ImageName;
129 TCHAR[256] LoadedImageName;
130 TCHAR[256] LoadedPdbName;
131 DWORD CVSig;
132 TCHAR[MAX_PATH*3] CVData;
133 DWORD PdbSig;
134 GUID PdbSig70;
135 DWORD PdbAge;
136 BOOL PdbUnmatched;
137 BOOL DbgUnmachted;
138 BOOL LineNumbers;
139 BOOL GlobalSymbols;
140 BOOL TypeInfo;
141 BOOL SourceIndexed;
142 BOOL Publics;
143 };
144
145 struct IMAGEHLP_SYMBOL64 {
146 DWORD SizeOfStruct;
147 DWORD64 Address;
148 DWORD Size;
149 DWORD Flags;
150 DWORD MaxNameLength;
151 TCHAR[1] Name;
152 };
153
154 extern(System){
155 typedef BOOL function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64;
156 typedef PVOID function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64;
157 typedef DWORD64 function(HANDLE hProcess, DWORD64 Address) GetModuleBaseProc64;
158 typedef DWORD64 function(HANDLE hProcess, HANDLE hThread, ADDRESS64 *lpaddr) TranslateAddressProc64;
159
160 typedef BOOL function(HANDLE hProcess, PCSTR UserSearchPath, bool fInvadeProcess) SymInitializeFunc;
161 typedef BOOL function(HANDLE hProcess) SymCleanupFunc;
162 typedef DWORD function(DWORD SymOptions) SymSetOptionsFunc;
163 typedef DWORD function() SymGetOptionsFunc;
164 typedef PVOID function(HANDLE hProcess, DWORD64 AddrBase) SymFunctionTableAccess64Func;
165 typedef BOOL function(DWORD MachineType, HANDLE hProcess, HANDLE hThread, STACKFRAME64 *StackFrame, PVOID ContextRecord,
166 ReadProcessMemoryProc64 ReadMemoryRoutine, FunctionTableAccessProc64 FunctoinTableAccess,
167 GetModuleBaseProc64 GetModuleBaseRoutine, TranslateAddressProc64 TranslateAddress) StackWalk64Func;
168 typedef BOOL function(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, IMAGEHLP_LINE64 *line) SymGetLineFromAddr64Func;
169 typedef DWORD64 function(HANDLE hProcess, DWORD64 dwAddr) SymGetModuleBase64Func;
170 typedef BOOL function(HANDLE hProcess, DWORD64 dwAddr, IMAGEHLP_MODULE64 *ModuleInfo) SymGetModuleInfo64Func;
171 typedef BOOL function(HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, IMAGEHLP_SYMBOL64 *Symbol) SymGetSymFromAddr64Func;
172 typedef DWORD function(CTSTR *DecoratedName, PTSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags) UnDecorateSymbolNameFunc;
173 typedef DWORD64 function(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) SymLoadModule64Func;
174 typedef BOOL function(HANDLE HProcess, PTSTR SearchPath, DWORD SearchPathLength) SymGetSearchPathFunc;
175 typedef BOOL function(HANDLE hProcess, DWORD64 Address) SymUnloadModule64Func;
176 }
177
178 private static bool isInit = false;
179 private static HANDLE dbghelp_lib = cast(HANDLE)null;
180 static SymInitializeFunc SymInitialize;
181 static SymCleanupFunc SymCleanup;
182 static StackWalk64Func StackWalk64;
183 static SymGetOptionsFunc SymGetOptions;
184 static SymSetOptionsFunc SymSetOptions;
185 static SymFunctionTableAccess64Func SymFunctionTableAccess64;
186 static SymGetLineFromAddr64Func SymGetLineFromAddr64;
187 static SymGetModuleBase64Func SymGetModuleBase64;
188 static SymGetModuleInfo64Func SymGetModuleInfo64;
189 static SymGetSymFromAddr64Func SymGetSymFromAddr64;
190 static UnDecorateSymbolNameFunc UnDecorateSymbolName;
191 static SymLoadModule64Func SymLoadModule64;
192 static SymGetSearchPathFunc SymGetSearchPath;
193 static SymUnloadModule64Func SymUnloadModule64;
194
195 static bool Init(){
196 if(isInit)
197 return true;
198
199 dbghelp_lib = cast(HANDLE)Runtime.loadLibrary("dbghelp.dll");
200 if(dbghelp_lib == null)
201 return false;
202
203 SymInitialize = cast(SymInitializeFunc) GetProcAddress(dbghelp_lib,"SymInitialize");
204 SymCleanup = cast(SymCleanupFunc) GetProcAddress(dbghelp_lib,"SymCleanup");
205 StackWalk64 = cast(StackWalk64Func) GetProcAddress(dbghelp_lib,"StackWalk64");
206 SymGetOptions = cast(SymGetOptionsFunc) GetProcAddress(dbghelp_lib,"SymGetOptions");
207 SymSetOptions = cast(SymSetOptionsFunc) GetProcAddress(dbghelp_lib,"SymSetOptions");
208 SymFunctionTableAccess64 = cast(SymFunctionTableAccess64Func) GetProcAddress(dbghelp_lib,"SymFunctionTableAccess64");
209 SymGetLineFromAddr64 = cast(SymGetLineFromAddr64Func) GetProcAddress(dbghelp_lib,"SymGetLineFromAddr64");
210 SymGetModuleBase64 = cast(SymGetModuleBase64Func) GetProcAddress(dbghelp_lib,"SymGetModuleBase64");
211 SymGetModuleInfo64 = cast(SymGetModuleInfo64Func) GetProcAddress(dbghelp_lib,"SymGetModuleInfo64");
212 SymGetSymFromAddr64 = cast(SymGetSymFromAddr64Func) GetProcAddress(dbghelp_lib,"SymGetSymFromAddr64");
213 SymLoadModule64 = cast(SymLoadModule64Func) GetProcAddress(dbghelp_lib,"SymLoadModule64");
214 SymGetSearchPath = cast(SymGetSearchPathFunc) GetProcAddress(dbghelp_lib,"SymGetSearchPath");
215 SymUnloadModule64 = cast(SymUnloadModule64Func) GetProcAddress(dbghelp_lib,"SymUnloadModule64");
216
217 if(!SymInitialize || !SymCleanup || !StackWalk64 || !SymGetOptions || !SymSetOptions || !SymFunctionTableAccess64
218 || !SymGetLineFromAddr64 || !SymGetModuleBase64 || !SymGetModuleInfo64 || !SymGetSymFromAddr64
219 || !SymLoadModule64 || !SymGetSearchPath || !SymUnloadModule64){
220 return false;
221 }
222
223 isInit = true;
224 return true;
225
226 }
227
228 void DeInit(){
229 if(isInit){
230 Runtime.unloadLibrary(dbghelp_lib);
231 isInit = false;
232 }
233 }
234 };
235
236 }