hkStackTracerWin32.cxx
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:9k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* 
  2.  * 
  3.  * Confidential Information of Telekinesys Research Limited (t/a Havok). Not for disclosure or distribution without Havok's
  4.  * prior written consent. This software contains code, techniques and know-how which is confidential and proprietary to Havok.
  5.  * Level 2 and Level 3 source code contains trade secrets of Havok. Havok Software (C) Copyright 1999-2009 Telekinesys Research Limited t/a Havok. All Rights Reserved. Use of this software is subject to the terms of an end user license agreement.
  6.  * 
  7.  */
  8. #include <Common/Base/hkBase.h>
  9. #include <Common/Base/Memory/StackTracer/hkStackTracer.h>
  10. #include <Common/Base/Fwd/hkcstdio.h>
  11. #include <Common/Base/Fwd/hkwindows.h>
  12. // dbghelp.h has an incorrect version of this block
  13. #ifndef __specstrings
  14. #define __specstrings
  15. # define __in
  16. # define __out
  17. # define __inout
  18. # define __in_opt
  19. # define __out_opt
  20. # define __inout_opt
  21. # define __in_ecount
  22. # define __out_ecount(A)
  23. # define __inout_ecount
  24. # define __in_bcount
  25. # define __out_bcount(A)
  26. # define __inout_bcount
  27. # define __deref_opt_out
  28. # define __deref_out
  29. # define __out_xcount(A)
  30. #endif
  31. typedef hkUlong ULONG_PTR, *PULONG_PTR;
  32. // VC7 and higher:
  33. #include <imagehlp.h>
  34. typedef BOOL    (__stdcall *tSymInitialize)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
  35. typedef DWORD   (__stdcall *tSymGetOptions)( VOID );
  36. typedef DWORD   (__stdcall *tSymSetOptions)( IN DWORD SymOptions );
  37. typedef BOOL    (__stdcall *tSymGetSymFromAddr)( IN HANDLE hProcess, IN DWORD dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_SYMBOL Symbol );
  38. typedef BOOL    (__stdcall *tStackWalk64)( DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );
  39. typedef PVOID   (__stdcall *tSymFunctionTableAccess64)( HANDLE hProcess, DWORD64 AddrBase );
  40. typedef DWORD64 (__stdcall *tSymGetModuleBase64)( IN HANDLE hProcess, IN DWORD64 dwAddr );
  41. typedef BOOL    (__stdcall *tSymGetLineFromAddr64)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );
  42. typedef BOOL    (__stdcall *tSymCleanup)( IN HANDLE hProcess );
  43. static HINSTANCE hDbgHelpDll;
  44. static int s_DllReferences;
  45. static tSymInitialize pSymInitialize;
  46. static tSymGetOptions pSymGetOptions;
  47. static tSymSetOptions pSymSetOptions;
  48. static tSymGetSymFromAddr pSymGetSymFromAddr;
  49. static tStackWalk64 pStackWalk64;
  50. static tSymFunctionTableAccess64 pSymFunctionTableAccess64;
  51. static tSymGetModuleBase64 pSymGetModuleBase64;
  52. static tSymGetLineFromAddr64 pSymGetLineFromAddr64;
  53. static tSymCleanup pSymCleanup;
  54. #define LOAD_FUNCTION(A) if(1) { p##A = (t##A) GetProcAddress(hDbgHelpDll, #A); HK_ASSERT2(0x7ff2db1c, p##A, "Could not load symbol from imghelp.dll"); } else
  55. extern const char* hkStackTracerDbghelpPath;
  56. const char* hkStackTracerDbghelpPath = "dbghelp.dll";
  57. hkStackTracer::hkStackTracer()
  58. {
  59. if( hDbgHelpDll == HK_NULL )
  60. {
  61. // If you do not get symbols in the stack trace, it could be because the version of dbghelp.dll
  62. // in your path is too old. You can download a new one from
  63. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/dbghelp_versions.asp
  64. // And set an explicit path for the dll to load
  65. // extern const char* hkStackTracerDbghelpPath;
  66. // hkStackTracerDbghelpPath = "C:\Program Files\Debugging Tools for Windows\dbghelp.dll";
  67. hDbgHelpDll = LoadLibrary(hkStackTracerDbghelpPath);
  68. HK_ASSERT2(0x6427e415, hDbgHelpDll != HK_NULL, "Unable to load dbghelp.dll");
  69. s_DllReferences = 1;
  70. LOAD_FUNCTION(SymInitialize);
  71. LOAD_FUNCTION(SymGetOptions);
  72. LOAD_FUNCTION(SymSetOptions);
  73. LOAD_FUNCTION(SymGetSymFromAddr);
  74. LOAD_FUNCTION(StackWalk64);
  75. LOAD_FUNCTION(SymFunctionTableAccess64);
  76. LOAD_FUNCTION(SymGetModuleBase64);
  77. LOAD_FUNCTION(SymGetLineFromAddr64);
  78. LOAD_FUNCTION(SymCleanup);
  79. DWORD symOptions = pSymGetOptions();
  80. symOptions |= SYMOPT_LOAD_LINES | SYMOPT_DEBUG;
  81. pSymSetOptions( symOptions );
  82. HK_ON_DEBUG( BOOL initsymbols = ) pSymInitialize( GetCurrentProcess(), HK_NULL, TRUE);
  83. HK_ASSERT(0x44b27798, initsymbols);
  84. }
  85. else
  86. {
  87. s_DllReferences += 1;
  88. }
  89. }
  90. hkStackTracer::~hkStackTracer()
  91. {
  92. s_DllReferences -= 1;
  93. if( s_DllReferences == 0 )
  94. {
  95. pSymCleanup( GetCurrentProcess() );
  96. pSymInitialize = 0;
  97. pSymGetOptions = 0;
  98. pSymSetOptions = 0;
  99. pSymGetSymFromAddr = 0;
  100. pStackWalk64 = 0;
  101. pSymFunctionTableAccess64 = 0;
  102. pSymGetModuleBase64 = 0;
  103. pSymGetLineFromAddr64 = 0;
  104. pSymCleanup = 0;
  105. FreeLibrary( hDbgHelpDll );
  106. hDbgHelpDll = 0;
  107. }
  108. }
  109. void hkStackTracer::dumpStackTrace( const hkUlong* trace, int maxtrace, printFunc pfunc, void* context )
  110. {
  111. char buf[2048];
  112. HANDLE curproc = GetCurrentProcess();
  113. for( int i = 0; i < maxtrace; ++i)
  114. {
  115. hkUlong symaddress = trace[i];
  116. IMAGEHLP_SYMBOL& sym = *(IMAGEHLP_SYMBOL*)buf;
  117. memset(&sym, 0, sizeof(IMAGEHLP_SYMBOL));
  118. sym.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
  119. sym.MaxNameLength = 2048 - sym.SizeOfStruct;
  120. DWORD displacement = 0;
  121. BOOL ok_symbol = pSymGetSymFromAddr( 
  122. curproc, 
  123. DWORD(symaddress),
  124. &displacement,
  125. &sym);
  126. if(! ok_symbol)
  127. {
  128. static bool haveWarned;
  129. if( ! haveWarned )
  130. {
  131. pfunc( "**************************************************************n" 
  132. "* Cannot find symbol for an addressn" 
  133. "* Either debug information was not found or your version ofn" 
  134. "* dbghelp.dll may be too old to understand the debug format.n" 
  135. "* See the comments in hkStackTracer::hkStackTracer()n" 
  136. "* " __FILE__ "n" 
  137. "**************************************************************n", context);
  138. haveWarned = 1;
  139. }
  140. ::strcpy(sym.Name, "(unknown)");
  141. }
  142. else if (::strcmp(sym.Name, "WinMain") == 0 )
  143. {
  144. break;
  145. }
  146. IMAGEHLP_LINE64 line;
  147. ::memset(&line, 0, sizeof(line));
  148. line.SizeOfStruct = sizeof(line);
  149. pSymGetLineFromAddr64(
  150. curproc,
  151. DWORD(symaddress),
  152. &displacement,
  153. &line);
  154. char trace[2048];
  155. _snprintf(trace, 2048, "%s(%i):'%s'n", line.FileName, line.LineNumber, sym.Name);
  156. pfunc(trace, context);
  157. }
  158. pfunc("-------------------------------------------------------------------nn", context);
  159. }
  160. //
  161. // Hardcoded 386
  162. //
  163. #if 1 
  164. int hkStackTracer::getStackTrace( hkUlong* trace, int maxtrace )
  165. {
  166. #if defined(HK_ARCH_X64) || !defined(HK_FULLDEBUG)
  167. return 0; // Hardcoded walker only works when full debug information (not just line numbers etc) are used.
  168. #else
  169. struct frame
  170. {
  171. frame* next;
  172. hkUlong retaddr;
  173. };
  174. frame* stackPtr;
  175. frame* framePtr;
  176. __asm
  177. {
  178. mov stackPtr, esp
  179. mov framePtr, ebp
  180. }
  181. int count = 0;
  182. if( stackPtr && framePtr )
  183. {
  184. frame* current = framePtr;
  185. while( (count < maxtrace)
  186. && (stackPtr < current)
  187. && (current != 0)
  188. && (current->retaddr != 0) )
  189. {
  190. trace[count++] = current->retaddr;
  191. current = current->next;
  192. }
  193. }
  194. return count;
  195. #endif
  196. }
  197. #else
  198. // 
  199. // Generic (32 / 64bit compat, but has issues..)
  200. //
  201. int hkStackTracer::getStackTrace( hkUlong* trace, int maxtrace )
  202. {
  203. HANDLE curproc   = GetCurrentProcess();
  204. HANDLE curthread = GetCurrentThread();
  205. CONTEXT context;
  206. ::memset(&context, 0, sizeof(context));
  207. /*
  208. __asm
  209. {
  210. call GetEIP
  211. jmp Done
  212. GetEIP:
  213. pop eax
  214. mov context.Eip, eax
  215. mov context.Ebp, ebp
  216. push eax
  217. ret
  218. Done:
  219. }
  220. */
  221. context.ContextFlags = CONTEXT_FULL;
  222. HK_ON_DEBUG( BOOL ok_context = ) GetThreadContext(curthread, &context);
  223. HK_ASSERT(0x62047d0a, ok_context);
  224. STACKFRAME64 sf;
  225. ::memset(&sf, 0, sizeof(sf));
  226. sf.AddrPC.Offset    = context.Eip;
  227. sf.AddrPC.Mode      = AddrModeFlat;
  228. sf.AddrFrame.Offset = context.Ebp;
  229. sf.AddrFrame.Mode   = AddrModeFlat;
  230. int frame = -2;
  231. for( ; frame < maxtrace; ++frame )
  232. {
  233. if( pStackWalk64(
  234. IMAGE_FILE_MACHINE_I386,
  235. curproc, 
  236. curthread,
  237. &sf,
  238. &context,
  239. HK_NULL,
  240. pSymFunctionTableAccess64,
  241. pSymGetModuleBase64,
  242. HK_NULL) )
  243. {
  244. if(frame >= 0)
  245. {
  246. trace[frame] = (hkUlong)sf.AddrPC.Offset;
  247. }
  248. }
  249. else
  250. {
  251. break;
  252. }
  253. }
  254. return frame >= 0 ? frame : 0;
  255. }
  256. #endif
  257. /*
  258. * Havok SDK - NO SOURCE PC DOWNLOAD, BUILD(#20090216)
  259. * Confidential Information of Havok.  (C) Copyright 1999-2009
  260. * Telekinesys Research Limited t/a Havok. All Rights Reserved. The Havok
  261. * Logo, and the Havok buzzsaw logo are trademarks of Havok.  Title, ownership
  262. * rights, and intellectual property rights in the Havok software remain in
  263. * Havok and/or its suppliers.
  264. * Use of this software for evaluation purposes is subject to and indicates
  265. * acceptance of the End User licence Agreement for this product. A copy of
  266. * the license is included with this software and is also available at www.havok.com/tryhavok.
  267. */