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.

576 lines
17 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: dsocode.c
  3. *
  4. * Copyright (c) 1985-96, Microsoft Corporation
  5. *
  6. * This file contains the dump structure offset (dso) extension. It is
  7. * included by $(ALT_PROJECT)\dsotable.c which is generated by structo.exe
  8. *
  9. * History:
  10. * 06/17/96 GerardoB Created
  11. * 10/06/98 Rajeshsu edited to use wdbgexts.h
  12. \***************************************************************************/
  13. #define DsoPrint(x) dprintf("%.*s", nIndent, " "); dprintf x
  14. #define OFLAG(l) (1L << ((DWORD)#@l - (DWORD)'a'))
  15. #define EvalExp GetExpression
  16. #define EXACT_MATCH 0xFFFF
  17. int gnIndent = 0; // caller should set and restore this appropriately.
  18. VOID moveBlock(
  19. PVOID pdst,
  20. PVOID src,
  21. DWORD size)
  22. {
  23. BOOL fSuccess = TRUE;
  24. ULONG Result;
  25. try {
  26. if (!ReadMemory((DWORD_PTR)src, pdst, size, &Result)) {
  27. fSuccess = FALSE;
  28. }
  29. } except (EXCEPTION_EXECUTE_HANDLER) {
  30. //dprintf(pszMoveException, pszExtName);
  31. fSuccess = FALSE;
  32. }
  33. if (!fSuccess) {
  34. dprintf("moveBlock(%x, %x, %x) failed.\n", pdst, src, size);
  35. }
  36. }
  37. /***************************************************************************\
  38. * dsoTerminateString
  39. *
  40. * This is used to "parse" the command line. It null-terminates a space
  41. * delimited string, returns its size and a pointer to the begining
  42. * of next string
  43. *
  44. * 06/17/96 Created Gerardob
  45. \***************************************************************************/
  46. LPSTR dsoTerminateString(LPSTR psz, PDWORD pdwSize)
  47. {
  48. LPSTR pszWork = psz;
  49. while (*pszWork != 0) {
  50. if (*pszWork == ' ') {
  51. *pszWork++ = 0;
  52. break;
  53. }
  54. pszWork++;
  55. }
  56. *pdwSize = (DWORD)(pszWork - psz);
  57. if (*pszWork != 0) {
  58. (*pdwSize)--;
  59. }
  60. while ((*pszWork != 0) && (*pszWork == ' ')) {
  61. pszWork++;
  62. }
  63. return pszWork;
  64. }
  65. /***************************************************************************\
  66. * dsoGetOffset
  67. *
  68. * If the highest order bit of psot->dwOffset is set, then the value is a
  69. * relative offset from the previous field; otherwise, it is the
  70. * actual field offset from the beginnig of the structure
  71. *
  72. * 06/20/96 Created Gerardob
  73. \***************************************************************************/
  74. UINT dsoGetOffset (PSTRUCTUREOFFSETSTABLE psot)
  75. {
  76. if (!(psot->dwOffset & 0x80000000)) {
  77. return psot->dwOffset;
  78. } else {
  79. return ((psot->dwOffset & ~0x80000000) + dsoGetOffset(psot - 1));
  80. }
  81. }
  82. /***************************************************************************\
  83. * dsoGetSize
  84. *
  85. * The field size is calculated by substracting its offset from the next
  86. * field's offset. If the struct has unions, several "fields" might have
  87. * the same offset, or a given table entry (i.e., a field) might have an
  88. * offset value greater than the offset value for the next entry (a union
  89. * of two structures).
  90. *
  91. * 06/26/96 Created Gerardob
  92. \***************************************************************************/
  93. UINT dsoGetSize (PSTRUCTUREOFFSETSTABLE psot, DWORD dwOffset)
  94. {
  95. DWORD dwNextFieldOffset;
  96. do {
  97. psot++;
  98. dwNextFieldOffset = dsoGetOffset(psot);
  99. } while (dwNextFieldOffset <= dwOffset);
  100. return dwNextFieldOffset - dwOffset;
  101. }
  102. /***************************************************************************\
  103. * dsoGetStruct
  104. *
  105. * 07/03/96 Created Gerardob
  106. \***************************************************************************/
  107. PSTRUCTURESTABLE dsoGetStruct (LPSTR pszStruct, DWORD dwSize)
  108. {
  109. PSTRUCTURESTABLE pst = gst;
  110. /*
  111. * If dwSize is EXACT_MATCH, we try an exact
  112. * case sensitive match
  113. */
  114. if (dwSize == EXACT_MATCH) {
  115. while (pst->pszName != NULL) {
  116. if (!strcmp(pszStruct, pst->pszName)) {
  117. return pst;
  118. }
  119. pst++;
  120. }
  121. return NULL;
  122. }
  123. /*
  124. * Try an exact case insensitive match
  125. */
  126. while (pst->pszName != NULL) {
  127. if (!_stricmp(pszStruct, pst->pszName)) {
  128. return pst;
  129. }
  130. pst++;
  131. }
  132. /*
  133. * Partial prefix match
  134. */
  135. pst = gst;
  136. while (pst->pszName != NULL) {
  137. if (!_strnicmp(pszStruct, pst->pszName, dwSize)) {
  138. return pst;
  139. }
  140. pst++;
  141. }
  142. return NULL;
  143. }
  144. /***************************************************************************\
  145. * dsoGetField
  146. *
  147. * 07/03/96 Created Gerardob
  148. \***************************************************************************/
  149. PSTRUCTUREOFFSETSTABLE dosGetField (PSTRUCTUREOFFSETSTABLE psot, LPSTR pszField, DWORD dwSize)
  150. {
  151. PSTRUCTUREOFFSETSTABLE psotFirst = psot;
  152. /*
  153. * try an exact match
  154. */
  155. while (psot->pszField != NULL) {
  156. if (!_stricmp(pszField, psot->pszField)) {
  157. return psot;
  158. }
  159. psot++;
  160. }
  161. /*
  162. * Partial prefix match
  163. */
  164. psot = psotFirst;
  165. while (psot->pszField != NULL) {
  166. if (!_strnicmp(pszField, psot->pszField, dwSize)) {
  167. return psot;
  168. }
  169. psot++;
  170. }
  171. return NULL;
  172. }
  173. /***************************************************************************\
  174. * Idso
  175. *
  176. * !dso StructName [FieldName] [Address]
  177. *
  178. * 06/17/96 Created Gerardob
  179. * 05/12/97 MCostea Added bit field support
  180. \***************************************************************************/
  181. #define NFIELDS 2 // per row.
  182. BOOL Idso(DWORD opts, LPSTR pszCmdLine)
  183. {
  184. BOOL fOneField = FALSE;
  185. DWORD dwValue, dwSize, dwBytesRead, dwOffset, dwOffsetNext, dwFieldsPerRow, dwMoveSize;
  186. DWORD dwBuffer [20]; /* Make sure it has an even number of elemnts and at least 4*/
  187. const DWORD *pcdwLimit = dwBuffer + (sizeof(dwBuffer) / sizeof(*dwBuffer));
  188. DWORD *pdwValue;
  189. LPSTR pszField, pszAddress;
  190. PBYTE pBufferOffset;
  191. PSTRUCTURESTABLE pst, pstNested;
  192. PSTRUCTUREOFFSETSTABLE psot;
  193. PVOID pAddress = NULL;
  194. int cBFStart, cBFLength; /* for printing bit field values: keeps count of field location */
  195. char* pTmp;
  196. DWORD dwMask;
  197. BOOL fBF;
  198. int cBF; /* no of dwords this set of bit-fields spread till now */
  199. int cchName; /* length of field name */
  200. int nIndent = gnIndent; /* amount to indent */
  201. UNREFERENCED_PARAMETER(opts);
  202. if (pszCmdLine == NULL) {
  203. return FALSE;
  204. }
  205. /*
  206. * Find the struct table
  207. */
  208. pszField = dsoTerminateString(pszCmdLine, &dwSize);
  209. pst = dsoGetStruct (pszCmdLine, dwSize);
  210. if (pst == NULL) {
  211. DsoPrint(("Structure not found: %s\n", pszCmdLine));
  212. return TRUE;
  213. }
  214. /*
  215. * Got a table
  216. */
  217. psot = pst->psot;
  218. /*
  219. * If there is another argument, let's assume a field name follows
  220. */
  221. if (*pszField != 0) {
  222. /*
  223. * Find the field
  224. */
  225. pszAddress = dsoTerminateString(pszField, &dwSize);
  226. psot = dosGetField (psot, pszField, dwSize);
  227. /*
  228. * If it didn't find the field and an address was provided, game over.
  229. * Otherwise, the second parameter might be the address
  230. */
  231. if (psot == NULL) {
  232. if (*pszAddress != 0) {
  233. DsoPrint(("Field not found: %s. Struct: %s\n", pszField, pst->pszName));
  234. return TRUE;
  235. } else {
  236. pszAddress = pszField;
  237. /*
  238. * Reset psot since this argument was not a field
  239. */
  240. psot = pst->psot;
  241. }
  242. } else {
  243. fOneField = TRUE;
  244. }
  245. /*
  246. * Get the pointer to the struct
  247. */
  248. if (*pszAddress != 0) {
  249. pAddress = (PVOID) EvalExp(pszAddress);
  250. if (pAddress == NULL) {
  251. /*
  252. * EvalExp displayed the error message, so return silently
  253. */
  254. return TRUE;
  255. }
  256. }
  257. } /* if (*pszField != 0) */
  258. /*
  259. * If a field name was specified, dump that field only
  260. * Otherwise, dump the whole table.
  261. */
  262. if (fOneField) {
  263. /*
  264. * If no address available, just display the field name and offset
  265. */
  266. dwOffset = dsoGetOffset(psot);
  267. DsoPrint(("Structure %s - Size: %#lx\n", pst->pszName, pst->dwSize));
  268. /*
  269. * Try to see if the fields are not nested structures
  270. */
  271. if (*psot->pszField >= 'A' && *psot->pszField <= 'Z') {
  272. /*
  273. * Probably the field is a nested structure
  274. */
  275. if (pstNested = dsoGetStruct (psot->pszField, EXACT_MATCH)) {
  276. DWORD dwNestedOffset = dsoGetOffset(psot);
  277. char cmdLine[80];
  278. DsoPrint(("\nNested at offset %03lx: ", dwNestedOffset));
  279. if (pAddress) {
  280. sprintf(cmdLine, "%s %p", psot->pszField, (PBYTE)pAddress + dwNestedOffset);
  281. pTmp = cmdLine;
  282. }
  283. else {
  284. pTmp = psot->pszField;
  285. }
  286. return Idso(opts, pTmp);
  287. }
  288. }
  289. DsoPrint(("Field: %s - Offset: %#lx\n", psot->pszField, dwOffset));
  290. if (pAddress == NULL) {
  291. return TRUE;
  292. }
  293. /*
  294. * Printing field value
  295. */
  296. /*123456789 1*/
  297. DsoPrint(("Address Value\n"));
  298. dwBytesRead = 0;
  299. dwSize = dsoGetSize(psot, dwOffset);
  300. /*
  301. * Print 4 DWORDS per row; one row per loop
  302. */
  303. do { /* while ((int)dwSize > 0) */
  304. /*
  305. * Read values for next row
  306. */
  307. if (4 * sizeof(DWORD) >= dwSize) {
  308. dwMoveSize = dwSize;
  309. } else {
  310. dwMoveSize = 4 * sizeof(DWORD);
  311. }
  312. moveBlock(dwBuffer, (PBYTE)pAddress + dwOffset + dwBytesRead, dwMoveSize);
  313. pBufferOffset = (PBYTE)dwBuffer;
  314. /*
  315. * Print the address
  316. */
  317. DsoPrint(("%p ", (DWORD_PTR)((PBYTE)pAddress + dwOffset + dwBytesRead)));
  318. /*
  319. * Keep track of bytes read (dwBytesRead) and bytes
  320. * remaining to be read (dwSize)
  321. */
  322. dwBytesRead += dwMoveSize;
  323. dwSize -= dwMoveSize;
  324. /*
  325. * Print the values, one dword at the time
  326. */
  327. while (dwMoveSize >= sizeof(DWORD)) {
  328. DsoPrint(("%08lx ", *((DWORD *)pBufferOffset)));
  329. pBufferOffset += sizeof(DWORD);
  330. dwMoveSize -= sizeof(DWORD);
  331. }
  332. /*
  333. * If less than a DWORD left, zero extend and print a DWORD
  334. */
  335. if (dwMoveSize > 0) {
  336. dwValue = 0;
  337. memcpy(&dwValue, pBufferOffset, dwMoveSize);
  338. DsoPrint(("%0*lx", dwMoveSize * 2, dwValue));
  339. }
  340. dprintf("\n");
  341. } while ((int)dwSize > 0);
  342. return TRUE;
  343. } /* if (fOneField) */
  344. /*
  345. * Printing all the fields.
  346. */
  347. if (pAddress != NULL) {
  348. DsoPrint(("Structure %s %#lx - Size: %#lx", pst->pszName, pAddress, pst->dwSize));
  349. } else {
  350. DsoPrint(("Structure %s - Size: %#lx", pst->pszName, pst->dwSize));
  351. }
  352. dwOffset = 0;
  353. pBufferOffset = NULL; /* Forces the local buffer to be loaded */
  354. dwFieldsPerRow = NFIELDS;
  355. cBFStart = 0;
  356. cBF = 0;
  357. /*
  358. * Loop through all fields in the table. Print one field per loop
  359. */
  360. while (psot->pszField != NULL) {
  361. /*
  362. * Print two fields per row
  363. */
  364. if (dwFieldsPerRow == NFIELDS) {
  365. dprintf("\n");
  366. dwFieldsPerRow = 1;
  367. cchName = 24 - gnIndent/NFIELDS;
  368. nIndent = gnIndent;
  369. // Print("cchName = %d\n", cchName);
  370. } else {
  371. dwFieldsPerRow++;
  372. cchName = 24 - (gnIndent + 1)/NFIELDS;
  373. nIndent = 0;
  374. // Print("cchName = %d\n", cchName);
  375. }
  376. /*
  377. * -v functionality
  378. * Try to see if the fields are not nested structures
  379. * The naming convention assigns Uppercase names for them
  380. */
  381. if (opts & OFLAG(v)) {
  382. if (*psot->pszField >= 'A' && *psot->pszField <= 'Z') {
  383. /*
  384. * Probably the field is a nested structure
  385. */
  386. if (pstNested = dsoGetStruct (psot->pszField, EXACT_MATCH)) {
  387. DWORD dwNestedOffset = dsoGetOffset(psot);
  388. char cmdLine[80];
  389. DsoPrint(("\nNested at offset %03lx: ", dwNestedOffset));
  390. if (pAddress) {
  391. sprintf(cmdLine, "%s %p", psot->pszField, (PBYTE)pAddress + dwNestedOffset);
  392. pTmp = cmdLine;
  393. }
  394. else {
  395. pTmp = psot->pszField;
  396. }
  397. Idso(opts, pTmp);
  398. dwOffsetNext = dsoGetOffset(psot + 1);
  399. dwFieldsPerRow = 0;
  400. goto Continue;
  401. }
  402. }
  403. }
  404. /*
  405. * If no address provided, Print field name(s) and offset(s) only
  406. */
  407. if (pAddress == NULL) {
  408. DsoPrint(("%03lx %-*.*s", dsoGetOffset(psot),
  409. cchName, cchName, psot->pszField));
  410. } else {
  411. /*
  412. * Printing offsets and values.
  413. *
  414. * Get the size of the value and max it to one DWORD
  415. */
  416. dwOffsetNext = dsoGetOffset(psot + 1);
  417. if (dwOffsetNext > dwOffset) {
  418. dwSize = dwOffsetNext - dwOffset;
  419. } else {
  420. dwSize = dsoGetSize(psot, dwOffset);
  421. }
  422. if (dwSize > sizeof(DWORD)) {
  423. dwSize = sizeof(DWORD);
  424. }
  425. /*
  426. * Get a pointer to the value in the local buffer
  427. * If the value is not in the buffer, load it
  428. */
  429. pdwValue = (PDWORD)(pBufferOffset + dwOffset);
  430. if ((pdwValue < dwBuffer) || (pdwValue + dwSize > pcdwLimit)) {
  431. pBufferOffset = (PBYTE)dwBuffer - dwOffset;
  432. pdwValue = dwBuffer;
  433. if (sizeof(dwBuffer) >= pst->dwSize - dwOffset) {
  434. dwMoveSize = pst->dwSize - dwOffset;
  435. } else {
  436. dwMoveSize = sizeof(dwBuffer);
  437. }
  438. moveBlock((PBYTE)dwBuffer, (PBYTE)pAddress + dwOffset, dwMoveSize);
  439. }
  440. /*
  441. * Copy the value and print it
  442. */
  443. dwValue = 0; /* in case size < sizeof(DWORD) */
  444. memcpy(&dwValue, pdwValue, dwSize);
  445. /*
  446. * Deal with bit fields
  447. */
  448. fBF = FALSE;
  449. pTmp = psot->pszField;
  450. while (*pTmp) {
  451. if (*pTmp++ == ':') {
  452. fBF = TRUE;
  453. while ((*pTmp == ' ') || (*pTmp == '\t')) { /* skip white spaces */
  454. ++pTmp;
  455. }
  456. cBFLength = *(pTmp++) - '0'; /* now get the bit size, maybe 2 digits */
  457. if ((*pTmp >= '0') && (*pTmp <= '9'))
  458. cBFLength = cBFLength*10 + (*pTmp - '0');
  459. if (cBFStart == 0) {
  460. DsoPrint(("(%03lx) %08lx BIT FIELDS\n", dwOffset, dwValue));
  461. dwFieldsPerRow = 1;
  462. }
  463. else if (cBFStart >= 8*sizeof(DWORD)) { /* check for multi-dword fields */
  464. cBF ++;
  465. cBFStart %= 8*sizeof(DWORD);
  466. }
  467. dwMask = (1L << cBFLength) - 1;
  468. dwMask <<= cBFStart;
  469. /* print byte offset and the bit offset inside it */
  470. DsoPrint(("(%03lx) (%d) %-2x %-*.*s", dwOffset + cBF*sizeof(DWORD) + cBFStart/8, cBFStart & 7,
  471. (dwMask & dwValue) >> cBFStart,
  472. cchName, cchName, psot->pszField));
  473. cBFStart += cBFLength;
  474. cBFLength = 0;
  475. break;
  476. }
  477. }
  478. if (!fBF) {
  479. int width = 8;
  480. if (dwSize == sizeof(BYTE)) {
  481. dwValue &= 0xff;
  482. width = 2;
  483. } else if (dwSize == sizeof(WORD)) {
  484. dwValue &= 0xffff;
  485. width = 4;
  486. }
  487. DsoPrint(("(%03lx) %*s%0*lx %-*.*s", dwOffset, 8 - width, "", width, dwValue,
  488. cchName, cchName, psot->pszField));
  489. cBFStart = 0;
  490. cBF = 0;
  491. }
  492. } /* if (pAddress == NULL) */
  493. Continue:
  494. dwOffset = dwOffsetNext;
  495. psot++;
  496. } /* while (psot->pszField != NULL) */
  497. dprintf("\n");
  498. return TRUE;
  499. }
  500. DECLARE_API( gpcdso )
  501. {
  502. LPSTR pszCmdLine;
  503. DWORD opts = 0;
  504. pszCmdLine = (LPSTR) args;
  505. Idso(opts, pszCmdLine);
  506. }