Leaked source code of windows server 2003
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.

454 lines
10 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. heap.c
  5. Abstract:
  6. This function contains the default ntsd debugger extensions
  7. Author:
  8. Bob Day (bobday) 29-Feb-1992 Grabbed standard header
  9. Revision History:
  10. Neil Sandlin (NeilSa) 15-Jan-1996 Merged with vdmexts
  11. --*/
  12. #include <precomp.h>
  13. #pragma hdrstop
  14. BOOL bWalkOnly = FALSE;
  15. ULONG
  16. GetHeapBase(
  17. VOID
  18. )
  19. {
  20. WORD selector;
  21. SELECTORINFO si;
  22. if (!ReadMemExpression("ntvdmd!DbgWowhGlobalHeap", &selector, sizeof(selector))) {
  23. return 0;
  24. }
  25. GetInfoFromSelector(selector, PROT_MODE, &si);
  26. return(si.Base + GetIntelBase());
  27. }
  28. void
  29. GetFileNameFromOwner(
  30. LPSTR filename,
  31. LPSTR OwnerName
  32. )
  33. {
  34. }
  35. VOID
  36. GetHeapOwnerInfo(
  37. HEAPENTRY *he
  38. )
  39. {
  40. BOOL b;
  41. NEHEADER owner;
  42. ULONG base;
  43. UCHAR len;
  44. int i;
  45. ULONG offset;
  46. WORD wTemp;
  47. he->SegmentNumber = -1;
  48. he->OwnerName[0] = 0;
  49. if (he->gnode.pga_owner == 0) {
  50. strcpy(he->OwnerName, "free");
  51. return;
  52. } else if (he->gnode.pga_owner>=0xFFF8) {
  53. strcpy(he->OwnerName, "sentinel");
  54. return;
  55. }
  56. base = GetInfoFromSelector(he->gnode.pga_owner, PROT_MODE, NULL)
  57. + GetIntelBase();
  58. b = READMEM((LPVOID)base, &owner, sizeof(owner));
  59. if (b) {
  60. if (owner.ne_magic == 0x454e) {
  61. len = ReadByteSafe(base+owner.ne_restab);
  62. if (len>8) {
  63. len=8;
  64. }
  65. READMEM((LPVOID)(base+owner.ne_restab+1), he->OwnerName, 8);
  66. he->OwnerName[len] = 0;
  67. if (!_stricmp(he->OwnerName, "kernel")) {
  68. strcpy(he->FileName, "krnl386");
  69. } else {
  70. strcpy(he->FileName, he->OwnerName);
  71. }
  72. offset = owner.ne_segtab;
  73. for (i=0; i<owner.ne_cseg; i++) {
  74. wTemp = ReadWordSafe(base+offset+8); //get handle
  75. if (wTemp == he->gnode.pga_handle) {
  76. he->SegmentNumber = i;
  77. break;
  78. }
  79. offset += 10;
  80. }
  81. }
  82. }
  83. }
  84. BOOL
  85. CheckGlobalHeap(
  86. BOOL bVerbose
  87. )
  88. {
  89. PGHI32 pghi;
  90. DWORD offset, prevoffset;
  91. DWORD count, heapcount;
  92. DWORD p;
  93. GNODE32 gnode;
  94. PBYTE pFault = NULL;
  95. BOOL bError = FALSE;
  96. pghi = (PGHI32)GetHeapBase();
  97. prevoffset = offset = (DWORD) ReadWord(&pghi->hi_first);
  98. heapcount = count = ReadWord(&pghi->hi_count);
  99. if (bVerbose) {
  100. PRINTF("Global Heap is at %08X\n", pghi);
  101. }
  102. while ((offset != 0) && (count)) {
  103. if (offset&0x1f) {
  104. PRINTF("Error! Kernel heap entry(%08X) contains invalid forward link (%08X)\n", prevoffset, offset);
  105. return FALSE;
  106. }
  107. p = (DWORD)pghi + offset;
  108. if (!ReadGNode32Safe(p, &gnode)) {
  109. PRINTF("Error! Kernel heap entry(%08X) contains invalid forward link (%08X)\n", prevoffset, offset);
  110. return FALSE;
  111. }
  112. if (count == heapcount) {
  113. // first entry
  114. if (offset != gnode.pga_prev) {
  115. PRINTF("Error! Kernel heap entry (%08X) contains invalid back link (%08X)\n", offset, gnode.pga_prev);
  116. PRINTF(" expecting (%08X)\n", offset);
  117. return FALSE;
  118. }
  119. } else {
  120. if (prevoffset != gnode.pga_prev) {
  121. PRINTF("Error! Kernel heap entry (%08X) contains invalid back link (%08X)\n", offset, gnode.pga_prev);
  122. PRINTF(" expecting (%08X)\n", prevoffset);
  123. return FALSE;
  124. }
  125. }
  126. prevoffset = offset;
  127. count--;
  128. if (offset == gnode.pga_next) {
  129. if (!count) {
  130. if (bVerbose) {
  131. PRINTF("%d entries scanned\n", heapcount);
  132. }
  133. return TRUE;
  134. } else {
  135. PRINTF("Error! Kernel heap count (%d) larger then forward chain (%d)\n", heapcount, heapcount-count);
  136. }
  137. }
  138. offset = gnode.pga_next;
  139. }
  140. PRINTF("Error! Kernel heap count (%d) smaller then forward chain\n", heapcount);
  141. return FALSE;
  142. }
  143. BOOL
  144. FindHeapEntry(
  145. HEAPENTRY *he,
  146. UINT FindMethod,
  147. BOOL bVerbose
  148. )
  149. {
  150. PGHI32 pghi;
  151. DWORD offset;
  152. DWORD MaxEntries, count;
  153. DWORD p;
  154. PBYTE pFault = NULL;
  155. BOOL bError = FALSE;
  156. pghi = (PGHI32)GetHeapBase();
  157. //
  158. // Verify that we are looking at a heap
  159. //
  160. offset = (DWORD) ReadWordSafe(&pghi->hi_first);
  161. p = (DWORD)pghi + offset;
  162. if (!ReadGNode32Safe(p, &he->gnode)) {
  163. if (bVerbose) {
  164. PRINTF("Heap not available\n");
  165. }
  166. return FALSE;
  167. }
  168. if (offset != he->gnode.pga_prev) {
  169. if (bVerbose) {
  170. PRINTF("Heap not valid\n");
  171. }
  172. return FALSE;
  173. }
  174. //
  175. // The caller has requested that we return the next heap
  176. // entry since the last invocation, or the first entry.
  177. //
  178. if (he->CurrentEntry == 0) {
  179. // get first entry
  180. offset = (DWORD) ReadWord(&pghi->hi_first);
  181. } else {
  182. if (he->CurrentEntry == he->NextEntry) {
  183. return FALSE;
  184. }
  185. // get next entry
  186. offset = he->NextEntry;
  187. }
  188. he->CurrentEntry = offset;
  189. if ((he->Selector == 0) && (FindMethod != FHE_FIND_MOD_ONLY)) {
  190. p = (DWORD)pghi + offset;
  191. if (!ReadGNode32(p, &he->gnode)) {
  192. return FALSE;
  193. }
  194. he->NextEntry = he->gnode.pga_next;
  195. GetHeapOwnerInfo(he);
  196. return TRUE;
  197. }
  198. //
  199. // If we get here, the caller wants us to scan the heap
  200. //
  201. MaxEntries = ReadWord(&pghi->hi_count);
  202. count = 0;
  203. while ((offset != 0) && (count <= MaxEntries)) {
  204. p = (DWORD)pghi + offset;
  205. if (!ReadGNode32(p, &he->gnode)) {
  206. return FALSE;
  207. } else {
  208. if (FindMethod == FHE_FIND_ANY) {
  209. WORD sel = he->Selector;
  210. if (((sel|1)==((WORD)he->gnode.pga_handle|1)) ||
  211. ((sel|1)==((WORD)he->gnode.pga_owner|1)) ||
  212. (sel==offset))
  213. {
  214. he->NextEntry = he->gnode.pga_next;
  215. GetHeapOwnerInfo(he);
  216. return TRUE;
  217. }
  218. } else if (FindMethod == FHE_FIND_MOD_ONLY) {
  219. GetHeapOwnerInfo(he);
  220. if (!_stricmp(he->OwnerName, he->ModuleArg)) {
  221. he->NextEntry = he->gnode.pga_next;
  222. return TRUE;
  223. }
  224. } else {
  225. if ((he->Selector|1)==((WORD)he->gnode.pga_handle|1)) {
  226. he->NextEntry = he->gnode.pga_next;
  227. GetHeapOwnerInfo(he);
  228. return TRUE;
  229. }
  230. }
  231. }
  232. count++;
  233. if (offset == he->gnode.pga_next) {
  234. break;
  235. }
  236. offset = he->gnode.pga_next;
  237. he->CurrentEntry = offset;
  238. }
  239. return FALSE;
  240. }
  241. VOID
  242. chkheap(
  243. CMD_ARGLIST
  244. )
  245. {
  246. CMD_INIT();
  247. if (CheckGlobalHeap(TRUE)) {
  248. PRINTF("Heap checks OK\n");
  249. }
  250. }
  251. //*************************************************************
  252. // dumpgheap xxx
  253. // where xxx is the 16-bit protect mode selector of the
  254. // Kernel global heap info.
  255. //
  256. //*************************************************************
  257. VOID
  258. dgh(
  259. CMD_ARGLIST
  260. )
  261. {
  262. HEAPENTRY he = {0};
  263. SELECTORINFO si;
  264. ULONG TotalAllocated = 0;
  265. ULONG TotalFree = 0;
  266. ULONG CountPrinted = 0;
  267. CMD_INIT();
  268. if (GetNextToken()) {
  269. he.Selector = (WORD) EXPRESSION( lpArgumentString );
  270. }
  271. PRINTF("Arena Base Limit Hnd Own Fl Lk Module Type Resid");
  272. PRINTF("\n");
  273. PRINTF("===== ======== ======== ==== ==== == == ======== ==== =====");
  274. PRINTF("\n");
  275. while (FindHeapEntry(&he, FHE_FIND_ANY, FHE_FIND_VERBOSE)) {
  276. PRINTF("%.5x", he.CurrentEntry);
  277. PRINTF(" %.8x", he.gnode.pga_address);
  278. PRINTF(" %.8X", he.gnode.pga_size);
  279. PRINTF(" %.4X", he.gnode.pga_handle);
  280. PRINTF(" %.4X", he.gnode.pga_owner);
  281. PRINTF(" %.2X", he.gnode.pga_flags);
  282. PRINTF(" %.2X", he.gnode.pga_count);
  283. PRINTF(" %-8.8s", he.OwnerName);
  284. GetInfoFromSelector((WORD)(he.gnode.pga_handle | 1), PROT_MODE, &si);
  285. PRINTF(" %s", si.bCode ? "Code" : "Data");
  286. if (he.SegmentNumber != -1) {
  287. PRINTF(" %d", he.SegmentNumber+1);
  288. }
  289. PRINTF("\n");
  290. if (!he.gnode.pga_owner) {
  291. TotalFree += he.gnode.pga_size;
  292. } else {
  293. TotalAllocated += he.gnode.pga_size;
  294. }
  295. CountPrinted++;
  296. }
  297. if (CountPrinted > 1) {
  298. PRINTF("\n Allocated = %dK, Free = %dK\n", TotalAllocated/1024, TotalFree/1024);
  299. }
  300. }
  301. VOID
  302. UpdateLockCount(
  303. int count
  304. )
  305. {
  306. HEAPENTRY he = {0};
  307. BYTE LockCount;
  308. if (GetNextToken()) {
  309. he.Selector = (WORD) EXPRESSION( lpArgumentString );
  310. } else {
  311. PRINTF("Please enter a selector or handle\n");
  312. return;
  313. }
  314. if (FindHeapEntry(&he, FHE_FIND_SEL_ONLY, FHE_FIND_VERBOSE)) {
  315. if (READMEM((LPVOID)(GetHeapBase()+he.CurrentEntry+0x14), &LockCount, 1)) {
  316. LockCount = (BYTE)((int) LockCount + count);
  317. WRITEMEM((LPVOID)(GetHeapBase()+he.CurrentEntry+0x14), &LockCount, 1);
  318. PRINTF("Lock count for %.4X is now %d\n", he.Selector, LockCount);
  319. } else {
  320. PRINTF("<can't read memory at that location>\n");
  321. }
  322. } else {
  323. PRINTF("Can't find selector %4X in WOW heap\n", he.Selector);
  324. }
  325. }
  326. VOID
  327. glock(
  328. CMD_ARGLIST
  329. )
  330. {
  331. CMD_INIT();
  332. UpdateLockCount(1);
  333. }
  334. VOID
  335. gunlock(
  336. CMD_ARGLIST
  337. )
  338. {
  339. CMD_INIT();
  340. UpdateLockCount(-1);
  341. }