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.

697 lines
19 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. ULONG IntelBase;
  15. void dump_params(
  16. ULONG params,
  17. char convention,
  18. int param_words
  19. ) {
  20. WORD word;
  21. int cnt;
  22. if ( param_words == 0 ) {
  23. param_words = 10;
  24. }
  25. PRINTF("(");
  26. cnt = 0;
  27. while ( cnt != param_words ) {
  28. if ( convention == 'c' ) {
  29. word = ReadWord(params+cnt);
  30. } else {
  31. word = ReadWord(params+(param_words-cnt));
  32. }
  33. if ( cnt == param_words - 1 ) {
  34. PRINTF("%04x",word);
  35. } else {
  36. PRINTF("%04x,",word);
  37. }
  38. cnt+=2;
  39. }
  40. PRINTF(")");
  41. }
  42. int look_for_near(
  43. ULONG pbp,
  44. WORD cs,
  45. WORD ss,
  46. WORD bp,
  47. int framed,
  48. ULONG csBase,
  49. int mode,
  50. BOOL fUseSymbols,
  51. BOOL fParams
  52. ) {
  53. WORD ip;
  54. ULONG ra;
  55. char call_type;
  56. char frame_type;
  57. char convention;
  58. int param_words;
  59. signed short dest;
  60. unsigned char opcode;
  61. unsigned char mod;
  62. unsigned char type;
  63. unsigned char rm;
  64. WORD dest_ip;
  65. char symbol[1000];
  66. BOOL fOk;
  67. BOOL fInst;
  68. BOOL b;
  69. LONG dist;
  70. BOOL fDest;
  71. fOk = TRUE;
  72. fInst = FALSE;
  73. fDest = FALSE;
  74. param_words = 0;
  75. if ( framed ) {
  76. frame_type = 'B';
  77. } else {
  78. frame_type = 'C';
  79. }
  80. ip = ReadWord(pbp+2);
  81. ra = csBase + (ULONG)ip;
  82. do {
  83. opcode = ReadByteSafe(ra - 2);
  84. if ( opcode == CALL_NEAR_INDIRECT ) {
  85. if ( ReadByteSafe(ra - 3) == PUSH_CS ) {
  86. call_type = 'f';
  87. } else {
  88. call_type = 'N';
  89. }
  90. opcode = ReadByteSafe(ra - 1);
  91. mod = opcode & MOD_BITS;
  92. type = opcode & TYPE_BITS;
  93. rm = opcode & RM_BITS;
  94. if ( type == INDIRECT_NEAR_TYPE ) {
  95. if ( mod == MOD0 && rm != RM6 ) {
  96. fInst = TRUE;
  97. break;
  98. }
  99. if ( mod == MOD3 ) {
  100. fInst = TRUE;
  101. break;
  102. }
  103. }
  104. }
  105. opcode = ReadByteSafe(ra - 3);
  106. if ( opcode == CALL_NEAR_RELATIVE ) {
  107. if ( ReadByteSafe(ra - 4) == PUSH_CS ) {
  108. call_type = 'f';
  109. } else {
  110. call_type = 'N';
  111. }
  112. dest = ReadWordSafe( ra - 2 );
  113. dest_ip = ip+dest;
  114. fInst = TRUE;
  115. fDest = TRUE;
  116. break;
  117. }
  118. if ( opcode == CALL_NEAR_INDIRECT ) {
  119. if ( ReadByteSafe(ra - 4) == PUSH_CS ) {
  120. call_type = 'f';
  121. } else {
  122. call_type = 'N';
  123. }
  124. opcode = ReadByteSafe(ra - 2);
  125. mod = opcode & MOD_BITS;
  126. type = opcode & TYPE_BITS;
  127. rm = opcode & RM_BITS;
  128. if ( type == INDIRECT_NEAR_TYPE
  129. && mod == MOD1 ) {
  130. fInst = TRUE;
  131. break;
  132. }
  133. }
  134. opcode = ReadByteSafe(ra - 4);
  135. if ( opcode == CALL_NEAR_INDIRECT ) {
  136. if ( ReadByteSafe(ra - 5) == PUSH_CS ) {
  137. call_type = 'f';
  138. } else {
  139. call_type = 'N';
  140. }
  141. opcode = ReadByteSafe(ra - 3);
  142. mod = opcode & MOD_BITS;
  143. type = opcode & TYPE_BITS;
  144. rm = opcode & RM_BITS;
  145. if ( type == INDIRECT_NEAR_TYPE ) {
  146. if ( mod == MOD0 && rm == RM6 ) {
  147. fInst = TRUE;
  148. break;
  149. }
  150. if ( mod == MOD2 ) {
  151. fInst = TRUE;
  152. break;
  153. }
  154. }
  155. }
  156. fOk = FALSE;
  157. } while ( FALSE );
  158. if ( fOk ) {
  159. if ( fUseSymbols ) {
  160. b = FindSymbol( cs, (LONG)ip, symbol, &dist, BEFORE, mode );
  161. } else {
  162. b = FALSE;
  163. }
  164. b = FALSE;
  165. if ( b ) {
  166. if ( dist == 0 ) {
  167. PRINTF("%04X:%04X %s %c%c", ss, bp, symbol, call_type, frame_type );
  168. } else {
  169. PRINTF("%04X:%04X %s+0x%lx %c%c", ss, bp, symbol, dist, call_type, frame_type );
  170. }
  171. } else {
  172. PRINTF("%04X:%04X %04X:%04X %c%c", ss, bp, cs, ip, call_type, frame_type );
  173. }
  174. if ( fInst ) {
  175. if ( ReadWordSafe(ra) == ADD_SP ) {
  176. convention = 'c';
  177. param_words = ReadByteSafe( ra+2 );
  178. } else {
  179. convention = 'p';
  180. }
  181. if ( fUseSymbols && fDest ) {
  182. b = FindSymbol( cs, (LONG)dest_ip, symbol, &dist, BEFORE, mode );
  183. } else {
  184. b = FALSE;
  185. }
  186. if ( b ) {
  187. if ( dist == 0 ) {
  188. PRINTF(" %ccall near %s", convention, symbol );
  189. } else {
  190. PRINTF(" %ccall near %s+0x%lx", convention, symbol, dist );
  191. }
  192. } else {
  193. if ( fDest ) {
  194. PRINTF(" %ccall near %04X", convention, dest_ip );
  195. } else {
  196. PRINTF(" %ccall near [Indirect]", convention );
  197. }
  198. }
  199. if ( fParams ) {
  200. dump_params( pbp+4, convention, param_words );
  201. }
  202. }
  203. PRINTF("\n");
  204. return( 1 );
  205. }
  206. return( 0 );
  207. }
  208. int look_for_far(
  209. ULONG pbp,
  210. WORD *cs,
  211. WORD ss,
  212. WORD bp,
  213. int framed,
  214. ULONG *csBase,
  215. int mode,
  216. BOOL fUseSymbols,
  217. BOOL fParams
  218. ) {
  219. WORD ip;
  220. WORD new_cs;
  221. ULONG new_csBase;
  222. ULONG ra;
  223. char frame_type;
  224. char convention;
  225. int param_words;
  226. WORD dest_cs;
  227. WORD dest_ip;
  228. unsigned char opcode;
  229. unsigned char mod;
  230. unsigned char type;
  231. unsigned char rm;
  232. char symbol[1000];
  233. BOOL fOk;
  234. BOOL fInst;
  235. BOOL b;
  236. LONG dist;
  237. BOOL fDest;
  238. int iMeth;
  239. WORD low_this;
  240. WORD high_this;
  241. fOk = TRUE;
  242. fInst = FALSE;
  243. fDest = FALSE;
  244. iMeth = -1;
  245. param_words = 0;
  246. if ( framed ) {
  247. frame_type = 'B';
  248. } else {
  249. frame_type = 'C';
  250. }
  251. ip = ReadWord(pbp+2);
  252. new_cs = ReadWord(pbp+4);
  253. new_csBase = GetInfoFromSelector( new_cs, mode, NULL ) + IntelBase;
  254. if ( new_csBase == -1 ) {
  255. return( 0 );
  256. }
  257. ra = new_csBase + (ULONG)ip;
  258. do {
  259. opcode = ReadByteSafe(ra - 2);
  260. if ( opcode == CALL_FAR_INDIRECT ) {
  261. opcode = ReadByte(ra - 1);
  262. mod = opcode & MOD_BITS;
  263. type = opcode & TYPE_BITS;
  264. rm = opcode & RM_BITS;
  265. if ( type == INDIRECT_FAR_TYPE ) {
  266. if ( mod == MOD0 && rm != RM6 ) {
  267. fInst = TRUE;
  268. iMeth = 0;
  269. break;
  270. }
  271. if ( mod == MOD3 ) {
  272. fInst = TRUE;
  273. break;
  274. }
  275. }
  276. }
  277. opcode = ReadByteSafe(ra - 3);
  278. if ( opcode == CALL_FAR_INDIRECT ) {
  279. opcode = ReadByteSafe(ra - 2);
  280. mod = opcode & MOD_BITS;
  281. type = opcode & TYPE_BITS;
  282. rm = opcode & RM_BITS;
  283. if ( type == INDIRECT_FAR_TYPE
  284. && mod == MOD1 ) {
  285. fInst = TRUE;
  286. iMeth = ReadByteSafe(ra - 1);
  287. break;
  288. }
  289. }
  290. opcode = ReadByteSafe(ra - 4);
  291. if ( opcode == CALL_FAR_INDIRECT ) {
  292. opcode = ReadByteSafe(ra - 3);
  293. mod = opcode & MOD_BITS;
  294. type = opcode & TYPE_BITS;
  295. rm = opcode & RM_BITS;
  296. if ( type == INDIRECT_FAR_TYPE ) {
  297. if ( mod == MOD0 && rm == RM6 ) {
  298. fInst = TRUE;
  299. break;
  300. }
  301. if ( mod == MOD2 ) {
  302. fInst = TRUE;
  303. break;
  304. }
  305. }
  306. }
  307. opcode = ReadByteSafe(ra - 5);
  308. if ( opcode == CALL_FAR_ABSOLUTE ) {
  309. dest_ip = ReadWordSafe( ra - 4 );
  310. dest_cs = ReadWordSafe( ra - 2 );
  311. fInst = TRUE;
  312. fDest = TRUE;
  313. break;
  314. }
  315. fOk = FALSE;
  316. } while ( FALSE );
  317. if ( fOk ) {
  318. if ( fUseSymbols ) {
  319. b = FindSymbol( new_cs, (LONG)ip, symbol, &dist, BEFORE, mode );
  320. } else {
  321. b = FALSE;
  322. }
  323. b = FALSE;
  324. if ( b ) {
  325. if ( dist == 0 ) {
  326. PRINTF("%04X:%04X %s F%c", ss, bp, symbol, frame_type );
  327. } else {
  328. PRINTF("%04X:%04X %s+0x%lx F%c", ss, bp, symbol, dist, frame_type );
  329. }
  330. } else {
  331. PRINTF("%04X:%04X %04X:%04X F%c", ss, bp, new_cs, ip, frame_type );
  332. }
  333. if ( fInst ) {
  334. if ( ReadWordSafe(ra) == ADD_SP ) {
  335. convention = 'c';
  336. param_words = ReadByteSafe( ra+2 );
  337. } else {
  338. convention = 'p';
  339. }
  340. if ( fUseSymbols && fDest ) {
  341. b = FindSymbol( dest_cs, (LONG)dest_ip, symbol, &dist, BEFORE, mode );
  342. } else {
  343. b = FALSE;
  344. }
  345. if ( b ) {
  346. if ( dist == 0 ) {
  347. PRINTF(" %ccall far %s", convention, symbol );
  348. } else {
  349. PRINTF(" %ccall far %s + 0x%lx", convention, symbol, dist );
  350. }
  351. } else {
  352. if ( fDest ) {
  353. PRINTF(" %ccall far %04X:%04X", convention, dest_cs, dest_ip );
  354. } else {
  355. ULONG thisBase;
  356. ULONG pvtbl;
  357. ULONG vtblBase;
  358. ULONG pfn;
  359. WORD low_vtbl;
  360. WORD high_vtbl;
  361. WORD low_fn;
  362. WORD high_fn;
  363. if ( iMeth != -1 ) {
  364. low_this = ReadWord(pbp+6);
  365. high_this = ReadWord(pbp+8);
  366. if ( low_this == 0 && high_this == 0 ) {
  367. low_fn = 0;
  368. high_fn = 0;
  369. strcpy(symbol,"");
  370. } else {
  371. thisBase = GetInfoFromSelector( high_this, mode, NULL ) + IntelBase;
  372. pvtbl = thisBase + (ULONG)low_this;
  373. low_vtbl = ReadWord(pvtbl);
  374. high_vtbl = ReadWord(pvtbl+2);
  375. vtblBase = GetInfoFromSelector( high_vtbl, mode, NULL ) + IntelBase;
  376. pfn = vtblBase + (ULONG)low_vtbl + iMeth;
  377. low_fn = ReadWord(pfn);
  378. high_fn = ReadWord(pfn+2);
  379. b = FindSymbol( high_fn, (LONG)low_fn, symbol, &dist, BEFORE, mode );
  380. if ( !b ) {
  381. wsprintf(symbol,"%04X:%04X", high_fn, low_fn );
  382. }
  383. }
  384. }
  385. switch( iMeth ) {
  386. default:
  387. case -1:
  388. if ( iMeth != -1 && (iMeth & 0x3) == 0 ) {
  389. PRINTF(" %ccall far [Ind-%04X:%04x Method %d] %s", convention, high_this, low_this, iMeth/4, symbol );
  390. } else {
  391. PRINTF(" %ccall far [Indirect]", convention );
  392. }
  393. break;
  394. case 0:
  395. PRINTF(" %ccall far [Ind-%04X:%04X Method 0 - QI?] %s", convention, high_this, low_this, symbol);
  396. break;
  397. case 4:
  398. PRINTF(" %ccall far [Ind-%04X:%04X Method 1 - AddRef?] %s", convention, high_this, low_this, symbol);
  399. break;
  400. case 8:
  401. PRINTF(" %ccall far [Ind-%04X:%04X Method 2 - Release?] %s", convention, high_this, low_this, symbol);
  402. break;
  403. }
  404. }
  405. }
  406. if ( fParams ) {
  407. dump_params( pbp+6, convention, param_words );
  408. }
  409. }
  410. PRINTF("\n");
  411. *cs = new_cs;
  412. *csBase = new_csBase;
  413. return( 1 );
  414. }
  415. return( 0 );
  416. }
  417. int scan_for_frameless(
  418. WORD ss,
  419. WORD sp,
  420. WORD next_bp,
  421. WORD *cs,
  422. ULONG ssBase,
  423. ULONG *csBase,
  424. int limit,
  425. int mode,
  426. BOOL fUseSymbols,
  427. BOOL fParams
  428. ) {
  429. ULONG pbp;
  430. int result;
  431. int cnt;
  432. cnt = 1000;
  433. sp -= 2;
  434. while ( limit ) {
  435. sp += 2;
  436. --cnt;
  437. if ( sp == next_bp || cnt == 0 ) {
  438. break;
  439. }
  440. pbp = ssBase + (ULONG)sp;
  441. result = look_for_near( pbp, *cs, ss, sp, 0, *csBase,
  442. mode, fUseSymbols, fParams );
  443. if ( result ) {
  444. --limit;
  445. continue;
  446. }
  447. /*
  448. ** Check for far calls
  449. */
  450. result = look_for_far( pbp, cs, ss, sp, 0, csBase,
  451. mode, fUseSymbols, fParams );
  452. if ( result ) {
  453. --limit;
  454. continue;
  455. }
  456. }
  457. return( 0 );
  458. }
  459. void stack_trace(
  460. WORD ss,
  461. ULONG ssBase,
  462. WORD sp,
  463. WORD bp,
  464. WORD cs,
  465. ULONG csBase,
  466. int limit,
  467. int mode,
  468. BOOL fUseSymbols,
  469. BOOL fGuessFrameless,
  470. BOOL fParams
  471. ) {
  472. WORD next_bp;
  473. ULONG pbp;
  474. int far_only;
  475. int result;
  476. WORD save_sp;
  477. WORD save_bp;
  478. WORD save_cs;
  479. ULONG save_csBase;
  480. int save_limit;
  481. save_sp = sp;
  482. save_bp = bp;
  483. save_cs = cs;
  484. save_csBase = csBase;
  485. save_limit = limit;
  486. PRINTF("[-Stack-] [-Retrn-] XY (X=Near/Far/far,Y=Call chain/BP Chain)\n");
  487. next_bp = bp;
  488. while ( limit ) {
  489. bp = next_bp;
  490. if ( bp == 0 ) {
  491. break;
  492. }
  493. if ( bp & 0x01 ) {
  494. far_only = 1;
  495. bp &= 0xFFFE;
  496. } else {
  497. far_only = 0;
  498. }
  499. pbp = ssBase + (ULONG)bp;
  500. next_bp = ReadWord(pbp);
  501. if ( fGuessFrameless ) {
  502. limit -= scan_for_frameless( ss, sp, bp, &cs,
  503. ssBase, &csBase, limit, mode, fUseSymbols,
  504. fParams );
  505. }
  506. if ( limit ) {
  507. /*
  508. ** Check for near calls
  509. */
  510. if ( far_only == 0 ) {
  511. result = look_for_near( pbp, cs, ss, bp, 1, csBase,
  512. mode, fUseSymbols, fParams );
  513. if ( result ) {
  514. sp = bp + 4;
  515. --limit;
  516. continue;
  517. }
  518. }
  519. /*
  520. ** Check for far calls
  521. */
  522. result = look_for_far( pbp, &cs, ss, bp, 1, &csBase,
  523. mode, fUseSymbols, fParams );
  524. if ( result ) {
  525. sp = bp + 6;
  526. --limit;
  527. continue;
  528. }
  529. PRINTF("Could not find call\n");
  530. break;
  531. }
  532. }
  533. if ( fGuessFrameless ) {
  534. if ( limit ) {
  535. limit -= scan_for_frameless(
  536. ss, sp, 0, &cs, ssBase, &csBase, limit, mode,
  537. fUseSymbols, fParams );
  538. }
  539. }
  540. }
  541. VOID
  542. WalkStack(
  543. ) {
  544. VDMCONTEXT ThreadContext;
  545. WORD bp;
  546. WORD sp;
  547. WORD ss;
  548. WORD cs;
  549. WORD ip;
  550. ULONG csBase;
  551. ULONG ssBase;
  552. int mode;
  553. int lines;
  554. mode = GetContext( &ThreadContext );
  555. IntelBase = GetIntelBase();
  556. sp = (WORD)ThreadContext.Esp;
  557. bp = (WORD)ThreadContext.Ebp;
  558. ss = (WORD)ThreadContext.SegSs;
  559. ip = (WORD)ThreadContext.Eip;
  560. cs = (WORD)ThreadContext.SegCs;
  561. csBase = GetInfoFromSelector( cs, mode, NULL ) + IntelBase;
  562. ssBase = GetInfoFromSelector( ss, mode, NULL ) + IntelBase;
  563. lines = 10;
  564. if (GetNextToken()) {
  565. lines = EXPRESSION( lpArgumentString );
  566. }
  567. stack_trace( ss,
  568. ssBase,
  569. sp,
  570. bp,
  571. cs,
  572. csBase,
  573. lines,
  574. mode,
  575. FALSE,
  576. FALSE,
  577. FALSE );
  578. }
  579. VOID
  580. WalkStackVerbose(
  581. ) {
  582. VDMCONTEXT ThreadContext;
  583. WORD bp;
  584. WORD sp;
  585. WORD ss;
  586. WORD cs;
  587. WORD ip;
  588. ULONG csBase;
  589. ULONG ssBase;
  590. int mode;
  591. int lines;
  592. mode = GetContext( &ThreadContext );
  593. IntelBase = GetIntelBase();
  594. sp = (WORD)ThreadContext.Esp;
  595. bp = (WORD)ThreadContext.Ebp;
  596. ss = (WORD)ThreadContext.SegSs;
  597. ip = (WORD)ThreadContext.Eip;
  598. cs = (WORD)ThreadContext.SegCs;
  599. csBase = GetInfoFromSelector( cs, mode, NULL ) + IntelBase;
  600. ssBase = GetInfoFromSelector( ss, mode, NULL ) + IntelBase;
  601. lines = 10;
  602. if (GetNextToken()) {
  603. lines = EXPRESSION( lpArgumentString );
  604. }
  605. stack_trace( ss,
  606. ssBase,
  607. sp,
  608. bp,
  609. cs,
  610. csBase,
  611. lines,
  612. mode,
  613. TRUE,
  614. FALSE,
  615. FALSE );
  616. }
  617. VOID
  618. k(
  619. CMD_ARGLIST
  620. )
  621. {
  622. CMD_INIT();
  623. WalkStack();
  624. }
  625. VOID
  626. kb(
  627. CMD_ARGLIST
  628. )
  629. {
  630. CMD_INIT();
  631. WalkStackVerbose();
  632. }