added more overlay handler infos
[TortoiseGit.git] / src / crashrpt / SymbolEngine.h
blob155afcc8356d33447b6620bb032aa8d440f75da7
1 /*----------------------------------------------------------------------
2 "Debugging Applications" (Microsoft Press)
3 Copyright (c) 1997-2000 John Robbins -- All rights reserved.
4 ------------------------------------------------------------------------
5 This class is a paper-thin layer around the DBGHELP.DLL symbol engine.
7 This class wraps only those functions that take the unique
8 HANDLE value. Other DBGHELP.DLL symbol engine functions are global in
9 scope, so I didn’t wrap them with this class.
11 ------------------------------------------------------------------------
12 Compilation Defines:
14 DO_NOT_WORK_AROUND_SRCLINE_BUG - If defined, the class will NOT work
15 around the SymGetLineFromAddr bug where
16 PDB file lookups fail after the first
17 lookup.
18 USE_BUGSLAYERUTIL - If defined, the class will have another
19 initialization method, BSUSymInitialize, which will
20 use BSUSymInitialize from BUGSLAYERUTIL.DLL to
21 initialize the symbol engine and allow the invade
22 process flag to work for all Win32 operating systems.
23 If you use this define, you must use
24 BUGSLAYERUTIL.H to include this file.
25 ----------------------------------------------------------------------*/
27 #ifndef _SYMBOLENGINE_H
28 #define _SYMBOLENGINE_H
30 // You could include either IMAGEHLP.DLL or DBGHELP.DLL.
31 #include "imagehlp.h"
32 #include <tchar.h>
34 // Include these in case the user forgets to link against them.
35 #pragma comment (lib,"dbghelp.lib")
36 #pragma comment (lib,"version.lib")
38 // The great Bugslayer idea of creating wrapper classes on structures
39 // that have size fields came from fellow MSJ columnist, Paul DiLascia.
40 // Thanks, Paul!
42 // I didn’t wrap IMAGEHLP_SYMBOL because that is a variable-size
43 // structure.
45 // The IMAGEHLP_MODULE wrapper class
46 struct CImageHlp_Module : public IMAGEHLP_MODULE
48 CImageHlp_Module ( )
50 memset ( this , NULL , sizeof ( IMAGEHLP_MODULE ) ) ;
51 SizeOfStruct = sizeof ( IMAGEHLP_MODULE ) ;
53 } ;
55 // The IMAGEHLP_LINE wrapper class
56 struct CImageHlp_Line : public IMAGEHLP_LINE
58 CImageHlp_Line ( )
60 memset ( this , NULL , sizeof ( IMAGEHLP_LINE ) ) ;
61 SizeOfStruct = sizeof ( IMAGEHLP_LINE ) ;
63 } ;
65 // The symbol engine class
66 class CSymbolEngine
68 /*----------------------------------------------------------------------
69 Public Construction and Destruction
70 ----------------------------------------------------------------------*/
71 public :
72 // To use this class, call the SymInitialize member function to
73 // initialize the symbol engine and then use the other member
74 // functions in place of their corresponding DBGHELP.DLL functions.
75 CSymbolEngine ( void )
79 virtual ~CSymbolEngine ( void )
83 /*----------------------------------------------------------------------
84 Public Helper Information Functions
85 ----------------------------------------------------------------------*/
86 public :
88 // Returns the file version of DBGHELP.DLL being used.
89 // To convert the return values into a readable format:
90 // wsprintf ( szVer ,
91 // ( "%d.%02d.%d.%d" ) ,
92 // HIWORD ( dwMS ) ,
93 // LOWORD ( dwMS ) ,
94 // HIWORD ( dwLS ) ,
95 // LOWORD ( dwLS ) ) ;
96 // szVer will contain a string like: 5.00.1878.1
97 BOOL GetImageHlpVersion ( DWORD & dwMS , DWORD & dwLS )
99 return( GetInMemoryFileVersion ( ( "DBGHELP.DLL" ) ,
100 dwMS ,
101 dwLS ) ) ;
104 BOOL GetDbgHelpVersion ( DWORD & dwMS , DWORD & dwLS )
106 return( GetInMemoryFileVersion ( ( "DBGHELP.DLL" ) ,
107 dwMS ,
108 dwLS ) ) ;
111 // Returns the file version of the PDB reading DLLs
112 BOOL GetPDBReaderVersion ( DWORD & dwMS , DWORD & dwLS )
114 // First try MSDBI.DLL.
115 if ( TRUE == GetInMemoryFileVersion ( ( "MSDBI.DLL" ) ,
116 dwMS ,
117 dwLS ) )
119 return ( TRUE ) ;
121 else if ( TRUE == GetInMemoryFileVersion ( ( "MSPDB60.DLL" ),
122 dwMS ,
123 dwLS ))
125 return ( TRUE ) ;
127 // Just fall down to MSPDB50.DLL.
128 return ( GetInMemoryFileVersion ( ( "MSPDB50.DLL" ) ,
129 dwMS ,
130 dwLS ) ) ;
133 // The worker function used by the previous two functions
134 BOOL GetInMemoryFileVersion ( LPCTSTR szFile ,
135 DWORD & dwMS ,
136 DWORD & dwLS )
138 HMODULE hInstIH = GetModuleHandle ( szFile ) ;
140 // Get the full filename of the loaded version.
141 TCHAR szImageHlp[ MAX_PATH ] ;
142 GetModuleFileName ( hInstIH , szImageHlp , MAX_PATH ) ;
144 dwMS = 0 ;
145 dwLS = 0 ;
147 // Get the version information size.
148 DWORD dwVerInfoHandle ;
149 DWORD dwVerSize ;
151 dwVerSize = GetFileVersionInfoSize ( szImageHlp ,
152 &dwVerInfoHandle ) ;
153 if ( 0 == dwVerSize )
155 return ( FALSE ) ;
158 // Got the version size, now get the version information.
159 LPVOID lpData = (LPVOID)new TCHAR [ dwVerSize ] ;
160 if ( FALSE == GetFileVersionInfo ( szImageHlp ,
161 dwVerInfoHandle ,
162 dwVerSize ,
163 lpData ) )
165 delete [] lpData ;
166 return ( FALSE ) ;
169 VS_FIXEDFILEINFO * lpVerInfo ;
170 UINT uiLen ;
171 BOOL bRet = VerQueryValue ( lpData ,
172 ( "\\" ) ,
173 (LPVOID*)&lpVerInfo ,
174 &uiLen ) ;
175 if ( TRUE == bRet )
177 dwMS = lpVerInfo->dwFileVersionMS ;
178 dwLS = lpVerInfo->dwFileVersionLS ;
181 delete [] lpData ;
183 return ( bRet ) ;
186 /*----------------------------------------------------------------------
187 Public Initialization and Cleanup
188 ----------------------------------------------------------------------*/
189 public :
191 BOOL SymInitialize ( IN HANDLE hProcess ,
192 IN LPSTR UserSearchPath ,
193 IN BOOL fInvadeProcess )
195 m_hProcess = hProcess ;
196 return ( ::SymInitialize ( hProcess ,
197 UserSearchPath ,
198 fInvadeProcess ) ) ;
201 #ifdef USE_BUGSLAYERUTIL
202 BOOL BSUSymInitialize ( DWORD dwPID ,
203 HANDLE hProcess ,
204 PSTR UserSearchPath ,
205 BOOL fInvadeProcess )
207 m_hProcess = hProcess ;
208 return ( ::BSUSymInitialize ( dwPID ,
209 hProcess ,
210 UserSearchPath ,
211 fInvadeProcess ) ) ;
213 #endif // USE_BUGSLAYERUTIL
214 BOOL SymCleanup ( void )
216 return ( ::SymCleanup ( m_hProcess ) ) ;
219 /*----------------------------------------------------------------------
220 Public Module Manipulation
221 ----------------------------------------------------------------------*/
222 public :
224 BOOL SymEnumerateModules ( IN PSYM_ENUMMODULES_CALLBACK
225 EnumModulesCallback,
226 IN PVOID UserContext )
228 return ( ::SymEnumerateModules ( m_hProcess ,
229 EnumModulesCallback ,
230 UserContext ) ) ;
233 BOOL SymLoadModule ( IN HANDLE hFile ,
234 IN PSTR ImageName ,
235 IN PSTR ModuleName ,
236 IN DWORD_PTR BaseOfDll ,
237 IN DWORD SizeOfDll )
239 return ( ::SymLoadModule ( m_hProcess ,
240 hFile ,
241 ImageName ,
242 ModuleName ,
243 BaseOfDll ,
244 SizeOfDll ) != NULL) ;
247 BOOL EnumerateLoadedModules ( IN PENUMLOADED_MODULES_CALLBACK
248 EnumLoadedModulesCallback,
249 IN PVOID UserContext )
251 return ( ::EnumerateLoadedModules ( m_hProcess ,
252 EnumLoadedModulesCallback ,
253 UserContext ));
256 BOOL SymUnloadModule ( IN DWORD_PTR BaseOfDll )
258 return ( ::SymUnloadModule ( m_hProcess , BaseOfDll ) ) ;
261 BOOL SymGetModuleInfo ( IN DWORD_PTR dwAddr ,
262 OUT PIMAGEHLP_MODULE ModuleInfo )
264 return ( ::SymGetModuleInfo ( m_hProcess ,
265 dwAddr ,
266 ModuleInfo ) ) ;
269 DWORD SymGetModuleBase ( IN DWORD_PTR dwAddr )
271 return ( ::SymGetModuleBase ( m_hProcess , dwAddr ) != NULL ) ;
274 /*----------------------------------------------------------------------
275 Public Symbol Manipulation
276 ----------------------------------------------------------------------*/
277 public :
279 BOOL SymEnumerateSymbols (IN DWORD_PTR BaseOfDll,
280 IN PSYM_ENUMSYMBOLS_CALLBACK
281 EnumSymbolsCallback,
282 IN PVOID UserContext )
284 return ( ::SymEnumerateSymbols ( m_hProcess ,
285 BaseOfDll ,
286 EnumSymbolsCallback ,
287 UserContext ) ) ;
290 BOOL SymGetSymFromAddr ( IN DWORD_PTR dwAddr ,
291 OUT PDWORD_PTR pdwDisplacement ,
292 OUT PIMAGEHLP_SYMBOL Symbol )
294 return ( ::SymGetSymFromAddr ( m_hProcess ,
295 dwAddr ,
296 pdwDisplacement ,
297 Symbol ) ) ;
300 BOOL SymGetSymFromName ( IN LPSTR Name ,
301 OUT PIMAGEHLP_SYMBOL Symbol )
303 return ( ::SymGetSymFromName ( m_hProcess ,
304 Name ,
305 Symbol ) ) ;
308 BOOL SymGetSymNext ( IN OUT PIMAGEHLP_SYMBOL Symbol )
310 return ( ::SymGetSymNext ( m_hProcess , Symbol ) ) ;
313 BOOL SymGetSymPrev ( IN OUT PIMAGEHLP_SYMBOL Symbol )
315 return ( ::SymGetSymPrev ( m_hProcess , Symbol ) ) ;
318 /*----------------------------------------------------------------------
319 Public Source Line Manipulation
320 ----------------------------------------------------------------------*/
321 public :
323 BOOL SymGetLineFromAddr ( IN DWORD_PTR dwAddr ,
324 OUT PDWORD pdwDisplacement ,
325 OUT PIMAGEHLP_LINE Line )
328 #ifdef DO_NOT_WORK_AROUND_SRCLINE_BUG
329 // Just pass along the values returned by the main function.
330 return ( ::SymGetLineFromAddr ( m_hProcess ,
331 dwAddr ,
332 pdwDisplacement ,
333 Line ) ) ;
335 #else
336 // The problem is that the symbol engine finds only those source
337 // line addresses (after the first lookup) that fall exactly on
338 // a zero displacement. I’ll walk backward 100 bytes to
339 // find the line and return the proper displacement.
340 DWORD dwTempDis = 0 ;
341 while ( FALSE == ::SymGetLineFromAddr ( m_hProcess ,
342 dwAddr - dwTempDis ,
343 pdwDisplacement ,
344 Line ) )
346 dwTempDis += 1 ;
347 if ( 100 == dwTempDis )
349 return ( FALSE ) ;
352 // I found it and the source line information is correct, so
353 // change the displacement if I had to search backward to find
354 // the source line.
355 if ( 0 != dwTempDis )
357 *pdwDisplacement = dwTempDis ;
359 return ( TRUE ) ;
360 #endif // DO_NOT_WORK_AROUND_SRCLINE_BUG
363 BOOL SymGetLineFromName ( IN LPSTR ModuleName ,
364 IN LPSTR FileName ,
365 IN DWORD dwLineNumber ,
366 OUT PLONG plDisplacement ,
367 IN OUT PIMAGEHLP_LINE Line )
369 return ( ::SymGetLineFromName ( m_hProcess ,
370 ModuleName ,
371 FileName ,
372 dwLineNumber ,
373 plDisplacement ,
374 Line ) ) ;
377 BOOL SymGetLineNext ( IN OUT PIMAGEHLP_LINE Line )
379 return ( ::SymGetLineNext ( m_hProcess , Line ) ) ;
382 BOOL SymGetLinePrev ( IN OUT PIMAGEHLP_LINE Line )
384 return ( ::SymGetLinePrev ( m_hProcess , Line ) ) ;
387 BOOL SymMatchFileName ( IN LPSTR FileName ,
388 IN LPSTR Match ,
389 OUT LPSTR * FileNameStop ,
390 OUT LPSTR * MatchStop )
392 return ( ::SymMatchFileName ( FileName ,
393 Match ,
394 FileNameStop ,
395 MatchStop ) ) ;
398 /*----------------------------------------------------------------------
399 Public Miscellaneous Members
400 ----------------------------------------------------------------------*/
401 public :
403 LPVOID SymFunctionTableAccess ( DWORD_PTR AddrBase )
405 return ( ::SymFunctionTableAccess ( m_hProcess , AddrBase ) ) ;
408 BOOL SymGetSearchPath ( OUT LPSTR SearchPath ,
409 IN DWORD SearchPathLength )
411 return ( ::SymGetSearchPath ( m_hProcess ,
412 SearchPath ,
413 SearchPathLength ) ) ;
416 BOOL SymSetSearchPath ( IN LPSTR SearchPath )
418 return ( ::SymSetSearchPath ( m_hProcess , SearchPath ) ) ;
421 /* BOOL SymRegisterCallback ( IN PSYMBOL_REGISTERED_CALLBACK
422 CallbackFunction,
423 IN DWORD_PTR UserContext )
425 return ( ::SymRegisterCallback ( m_hProcess ,
426 CallbackFunction ,
427 UserContext ) ) ;
431 /*----------------------------------------------------------------------
432 Protected Data Members
433 ----------------------------------------------------------------------*/
434 protected :
435 // The unique value that will be used for this instance of the
436 // symbol engine. This value doesn’t have to be an actual
437 // process value, just a unique value.
438 HANDLE m_hProcess ;
442 #endif // _SYMBOLENGINE_H