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.

902 lines
21 KiB

  1. /*++
  2. Copyright (c) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. dbginet.cxx
  5. Abstract:
  6. This module contains the default ntsd debugger extensions for
  7. Internet Information Server
  8. Author:
  9. Murali R. Krishnan (MuraliK) 16-Sept-1996
  10. Revision History:
  11. --*/
  12. #include "inetdbgp.h"
  13. /************************************************************
  14. * Scheduler Related functions
  15. ************************************************************/
  16. // Keep this array in synch with the SCHED_ITEM_STATE enumeration
  17. char * g_rgchSchedState[] = {
  18. "SiError",
  19. "SiIdle",
  20. "SiActive",
  21. "SiActivePeriodic",
  22. "SiCallbackPeriodic",
  23. "SiToBeDeleted",
  24. "SiMaxItems"
  25. };
  26. #define LookupSchedState( ItemState ) \
  27. ((((ItemState) >= SI_ERROR) && ((ItemState) <= SI_MAX_ITEMS)) ? \
  28. g_rgchSchedState[ (ItemState)] : "<Invalid>")
  29. // Initialize class static members
  30. CSchedData* CSchedData::sm_psd = NULL;
  31. CLockedDoubleList CSchedData::sm_lstSchedulers;
  32. LONG CSchedData::sm_nID = 0;
  33. LONG CThreadData::sm_nID = 1000;
  34. LONG SCHED_ITEM::sm_lSerialNumber = SCHED_ITEM::SERIAL_NUM_INITIAL_VALUE;
  35. VOID
  36. PrintSchedItem( SCHED_ITEM * pschDebuggee,
  37. SCHED_ITEM * pschDebugger,
  38. CHAR Verbosity);
  39. VOID
  40. PrintThreadDataThunk( PVOID ptdDebuggee,
  41. PVOID ptdDebugger,
  42. CHAR chVerbosity,
  43. DWORD iThunk);
  44. VOID
  45. PrintThreadData( CThreadData* ptdDebuggee,
  46. CThreadData* ptdDebugger,
  47. CHAR chVerbosity);
  48. VOID
  49. PrintSchedData( CSchedData* psdDebuggee,
  50. CSchedData* psdDebugger,
  51. CHAR chVerbosity);
  52. VOID
  53. PrintSchedDataThunk( PVOID psdDebuggee,
  54. PVOID psdDebugger,
  55. CHAR chVerbosity,
  56. DWORD iThunk);
  57. VOID
  58. DumpSchedItemList(
  59. CHAR Verbosity
  60. );
  61. VOID
  62. DumpSchedulersList(
  63. CHAR Verbosity
  64. );
  65. DECLARE_API( sched )
  66. /*++
  67. Routine Description:
  68. This function is called as an NTSD extension to format and dump
  69. an object attributes structure.
  70. Arguments:
  71. hCurrentProcess - Supplies a handle to the current process (at the
  72. time the extension was called).
  73. hCurrentThread - Supplies a handle to the current thread (at the
  74. time the extension was called).
  75. CurrentPc - Supplies the current pc at the time the extension is
  76. called.
  77. lpExtensionApis - Supplies the address of the functions callable
  78. by this extension.
  79. lpArgumentString - Supplies the asciiz string that describes the
  80. ansi string to be dumped.
  81. Return Value:
  82. None.
  83. --*/
  84. {
  85. BOOL fRet;
  86. SCHED_ITEM sch( NULL, NULL, NULL);
  87. SCHED_ITEM * psch;
  88. INIT_API();
  89. while (*lpArgumentString == ' ')
  90. lpArgumentString++;
  91. if ( !*lpArgumentString )
  92. {
  93. PrintUsage( "sched" );
  94. return;
  95. }
  96. if ( *lpArgumentString == '-' )
  97. {
  98. lpArgumentString++;
  99. if ( *lpArgumentString == 'h' )
  100. {
  101. PrintUsage( "sched" );
  102. return;
  103. }
  104. else if ( *lpArgumentString == 'l' )
  105. {
  106. DumpSchedItemList( lpArgumentString[1] );
  107. return;
  108. }
  109. else if ( *lpArgumentString == 's' )
  110. {
  111. DumpSchedulersList( lpArgumentString[1] );
  112. return;
  113. }
  114. else if ( *lpArgumentString == 'S' )
  115. {
  116. CSchedData* psd = (CSchedData*) GetExpression(++lpArgumentString);
  117. if ( !psd )
  118. {
  119. dprintf( "inetdbg.sched: Unable to evaluate \"%s\"\n",
  120. lpArgumentString );
  121. return;
  122. }
  123. DEFINE_CPP_VAR(CSchedData, sd);
  124. move(sd, psd);
  125. PrintSchedData(psd, GET_CPP_VAR_PTR(CSchedData, sd), '2');
  126. return;
  127. }
  128. else if ( *lpArgumentString == 'T' )
  129. {
  130. CThreadData* ptd =(CThreadData*) GetExpression(++lpArgumentString);
  131. if ( !ptd )
  132. {
  133. dprintf( "inetdbg.sched: Unable to evaluate \"%s\"\n",
  134. lpArgumentString );
  135. return;
  136. }
  137. DEFINE_CPP_VAR(CThreadData, td);
  138. move(td, ptd);
  139. PrintThreadData(ptd, GET_CPP_VAR_PTR(CThreadData, td), '2');
  140. return;
  141. }
  142. } // while
  143. //
  144. // Treat the argument as the address of a SCHED_ITEM
  145. //
  146. psch = (SCHED_ITEM * ) GetExpression( lpArgumentString );
  147. if ( !psch )
  148. {
  149. dprintf( "inetdbg.sched: Unable to evaluate \"%s\"\n",
  150. lpArgumentString );
  151. return;
  152. }
  153. move( sch, psch );
  154. PrintSchedItem( psch, &sch, '2' );
  155. return;
  156. } // DECLARE_API( sched )
  157. VOID
  158. PrintSchedItem( SCHED_ITEM * pschDebuggee,
  159. SCHED_ITEM * pschDebugger,
  160. CHAR chVerbosity)
  161. {
  162. if ( chVerbosity >= '0' )
  163. {
  164. // Print all with one line summary info
  165. dprintf( "%p: Serial=%-6d Flink=%p, Blink=%p, State=%s\n",
  166. pschDebuggee,
  167. pschDebugger->_dwSerialNumber,
  168. pschDebugger->_ListEntry.Flink,
  169. pschDebugger->_ListEntry.Blink,
  170. LookupSchedState( pschDebugger->_siState) );
  171. }
  172. if ( chVerbosity >= '1')
  173. {
  174. UCHAR szSymFnCallback[MAX_SYMBOL_LEN];
  175. ULONG_PTR offset;
  176. GetSymbol((ULONG_PTR) pschDebugger->_pfnCallback,
  177. szSymFnCallback, &offset);
  178. if (!*szSymFnCallback)
  179. sprintf((char*) szSymFnCallback, "%p()",
  180. pschDebugger->_pfnCallback);
  181. dprintf( "\tSignature = '%c%c%c%c' Context = %08p\n"
  182. "\tmsecInterval = %8d msecExpires = %I64d\n"
  183. "\tpfnCallBack = %s\n",
  184. DECODE_SIGNATURE(pschDebugger->_Signature),
  185. pschDebugger->_pContext,
  186. pschDebugger->_msecInterval,
  187. pschDebugger->_msecExpires,
  188. szSymFnCallback
  189. );
  190. }
  191. return;
  192. } // PrintSchedItem()
  193. VOID
  194. PrintSchedItemThunk( PVOID pschDebuggee,
  195. PVOID pschDebugger,
  196. CHAR chVerbosity,
  197. DWORD iThunk)
  198. {
  199. if ( ((SCHED_ITEM * )pschDebugger)->_Signature != SIGNATURE_SCHED_ITEM) {
  200. dprintf( "SCHED_ITEM(%p) signature %08lx doesn't"
  201. " match expected %08lx\n",
  202. pschDebuggee,
  203. ((SCHED_ITEM * )pschDebugger)->_Signature,
  204. SIGNATURE_SCHED_ITEM
  205. );
  206. return;
  207. }
  208. PrintSchedItem( (SCHED_ITEM*) pschDebuggee,
  209. (SCHED_ITEM*) pschDebugger,
  210. chVerbosity);
  211. } // PrintSchedItemThunk()
  212. VOID
  213. PrintThreadData( CThreadData* ptdDebuggee,
  214. CThreadData* ptdDebugger,
  215. CHAR chVerbosity)
  216. {
  217. if ( chVerbosity >= '0' )
  218. {
  219. // Print all with one line summary info
  220. dprintf( "CThreadData %p: ID=%-6d, Flink=%p, Blink=%p\n",
  221. ptdDebuggee,
  222. ptdDebugger->m_nID,
  223. ptdDebugger->m_leThreads.Flink,
  224. ptdDebugger->m_leThreads.Blink
  225. );
  226. }
  227. if ( chVerbosity >= '1')
  228. {
  229. dprintf( "\tm_dwSignature = '%c%c%c%c' m_psdOwner = %08lp\n"
  230. "\tm_hevtShutdown = %08lp m_hThreadSelf = %08lx.\n"
  231. ,
  232. DECODE_SIGNATURE(ptdDebugger->m_dwSignature),
  233. ptdDebugger->m_psdOwner,
  234. ptdDebugger->m_hevtShutdown,
  235. ptdDebugger->m_hThreadSelf
  236. );
  237. }
  238. return;
  239. } // PrintThreadData()
  240. VOID
  241. PrintThreadDataThunk( PVOID ptdDebuggee,
  242. PVOID ptdDebugger,
  243. CHAR chVerbosity,
  244. DWORD iThunk)
  245. {
  246. if (((CThreadData*) ptdDebugger)->m_dwSignature != SIGNATURE_THREADDATA)
  247. {
  248. dprintf( "CThreadData(%08p) signature %08lx doesn't"
  249. " match expected: %08lx\n",
  250. ptdDebuggee,
  251. ((CThreadData * )ptdDebugger)->m_dwSignature,
  252. SIGNATURE_THREADDATA
  253. );
  254. return;
  255. }
  256. PrintThreadData( (CThreadData *) ptdDebuggee,
  257. (CThreadData *) ptdDebugger,
  258. chVerbosity);
  259. } // PrintThreadDataThunk()
  260. VOID
  261. PrintSchedData( CSchedData* psdDebuggee,
  262. CSchedData* psdDebugger,
  263. CHAR chVerbosity)
  264. {
  265. if ( chVerbosity >= '0' )
  266. {
  267. // Print all with one line summary info
  268. dprintf( "CSchedData %p: ID=%d, Flink=%p, Blink=%p\n",
  269. psdDebuggee,
  270. psdDebugger->m_nID,
  271. psdDebugger->m_leGlobalList.Flink,
  272. psdDebugger->m_leGlobalList.Blink
  273. );
  274. }
  275. if ( chVerbosity >= '1')
  276. {
  277. dprintf( "\tm_dwSignature = '%c%c%c%c' m_lstItems = %08lp\n"
  278. "\tm_lstThreads = %08lp m_cRefs = %d\n"
  279. "\tm_hevtNotify = %08lp m_fShutdown = %s\n"
  280. "\tm_pachSchedItems= %08lp\n"
  281. ,
  282. DECODE_SIGNATURE(psdDebugger->m_dwSignature),
  283. &psdDebuggee->m_lstItems,
  284. &psdDebuggee->m_lstThreads,
  285. psdDebugger->m_cRefs,
  286. psdDebugger->m_hevtNotify,
  287. BoolValue(psdDebugger->m_fShutdown),
  288. psdDebugger->m_pachSchedItems
  289. );
  290. }
  291. if ( chVerbosity >= '2')
  292. {
  293. dprintf("Threads\n");
  294. EnumLinkedList((LIST_ENTRY*)&psdDebuggee->m_lstThreads.m_list.m_leHead,
  295. PrintThreadDataThunk,
  296. chVerbosity,
  297. sizeof(CThreadData),
  298. FIELD_OFFSET( CThreadData, m_leThreads)
  299. );
  300. }
  301. return;
  302. } // PrintSchedData()
  303. VOID
  304. PrintSchedDataThunk( PVOID psdDebuggee,
  305. PVOID psdDebugger,
  306. CHAR chVerbosity,
  307. DWORD iThunk)
  308. {
  309. if (((CSchedData*) psdDebugger)->m_dwSignature != SIGNATURE_SCHEDDATA)
  310. {
  311. dprintf( "CSchedData(%08p) signature %08lx doesn't"
  312. " match expected: %08lx\n",
  313. psdDebuggee,
  314. ((CSchedData*) psdDebugger)->m_dwSignature,
  315. SIGNATURE_SCHEDDATA
  316. );
  317. return;
  318. }
  319. PrintSchedData( (CSchedData*) psdDebuggee,
  320. (CSchedData*) psdDebugger,
  321. chVerbosity);
  322. } // PrintSchedDataThunk()
  323. VOID
  324. DumpSchedItemList(
  325. CHAR Verbosity
  326. )
  327. {
  328. CSchedData** ppsd = (CSchedData**) GetExpression(
  329. IisRtlVar("&%s!CSchedData__sm_psd"));
  330. if (NULL == ppsd)
  331. {
  332. dprintf("Unable to get %s\n", IisRtlVar("&%s!CSchedData__sm_psd"));
  333. return;
  334. }
  335. CSchedData* psd;
  336. move(psd, ppsd);
  337. DEFINE_CPP_VAR( CSchedData, sd);
  338. move(sd, psd);
  339. PrintSchedData(psd, GET_CPP_VAR_PTR(CSchedData, sd), Verbosity);
  340. dprintf("\n");
  341. EnumLinkedList( (LIST_ENTRY*) &psd->m_lstItems.m_list.m_leHead,
  342. PrintSchedItemThunk,
  343. Verbosity,
  344. sizeof( SCHED_ITEM),
  345. FIELD_OFFSET( SCHED_ITEM, _ListEntry)
  346. );
  347. return;
  348. } // DumpSchedItemList()
  349. VOID
  350. DumpSchedulersList(
  351. CHAR Verbosity
  352. )
  353. {
  354. CLockedDoubleList* plstSchedulers = (CLockedDoubleList*) GetExpression(
  355. IisRtlVar("&%s!CSchedData__sm_lstSchedulers"));
  356. if (NULL == plstSchedulers)
  357. {
  358. dprintf("Unable to get %s\n",
  359. IisRtlVar("&%s!CSchedData__sm_lstSchedulers"));
  360. return;
  361. }
  362. EnumLinkedList( (LIST_ENTRY*) &plstSchedulers->m_list.m_leHead,
  363. PrintSchedDataThunk,
  364. Verbosity,
  365. sizeof(CSchedData),
  366. FIELD_OFFSET( CSchedData, m_leGlobalList)
  367. );
  368. return;
  369. } // DumpSchedulersList()
  370. /************************************************************
  371. * Allocation cache Related functions
  372. ************************************************************/
  373. ALLOC_CACHE_HANDLER::ALLOC_CACHE_HANDLER(
  374. IN LPCSTR pszName,
  375. IN const ALLOC_CACHE_CONFIGURATION * pacConfig)
  376. {}
  377. ALLOC_CACHE_HANDLER::~ALLOC_CACHE_HANDLER(VOID)
  378. {}
  379. VOID
  380. PrintAcacheHandler( IN ALLOC_CACHE_HANDLER * pachDebuggee,
  381. IN ALLOC_CACHE_HANDLER * pachDebugger,
  382. IN CHAR chVerbostity);
  383. VOID
  384. DumpAcacheGlobals( VOID );
  385. VOID
  386. DumpAcacheList(
  387. CHAR Verbosity
  388. );
  389. DECLARE_API( acache )
  390. /*++
  391. Routine Description:
  392. This function is called as an NTSD extension to format and dump
  393. an object attributes structure.
  394. Arguments:
  395. hCurrentProcess - Supplies a handle to the current process (at the
  396. time the extension was called).
  397. hCurrentThread - Supplies a handle to the current thread (at the
  398. time the extension was called).
  399. CurrentPc - Supplies the current pc at the time the extension is
  400. called.
  401. lpExtensionApis - Supplies the address of the functions callable
  402. by this extension.
  403. lpArgumentString - Supplies the asciiz string that describes the
  404. ansi string to be dumped.
  405. Return Value:
  406. None.
  407. --*/
  408. {
  409. BOOL fRet;
  410. ALLOC_CACHE_HANDLER * pach;
  411. //
  412. // Since ALLOC_CACHE_HANDLER is a C++ object with a non-void
  413. // constructor, we will have to copy the contents to a temporary
  414. // buffer and cast the value appropriately.
  415. //
  416. CHAR achItem[sizeof(ALLOC_CACHE_HANDLER)];
  417. ALLOC_CACHE_HANDLER * pachCopy = (ALLOC_CACHE_HANDLER *) achItem;
  418. INIT_API();
  419. while (*lpArgumentString == ' ')
  420. lpArgumentString++;
  421. if ( !*lpArgumentString )
  422. {
  423. PrintUsage( "acache" );
  424. return;
  425. }
  426. if ( *lpArgumentString == '-' )
  427. {
  428. lpArgumentString++;
  429. if ( *lpArgumentString == 'h' )
  430. {
  431. PrintUsage( "acache" );
  432. return;
  433. }
  434. if ( *lpArgumentString == 'g' )
  435. {
  436. DumpAcacheGlobals();
  437. return;
  438. }
  439. if ( *lpArgumentString == 'l' ) {
  440. DumpAcacheList( lpArgumentString[1] );
  441. return;
  442. }
  443. } // while
  444. //
  445. // Treat the argument as the address of an AtqContext
  446. //
  447. dprintf( "inetdbg.acache: Trying to access %s\n",
  448. lpArgumentString );
  449. pach = (ALLOC_CACHE_HANDLER * ) GetExpression( lpArgumentString );
  450. if ( !pach )
  451. {
  452. dprintf( "inetdbg.acache: Unable to evaluate \"%s\"\n",
  453. lpArgumentString );
  454. return;
  455. }
  456. moveBlock( achItem, pach, sizeof(ALLOC_CACHE_HANDLER));
  457. PrintAcacheHandler( pach, pachCopy, '2' );
  458. return;
  459. } // DECLARE_API( acache )
  460. VOID
  461. PrintAcacheHandler( ALLOC_CACHE_HANDLER * pachDebuggee,
  462. ALLOC_CACHE_HANDLER * pachDebugger,
  463. CHAR chVerbosity)
  464. {
  465. if ( chVerbosity >= '0') {
  466. dprintf(
  467. "ACACHE[%8p] "
  468. , pachDebuggee
  469. );
  470. dstring( "Name", (PVOID) pachDebugger->m_pszName, 40);
  471. }
  472. if ( chVerbosity >= '1') {
  473. dprintf("\t(Size=%d bytes, Concurrency=%d, Threshold=%u)"
  474. " FillPattern=%08lX\n"
  475. "\tTotal=%d."
  476. " Calls:(Alloc=%d, Free=%d)"
  477. " FreeEntries=%d. Heap=%p.\n"
  478. ,
  479. pachDebugger->m_acConfig.cbSize,
  480. pachDebugger->m_acConfig.nConcurrency,
  481. pachDebugger->m_acConfig.nThreshold,
  482. pachDebugger->m_nFillPattern,
  483. pachDebugger->m_nTotal,
  484. pachDebugger->m_nAllocCalls, pachDebugger->m_nFreeCalls,
  485. pachDebugger->m_nFreeEntries, pachDebugger->m_hHeap
  486. );
  487. }
  488. return;
  489. } // PrintAcacheHandler()
  490. VOID
  491. PrintAcacheHandlerThunk( PVOID pachDebuggee,
  492. PVOID pachDebugger,
  493. CHAR chVerbosity,
  494. DWORD iCount)
  495. {
  496. dprintf( "[%d] ", iCount);
  497. PrintAcacheHandler( (ALLOC_CACHE_HANDLER *) pachDebuggee,
  498. (ALLOC_CACHE_HANDLER *) pachDebugger,
  499. chVerbosity);
  500. return;
  501. } // PrintAcacheHandlerThunk()
  502. VOID
  503. DumpAcacheGlobals( VOID )
  504. {
  505. LIST_ENTRY * pachList;
  506. LIST_ENTRY achList;
  507. dprintf("Allocation Cache Globals:\n");
  508. pachList = (LIST_ENTRY *)
  509. GetExpression( IisRtlVar("&%s!ALLOC_CACHE_HANDLER__sm_lItemsHead"));
  510. if ( NULL == pachList) {
  511. dprintf( " Unable to get Allocation cache list object, %s\n",
  512. IisRtlVar("&%s!ALLOC_CACHE_HANDLER__sm_lItemsHead"));
  513. return;
  514. }
  515. move( achList, pachList);
  516. dprintf( " AllocCacheList Flink = %08p Blink = %08p\n",
  517. achList.Flink, achList.Blink
  518. );
  519. dprintf("\tsizeof(ALLOC_CACHE_HANDLER) = %d\n",
  520. sizeof(ALLOC_CACHE_HANDLER));
  521. return;
  522. } // DumpAcacheGlobals()
  523. VOID
  524. DumpAcacheList(
  525. CHAR Verbosity
  526. )
  527. {
  528. LIST_ENTRY * pachListHead;
  529. pachListHead = (LIST_ENTRY *)
  530. GetExpression( IisRtlVar("&%s!ALLOC_CACHE_HANDLER__sm_lItemsHead"));
  531. if ( NULL == pachListHead) {
  532. dprintf( " Unable to get Alloc Cache List object, %s\n",
  533. IisRtlVar("&%s!ALLOC_CACHE_HANDLER__sm_lItemsHead"));
  534. return;
  535. }
  536. EnumLinkedList( pachListHead, PrintAcacheHandlerThunk, Verbosity,
  537. sizeof( ALLOC_CACHE_HANDLER),
  538. FIELD_OFFSET( ALLOC_CACHE_HANDLER, m_lItemsEntry)
  539. );
  540. return;
  541. } // DumpAcacheList()
  542. /************************************************************
  543. * Dump Symbols from stack
  544. ************************************************************/
  545. DECLARE_API( ds )
  546. /*++
  547. Routine Description:
  548. This function is called as an NTSD extension to format and dump
  549. symbols on the stack.
  550. Arguments:
  551. hCurrentProcess - Supplies a handle to the current process (at the
  552. time the extension was called).
  553. hCurrentThread - Supplies a handle to the current thread (at the
  554. time the extension was called).
  555. CurrentPc - Supplies the current pc at the time the extension is
  556. called.
  557. lpExtensionApis - Supplies the address of the functions callable
  558. by this extension.
  559. lpArgumentString - Supplies the asciiz string that describes the
  560. ansi string to be dumped.
  561. Return Value:
  562. None.
  563. --*/
  564. {
  565. ULONG_PTR startingAddress;
  566. ULONG_PTR stack;
  567. DWORD i;
  568. UCHAR symbol[MAX_SYMBOL_LEN];
  569. ULONG_PTR offset;
  570. PCHAR format;
  571. BOOL validSymbolsOnly = FALSE;
  572. MODULE_INFO moduleInfo;
  573. INIT_API();
  574. //
  575. // Skip leading blanks.
  576. //
  577. while( *lpArgumentString == ' ' ) {
  578. lpArgumentString++;
  579. }
  580. if( *lpArgumentString == '-' ) {
  581. lpArgumentString++;
  582. switch( *lpArgumentString ) {
  583. case 'v' :
  584. case 'V' :
  585. validSymbolsOnly = TRUE;
  586. lpArgumentString++;
  587. break;
  588. default :
  589. PrintUsage( "ds" );
  590. return;
  591. }
  592. }
  593. while( *lpArgumentString == ' ' ) {
  594. lpArgumentString++;
  595. }
  596. //
  597. // By default, start at the current stack location. Otherwise,
  598. // start at the given address.
  599. //
  600. if( !*lpArgumentString ) {
  601. #if defined(_X86_)
  602. lpArgumentString = "esp";
  603. #elif defined(_AMD64_)
  604. lpArgumentString = "rsp";
  605. #elif defined(_IA64_)
  606. lpArgumentString = "sp";
  607. #else
  608. #error "unsupported CPU"
  609. #endif
  610. }
  611. startingAddress = GetExpression( lpArgumentString );
  612. if( startingAddress == 0 ) {
  613. dprintf(
  614. "!inetdbg.ds: cannot evaluate \"%s\"\n",
  615. lpArgumentString
  616. );
  617. return;
  618. }
  619. //
  620. // Ensure startingAddress is DWORD aligned.
  621. //
  622. startingAddress &= ~(sizeof(ULONG_PTR)-1);
  623. //
  624. // Read the stack.
  625. //
  626. for( i = 0 ; i < NUM_STACK_SYMBOLS_TO_DUMP ; startingAddress += sizeof(ULONG_PTR) ) {
  627. if( CheckControlC() ) {
  628. break;
  629. }
  630. if( ReadMemory(
  631. startingAddress,
  632. &stack,
  633. sizeof(stack),
  634. NULL
  635. ) ) {
  636. GetSymbol(
  637. stack,
  638. symbol,
  639. &offset
  640. );
  641. if( symbol[0] == '\0' ) {
  642. if( FindModuleByAddress(
  643. stack,
  644. &moduleInfo
  645. ) ) {
  646. strcpy( (CHAR *)symbol, moduleInfo.FullName );
  647. offset = DIFF(stack - moduleInfo.DllBase);
  648. }
  649. }
  650. if( symbol[0] == '\0' ) {
  651. if( validSymbolsOnly ) {
  652. continue;
  653. }
  654. format = "%p : %p\n";
  655. } else
  656. if( offset == 0 ) {
  657. format = "%p : %p : %s\n";
  658. } else {
  659. format = "%p : %p : %s+0x%lx\n";
  660. }
  661. dprintf(
  662. format,
  663. startingAddress,
  664. stack,
  665. symbol,
  666. (DWORD)offset
  667. );
  668. i++;
  669. } else {
  670. dprintf(
  671. "!inetdbg.ds: cannot read memory @ %p\n",
  672. startingAddress
  673. );
  674. return;
  675. }
  676. }
  677. dprintf(
  678. "!inetdbg.ds %s%lx to dump next block\n",
  679. validSymbolsOnly ? "-v " : "",
  680. startingAddress
  681. );
  682. } // DECLARE_API( ds )