Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. dbgback.cxx
  6. Abstract:
  7. Debug Imagehlp
  8. Author:
  9. Steve Kiraly (SteveKi) 17-May-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "dbgloadl.hxx"
  15. #include "dbgimage.hxx"
  16. #include <wtypes.h>
  17. //
  18. // Initialize the imagehlp library.
  19. //
  20. TDebugImagehlp::
  21. TDebugImagehlp(
  22. VOID
  23. ) : _ImageHlp( TEXT("ImageHlp.dll") ),
  24. _bValid( FALSE ),
  25. _pfSymGetModuleInfo( NULL ),
  26. _pfSymFunctionTableAccess( NULL ),
  27. _pfSymGetModuleBase( NULL ),
  28. _pfStackWalk( NULL ),
  29. _pfSymInitialize( NULL ),
  30. _pfSymSetOptions( NULL ),
  31. _pfSymGetSymFromAddr( NULL ),
  32. _pfSymUnDName( NULL )
  33. {
  34. if( _ImageHlp.bValid() )
  35. {
  36. _pfSymGetModuleInfo = (pfSymGetModuleInfo) _ImageHlp.pfnGetProc( "SymGetModuleInfo" );
  37. _pfStackWalk = (pfStackWalk) _ImageHlp.pfnGetProc( "StackWalk" );
  38. _pfSymSetOptions = (pfSymSetOptions) _ImageHlp.pfnGetProc( "SymSetOptions" );
  39. _pfSymInitialize = (pfSymInitialize) _ImageHlp.pfnGetProc( "SymInitialize" );
  40. _pfSymFunctionTableAccess = (pfSymFunctionTableAccess)_ImageHlp.pfnGetProc( "SymFunctionTableAccess" );
  41. _pfSymGetModuleBase = (pfSymGetModuleBase) _ImageHlp.pfnGetProc( "SymGetModuleBase" );
  42. _pfSymGetSymFromAddr = (pfSymGetSymFromAddr) _ImageHlp.pfnGetProc( "SymGetSymFromAddr" );
  43. _pfSymUnDName = (pfSymUnDName) _ImageHlp.pfnGetProc( "SymUnDName" );
  44. _pfSymGetSearchPath = (pfSymGetSearchPath) _ImageHlp.pfnGetProc( "SymGetSearchPath" );
  45. _pfSymSetSearchPath = (pfSymSetSearchPath) _ImageHlp.pfnGetProc( "SymSetSearchPath" );
  46. if( _pfSymGetModuleInfo &&
  47. _pfStackWalk &&
  48. _pfSymSetOptions &&
  49. _pfSymInitialize &&
  50. _pfSymFunctionTableAccess &&
  51. _pfSymGetModuleBase &&
  52. _pfSymGetSymFromAddr &&
  53. _pfSymUnDName )
  54. {
  55. _pfSymSetOptions( SYMOPT_DEFERRED_LOADS );
  56. _pfSymInitialize( GetCurrentProcess(), NULL, TRUE );
  57. _bValid = TRUE;
  58. #ifndef UNICODE
  59. _pszSymbolFormatSpecifier = _T("%08lx %s!%s+0x%x\n");
  60. #else
  61. _pszSymbolFormatSpecifier = _T("%08lx %S!%S+0x%x\n");
  62. #endif
  63. }
  64. }
  65. }
  66. //
  67. // Destroy the imagehlp library.
  68. //
  69. TDebugImagehlp::
  70. ~TDebugImagehlp(
  71. VOID
  72. )
  73. {
  74. }
  75. //
  76. // Return the object state.
  77. //
  78. BOOL
  79. TDebugImagehlp::
  80. bValid(
  81. VOID
  82. )
  83. {
  84. return _bValid;
  85. }
  86. //
  87. // Capture the current backtrace.
  88. //
  89. BOOL
  90. TDebugImagehlp::
  91. bCaptureBacktrace(
  92. IN UINT nSkip,
  93. IN ULONG nTotal,
  94. OUT VOID **apvBacktrace,
  95. OUT ULONG *puCount
  96. )
  97. {
  98. HANDLE hThread = NULL;
  99. CONTEXT context = {0};
  100. hThread = GetCurrentThread();
  101. context.ContextFlags = CONTEXT_FULL;
  102. if (GetThreadContext(hThread, &context))
  103. {
  104. STACKFRAME stkfrm = {0};
  105. DWORD dwMachType = 0;
  106. stkfrm.AddrPC.Mode = AddrModeFlat;
  107. #if defined(_M_IX86)
  108. dwMachType = IMAGE_FILE_MACHINE_I386;
  109. stkfrm.AddrPC.Offset = context.Eip; // Program Counter
  110. stkfrm.AddrStack.Offset = context.Esp; // Stack Pointer
  111. stkfrm.AddrStack.Mode = AddrModeFlat; // Stack address mode
  112. stkfrm.AddrFrame.Offset = context.Ebp; // Frame Pointer
  113. stkfrm.AddrFrame.Mode = AddrModeFlat; // Frame address mode
  114. #elif defined(_M_MRX000)
  115. dwMachType = IMAGE_FILE_MACHINE_R4000;
  116. stkfrm.AddrPC.Offset = context.Fir; // Program Counter
  117. #elif defined(_M_ALPHA)
  118. dwMachType = IMAGE_FILE_MACHINE_ALPHA;
  119. stkfrm.AddrPC.Offset = (ULONG) context.Fir; // Program Counter
  120. #elif defined(_M_PPC)
  121. dwMachType = IMAGE_FILE_MACHINE_POWERPC;
  122. stkfrm.AddrPC.Offset = context.Iar; // Program Counter
  123. #elif defined(_M_IA64)
  124. dwMachType = IMAGE_FILE_MACHINE_IA64;
  125. stkfrm.AddrPC.Offset = context.StIIP;
  126. #else
  127. #error("Unknown Target Machine");
  128. #endif
  129. //
  130. // Clear the valid entry count.
  131. //
  132. *puCount = 0;
  133. //
  134. // Walk the stack saving the addresses.
  135. //
  136. for( UINT i = 0; i < nSkip + nTotal; i++ )
  137. {
  138. if( !_pfStackWalk( dwMachType,
  139. GetCurrentProcess(),
  140. GetCurrentProcess(),
  141. &stkfrm,
  142. &context,
  143. NULL,
  144. _pfSymFunctionTableAccess,
  145. _pfSymGetModuleBase,
  146. NULL ))
  147. {
  148. break;
  149. }
  150. if (i >= nSkip)
  151. {
  152. if( stkfrm.AddrPC.Offset )
  153. {
  154. apvBacktrace[(*puCount)++] = (VOID *)stkfrm.AddrPC.Offset;
  155. }
  156. }
  157. }
  158. }
  159. return *puCount > 0;
  160. }
  161. //
  162. // Resolve the specified address to a human readable symbol.
  163. //
  164. BOOL
  165. TDebugImagehlp::
  166. ResolveAddressToSymbol(
  167. IN PVOID pvAddress,
  168. IN LPTSTR pszName,
  169. IN UINT cchNameLength,
  170. IN EDecoration eDecorateType
  171. )
  172. {
  173. IMAGEHLP_MODULE mod = {0};
  174. DWORD dwDisplacement = 0;
  175. INT iLen = 0;
  176. UINT_PTR Address = (UINT_PTR)pvAddress;
  177. LPCSTR pszSymbolName = NULL;
  178. CHAR szUnDDump[kMaxSymbolNameLength];
  179. CHAR dump[sizeof(IMAGEHLP_SYMBOL) + kMaxSymbolNameLength];
  180. PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&dump;
  181. //
  182. // Fetch the module name
  183. //
  184. mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
  185. _pfSymGetModuleInfo(GetCurrentProcess(), Address, &mod);
  186. //
  187. // Have to do this because size of sym is dynamically determined
  188. //
  189. pSym->SizeOfStruct = sizeof(dump);
  190. pSym->MaxNameLength = kMaxSymbolNameLength;
  191. //
  192. // Fetch the symbol
  193. //
  194. if (_pfSymGetSymFromAddr(GetCurrentProcess(),
  195. Address,
  196. &dwDisplacement,
  197. pSym))
  198. {
  199. //
  200. // Assume the caller wants a decorated symbol name.
  201. //
  202. pszSymbolName = pSym->Name;
  203. if( eDecorateType == kUnDecorateName )
  204. {
  205. //
  206. // Get the undecorated name for this symbol.
  207. //
  208. if( _pfSymUnDName( pSym, szUnDDump, sizeof( szUnDDump ) ) )
  209. {
  210. pszSymbolName = szUnDDump;
  211. }
  212. }
  213. }
  214. //
  215. // Format the symbol name.
  216. //
  217. iLen = _sntprintf( pszName,
  218. cchNameLength,
  219. _pszSymbolFormatSpecifier,
  220. Address,
  221. mod.ModuleName,
  222. pszSymbolName,
  223. dwDisplacement );
  224. return iLen > 0;
  225. }
  226. //
  227. // Get the current symbol search path for this process
  228. //
  229. BOOL
  230. TDebugImagehlp::
  231. GetSymbolPath(
  232. IN TDebugString &strSearchPath
  233. ) const
  234. {
  235. BOOL bRetval = FALSE;
  236. CHAR szNarowSearchPath[MAX_PATH];
  237. LPTSTR pszSearchPath;
  238. bRetval = _pfSymGetSearchPath( GetCurrentProcess(), szNarowSearchPath, COUNTOF( szNarowSearchPath ) );
  239. if( bRetval )
  240. {
  241. bRetval = StringA2T( &pszSearchPath, szNarowSearchPath );
  242. if( bRetval )
  243. {
  244. bRetval = strSearchPath.bUpdate( pszSearchPath );
  245. INTERNAL_DELETE [] pszSearchPath;
  246. }
  247. }
  248. return bRetval;
  249. }
  250. //
  251. // Set the current symbol search path for this process
  252. //
  253. BOOL
  254. TDebugImagehlp::
  255. SetSymbolPath(
  256. IN LPCTSTR pszSearchPath
  257. )
  258. {
  259. BOOL bRetval = FALSE;
  260. LPSTR pszNarrowSearchPath = NULL;
  261. bRetval = StringT2A( &pszNarrowSearchPath, pszSearchPath );
  262. if( bRetval )
  263. {
  264. bRetval = _pfSymSetSearchPath( GetCurrentProcess(), pszNarrowSearchPath );
  265. INTERNAL_DELETE [] pszNarrowSearchPath;
  266. }
  267. return bRetval;
  268. }