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.

1113 lines
20 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. util.c - Generic Debugger Extension Utilities
  5. Abstract:
  6. Taken from AliD's ndiskd(ndiskd.c).
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 03-30-98 Created (taken fron AliD's ndiskd (ndiskd.c).
  11. Notes:
  12. --*/
  13. #include "common.h"
  14. WINDBG_EXTENSION_APIS ExtensionApis;
  15. EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 };
  16. #define ERRPRT dprintf
  17. #define NL 1
  18. #define NONL 0
  19. USHORT SavedMajorVersion;
  20. USHORT SavedMinorVersion;
  21. BOOL ChkTarget; // is debuggee a CHK build?
  22. /*
  23. * Print out an optional message, an ANSI_STRING, and maybe a new-line
  24. */
  25. BOOL
  26. PrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
  27. {
  28. PCHAR StringData;
  29. ULONG BytesRead;
  30. if( msg )
  31. dprintf( msg );
  32. if( pStr->Length == 0 ) {
  33. if( nl )
  34. dprintf( "\n" );
  35. return TRUE;
  36. }
  37. StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
  38. if( StringData == NULL ) {
  39. ERRPRT( "Out of memory!\n" );
  40. return FALSE;
  41. }
  42. ReadMemory((ULONG_PTR) pStr->Buffer,
  43. StringData,
  44. pStr->Length,
  45. &BytesRead );
  46. if ( BytesRead ) {
  47. StringData[ pStr->Length ] = '\0';
  48. dprintf("%s%s", StringData, nl ? "\n" : "" );
  49. }
  50. LocalFree((HLOCAL)StringData);
  51. return BytesRead;
  52. }
  53. /*
  54. * Get 'size' bytes from the debuggee program at 'dwAddress' and place it
  55. * in our address space at 'ptr'. Use 'type' in an error printout if necessary
  56. */
  57. BOOL
  58. GetData( IN LPVOID ptr, IN UINT_PTR dwAddress, IN ULONG size, IN PCSTR type )
  59. {
  60. BOOL b;
  61. ULONG BytesRead;
  62. ULONG count = size;
  63. while( size > 0 ) {
  64. if (count >= 3000)
  65. count = 3000;
  66. b = ReadMemory(dwAddress, ptr, count, &BytesRead );
  67. if (!b || BytesRead != count ) {
  68. ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  69. return FALSE;
  70. }
  71. dwAddress += count;
  72. size -= count;
  73. ptr = (LPVOID)((ULONG_PTR)ptr + count);
  74. }
  75. return TRUE;
  76. }
  77. /*
  78. * Print out a single HEX character
  79. */
  80. VOID
  81. PrintHexChar( IN UCHAR c )
  82. {
  83. dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
  84. }
  85. /*
  86. * Print out 'buf' of 'cbuf' bytes as HEX characters
  87. */
  88. VOID
  89. PrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
  90. {
  91. while( cbuf-- ) {
  92. PrintHexChar( *buf++ );
  93. dprintf( " " );
  94. }
  95. }
  96. /*
  97. * Fetch the null terminated UNICODE string at dwAddress into buf
  98. */
  99. BOOL
  100. GetString( IN UINT_PTR dwAddress, IN LPWSTR buf, IN ULONG MaxChars )
  101. {
  102. do {
  103. if( !GetData( buf, dwAddress, sizeof( *buf ), "Character" ) )
  104. return FALSE;
  105. dwAddress += sizeof( *buf );
  106. } while( --MaxChars && *buf++ != '\0' );
  107. return TRUE;
  108. }
  109. char *mystrtok ( char *string, char * control )
  110. {
  111. static UCHAR *str;
  112. char *p, *s;
  113. if( string )
  114. str = string;
  115. if( str == NULL || *str == '\0' )
  116. return NULL;
  117. //
  118. // Skip leading delimiters...
  119. //
  120. for( ; *str; str++ ) {
  121. for( s=control; *s; s++ ) {
  122. if( *str == *s )
  123. break;
  124. }
  125. if( *s == '\0' )
  126. break;
  127. }
  128. //
  129. // Was it was all delimiters?
  130. //
  131. if( *str == '\0' ) {
  132. str = NULL;
  133. return NULL;
  134. }
  135. //
  136. // We've got a string, terminate it at first delimeter
  137. //
  138. for( p = str+1; *p; p++ ) {
  139. for( s = control; *s; s++ ) {
  140. if( *p == *s ) {
  141. s = str;
  142. *p = '\0';
  143. str = p+1;
  144. return s;
  145. }
  146. }
  147. }
  148. //
  149. // We've got a string that ends with the NULL
  150. //
  151. s = str;
  152. str = NULL;
  153. return s;
  154. }
  155. VOID
  156. WinDbgExtensionDllInit(
  157. PWINDBG_EXTENSION_APIS lpExtensionApis,
  158. USHORT MajorVersion,
  159. USHORT MinorVersion
  160. )
  161. {
  162. ExtensionApis = *lpExtensionApis;
  163. g_pfnDbgPrintf = dprintf;
  164. SavedMajorVersion = MajorVersion;
  165. SavedMinorVersion = MinorVersion;
  166. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  167. }
  168. DECLARE_API( version )
  169. {
  170. #if DBG
  171. PCSTR kind = "Checked";
  172. #else
  173. PCSTR kind = "Free";
  174. #endif
  175. dprintf(
  176. "%s IPATM Extension dll for Build %d debugging %s kernel for Build %d\n",
  177. kind,
  178. VER_PRODUCTBUILD,
  179. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  180. SavedMinorVersion
  181. );
  182. }
  183. VOID
  184. CheckVersion(
  185. VOID
  186. )
  187. {
  188. //
  189. // for now don't bother to version check
  190. //
  191. return;
  192. #if DBG
  193. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  194. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  195. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  196. }
  197. #else
  198. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  199. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  200. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  201. }
  202. #endif
  203. }
  204. LPEXT_API_VERSION
  205. ExtensionApiVersion(
  206. VOID
  207. )
  208. {
  209. return &ApiVersion;
  210. }
  211. //
  212. // VOID
  213. // PrintName(
  214. // PUNICODE_STRING Name
  215. // );
  216. // print a unicode string
  217. // Note: the Buffer field in unicode string is unmapped
  218. //
  219. VOID
  220. PrintName(
  221. PUNICODE_STRING Name
  222. )
  223. {
  224. USHORT i;
  225. WCHAR ubuf[256];
  226. UCHAR abuf[256];
  227. if (!GetString((UINT_PTR)Name->Buffer, ubuf, (ULONG)Name->Length))
  228. {
  229. return;
  230. }
  231. for (i = 0; i < Name->Length/2; i++)
  232. {
  233. abuf[i] = (UCHAR)ubuf[i];
  234. }
  235. abuf[i] = 0;
  236. dprintf("%s",abuf);
  237. }
  238. MYPWINDBG_OUTPUT_ROUTINE g_pfnDbgPrintf = NULL;
  239. bool
  240. dbgextReadMemory(
  241. UINT_PTR uOffset,
  242. void * pvBuffer,
  243. UINT cb,
  244. char *pszDescription
  245. )
  246. {
  247. UINT cbBytesRead=0;
  248. bool fRet = ReadMemory(
  249. uOffset,
  250. pvBuffer,
  251. cb,
  252. &cbBytesRead
  253. );
  254. if (!fRet || cbBytesRead != cb)
  255. {
  256. ERRPRT("Read failed: 0x%X(%s, %u bytes)\n",uOffset,pszDescription,cb);
  257. fRet = FALSE;
  258. }
  259. return fRet;
  260. }
  261. bool
  262. dbgextWriteMemory(
  263. UINT_PTR uOffset,
  264. void * pvBuffer,
  265. UINT cb,
  266. char *pszDescription
  267. )
  268. {
  269. UINT cbBytesWritten=0;
  270. bool fRet = WriteMemory(
  271. uOffset,
  272. pvBuffer,
  273. cb,
  274. &cbBytesWritten
  275. );
  276. if (!fRet || cbBytesWritten != cb)
  277. {
  278. ERRPRT("Write failed: 0x%X(%s, %u bytes)\n",uOffset,pszDescription,cb);
  279. fRet = FALSE;
  280. }
  281. return 0;
  282. }
  283. bool
  284. dbgextReadUINT_PTR(
  285. UINT_PTR uOffset,
  286. UINT_PTR *pu,
  287. char *pszDescription
  288. )
  289. {
  290. UINT cbBytesRead=0;
  291. bool fRet = ReadMemory(
  292. uOffset,
  293. pu,
  294. sizeof(*pu),
  295. &cbBytesRead
  296. );
  297. if (!fRet || cbBytesRead != sizeof(*pu))
  298. {
  299. ERRPRT("Read failed: 0x%X(%s, UINT_PTR)\n",uOffset,pszDescription);
  300. fRet = FALSE;
  301. }
  302. return fRet;
  303. }
  304. bool
  305. dbgextReadUINT(
  306. UINT_PTR uOffset,
  307. UINT *pu,
  308. char *pszDescription
  309. )
  310. {
  311. UINT cbBytesRead=0;
  312. bool fRet = ReadMemory(
  313. uOffset,
  314. pu,
  315. sizeof(*pu),
  316. &cbBytesRead
  317. );
  318. if (!fRet || cbBytesRead != sizeof(*pu))
  319. {
  320. ERRPRT("Read failed: 0x%X(%s, UINT)\n",uOffset,pszDescription);
  321. fRet = FALSE;
  322. }
  323. return fRet;
  324. }
  325. bool
  326. dbgextReadSZ(
  327. UINT_PTR uOffset,
  328. char *szBuf,
  329. UINT cbMax,
  330. char *pszDescription
  331. )
  332. // Read a NULL-terminated string (upto cbMax)
  333. //
  334. {
  335. UINT cbBytesRead=0;
  336. bool fRet = ReadMemory(
  337. uOffset,
  338. szBuf,
  339. cbMax,
  340. &cbBytesRead
  341. );
  342. if (!fRet)
  343. {
  344. ERRPRT("Read failed: 0x%p(%s, SZ)\n",uOffset,pszDescription);
  345. fRet = FALSE;
  346. }
  347. else
  348. {
  349. if (cbBytesRead)
  350. {
  351. szBuf[cbBytesRead-1] = 0;
  352. }
  353. else
  354. {
  355. *szBuf = 0;
  356. }
  357. }
  358. return fRet;
  359. }
  360. bool
  361. dbgextWriteUINT_PTR(
  362. UINT_PTR uOffset,
  363. UINT_PTR u,
  364. char *pszDescription
  365. )
  366. {
  367. UINT cbBytesWritten=0;
  368. bool fRet = WriteMemory(
  369. uOffset,
  370. &u,
  371. sizeof(uOffset),
  372. &cbBytesWritten
  373. );
  374. if (!fRet || cbBytesWritten != sizeof(u))
  375. {
  376. ERRPRT("Write failed: 0x%X(%s, UINT_PTR)\n",uOffset,pszDescription);
  377. fRet = FALSE;
  378. }
  379. return fRet;
  380. }
  381. UINT_PTR
  382. dbgextGetExpression(
  383. const char *pcszExpression
  384. )
  385. {
  386. UINT_PTR uRet = GetExpression(pcszExpression);
  387. //
  388. // At such a point we use this for something besides pointers,
  389. // we will remove the check below.
  390. //
  391. if (!uRet)
  392. {
  393. ERRPRT("Eval failed: \"%s\"\n", pcszExpression);
  394. }
  395. return uRet;
  396. }
  397. void
  398. dbgextDumpDLlist(
  399. UINT_PTR uOffset,
  400. UINT uContainingOffset,
  401. char *pszDescription
  402. )
  403. /*++
  404. Print the pointers to the containing records of
  405. all the items in the doubly-linked list.
  406. --*/
  407. {
  408. bool fRet;
  409. LIST_ENTRY Link;
  410. LIST_ENTRY *pHead;
  411. LIST_ENTRY *pFlink;
  412. UINT uCount = 0;
  413. UINT uMax = 16;
  414. do
  415. {
  416. char *szPrefix;
  417. char *szSuffix;
  418. // Read the list header.
  419. //
  420. fRet = dbgextReadMemory(
  421. uOffset,
  422. &Link,
  423. sizeof(Link),
  424. pszDescription
  425. );
  426. if (!fRet) break;
  427. pHead = (LIST_ENTRY *) uOffset;
  428. pFlink = Link.Flink;
  429. if (pFlink == pHead)
  430. {
  431. MyDbgPrintf(" <empty>\n");
  432. break;
  433. }
  434. for(
  435. ;
  436. (pFlink != pHead);
  437. pFlink = Link.Flink, uCount++)
  438. {
  439. char *pContainingRecord = ((char *)pFlink) - uContainingOffset;
  440. szPrefix = " ";
  441. szSuffix = "";
  442. if (uCount%4)
  443. {
  444. szPrefix = " ";
  445. if ((uCount%4)==3)
  446. {
  447. szSuffix = "\n";
  448. }
  449. }
  450. if (uCount >= uMax) break;
  451. // Read the next link.
  452. //
  453. fRet = dbgextReadMemory(
  454. (UINT_PTR) pFlink,
  455. &Link,
  456. sizeof(Link),
  457. pszDescription
  458. );
  459. if (!fRet) break;
  460. MyDbgPrintf("%s0x%p%s", szPrefix, pContainingRecord, szSuffix);
  461. }
  462. if (uCount%4)
  463. {
  464. MyDbgPrintf("\n");
  465. }
  466. if (pFlink != pHead && uCount >= uMax)
  467. {
  468. MyDbgPrintf(" ...\n");
  469. }
  470. } while (FALSE);
  471. }
  472. void
  473. WalkDLlist(
  474. UINT_PTR uOffsetHeadList,
  475. UINT_PTR uOffsetStartLink, OPTIONAL
  476. void *pvContext,
  477. PFNNODEFUNC pFunc,
  478. UINT MaxToWalk,
  479. char *pszDescription
  480. )
  481. /*++
  482. Print the pointers to the containing records of
  483. all the items in the doubly-linked list.
  484. --*/
  485. {
  486. bool fRet;
  487. LIST_ENTRY Link;
  488. LIST_ENTRY *pHead;
  489. LIST_ENTRY *pFlink;
  490. UINT uCount = 0;
  491. UINT uMax = MaxToWalk;
  492. do
  493. {
  494. // Read the list header.
  495. //
  496. fRet = dbgextReadMemory(
  497. uOffsetHeadList,
  498. &Link,
  499. sizeof(Link),
  500. pszDescription
  501. );
  502. if (!fRet) break;
  503. pHead = (LIST_ENTRY *) uOffsetHeadList;
  504. if (uOffsetStartLink == 0)
  505. {
  506. pFlink = Link.Flink;
  507. }
  508. else
  509. {
  510. pFlink = (LIST_ENTRY*) uOffsetStartLink;
  511. }
  512. if (pFlink == pHead)
  513. {
  514. // MyDbgPrintf(" <end-of-list>\n");
  515. break;
  516. }
  517. for(
  518. ;
  519. (pFlink != pHead);
  520. pFlink = Link.Flink, uCount++)
  521. {
  522. if (uCount >= uMax) break;
  523. // Read the next link.
  524. //
  525. fRet = dbgextReadMemory(
  526. (UINT_PTR) pFlink,
  527. &Link,
  528. sizeof(Link),
  529. pszDescription
  530. );
  531. if (!fRet) break;
  532. // Call the nodefunc..
  533. //
  534. pFunc((UINT_PTR)pFlink, 0 /*uIndex*/, pvContext);
  535. }
  536. } while (FALSE);
  537. }
  538. void
  539. DumpObjects(TYPE_INFO *pType, UINT_PTR uAddr, UINT cObjects, UINT uFlags)
  540. {
  541. //
  542. // Print object's type and size
  543. //
  544. dprintf(
  545. "%s@0x%X (%lu Bytes)\n",
  546. pType->szName,
  547. uAddr,
  548. pType->cbSize
  549. );
  550. DumpMemory(
  551. uAddr,
  552. pType->cbSize,
  553. 0,
  554. pType->szName
  555. );
  556. //
  557. // Dump bytes...
  558. //
  559. return;
  560. }
  561. BYTE rgbScratchBuffer[100000];
  562. bool
  563. DumpMemory(
  564. UINT_PTR uAddr,
  565. UINT cb,
  566. UINT uFlags,
  567. const char *pszDescription
  568. )
  569. {
  570. bool fTruncated = FALSE;
  571. bool fRet = FALSE;
  572. UINT cbLeft = cb;
  573. char *pbSrc = rgbScratchBuffer;
  574. if (cbLeft>1024)
  575. {
  576. cbLeft = 1024;
  577. fTruncated = TRUE;
  578. }
  579. fRet = dbgextReadMemory(
  580. uAddr,
  581. rgbScratchBuffer,
  582. cbLeft,
  583. (char*)pszDescription
  584. );
  585. if (!fRet) goto end;
  586. #define ROWSIZE 16 // bytes
  587. //
  588. // Dump away...
  589. //
  590. while (cbLeft)
  591. {
  592. char rgTmp_dwords[ROWSIZE];
  593. char rgTmp_bytes[ROWSIZE];
  594. char *pb=NULL;
  595. UINT cbRow = ROWSIZE;
  596. if (cbRow > cbLeft)
  597. {
  598. cbRow = cbLeft;
  599. }
  600. memset(rgTmp_dwords, 0xff, sizeof(rgTmp_dwords));
  601. memset(rgTmp_bytes, ' ', sizeof(rgTmp_bytes));
  602. memcpy(rgTmp_dwords, pbSrc, cbRow);
  603. memcpy(rgTmp_bytes, pbSrc, cbRow);
  604. // sanitize bytes
  605. for (pb=rgTmp_bytes; pb<(rgTmp_bytes+sizeof(rgTmp_bytes)); pb++)
  606. {
  607. char c = *pb;
  608. if (c>=0x20 && c<0x7f) // isprint is too permissive.
  609. {
  610. if (*pb=='\t')
  611. {
  612. *pb=' ';
  613. }
  614. }
  615. else
  616. {
  617. *pb='.';
  618. }
  619. }
  620. dprintf(
  621. " %08lx: %08lx %08lx %08lx %08lx |%4.4s|%4.4s|%4.4s|%4.4s|\n",
  622. uAddr,
  623. ((DWORD*) rgTmp_dwords)[0],
  624. ((DWORD*) rgTmp_dwords)[1],
  625. ((DWORD*) rgTmp_dwords)[2],
  626. ((DWORD*) rgTmp_dwords)[3],
  627. #if 1
  628. rgTmp_bytes+0,
  629. rgTmp_bytes+4,
  630. rgTmp_bytes+8,
  631. rgTmp_bytes+12
  632. #else
  633. "aaaabbbbccccdddd",
  634. "bbbb",
  635. "cccc",
  636. "dddd"
  637. #endif
  638. );
  639. cbLeft -= cbRow;
  640. pbSrc += cbRow;
  641. uAddr += cbRow;
  642. }
  643. #if 0
  644. 0x00000000: 00000000 00000000 00000000 00000000 |xxxx|xxxx|xxxx|xxxx|
  645. 0x00000000: 00000000 00000000 00000000 00000000 |xxxx|xxxx|xxxx|xxxx|
  646. 0x00000000: 00000000 00000000 00000000 00000000 |xxxx|xxxx|xxxx|xxxx|
  647. #endif //
  648. end:
  649. return fRet;
  650. }
  651. bool
  652. MatchPrefix(const char *szPattern, const char *szString)
  653. {
  654. BOOL fRet = FALSE;
  655. ULONG uP = lstrlenA(szPattern);
  656. ULONG uS = lstrlenA(szString);
  657. if (uP<=uS)
  658. {
  659. fRet = (_memicmp(szPattern, szString, uP)==0);
  660. }
  661. return fRet;
  662. }
  663. bool
  664. MatchSuffix(const char *szPattern, const char *szString)
  665. {
  666. BOOL fRet = FALSE;
  667. ULONG uP = lstrlenA(szPattern);
  668. ULONG uS = lstrlenA(szString);
  669. if (uP<=uS)
  670. {
  671. szString += (uS-uP);
  672. fRet = (_memicmp(szPattern, szString, uP)==0);
  673. }
  674. return fRet;
  675. }
  676. bool
  677. MatchSubstring(const char *szPattern, const char *szString)
  678. {
  679. BOOL fRet = FALSE;
  680. ULONG uP = lstrlenA(szPattern);
  681. ULONG uS = lstrlenA(szString);
  682. if (uP<=uS)
  683. {
  684. const char *szLast = szString + (uS-uP);
  685. do
  686. {
  687. fRet = (_memicmp(szPattern, szString, uP)==0);
  688. } while (!fRet && szString++ < szLast);
  689. }
  690. return fRet;
  691. }
  692. bool
  693. MatchExactly(const char *szPattern, const char *szString)
  694. {
  695. BOOL fRet = FALSE;
  696. ULONG uP = lstrlenA(szPattern);
  697. ULONG uS = lstrlenA(szString);
  698. if (uP==uS)
  699. {
  700. fRet = (_memicmp(szPattern, szString, uP)==0);
  701. }
  702. return fRet;
  703. }
  704. bool
  705. MatchAlways(const char *szPattern, const char *szString)
  706. {
  707. return TRUE;
  708. }
  709. void
  710. DumpBitFields(
  711. ULONG Flags,
  712. BITFIELD_INFO rgBitFieldInfo[]
  713. )
  714. {
  715. BITFIELD_INFO *pbf = rgBitFieldInfo;
  716. for(;pbf->szName; pbf++)
  717. {
  718. if ((Flags & pbf->Mask) == pbf->Value)
  719. {
  720. MyDbgPrintf(" %s", pbf->szName);
  721. }
  722. }
  723. }
  724. void
  725. DumpStructure(
  726. TYPE_INFO *pType,
  727. UINT_PTR uAddr,
  728. char *szFieldSpec,
  729. UINT uFlags
  730. )
  731. {
  732. //
  733. // Determine field comparision function ...
  734. //
  735. PFNMATCHINGFUNCTION pfnMatchingFunction = MatchAlways;
  736. if (pType->pfnSpecializedDump)
  737. {
  738. // Call the specialized function to handle this...
  739. //
  740. pType->pfnSpecializedDump(
  741. pType,
  742. uAddr,
  743. szFieldSpec,
  744. uFlags
  745. );
  746. return;
  747. }
  748. //
  749. // Pick a selection function ...
  750. //
  751. if (szFieldSpec)
  752. {
  753. if (uFlags & fMATCH_SUBSTRING)
  754. {
  755. pfnMatchingFunction = MatchSubstring;
  756. }
  757. else if (uFlags & fMATCH_SUFFIX)
  758. {
  759. pfnMatchingFunction = MatchSuffix;
  760. }
  761. else if (uFlags & fMATCH_PREFIX)
  762. {
  763. pfnMatchingFunction = MatchPrefix;
  764. }
  765. else
  766. {
  767. pfnMatchingFunction = MatchExactly;
  768. }
  769. }
  770. //
  771. // Print object's type and size
  772. //
  773. dprintf(
  774. "%s@0x%X (%lu Bytes)\n",
  775. pType->szName,
  776. uAddr,
  777. pType->cbSize
  778. );
  779. //
  780. // Run through all the fields in this type, and if the entry is selected,
  781. // we will display it.
  782. //
  783. {
  784. STRUCT_FIELD_INFO *pField = pType->rgFields;
  785. for (;pField->szFieldName; pField++)
  786. {
  787. bool fMatch = !szFieldSpec
  788. || pfnMatchingFunction(szFieldSpec, pField->szFieldName);
  789. if (fMatch)
  790. {
  791. UINT_PTR uFieldAddr = uAddr + pField->uFieldOffset;
  792. // special-case small fields...
  793. if (pField->uFieldSize<=sizeof(ULONG_PTR))
  794. {
  795. ULONG_PTR Buf=0;
  796. BOOL fRet = dbgextReadMemory(
  797. uFieldAddr,
  798. &Buf,
  799. pField->uFieldSize,
  800. (char*)pField->szFieldName
  801. );
  802. if (fRet)
  803. {
  804. // print it as a hex number
  805. MyDbgPrintf(
  806. "\n%s\t[%lx,%lx]: 0x%lx",
  807. pField->szFieldName,
  808. pField->uFieldOffset,
  809. pField->uFieldSize,
  810. Buf
  811. );
  812. //
  813. // If it's an embedded object and it's a bitfield,
  814. // print the bitfields...
  815. //
  816. if ( FIELD_IS_EMBEDDED_TYPE(pField)
  817. && TYPEISBITFIELD(pField->pBaseType) )
  818. {
  819. DumpBitFields(
  820. (ULONG)Buf,
  821. pField->pBaseType->rgBitFieldInfo
  822. );
  823. }
  824. MyDbgPrintf("\n");
  825. }
  826. continue;
  827. }
  828. #if 0
  829. MyDbgPrintf(
  830. "%s\ndc 0x%08lx L %03lx %s\n",
  831. pField->szSourceText,
  832. uFieldAddr,
  833. pField->uFieldSize,
  834. pField->szFieldName
  835. );
  836. #else // 1
  837. MyDbgPrintf(
  838. "\n%s\t[%lx,%lx]\n",
  839. pField->szFieldName,
  840. pField->uFieldOffset,
  841. pField->uFieldSize
  842. );
  843. #endif // 1
  844. // if (szFieldSpec)
  845. {
  846. #if 0
  847. MyDumpObjects(
  848. pCmd,
  849. pgi->pBaseType,
  850. pgi->uAddr,
  851. pgi->cbSize,
  852. pgi->szName
  853. );
  854. #endif // 0
  855. DumpMemory(
  856. uFieldAddr,
  857. pField->uFieldSize,
  858. 0,
  859. pField->szFieldName
  860. );
  861. }
  862. }
  863. }
  864. }
  865. return;
  866. }
  867. DECLARE_API( help )
  868. {
  869. do_help(args);
  870. }
  871. DECLARE_API( rm )
  872. {
  873. do_rm(args);
  874. }
  875. DECLARE_API( arp )
  876. {
  877. do_arp(args);
  878. }
  879. ULONG
  880. NodeFunc_DumpAddress (
  881. UINT_PTR uNodeAddr,
  882. UINT uIndex,
  883. void *pvContext
  884. )
  885. {
  886. MyDbgPrintf("[%lu] 0x%08lx\n", uIndex, uNodeAddr);
  887. return 0;
  888. }
  889. UINT
  890. WalkList(
  891. UINT_PTR uStartAddress,
  892. UINT uNextOffset,
  893. UINT uStartIndex,
  894. UINT uEndIndex,
  895. void *pvContext,
  896. PFNNODEFUNC pFunc,
  897. char *pszDescription
  898. )
  899. //
  900. // Visit each node in the list in turn,
  901. // reading just the next pointers. It calls pFunc for each list node
  902. // between uStartIndex and uEndIndex. It terminates under the first of
  903. // the following conditions:
  904. // * Null pointer
  905. // * ReadMemoryError
  906. // * Read past uEndIndex
  907. // * pFunc returns FALSE
  908. //
  909. {
  910. UINT uIndex = 0;
  911. UINT_PTR uAddress = uStartAddress;
  912. BOOL fRet = TRUE;
  913. UINT uRet = 0;
  914. //
  915. // First skip until we get to uStart Index
  916. //
  917. for (;fRet && uAddress && uIndex < uStartIndex; uIndex++)
  918. {
  919. fRet = dbgextReadUINT_PTR(
  920. uAddress+uNextOffset,
  921. &uAddress,
  922. pszDescription
  923. );
  924. }
  925. //
  926. // Now call pFunc with each node
  927. //
  928. for (;fRet && uAddress && uIndex <= uEndIndex; uIndex++)
  929. {
  930. uRet = pFunc(uAddress, uIndex, pvContext);
  931. fRet = dbgextReadUINT_PTR(
  932. uAddress+uNextOffset,
  933. &uAddress,
  934. pszDescription
  935. );
  936. }
  937. pFunc = NodeFunc_DumpAddress;
  938. return uRet;
  939. }