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.

494 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. spllib.cxx
  6. Abstract:
  7. Extensions for spllib
  8. Author:
  9. Albert Ting (AlbertT) 20-Feb-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. /********************************************************************
  14. Helper routines
  15. ********************************************************************/
  16. #if !DBG
  17. #error "Only the debug version should be built."
  18. #endif
  19. BOOL
  20. TDebugExt::
  21. bDumpThreadM(
  22. PVOID pThreadM_,
  23. ULONG_PTR dwAddr
  24. )
  25. {
  26. TThreadM* pThreadM = (TThreadM*)pThreadM_;
  27. static DEBUG_FLAGS DebugFlags[] = {
  28. { "DESTROYED_REQ" , 1 },
  29. { "DESTROYED" , 2 },
  30. { "PRIVATE_CRIT_SEC", 4 }
  31. };
  32. if( !pThreadM->bSigCheck( )){
  33. return FALSE;
  34. }
  35. Print( "TThreadM*\n" );
  36. Print( " uMaxThreads <%d>\n", pThreadM->_uMaxThreads );
  37. Print( " uIdleLife <%d>\n", pThreadM->_uIdleLife );
  38. Print( "uActiveThreads <%d>\n", pThreadM->_uActiveThreads );
  39. Print( " iIdleThreads <%d>\n", pThreadM->_iIdleThreads );
  40. Print( " hTrigger %x\n", pThreadM->_hTrigger );
  41. Print( " State %x %x\n", (ULONG_PTR)pThreadM->_State, &pThreadM->_State );
  42. Print( " pCritSec %x\n", pThreadM->_pCritSec );
  43. return TRUE;
  44. }
  45. BOOL
  46. TDebugExt::
  47. bDumpCritSec(
  48. PVOID pCritSec_,
  49. ULONG_PTR dwAddr
  50. )
  51. {
  52. MCritSec* pCritSec = (MCritSec*)pCritSec_;
  53. if( !pCritSec->bSigCheck( )){
  54. return FALSE;
  55. }
  56. Print( "MCritSec*\n" );
  57. Print( " CriticalSection @ %x\n", dwAddr + OFFSETOF( MCritSec, _CritSec ));
  58. Print( " dwThreadOwner %x\n", pCritSec->_dwThreadOwner );
  59. Print( " dwEntryCount <%d> ", pCritSec->_dwEntryCount );
  60. if( pCritSec->_dwEntryCount ){
  61. Print( "Owned\n" );
  62. } else {
  63. Print( "Not Owned\n" );
  64. }
  65. Print( "dwTickCountEntered <%d>\n", pCritSec->_dwTickCountEntered );
  66. Print( "==== Statistics\n" );
  67. Print( " dwTickCountBlockedTotal <%d>\n", pCritSec->_dwTickCountBlockedTotal );
  68. Print( " dwTickCountInsideTotal <%d>\n", pCritSec->_dwTickCountInsideTotal );
  69. Print( " dwEntryCountTotal <%d>\n", pCritSec->_dwEntryCountTotal );
  70. Print( " CritSecHardLock_base " ); vDumpPDL( pCritSec->CritSecHardLock_pdlBase( ));
  71. ULONG_PTR dwAddrBt = dwAddr + OFFSETOF( MCritSec, _BackTrace )
  72. - OFFSETOF_BASE( TBackTraceMem, VBackTrace );
  73. Print( " VBackTrace @ %x !splx.ddt -x %x\n",
  74. dwAddrBt, dwAddrBt );
  75. return TRUE;
  76. }
  77. BOOL
  78. TDebugExt::
  79. bDumpBackTrace(
  80. ULONG_PTR dwAddr,
  81. COUNT Count,
  82. PDWORD pdwSkip,
  83. DWORD DebugTrace,
  84. DWORD DebugLevel,
  85. DWORD dwThreadId,
  86. ULONG_PTR dwMem
  87. )
  88. {
  89. #ifdef TRACE_ENABLED
  90. BYTE abyBackTraceBuffer[sizeof(TBackTraceMem)];
  91. TBackTraceMem* pBackTraceMem = (TBackTraceMem*)abyBackTraceBuffer;
  92. move2( pBackTraceMem, dwAddr, sizeof( TBackTraceMem ));
  93. if( !pBackTraceMem->bSigCheck( )){
  94. return FALSE;
  95. }
  96. INT iLineStart = pBackTraceMem->_uNextFree;
  97. INT iLine;
  98. if( iLineStart < 0 ){
  99. iLineStart = TBackTraceMem::kMaxCall - 1;
  100. }
  101. for( iLine = iLineStart - 1; Count; --iLine, --Count ){
  102. if( CheckControlCRtn()){
  103. return TRUE;
  104. }
  105. //
  106. // Handle wrap around case.
  107. //
  108. if( iLine < 0 ){
  109. iLine = TBackTraceMem::kMaxCall - 1;
  110. }
  111. if( iLine == iLineStart ||
  112. !TDebugExt::bDumpDebugTrace( (ULONG_PTR)&pBackTraceMem->_pLines[iLine],
  113. 1,
  114. pdwSkip,
  115. DebugTrace,
  116. DebugLevel,
  117. dwThreadId,
  118. dwMem )){
  119. //
  120. // Wrapped around yet didn't find enough.
  121. //
  122. Print( "Out of lines\n" );
  123. return TRUE;
  124. }
  125. }
  126. return TRUE;
  127. #else // #ifdef TRACE_ENABLED
  128. return FALSE;
  129. #endif // #ifdef TRACE_ENABLED
  130. }
  131. BOOL
  132. TDebugExt::
  133. bDumpDebugTrace(
  134. ULONG_PTR dwLineAddr,
  135. COUNT Count,
  136. PDWORD pdwSkip,
  137. DWORD DebugTrace,
  138. DWORD DebugLevel,
  139. DWORD dwThreadId,
  140. ULONG_PTR dwMem
  141. )
  142. {
  143. //
  144. // TLine is a simple class, and can be treated as a "C" struct.
  145. //
  146. COUNTB cbTotalLine = sizeof( TBackTraceMem::TLine ) * Count;
  147. TBackTraceMem::TLine* pLineBase =
  148. (TBackTraceMem::TLine*) LocalAlloc( LPTR, cbTotalLine );
  149. BOOL bValidLines = TRUE;
  150. TBackTraceMem::TLine* pLine;
  151. if( !pLineBase ){
  152. Print( "Cannot alloc 0x%x bytes.\n", cbTotalLine );
  153. return FALSE;
  154. }
  155. move2( pLineBase, dwLineAddr, cbTotalLine );
  156. //
  157. // Dump out the lines.
  158. //
  159. for( pLine = pLineBase ; Count; Count--, pLine++ ){
  160. if( CheckControlCRtn()){
  161. goto Done;
  162. }
  163. //
  164. // If we are out of lines, quit.
  165. //
  166. if( !pLine->_TickCount ){
  167. bValidLines = FALSE;
  168. goto Done;
  169. }
  170. //
  171. // If we are processing DBGMSG, skip levels we don't want.
  172. //
  173. if( DebugTrace & DEBUG_TRACE_DBGMSG ){
  174. if( !( DebugLevel & ( pLine->_Info2 >> DBG_BREAK_SHIFT ))){
  175. continue;
  176. }
  177. }
  178. //
  179. // Skip thread Ids we don't want.
  180. //
  181. if( dwThreadId && dwThreadId != pLine->_ThreadId ){
  182. continue;
  183. }
  184. //
  185. // Skip mem we don't want.
  186. // This is used when we are dumping the memory functions in
  187. // spllib (gpbtAlloc and gpbtFree).
  188. //
  189. if( dwMem &&
  190. ( dwMem < pLine->_Info1 ||
  191. dwMem > pLine->_Info1 + pLine->_Info2 )){
  192. continue;
  193. }
  194. if( *pdwSkip ){
  195. --*pdwSkip;
  196. continue;
  197. }
  198. if( DebugTrace & DEBUG_TRACE_DBGMSG ){
  199. CHAR szMsg[kStringDefaultMax];
  200. szMsg[0] = 0;
  201. if( pLine->_Info1 ){
  202. move( szMsg, pLine->_Info1 );
  203. //
  204. // PageHeap forces all allocated blocks to be placed
  205. // at the end of a page, with the next page marked
  206. // as unreadable. If we don't get a string here,
  207. // then read up chunk.
  208. //
  209. if( !szMsg[0] ){
  210. move2( szMsg,
  211. pLine->_Info1,
  212. kStringChunk -
  213. ( (DWORD)pLine->_Info1 & ( kStringChunk - 1 )));
  214. }
  215. Print( "* %s", szMsg );
  216. UINT cchLen = lstrlenA( szMsg );
  217. if( !cchLen || szMsg[cchLen-1] != '\n' ){
  218. Print( "\n" );
  219. }
  220. } else {
  221. Print( "\n" );
  222. }
  223. }
  224. if( DebugTrace & DEBUG_TRACE_HEX ){
  225. Print( "%08x %08x %08x bt=%x threadid=%x tc=%x [%x]\n",
  226. pLine->_Info1,
  227. pLine->_Info2,
  228. pLine->_Info3,
  229. pLine->_hTrace,
  230. pLine->_ThreadId,
  231. pLine->_TickCount,
  232. pLine->_Info1 + pLine->_Info2 );
  233. }
  234. if( DebugTrace & DEBUG_TRACE_BT ){
  235. vDumpTrace( (ULONG_PTR)pLine->_hTrace );
  236. }
  237. }
  238. Done:
  239. LocalFree( pLineBase );
  240. return bValidLines;
  241. }
  242. BOOL
  243. TDebugExt::
  244. bDumpDbgPointers(
  245. PVOID pDbgPointers_,
  246. ULONG_PTR dwAddress
  247. )
  248. {
  249. PDBG_POINTERS pDbgPointers = (PDBG_POINTERS)pDbgPointers_;
  250. Print( "DBG_POINTERS*\n" );
  251. Print( "hMemHeap !heap -a %x\n", pDbgPointers->hMemHeap );
  252. Print( "hDbgMemHeap !heap -a %x\n", pDbgPointers->hDbgMemHeap );
  253. Print( "pbtAlloc !splx.ddt -x %x\n", pDbgPointers->pbtAlloc );
  254. Print( "pbtFree !splx.ddt -x %x\n", pDbgPointers->pbtFree );
  255. Print( "pbtErrLog !splx.ddt %x\n", pDbgPointers->pbtErrLog );
  256. Print( "pbtTraceLog !splx.ddt %x\n", pDbgPointers->pbtTraceLog );
  257. return TRUE;
  258. }
  259. /********************************************************************
  260. Extension entrypoints.
  261. ********************************************************************/
  262. DEBUG_EXT_ENTRY( dthdm, TThreadM, bDumpThreadM, NULL, FALSE )
  263. DEBUG_EXT_ENTRY( dcs, MCritSec, bDumpCritSec, NULL, FALSE )
  264. DEBUG_EXT_ENTRY( ddp, DBG_POINTERS, bDumpDbgPointers, "&gpDbgPointers", FALSE )
  265. DEBUG_EXT_HEAD(dbt)
  266. {
  267. DEBUG_EXT_SETUP_VARS();
  268. TDebugExt::vDumpTrace( TDebugExt::dwEval( lpArgumentString, FALSE ));
  269. }
  270. DEBUG_EXT_HEAD(ddt)
  271. {
  272. DEBUG_EXT_SETUP_VARS();
  273. vDumpTraceWithFlags( lpArgumentString, 0 );
  274. }
  275. DEBUG_EXT_HEAD(dmem)
  276. {
  277. DEBUG_EXT_SETUP_VARS();
  278. TDebugExt::vDumpMem( lpArgumentString );
  279. }
  280. /********************************************************************
  281. Helper funcs.
  282. ********************************************************************/
  283. VOID
  284. vDumpTraceWithFlags(
  285. LPSTR lpArgumentString,
  286. ULONG_PTR dwAddress
  287. )
  288. {
  289. COUNT Count = 10;
  290. BOOL bRaw = FALSE;
  291. DWORD DebugTrace = DEBUG_TRACE_NONE;
  292. DWORD DebugLevel = (DWORD)-1;
  293. DWORD dwThreadId = 0;
  294. DWORD dwSkip = 0;
  295. ULONG_PTR dwMem = 0;
  296. for( ; *lpArgumentString; ++lpArgumentString ){
  297. while( *lpArgumentString == ' ' ){
  298. ++lpArgumentString;
  299. }
  300. if (*lpArgumentString != '-') {
  301. break;
  302. }
  303. ++lpArgumentString;
  304. switch( *lpArgumentString++ ){
  305. case 'T':
  306. case 't':
  307. dwThreadId = (DWORD)TDebugExt::dwEvalParam( lpArgumentString );
  308. break;
  309. case 'L':
  310. case 'l':
  311. DebugLevel = (DWORD)TDebugExt::dwEvalParam( lpArgumentString );
  312. break;
  313. case 'C':
  314. case 'c':
  315. Count = (COUNT)TDebugExt::dwEvalParam( lpArgumentString );
  316. break;
  317. case 'M':
  318. case 'm':
  319. dwMem = TDebugExt::dwEvalParam( lpArgumentString );
  320. break;
  321. case 'R':
  322. case 'r':
  323. bRaw = TRUE;
  324. break;
  325. case 'b':
  326. case 'B':
  327. DebugTrace |= DEBUG_TRACE_BT;
  328. break;
  329. case 'X':
  330. case 'x':
  331. DebugTrace |= DEBUG_TRACE_HEX;
  332. break;
  333. case 'd':
  334. case 'D':
  335. DebugTrace |= DEBUG_TRACE_DBGMSG;
  336. break;
  337. case 's':
  338. case 'S':
  339. dwSkip = (DWORD)TDebugExt::dwEvalParam( lpArgumentString );
  340. break;
  341. default:
  342. Print( "Unknown option %c.\n", lpArgumentString[-1] );
  343. return;
  344. }
  345. }
  346. if( !dwAddress ){
  347. dwAddress = TDebugExt::dwEval( lpArgumentString );
  348. }
  349. if( bRaw ){
  350. TDebugExt::bDumpDebugTrace( dwAddress,
  351. Count,
  352. &dwSkip,
  353. DebugTrace,
  354. DebugLevel,
  355. dwThreadId,
  356. dwMem );
  357. return;
  358. }
  359. //
  360. // If nothing is set, default to dbg msgs.
  361. //
  362. if( !DebugTrace ){
  363. DebugTrace |= DEBUG_TRACE_DBGMSG;
  364. }
  365. if( !TDebugExt::bDumpBackTrace( dwAddress,
  366. Count,
  367. &dwSkip,
  368. DebugTrace,
  369. DebugLevel,
  370. dwThreadId,
  371. dwMem )){
  372. Print( "Unknown Signature\n" );
  373. }
  374. }