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.

649 lines
13 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. #define MYOF_FLAGS (OF_READ | OF_SHARE_DENY_NONE)
  15. #define MAX_MODULE_LIST 200
  16. char ModuleList[MAX_MODULE_LIST][9];
  17. int ModuleListCount = 0;
  18. BOOL
  19. GetVdmDbgEntry(
  20. LPSTR szEntryPoint,
  21. PVOID *pProc
  22. )
  23. {
  24. HANDLE hModVDM;
  25. hModVDM = GetModuleHandle("VDMDBG.DLL");
  26. if (hModVDM == (HANDLE)NULL) {
  27. PRINTF("VDMEXTS: Can't find vdmdbg.dll\n");
  28. return FALSE;
  29. }
  30. *pProc = GetProcAddress(hModVDM, szEntryPoint);
  31. if (!*pProc) {
  32. PRINTF("VDMEXTS: Can't find VDMDBG.DLL entry point %s\n", szEntryPoint);
  33. return FALSE;
  34. }
  35. return TRUE;
  36. }
  37. PSEGENTRY
  38. GetSegtablePointer(
  39. VOID
  40. )
  41. {
  42. static PSEGENTRY (WINAPI *pfnVDMGetSegtablePointer)(VOID) = NULL;
  43. if (!pfnVDMGetSegtablePointer && !GetVdmDbgEntry("VDMGetSegtablePointer",
  44. (PVOID)&pfnVDMGetSegtablePointer)) {
  45. return NULL;
  46. }
  47. return((*pfnVDMGetSegtablePointer)());
  48. }
  49. VOID
  50. ParseModuleName(
  51. LPSTR szName,
  52. LPSTR szPath
  53. )
  54. /*++
  55. Routine Description:
  56. This routine strips off the 8 character file name from a path
  57. Arguments:
  58. szName - pointer to buffer of 8 characters (plus null)
  59. szPath - full path of file
  60. Return Value
  61. None.
  62. --*/
  63. {
  64. LPSTR lPtr = szPath;
  65. LPSTR lDest = szName;
  66. int BufferSize = 9;
  67. while(*lPtr) lPtr++; // scan to end
  68. while( ((DWORD)lPtr > (DWORD)szPath) &&
  69. ((*lPtr != '\\') && (*lPtr != '/'))) lPtr--;
  70. if (*lPtr) lPtr++;
  71. while((*lPtr) && (*lPtr!='.')) {
  72. if (!--BufferSize) break;
  73. *lDest++ = *lPtr++;
  74. }
  75. *lDest = 0;
  76. }
  77. BOOL
  78. FindModuleNameList(
  79. LPSTR filename
  80. )
  81. {
  82. int i;
  83. for (i=0; i<ModuleListCount; i++) {
  84. if (!_stricmp(filename, ModuleList[i])) {
  85. return TRUE;
  86. }
  87. }
  88. return FALSE;
  89. }
  90. BOOL
  91. AddModuleNameList(
  92. LPSTR filename
  93. )
  94. {
  95. if (!strlen(filename)) {
  96. return FALSE;
  97. }
  98. if (!FindModuleNameList(filename)) {
  99. if (ModuleListCount>=(MAX_MODULE_LIST-1)) {
  100. return FALSE;
  101. }
  102. strcpy (ModuleList[ModuleListCount++], filename);
  103. }
  104. return TRUE;
  105. }
  106. VOID
  107. FreeModuleNameList(
  108. VOID
  109. )
  110. {
  111. ModuleListCount = 0;
  112. return;
  113. }
  114. VOID
  115. BuildModuleNameList(
  116. VOID
  117. )
  118. {
  119. HEAPENTRY he = {0};
  120. SEGENTRY *se;
  121. char filename[9];
  122. WORD sel;
  123. BOOL b;
  124. NEHEADER owner;
  125. ULONG base;
  126. CHAR ModuleName[9];
  127. UCHAR len;
  128. //
  129. // Search WOW Module list
  130. //
  131. if (!ReadMemExpression("ntvdmd!DbgWowhExeHead", &sel, sizeof(sel))) {
  132. return;
  133. }
  134. while(sel) {
  135. base = GetInfoFromSelector(sel, PROT_MODE, NULL) + GetIntelBase();
  136. b = READMEM((LPVOID)base, &owner, sizeof(owner));
  137. if (!b || (owner.ne_magic != 0x454e)) {
  138. PRINTF("Invalid module list! (started with hExeHead)\n");
  139. return;
  140. }
  141. len = ReadByteSafe(base+owner.ne_restab);
  142. if (len>8) {
  143. len=8;
  144. }
  145. READMEM((LPVOID)(base+owner.ne_restab+1), ModuleName, 8);
  146. ModuleName[len] = 0;
  147. AddModuleNameList(ModuleName);
  148. // This is mapped to ne_pnextexe in kernel
  149. sel = owner.ne_cbenttab;
  150. }
  151. //
  152. // Search debugger segment array
  153. //
  154. se = GetSegtablePointer();
  155. while ( se ) {
  156. ParseModuleName(filename, se->szExePath);
  157. AddModuleNameList(filename);
  158. se = se->Next;
  159. }
  160. }
  161. BOOL
  162. GetOwnerSegmentFromSelector(
  163. WORD selector,
  164. int mode,
  165. LPSTR szModule,
  166. WORD *psegment
  167. )
  168. /*++
  169. Routine Description:
  170. This routine returns the "segment number" and owner name
  171. of the given selector or v86mode segment. The returned number
  172. represents the position of the segment in the binary, and is 1-based.
  173. Arguments:
  174. selector - either PMODE selector or V86 mode segment
  175. mode - PROT_MODE or V86_MODE
  176. filename - pointer to buffer to receive module name
  177. psegment - pointer to WORD to receive segment number
  178. Return Value
  179. TRUE if found
  180. --*/
  181. {
  182. HEAPENTRY he = {0};
  183. SEGENTRY *se;
  184. he.Selector = selector;
  185. if (FindHeapEntry(&he, FHE_FIND_SEL_ONLY, FHE_FIND_QUIET)) {
  186. strcpy(szModule, he.FileName);
  187. *psegment = he.SegmentNumber+1;
  188. return TRUE;
  189. }
  190. se = GetSegtablePointer();
  191. while ( se ) {
  192. if (se->selector == selector) {
  193. ParseModuleName(szModule, se->szExePath);
  194. *psegment = se->segment;
  195. return TRUE;
  196. }
  197. se = se->Next;
  198. }
  199. return FALSE;
  200. }
  201. BOOL
  202. GetSelectorFromOwnerSegment(
  203. LPSTR szModule,
  204. WORD segment,
  205. WORD *pselector,
  206. int *pmode
  207. )
  208. {
  209. HEAPENTRY he = {0};
  210. char tempModule[9];
  211. SEGENTRY *se;
  212. while (FindHeapEntry(&he, FHE_FIND_SEL_ONLY, FHE_FIND_QUIET)) {
  213. if (!_stricmp(szModule, he.FileName) &&
  214. (segment == he.SegmentNumber+1)) {
  215. *pselector = he.gnode.pga_handle|1;
  216. *pmode = PROT_MODE;
  217. return TRUE;
  218. }
  219. }
  220. se = GetSegtablePointer();
  221. while ( se ) {
  222. ParseModuleName(tempModule, se->szExePath);
  223. if (!_stricmp(szModule, tempModule) &&
  224. (segment == se->segment+1)) {
  225. *pselector = se->selector;
  226. if (se->type == SEGTYPE_V86) {
  227. *pmode = V86_MODE;
  228. } else {
  229. *pmode = PROT_MODE;
  230. }
  231. return TRUE;
  232. }
  233. se = se->Next;
  234. }
  235. return FALSE;
  236. }
  237. BOOL
  238. FindSymbol(
  239. WORD selector,
  240. LONG offset,
  241. LPSTR sym_text,
  242. LONG *dist,
  243. int direction,
  244. int mode
  245. )
  246. {
  247. char filename[9];
  248. WORD segment;
  249. static VDMGETSYMBOLPROC pfnGetSymbol = NULL;
  250. if (!pfnGetSymbol && !GetVdmDbgEntry("VDMGetSymbol", (PVOID)&pfnGetSymbol)) {
  251. return FALSE;
  252. }
  253. if (GetOwnerSegmentFromSelector(selector, mode, filename, &segment)) {
  254. return(pfnGetSymbol(filename,
  255. segment,
  256. offset,
  257. (mode == PROT_MODE),
  258. (direction == AFTER),
  259. sym_text,
  260. dist));
  261. }
  262. return FALSE;
  263. }
  264. BOOL
  265. FindAddress(
  266. LPSTR sym_text,
  267. LPSTR filename,
  268. WORD *psegment,
  269. WORD *pselector,
  270. LONG *poffset,
  271. int *pmode,
  272. BOOL bDumpAll
  273. )
  274. {
  275. int i;
  276. BOOL bResult;
  277. static VDMGETADDREXPRESSIONPROC pfnGetAddrExpression = NULL;
  278. WORD type;
  279. char module[9];
  280. if (!pfnGetAddrExpression && !GetVdmDbgEntry("VDMGetAddrExpression",
  281. (PVOID)&pfnGetAddrExpression)) {
  282. return FALSE;
  283. }
  284. BuildModuleNameList();
  285. for (i=0; i<ModuleListCount; i++) {
  286. bResult = pfnGetAddrExpression(ModuleList[i],
  287. sym_text,
  288. pselector,
  289. poffset,
  290. &type);
  291. if (bResult) {
  292. strcpy(filename, ModuleList[i]);
  293. if (type == VDMADDR_V86) {
  294. *pmode = V86_MODE;
  295. } else {
  296. *pmode = PROT_MODE;
  297. }
  298. if (!GetOwnerSegmentFromSelector(*pselector, *pmode,
  299. module, psegment)) {
  300. *pmode = NOT_LOADED;
  301. }
  302. return TRUE;
  303. }
  304. }
  305. return FALSE;
  306. }
  307. VOID
  308. ln(
  309. CMD_ARGLIST
  310. ) {
  311. VDMCONTEXT ThreadContext;
  312. WORD selector;
  313. LONG offset;
  314. CHAR sym_text[1000];
  315. DWORD dist;
  316. BOOL b;
  317. int mode;
  318. CMD_INIT();
  319. mode = GetContext( &ThreadContext );
  320. if (!GetNextToken()) {
  321. selector = (WORD) ThreadContext.SegCs;
  322. offset = ThreadContext.Eip;
  323. } else if (!ParseIntelAddress(&mode, &selector, &offset)) {
  324. return;
  325. }
  326. if ( mode == PROT_MODE ) {
  327. PRINTF( "#%04X:%04lX", selector, offset );
  328. }
  329. if ( mode == V86_MODE ) {
  330. PRINTF( "&%04X:%04lX", selector, offset );
  331. }
  332. b = FindSymbol( selector, offset, sym_text, &dist, BEFORE, mode );
  333. if ( !b ) {
  334. PRINTF(" = Could not find symbol before");
  335. } else {
  336. if ( dist == 0 ) {
  337. PRINTF(" = %s", sym_text );
  338. } else {
  339. PRINTF(" = %s+0x%lx", sym_text, dist );
  340. }
  341. }
  342. b = FindSymbol( selector, offset, sym_text, &dist, AFTER, mode );
  343. if ( !b ) {
  344. PRINTF(" | Could not find symbol after");
  345. } else {
  346. if ( dist == 0 ) {
  347. PRINTF(" | %s", sym_text );
  348. } else {
  349. PRINTF(" | %s-0x%lx", sym_text, dist );
  350. }
  351. }
  352. PRINTF("\n");
  353. }
  354. VOID
  355. x(
  356. CMD_ARGLIST
  357. ) {
  358. VDMCONTEXT ThreadContext;
  359. BOOL result;
  360. WORD selector;
  361. WORD segment;
  362. LONG offset;
  363. int mode;
  364. char filename[9];
  365. CMD_INIT();
  366. try {
  367. mode = GetContext( &ThreadContext );
  368. result = FindAddress( lpArgumentString,
  369. filename,
  370. &segment,
  371. &selector,
  372. &offset,
  373. &mode,
  374. TRUE);
  375. if ( result ) {
  376. if ( mode == PROT_MODE ) {
  377. PRINTF("#");
  378. } else if ( mode == V86_MODE ) {
  379. PRINTF("&");
  380. } else if ( mode == NOT_LOADED ) {
  381. selector = 0;
  382. PRINTF("?");
  383. }
  384. PRINTF("%04X:%04X = %s(%04X)!%s\n",
  385. selector, offset, filename, segment, lpArgumentString );
  386. return;
  387. }
  388. PRINTF("Could not find symbol '%s'\n", lpArgumentString );
  389. } except (1) {
  390. PRINTF("Exception 0x%08x in vdmexts!\n", GetExceptionCode());
  391. }
  392. }
  393. /****************************************************************************
  394. ****************************************************************************
  395. extension debugging routines
  396. The following functions were added to help debug the debugger extension.
  397. They are not intended to be used in normal operation.
  398. ****************************************************************************
  399. ****************************************************************************/
  400. VOID
  401. DumpModuleNameList(
  402. VOID
  403. )
  404. {
  405. int i;
  406. for (i=0; i<ModuleListCount; i++) {
  407. PRINTF("%d %s\n", i, ModuleList[i]);
  408. }
  409. }
  410. VOID
  411. moddump(
  412. CMD_ARGLIST
  413. )
  414. {
  415. CMD_INIT();
  416. BuildModuleNameList();
  417. DumpModuleNameList();
  418. }
  419. VOID
  420. segdef(
  421. CMD_ARGLIST
  422. )
  423. {
  424. int cnt;
  425. int UpdateCnt;
  426. SEGENTRY *se;
  427. WORD selector;
  428. WORD segment;
  429. DWORD length;
  430. int type;
  431. CMD_INIT();
  432. se = GetSegtablePointer();
  433. if (!GetNextToken()) {
  434. PRINTF("Missing index\n");
  435. return;
  436. }
  437. UpdateCnt = (int) EvaluateToken();
  438. if (!GetNextToken()) {
  439. PRINTF("Missing selector\n");
  440. return;
  441. }
  442. selector = (WORD) EvaluateToken();
  443. if (!GetNextToken()) {
  444. PRINTF("Missing segment\n");
  445. return;
  446. }
  447. segment = (WORD) EvaluateToken();
  448. if (!GetNextToken()) {
  449. PRINTF("Missing limit\n");
  450. return;
  451. }
  452. length = EvaluateToken();
  453. if (!GetNextToken()) {
  454. PRINTF("Missing type\n");
  455. return;
  456. }
  457. type = (int) EvaluateToken();
  458. if (!GetNextToken()) {
  459. PRINTF("Missing path\n");
  460. return;
  461. }
  462. cnt = 0;
  463. while ( se ) {
  464. if (cnt == UpdateCnt) {
  465. se->selector = selector;
  466. se->segment = segment;
  467. se->length = length;
  468. se->type = type;
  469. strcpy(se->szExePath, lpArgumentString);
  470. break;
  471. }
  472. cnt++;
  473. se = se->Next;
  474. }
  475. }
  476. VOID
  477. segdump(
  478. CMD_ARGLIST
  479. )
  480. {
  481. int cnt;
  482. int DumpCnt;
  483. SEGENTRY *se;
  484. CMD_INIT();
  485. PRINTF("Index Sel Seg Length Type Module Path\n");
  486. se = GetSegtablePointer();
  487. if (GetNextToken()) {
  488. DumpCnt = (int) EvaluateToken();
  489. cnt = 0;
  490. while ( se ) {
  491. if (DumpCnt == cnt) {
  492. PRINTF("%03x %04x %04x %08x %s %s %s\n", cnt,
  493. se->selector, se->segment, se->length,
  494. ((se->type==SEGTYPE_V86) ? "v86 " : "prot"),
  495. se->szModule, se->szExePath);
  496. break;
  497. }
  498. cnt++;
  499. se = se->Next;
  500. }
  501. return;
  502. }
  503. cnt = 0;
  504. while ( se ) {
  505. PRINTF("%03x %04x %04x %08x %s %s %s\n", cnt,
  506. se->selector, se->segment, se->length,
  507. ((se->type==SEGTYPE_V86) ? "v86 " : "prot"),
  508. se->szModule, se->szExePath);
  509. cnt++;
  510. se = se->Next;
  511. }
  512. }