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.

362 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. dbgback.cxx
  6. Abstract:
  7. Debug Backtrace Device
  8. Author:
  9. Steve Kiraly (SteveKi) 16-May-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "dbgloadl.hxx"
  15. #include "dbgimage.hxx"
  16. #include "dbgback.hxx"
  17. #include "dbgreg.hxx"
  18. //
  19. // Construct the backtrace device.
  20. //
  21. TDebugDeviceBacktrace::
  22. TDebugDeviceBacktrace(
  23. IN LPCTSTR pszConfiguration,
  24. IN EDebugType eDebugType
  25. ) : TDebugDevice( pszConfiguration, eDebugType ),
  26. _pDbgImagehlp( NULL ),
  27. _bValid( FALSE ),
  28. _pDbgDevice( NULL ),
  29. _bDisplaySymbols( FALSE )
  30. {
  31. //
  32. // Collect andy device arguments.
  33. //
  34. CollectDeviceArguments();
  35. //
  36. // Create the debug imagehlp object.
  37. //
  38. _pDbgImagehlp = INTERNAL_NEW TDebugImagehlp;
  39. //
  40. // Set the valid flag.
  41. //
  42. _bValid = _pDbgImagehlp && _pDbgImagehlp->bValid();
  43. }
  44. //
  45. // Close the backtrace device.
  46. //
  47. TDebugDeviceBacktrace::
  48. ~TDebugDeviceBacktrace(
  49. )
  50. {
  51. INTERNAL_DELETE _pDbgImagehlp;
  52. INTERNAL_DELETE _pDbgDevice;
  53. }
  54. //
  55. // Indicates the deveice object is valid.
  56. //
  57. BOOL
  58. TDebugDeviceBacktrace::
  59. bValid(
  60. VOID
  61. )
  62. {
  63. return _bValid;
  64. }
  65. //
  66. // Output the string to the backtrace device
  67. //
  68. BOOL
  69. TDebugDeviceBacktrace::
  70. bOutput(
  71. IN UINT uSize,
  72. IN LPBYTE pBuffer
  73. )
  74. {
  75. //
  76. // Is the class in a good state and we have an output device.
  77. //
  78. BOOL bRetval = bValid() && _pDbgDevice;
  79. if( bRetval )
  80. {
  81. //
  82. // Send the string to the output device.
  83. //
  84. bRetval = _pDbgDevice->bOutput( uSize, pBuffer );
  85. if( bRetval )
  86. {
  87. PVOID apvBacktrace[kMaxDepth];
  88. ULONG uCount = 0;
  89. memset( apvBacktrace, 0, sizeof( apvBacktrace ) );
  90. //
  91. // Capture the current backtrace skiping the call stack of this class
  92. //
  93. bRetval = _pDbgImagehlp->bCaptureBacktrace( 3, kMaxDepth, apvBacktrace, &uCount );
  94. if( bRetval )
  95. {
  96. //
  97. // Send the backtrace to the output device.
  98. //
  99. bRetval = OutputBacktrace( uCount, apvBacktrace );
  100. }
  101. }
  102. }
  103. return bRetval;
  104. }
  105. //
  106. // Send the backtrace to the output device.
  107. //
  108. BOOL
  109. TDebugDeviceBacktrace::
  110. OutputBacktrace(
  111. IN UINT uCount,
  112. IN PVOID *apvBacktrace
  113. )
  114. {
  115. TCHAR szBuffer [kMaxSymbolName];
  116. BOOL bRetval = FALSE;
  117. LPCTSTR pszFmt = NULL;
  118. for( UINT i = 0; i < uCount && apvBacktrace[i]; i++ )
  119. {
  120. if( _bDisplaySymbols )
  121. {
  122. bRetval = _pDbgImagehlp->ResolveAddressToSymbol( apvBacktrace[i],
  123. szBuffer,
  124. COUNTOF( szBuffer ),
  125. TDebugImagehlp::kUnDecorateName );
  126. }
  127. else
  128. {
  129. if( i == 0 )
  130. {
  131. pszFmt = kstrBacktraceStart;
  132. }
  133. else if( !apvBacktrace[i+1] )
  134. {
  135. pszFmt = kstrBacktraceEnd;
  136. }
  137. else
  138. {
  139. pszFmt = kstrBacktraceMiddle;
  140. }
  141. bRetval = _sntprintf( szBuffer, COUNTOF(szBuffer), pszFmt, apvBacktrace[i] ) > 0;
  142. }
  143. if( bRetval )
  144. {
  145. bRetval = _pDbgDevice->bOutput( _tcslen( szBuffer ) * sizeof(TCHAR),
  146. reinterpret_cast<LPBYTE>( szBuffer ) );
  147. }
  148. }
  149. return bRetval;
  150. }
  151. //
  152. // Initialize the specified symbol path.
  153. //
  154. VOID
  155. TDebugDeviceBacktrace::
  156. InitSympath(
  157. VOID
  158. )
  159. {
  160. if( _bDisplaySymbols )
  161. {
  162. TDebugString strRegistryPath;
  163. //
  164. // Get the base registry path.
  165. //
  166. BOOL bRetval = strRegistryPath.bUpdate( kstrSympathRegistryPath );
  167. if( bRetval )
  168. {
  169. TDebugString strProcessName;
  170. //
  171. // Get this processes short name.
  172. //
  173. bRetval = GetProcessName( strProcessName );
  174. if( bRetval )
  175. {
  176. //
  177. // Build the registry path Path\processname
  178. //
  179. bRetval = strRegistryPath.bCat( kstrSlash ) && strRegistryPath.bCat( strProcessName );
  180. if( bRetval )
  181. {
  182. //
  183. // Open the registry key.
  184. //
  185. TDebugRegistry Registry( strRegistryPath, TDebugRegistry::kOpen|TDebugRegistry::kRead, HKEY_LOCAL_MACHINE );
  186. bRetval = Registry.bValid();
  187. if( bRetval )
  188. {
  189. //
  190. // Read the symbol path if there.
  191. //
  192. bRetval = Registry.bRead( kstrSympathRegistryKey, _strSympath );
  193. }
  194. }
  195. }
  196. }
  197. //
  198. // If the registry did not specifiy a symbol path then use the
  199. // default symbol path that imagehlp has.
  200. //
  201. if( !bRetval )
  202. {
  203. _pDbgImagehlp->GetSymbolPath( _strSympath );
  204. }
  205. else
  206. {
  207. //
  208. // Set the symbol path
  209. //
  210. _pDbgImagehlp->SetSymbolPath( _strSympath );
  211. }
  212. }
  213. }
  214. //
  215. // If we are displaying symbols then as the first line in the output
  216. // device indicate the symbol path.
  217. //
  218. VOID
  219. TDebugDeviceBacktrace::
  220. WriteSympathToOutputDevice(
  221. VOID
  222. )
  223. {
  224. if( _bDisplaySymbols )
  225. {
  226. TDebugString strSympath;
  227. strSympath.bFormat(kstrSympathFormat, _strSympath);
  228. _pDbgDevice->bOutput(strSympath.uLen() * sizeof(TCHAR),
  229. reinterpret_cast<LPBYTE>(
  230. const_cast<LPTSTR>(
  231. static_cast<LPCTSTR>(
  232. strSympath))));
  233. }
  234. }
  235. //
  236. // Create and the set the output device type.
  237. //
  238. BOOL
  239. TDebugDeviceBacktrace::
  240. InitializeOutputDevice(
  241. IN UINT uDevice,
  242. IN LPCTSTR pszConfiguration,
  243. IN UINT uCharacterType
  244. )
  245. {
  246. if( bValid() )
  247. {
  248. //
  249. // Get access to the debug factory.
  250. //
  251. TDebugFactory DebugFactory;
  252. //
  253. // If we failed to create the debug factory then exit.
  254. //
  255. if (DebugFactory.bValid())
  256. {
  257. //
  258. // Release the existing debug device.
  259. //
  260. delete _pDbgDevice;
  261. //
  262. // Create the specified debug device using the factory.
  263. //
  264. _pDbgDevice = DebugFactory.Produce( uDevice, pszConfiguration, uCharacterType );
  265. //
  266. // If the debug device was created successfully.
  267. //
  268. if( _pDbgDevice )
  269. {
  270. //
  271. // Initialize the sympath
  272. //
  273. InitSympath();
  274. //
  275. // Write sympath to output device.
  276. //
  277. WriteSympathToOutputDevice();
  278. }
  279. }
  280. }
  281. //
  282. // Indicate the debug device was created.
  283. //
  284. return _pDbgDevice != NULL;
  285. }
  286. //
  287. // Get the device arguments from the configuration string.
  288. //
  289. BOOL
  290. TDebugDeviceBacktrace::
  291. CollectDeviceArguments(
  292. VOID
  293. )
  294. {
  295. TDebugDevice::TIterator i( this );
  296. for( i.First(); !i.IsDone(); i.Next() )
  297. {
  298. switch( i.Index() )
  299. {
  300. //
  301. // Ignore the character type.
  302. //
  303. case 1:
  304. break;
  305. //
  306. // The second aregument is the symbol specifier.
  307. //
  308. case 2:
  309. _bDisplaySymbols = !_tcsicmp( kstrSymbols, i.Current() );
  310. break;
  311. }
  312. }
  313. return FALSE;
  314. }