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.

630 lines
13 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Wesley Witt (wesw) 15-Aug-1993
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. ULONG
  16. GetBitFieldOffset (
  17. IN LPSTR Type,
  18. IN LPSTR Field,
  19. OUT PULONG pOffset,
  20. OUT PULONG pSize
  21. )
  22. {
  23. FIELD_INFO flds = {
  24. Field, "", 0,
  25. DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS | DBG_DUMP_FIELD_SIZE_IN_BITS,
  26. 0, NULL};
  27. SYM_DUMP_PARAM Sym = {
  28. sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0,
  29. NULL, NULL, NULL, 1, &flds
  30. };
  31. ULONG Err, i=0;
  32. LPSTR dot, last=Field;
  33. Sym.nFields = 1;
  34. Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  35. *pOffset = (ULONG) (flds.address - Sym.addr);
  36. *pSize = flds.size;
  37. return Err;
  38. }
  39. ULONG
  40. GetFieldOffsetEx (
  41. IN LPSTR Type,
  42. IN LPSTR Field,
  43. OUT PULONG pOffset,
  44. OUT PULONG pSize
  45. )
  46. {
  47. FIELD_INFO flds = {
  48. Field, "", 0,
  49. DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS,
  50. 0, NULL};
  51. SYM_DUMP_PARAM Sym = {
  52. sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0,
  53. NULL, NULL, NULL, 1, &flds
  54. };
  55. ULONG Err, i=0;
  56. LPSTR dot, last=Field;
  57. Sym.nFields = 1;
  58. Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  59. *pOffset = (ULONG) (flds.address - Sym.addr);
  60. *pSize = flds.size;
  61. return Err;
  62. } // GetFieldOffsetEx()
  63. ULONG
  64. GetUlongFromAddress (
  65. ULONG64 Location
  66. )
  67. {
  68. ULONG Value;
  69. ULONG result;
  70. if ((!ReadMemory(Location,&Value,sizeof(ULONG),&result)) ||
  71. (result < sizeof(ULONG))) {
  72. dprintf("GetUlongFromAddress: unable to read from %p\n", Location);
  73. return 0;
  74. }
  75. return Value;
  76. }
  77. ULONG64
  78. GetPointerFromAddress (
  79. ULONG64 Location
  80. )
  81. {
  82. ULONG64 Value;
  83. ULONG result;
  84. if (!ReadPointer( Location, &Value )) {
  85. dprintf( "GetPointerFromAddress: unable to read from %p\n", Location );
  86. return 0;
  87. }
  88. return Value;
  89. }
  90. ULONG
  91. GetUlongValue (
  92. PCHAR String
  93. )
  94. {
  95. ULONG64 Location;
  96. ULONG Value;
  97. ULONG result;
  98. Location = GetExpression( String );
  99. if (!Location) {
  100. dprintf("unable to get %s\n",String);
  101. return 0;
  102. }
  103. return GetUlongFromAddress( Location );
  104. }
  105. ULONG64
  106. GetPointerValue (
  107. PCHAR String
  108. )
  109. {
  110. ULONG64 Location, Val=0;
  111. Location = GetExpression( String );
  112. if (!Location) {
  113. dprintf("unable to get %s\n",String);
  114. return 0;
  115. }
  116. ReadPointer(Location, &Val);
  117. return Val;
  118. }
  119. ULONG64
  120. GetGlobalFromAddress (
  121. ULONG64 Location,
  122. ULONG Size
  123. )
  124. {
  125. ULONG64 value;
  126. ULONG result;
  127. value = 0;
  128. if ((!ReadMemory(Location,&value,Size,&result)) || (result < Size)) {
  129. dprintf("GetGlobalFromAddress: unable to read from %p\n", Location);
  130. return 0;
  131. }
  132. return value;
  133. } // GetGlobalFromAddress()
  134. ULONG64
  135. GetGlobalValue (
  136. PCHAR String
  137. )
  138. {
  139. ULONG64 location;
  140. ULONG size;
  141. location = GetExpression( String );
  142. if (!location) {
  143. dprintf("GetGlobalValue: unable to get %s\n",String);
  144. return 0;
  145. }
  146. size = GetTypeSize( String );
  147. if (!size) {
  148. dprintf("GetGlobalValue: unable to get %s type size\n",String);
  149. return 0;
  150. }
  151. return GetGlobalFromAddress( location, size );
  152. } // GetGlobalValue()
  153. HRESULT
  154. GetGlobalEx(
  155. PCHAR String,
  156. PVOID OutValue,
  157. ULONG OutSize
  158. )
  159. {
  160. ULONG64 location;
  161. ULONG size;
  162. ULONG result;
  163. ZeroMemory( OutValue, OutSize );
  164. location = GetExpression( String );
  165. if (!location) {
  166. return E_INVALIDARG;
  167. }
  168. size = GetTypeSize( String );
  169. if (!size) {
  170. return E_INVALIDARG;
  171. }
  172. if ( size > OutSize ) {
  173. return E_OUTOFMEMORY;
  174. }
  175. if ((!ReadMemory(location,OutValue,size,&result)) || (result < size)) {
  176. return E_FAIL;
  177. }
  178. return S_OK;
  179. } // GetGlobalEx()
  180. #if 0
  181. VOID
  182. DumpImageName(
  183. IN ULONG64 Process
  184. )
  185. {
  186. ULONG64 ImageFileName;
  187. STRING String;
  188. ULONG Result;
  189. IN WCHAR Buf[512];
  190. if ( !GetFieldValue(Process, "EPROCESS", "ImageFileName.Buffer", ImageFileName ) ){
  191. wcscpy(Buf,L"*** image name unavailable ***");
  192. if ( ReadMemory( ImageFileName,
  193. &String,
  194. sizeof(STRING),
  195. &Result) ) {
  196. if ( ReadMemory( (DWORD)String.Buffer,
  197. &Buf[0],
  198. String.Length,
  199. &Result) ) {
  200. Buf[String.Length/sizeof(WCHAR)] = UNICODE_NULL;
  201. }
  202. }
  203. } else {
  204. wcscpy(Buf,L"System Process");
  205. }
  206. dprintf("%ws",Buf);
  207. }
  208. #endif
  209. BOOLEAN
  210. DbgRtlIsRightChild(
  211. ULONG64 pLinks,
  212. ULONG64 Parent
  213. )
  214. {
  215. ULONG64 RightChild;
  216. if (Parent == pLinks) {
  217. return FALSE;
  218. }
  219. if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "RightChild", RightChild)) {
  220. return FALSE;
  221. }
  222. if (RightChild == pLinks) {
  223. return TRUE;
  224. }
  225. return FALSE;
  226. }
  227. BOOLEAN
  228. DbgRtlIsLeftChild(
  229. ULONG64 pLinks,
  230. ULONG64 Parent
  231. )
  232. {
  233. ULONG64 LeftChild;
  234. if (Parent == pLinks) {
  235. return FALSE;
  236. }
  237. if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) {
  238. return FALSE;
  239. }
  240. if (LeftChild == pLinks) {
  241. return TRUE;
  242. }
  243. return FALSE;
  244. }
  245. ULONG
  246. DumpSplayTree(
  247. IN ULONG64 pSplayLinks,
  248. IN PDUMP_SPLAY_NODE_FN DumpNodeFn
  249. )
  250. /*++
  251. Purpose:
  252. Perform an in-order iteration across a splay tree, calling a
  253. user supplied function with a pointer to each RTL_SPLAY_LINKS
  254. structure encountered in the tree, and the level in the tree
  255. at which it was encountered (zero based).
  256. Arguments:
  257. pSplayLinks - pointer to root of a splay tree
  258. DumpNodeFn - user supplied dumping function
  259. Returns:
  260. Count of nodes encountered in the tree.
  261. Notes:
  262. Errors reading memory do not terminate the iteration if more
  263. work is possible.
  264. Consumes the Control-C flag to terminate possible loops in
  265. corrupt structures.
  266. --*/
  267. {
  268. ULONG Level = 0;
  269. ULONG NodeCount = 0;
  270. if (pSplayLinks) {
  271. ULONG64 LeftChild, RightChild, Parent, Current;
  272. //
  273. // Retrieve the root links, find the leftmost node in the tree
  274. //
  275. if (GetFieldValue(Current = pSplayLinks,
  276. "RTL_SPLAY_LINKS",
  277. "LeftChild",
  278. LeftChild)) {
  279. return NodeCount;
  280. }
  281. while (LeftChild != 0) {
  282. if ( CheckControlC() ) {
  283. return NodeCount;
  284. }
  285. if (GetFieldValue(Current = LeftChild,
  286. "RTL_SPLAY_LINKS",
  287. "LeftChild",
  288. LeftChild)) {
  289. //
  290. // We can try to continue from this
  291. //
  292. break;
  293. }
  294. Level++;
  295. }
  296. while (TRUE) {
  297. if ( CheckControlC() ) {
  298. return NodeCount;
  299. }
  300. NodeCount++;
  301. pSplayLinks = Current;
  302. (*DumpNodeFn)(pSplayLinks, Level);
  303. /*
  304. first check to see if there is a right subtree to the input link
  305. if there is then the real successor is the left most node in
  306. the right subtree. That is find and return P in the following diagram
  307. Links
  308. \
  309. .
  310. .
  311. .
  312. /
  313. P
  314. \
  315. */
  316. GetFieldValue(Current, "RTL_SPLAY_LINKS", "RightChild", RightChild);
  317. if (RightChild != 0) {
  318. if (GetFieldValue(Current = RightChild,
  319. "RTL_SPLAY_LINKS",
  320. "RightChild",
  321. RightChild)) {
  322. //
  323. // We've failed to step through to a successor, so
  324. // there is no more to do
  325. //
  326. return NodeCount;
  327. }
  328. Level++;
  329. GetFieldValue(Current,"RTL_SPLAY_LINKS","LeftChild",LeftChild);
  330. while (LeftChild != 0) {
  331. if ( CheckControlC() ) {
  332. return NodeCount;
  333. }
  334. if (GetFieldValue(Current = LeftChild,
  335. "RTL_SPLAY_LINKS",
  336. "LeftChild",
  337. LeftChild)) {
  338. //
  339. // We can continue from this
  340. //
  341. break;
  342. }
  343. Level++;
  344. }
  345. } else {
  346. /*
  347. we do not have a right child so check to see if have a parent and if
  348. so find the first ancestor that we are a left decendent of. That
  349. is find and return P in the following diagram
  350. P
  351. /
  352. .
  353. .
  354. .
  355. Links
  356. */
  357. //
  358. // If the IsLeft or IsRight functions fail to read through a parent
  359. // pointer, then we will quickly exit through the break below
  360. //
  361. GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent);
  362. while (DbgRtlIsRightChild(Current, Parent)) {
  363. if ( CheckControlC() ) {
  364. return NodeCount;
  365. }
  366. Level--;
  367. pSplayLinks = (Current = Parent);
  368. }
  369. GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent);
  370. if (!DbgRtlIsLeftChild(Current, Parent)) {
  371. //
  372. // we do not have a real successor so we break out
  373. //
  374. break;
  375. } else {
  376. Level--;
  377. pSplayLinks = (Current = Parent);
  378. }
  379. }
  380. }
  381. }
  382. return NodeCount;
  383. }
  384. VOID
  385. DumpUnicode64(
  386. UNICODE_STRING64 u
  387. )
  388. {
  389. UNICODE_STRING v;
  390. DWORD BytesRead;
  391. // dprintf("L %x, M %x, B %p ", u.Length, u.MaximumLength, u.Buffer);
  392. if ((u.Length <= u.MaximumLength) &&
  393. (u.Buffer) &&
  394. (u.Length > 0)) {
  395. v.Buffer = LocalAlloc(LPTR, u.MaximumLength);
  396. if (v.Buffer != NULL) {
  397. v.MaximumLength = u.MaximumLength;
  398. v.Length = u.Length;
  399. if (ReadMemory(u.Buffer,
  400. v.Buffer,
  401. u.Length,
  402. (PULONG) &u.Buffer)) {
  403. dprintf("%wZ", &v);
  404. } else {
  405. dprintf("<???>");
  406. }
  407. LocalFree(v.Buffer);
  408. return;
  409. }
  410. }
  411. }
  412. BOOLEAN
  413. IsHexNumber(
  414. const char *szExpression
  415. )
  416. {
  417. if (!szExpression[0]) {
  418. return FALSE ;
  419. }
  420. for(;*szExpression; szExpression++) {
  421. if ((*szExpression)< '0') { return FALSE ; }
  422. else if ((*szExpression)> 'f') { return FALSE ; }
  423. else if ((*szExpression)>='a') { continue ; }
  424. else if ((*szExpression)> 'F') { return FALSE ; }
  425. else if ((*szExpression)<='9') { continue ; }
  426. else if ((*szExpression)>='A') { continue ; }
  427. else { return FALSE ; }
  428. }
  429. return TRUE ;
  430. }
  431. BOOLEAN
  432. IsDecNumber(
  433. const char *szExpression
  434. )
  435. {
  436. if (!szExpression[0]) {
  437. return FALSE ;
  438. }
  439. while(*szExpression) {
  440. if ((*szExpression)<'0') { return FALSE ; }
  441. else if ((*szExpression)>'9') { return FALSE ; }
  442. szExpression ++ ;
  443. }
  444. return TRUE ;
  445. }
  446. ULONG64
  447. UtilStringToUlong64 (
  448. UCHAR *String
  449. )
  450. {
  451. UCHAR LowDword[9], HighDword[9];
  452. ZeroMemory (&HighDword, sizeof (HighDword));
  453. ZeroMemory (&LowDword, sizeof (LowDword));
  454. if (strlen (String) > 8) {
  455. memcpy (&LowDword, (void *) &String[strlen (String) - 8], 8);
  456. memcpy (&HighDword, (void *) &String[0], strlen (String) - 8);
  457. } else {
  458. return strtoul (String, 0, 16);
  459. }
  460. return ((ULONG64) strtoul (HighDword, 0, 16) << 32) + strtoul (LowDword, 0, 16);
  461. }
  462. const char *
  463. getEnumName(
  464. ULONG EnumVal,
  465. PENUM_NAME EnumTable
  466. )
  467. /*++
  468. Routine Description:
  469. Gets the supplied enum value's name in string format
  470. Arguments:
  471. EnumVal - Enum to be retrieved
  472. EnumTable - Table in which the enum is looked up to find
  473. the string to be retrieved (since we can't rely on the debugger)
  474. Return Value:
  475. None
  476. --*/
  477. {
  478. ULONG i;
  479. for (i=0; EnumTable[i].Name != NULL; i++) {
  480. if (EnumTable[i].EnumVal == EnumVal) {
  481. break;
  482. }
  483. }
  484. if (EnumTable[i].Name != NULL) {
  485. return EnumTable[i].Name;
  486. } else {
  487. return "Unknown ";
  488. }
  489. }