summaryrefslogtreecommitdiffstats
path: root/private/mvdm/bde/bdestack.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/bde/bdestack.c')
-rw-r--r--private/mvdm/bde/bdestack.c653
1 files changed, 653 insertions, 0 deletions
diff --git a/private/mvdm/bde/bdestack.c b/private/mvdm/bde/bdestack.c
new file mode 100644
index 000000000..b25b9b618
--- /dev/null
+++ b/private/mvdm/bde/bdestack.c
@@ -0,0 +1,653 @@
+#include <precomp.h>
+#pragma hdrstop
+
+ULONG IntelBase;
+
+void dump_params(
+ ULONG params,
+ char convention,
+ int param_words
+) {
+ WORD word;
+ int cnt;
+
+ if ( param_words == 0 ) {
+ param_words = 10;
+ }
+ PRINTF("(");
+ cnt = 0;
+ while ( cnt != param_words ) {
+ if ( convention == 'c' ) {
+ word = ReadWord(params+cnt);
+ } else {
+ word = ReadWord(params+(param_words-cnt));
+ }
+ if ( cnt == param_words - 1 ) {
+ PRINTF("%04x",word);
+ } else {
+ PRINTF("%04x,",word);
+ }
+ cnt+=2;
+ }
+ PRINTF(")");
+}
+
+int look_for_near(
+ ULONG pbp,
+ WORD cs,
+ WORD ss,
+ WORD bp,
+ int framed,
+ ULONG csBase,
+ int mode,
+ BOOL fUseSymbols,
+ BOOL fParams
+) {
+ WORD ip;
+ ULONG ra;
+ char call_type;
+ char frame_type;
+ char convention;
+ int param_words;
+ signed short dest;
+ unsigned char opcode;
+ unsigned char mod;
+ unsigned char type;
+ unsigned char rm;
+ WORD dest_ip;
+ char symbol[1000];
+ BOOL fOk;
+ BOOL fInst;
+ BOOL b;
+ LONG dist;
+ BOOL fDest;
+
+ fOk = TRUE;
+ fInst = FALSE;
+ fDest = FALSE;
+
+ param_words = 0;
+ if ( framed ) {
+ frame_type = 'B';
+ } else {
+ frame_type = 'C';
+ }
+ ip = ReadWord(pbp+2);
+ ra = csBase + (ULONG)ip;
+
+ do {
+ opcode = ReadByteSafe(ra - 2);
+ if ( opcode == CALL_NEAR_INDIRECT ) {
+ if ( ReadByteSafe(ra - 3) == PUSH_CS ) {
+ call_type = 'f';
+ } else {
+ call_type = 'N';
+ }
+ opcode = ReadByteSafe(ra - 1);
+ mod = opcode & MOD_BITS;
+ type = opcode & TYPE_BITS;
+ rm = opcode & RM_BITS;
+ if ( type == INDIRECT_NEAR_TYPE ) {
+ if ( mod == MOD0 && rm != RM6 ) {
+ fInst = TRUE;
+ break;
+ }
+ if ( mod == MOD3 ) {
+ fInst = TRUE;
+ break;
+ }
+ }
+ }
+ opcode = ReadByteSafe(ra - 3);
+ if ( opcode == CALL_NEAR_RELATIVE ) {
+ if ( ReadByteSafe(ra - 4) == PUSH_CS ) {
+ call_type = 'f';
+ } else {
+ call_type = 'N';
+ }
+ dest = ReadWordSafe( ra - 2 );
+ dest_ip = ip+dest;
+ fInst = TRUE;
+ fDest = TRUE;
+ break;
+ }
+ if ( opcode == CALL_NEAR_INDIRECT ) {
+ if ( ReadByteSafe(ra - 4) == PUSH_CS ) {
+ call_type = 'f';
+ } else {
+ call_type = 'N';
+ }
+ opcode = ReadByteSafe(ra - 2);
+ mod = opcode & MOD_BITS;
+ type = opcode & TYPE_BITS;
+ rm = opcode & RM_BITS;
+ if ( type == INDIRECT_NEAR_TYPE
+ && mod == MOD1 ) {
+ fInst = TRUE;
+ break;
+ }
+ }
+ opcode = ReadByteSafe(ra - 4);
+ if ( opcode == CALL_NEAR_INDIRECT ) {
+ if ( ReadByteSafe(ra - 5) == PUSH_CS ) {
+ call_type = 'f';
+ } else {
+ call_type = 'N';
+ }
+ opcode = ReadByteSafe(ra - 3);
+ mod = opcode & MOD_BITS;
+ type = opcode & TYPE_BITS;
+ rm = opcode & RM_BITS;
+ if ( type == INDIRECT_NEAR_TYPE ) {
+ if ( mod == MOD0 && rm == RM6 ) {
+ fInst = TRUE;
+ break;
+ }
+ if ( mod == MOD2 ) {
+ fInst = TRUE;
+ break;
+ }
+ }
+ }
+ fOk = FALSE;
+ } while ( FALSE );
+
+ if ( fOk ) {
+ if ( fUseSymbols ) {
+ b = FindSymbol( cs, (LONG)ip, symbol, &dist, BEFORE, mode );
+ } else {
+ b = FALSE;
+ }
+ b = FALSE;
+
+ if ( b ) {
+ if ( dist == 0 ) {
+ PRINTF("%04X:%04X %s %c%c", ss, bp, symbol, call_type, frame_type );
+ } else {
+ PRINTF("%04X:%04X %s+0x%lx %c%c", ss, bp, symbol, dist, call_type, frame_type );
+ }
+ } else {
+ PRINTF("%04X:%04X %04X:%04X %c%c", ss, bp, cs, ip, call_type, frame_type );
+ }
+ if ( fInst ) {
+ if ( ReadWordSafe(ra) == ADD_SP ) {
+ convention = 'c';
+ param_words = ReadByteSafe( ra+2 );
+ } else {
+ convention = 'p';
+ }
+ if ( fUseSymbols && fDest ) {
+ b = FindSymbol( cs, (LONG)dest_ip, symbol, &dist, BEFORE, mode );
+ } else {
+ b = FALSE;
+ }
+ if ( b ) {
+ if ( dist == 0 ) {
+ PRINTF(" %ccall near %s", convention, symbol );
+ } else {
+ PRINTF(" %ccall near %s+0x%lx", convention, symbol, dist );
+ }
+ } else {
+ if ( fDest ) {
+ PRINTF(" %ccall near %04X", convention, dest_ip );
+ } else {
+ PRINTF(" %ccall near [Indirect]", convention );
+ }
+ }
+ if ( fParams ) {
+ dump_params( pbp+4, convention, param_words );
+ }
+ }
+ PRINTF("\n");
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+int look_for_far(
+ ULONG pbp,
+ WORD *cs,
+ WORD ss,
+ WORD bp,
+ int framed,
+ ULONG *csBase,
+ int mode,
+ BOOL fUseSymbols,
+ BOOL fParams
+) {
+ WORD ip;
+ WORD new_cs;
+ ULONG new_csBase;
+ ULONG ra;
+ char frame_type;
+ char convention;
+ int param_words;
+ WORD dest_cs;
+ WORD dest_ip;
+ unsigned char opcode;
+ unsigned char mod;
+ unsigned char type;
+ unsigned char rm;
+ char symbol[1000];
+ BOOL fOk;
+ BOOL fInst;
+ BOOL b;
+ LONG dist;
+ BOOL fDest;
+ int iMeth;
+ WORD low_this;
+ WORD high_this;
+
+ fOk = TRUE;
+ fInst = FALSE;
+ fDest = FALSE;
+ iMeth = -1;
+
+ param_words = 0;
+ if ( framed ) {
+ frame_type = 'B';
+ } else {
+ frame_type = 'C';
+ }
+ ip = ReadWord(pbp+2);
+ new_cs = ReadWord(pbp+4);
+ new_csBase = GetInfoFromSelector( new_cs, mode, NULL ) + IntelBase;
+ if ( new_csBase == -1 ) {
+ return( 0 );
+ }
+ ra = new_csBase + (ULONG)ip;
+
+ do {
+ opcode = ReadByteSafe(ra - 2);
+ if ( opcode == CALL_FAR_INDIRECT ) {
+ opcode = ReadByte(ra - 1);
+ mod = opcode & MOD_BITS;
+ type = opcode & TYPE_BITS;
+ rm = opcode & RM_BITS;
+ if ( type == INDIRECT_FAR_TYPE ) {
+ if ( mod == MOD0 && rm != RM6 ) {
+ fInst = TRUE;
+ iMeth = 0;
+ break;
+ }
+ if ( mod == MOD3 ) {
+ fInst = TRUE;
+ break;
+ }
+ }
+ }
+ opcode = ReadByteSafe(ra - 3);
+ if ( opcode == CALL_FAR_INDIRECT ) {
+ opcode = ReadByteSafe(ra - 2);
+ mod = opcode & MOD_BITS;
+ type = opcode & TYPE_BITS;
+ rm = opcode & RM_BITS;
+ if ( type == INDIRECT_FAR_TYPE
+ && mod == MOD1 ) {
+ fInst = TRUE;
+ iMeth = ReadByteSafe(ra - 1);
+ break;
+ }
+ }
+ opcode = ReadByteSafe(ra - 4);
+ if ( opcode == CALL_FAR_INDIRECT ) {
+ opcode = ReadByteSafe(ra - 3);
+ mod = opcode & MOD_BITS;
+ type = opcode & TYPE_BITS;
+ rm = opcode & RM_BITS;
+ if ( type == INDIRECT_FAR_TYPE ) {
+ if ( mod == MOD0 && rm == RM6 ) {
+ fInst = TRUE;
+ break;
+ }
+ if ( mod == MOD2 ) {
+ fInst = TRUE;
+ break;
+ }
+ }
+ }
+ opcode = ReadByteSafe(ra - 5);
+ if ( opcode == CALL_FAR_ABSOLUTE ) {
+ dest_ip = ReadWordSafe( ra - 4 );
+ dest_cs = ReadWordSafe( ra - 2 );
+ fInst = TRUE;
+ fDest = TRUE;
+ break;
+ }
+ fOk = FALSE;
+ } while ( FALSE );
+
+ if ( fOk ) {
+ if ( fUseSymbols ) {
+ b = FindSymbol( new_cs, (LONG)ip, symbol, &dist, BEFORE, mode );
+ } else {
+ b = FALSE;
+ }
+ b = FALSE;
+
+ if ( b ) {
+ if ( dist == 0 ) {
+ PRINTF("%04X:%04X %s F%c", ss, bp, symbol, frame_type );
+ } else {
+ PRINTF("%04X:%04X %s+0x%lx F%c", ss, bp, symbol, dist, frame_type );
+ }
+ } else {
+ PRINTF("%04X:%04X %04X:%04X F%c", ss, bp, new_cs, ip, frame_type );
+ }
+ if ( fInst ) {
+ if ( ReadWordSafe(ra) == ADD_SP ) {
+ convention = 'c';
+ param_words = ReadByteSafe( ra+2 );
+ } else {
+ convention = 'p';
+ }
+ if ( fUseSymbols && fDest ) {
+ b = FindSymbol( dest_cs, (LONG)dest_ip, symbol, &dist, BEFORE, mode );
+ } else {
+ b = FALSE;
+ }
+ if ( b ) {
+ if ( dist == 0 ) {
+ PRINTF(" %ccall far %s", convention, symbol );
+ } else {
+ PRINTF(" %ccall far %s + 0x%lx", convention, symbol, dist );
+ }
+ } else {
+ if ( fDest ) {
+ PRINTF(" %ccall far %04X:%04X", convention, dest_cs, dest_ip );
+ } else {
+ ULONG thisBase;
+ ULONG pvtbl;
+ ULONG vtblBase;
+ ULONG pfn;
+ WORD low_vtbl;
+ WORD high_vtbl;
+ WORD low_fn;
+ WORD high_fn;
+
+ if ( iMeth != -1 ) {
+ low_this = ReadWord(pbp+6);
+ high_this = ReadWord(pbp+8);
+
+ if ( low_this == 0 && high_this == 0 ) {
+ low_fn = 0;
+ high_fn = 0;
+ strcpy(symbol,"");
+ } else {
+ thisBase = GetInfoFromSelector( high_this, mode, NULL ) + IntelBase;
+ pvtbl = thisBase + (ULONG)low_this;
+
+ low_vtbl = ReadWord(pvtbl);
+ high_vtbl = ReadWord(pvtbl+2);
+
+ vtblBase = GetInfoFromSelector( high_vtbl, mode, NULL ) + IntelBase;
+ pfn = vtblBase + (ULONG)low_vtbl + iMeth;
+
+ low_fn = ReadWord(pfn);
+ high_fn = ReadWord(pfn+2);
+
+ b = FindSymbol( high_fn, (LONG)low_fn, symbol, &dist, BEFORE, mode );
+ if ( !b ) {
+ wsprintf(symbol,"%04X:%04X", high_fn, low_fn );
+ }
+ }
+ }
+ switch( iMeth ) {
+ default:
+ case -1:
+ if ( iMeth != -1 && (iMeth & 0x3) == 0 ) {
+ PRINTF(" %ccall far [Ind-%04X:%04x Method %d] %s", convention, high_this, low_this, iMeth/4, symbol );
+ } else {
+ PRINTF(" %ccall far [Indirect]", convention );
+ }
+ break;
+ case 0:
+ PRINTF(" %ccall far [Ind-%04X:%04X Method 0 - QI?] %s", convention, high_this, low_this, symbol);
+ break;
+ case 4:
+ PRINTF(" %ccall far [Ind-%04X:%04X Method 1 - AddRef?] %s", convention, high_this, low_this, symbol);
+ break;
+ case 8:
+ PRINTF(" %ccall far [Ind-%04X:%04X Method 2 - Release?] %s", convention, high_this, low_this, symbol);
+ break;
+ }
+ }
+ }
+ if ( fParams ) {
+ dump_params( pbp+6, convention, param_words );
+ }
+ }
+ PRINTF("\n");
+ *cs = new_cs;
+ *csBase = new_csBase;
+ return( 1 );
+ }
+ return( 0 );
+}
+
+int scan_for_frameless(
+ WORD ss,
+ WORD sp,
+ WORD next_bp,
+ WORD *cs,
+ ULONG ssBase,
+ ULONG *csBase,
+ int limit,
+ int mode,
+ BOOL fUseSymbols,
+ BOOL fParams
+) {
+ ULONG pbp;
+ int result;
+ int cnt;
+
+ cnt = 1000;
+ sp -= 2;
+ while ( limit ) {
+ sp += 2;
+ --cnt;
+ if ( sp == next_bp || cnt == 0 ) {
+ break;
+ }
+
+ pbp = ssBase + (ULONG)sp;
+
+ result = look_for_near( pbp, *cs, ss, sp, 0, *csBase,
+ mode, fUseSymbols, fParams );
+ if ( result ) {
+ --limit;
+ continue;
+ }
+ /*
+ ** Check for far calls
+ */
+ result = look_for_far( pbp, cs, ss, sp, 0, csBase,
+ mode, fUseSymbols, fParams );
+ if ( result ) {
+ --limit;
+ continue;
+ }
+ }
+
+ return( 0 );
+}
+
+void stack_trace(
+ WORD ss,
+ ULONG ssBase,
+ WORD sp,
+ WORD bp,
+ WORD cs,
+ ULONG csBase,
+ int limit,
+ int mode,
+ BOOL fUseSymbols,
+ BOOL fGuessFrameless,
+ BOOL fParams
+) {
+ WORD next_bp;
+ ULONG pbp;
+ int far_only;
+ int result;
+ WORD save_sp;
+ WORD save_bp;
+ WORD save_cs;
+ ULONG save_csBase;
+ int save_limit;
+
+ save_sp = sp;
+ save_bp = bp;
+ save_cs = cs;
+ save_csBase = csBase;
+ save_limit = limit;
+
+ PRINTF("[-Stack-] [-Retrn-] XY (X=Near/Far/far,Y=Call chain/BP Chain)\n");
+
+ next_bp = bp;
+
+ while ( limit ) {
+ bp = next_bp;
+ if ( bp == 0 ) {
+ break;
+ }
+ if ( bp & 0x01 ) {
+ far_only = 1;
+ bp &= 0xFFFE;
+ } else {
+ far_only = 0;
+ }
+ pbp = ssBase + (ULONG)bp;
+ next_bp = ReadWord(pbp);
+
+ if ( fGuessFrameless ) {
+ limit -= scan_for_frameless( ss, sp, bp, &cs,
+ ssBase, &csBase, limit, mode, fUseSymbols,
+ fParams );
+ }
+
+ if ( limit ) {
+ /*
+ ** Check for near calls
+ */
+ if ( far_only == 0 ) {
+ result = look_for_near( pbp, cs, ss, bp, 1, csBase,
+ mode, fUseSymbols, fParams );
+ if ( result ) {
+ sp = bp + 4;
+ --limit;
+ continue;
+ }
+ }
+ /*
+ ** Check for far calls
+ */
+ result = look_for_far( pbp, &cs, ss, bp, 1, &csBase,
+ mode, fUseSymbols, fParams );
+ if ( result ) {
+ sp = bp + 6;
+ --limit;
+ continue;
+ }
+ PRINTF("Could not find call\n");
+ break;
+ }
+ }
+ if ( fGuessFrameless ) {
+ if ( limit ) {
+ limit -= scan_for_frameless(
+ ss, sp, 0, &cs, ssBase, &csBase, limit, mode,
+ fUseSymbols, fParams );
+ }
+ }
+}
+
+VOID
+WalkStack(
+) {
+ VDMCONTEXT ThreadContext;
+ WORD bp;
+ WORD sp;
+ WORD ss;
+ WORD cs;
+ WORD ip;
+
+ ULONG csBase;
+ ULONG ssBase;
+ int mode;
+ int lines;
+
+ mode = GetContext( &ThreadContext );
+ IntelBase = GetIntelBase();
+
+ sp = (WORD)ThreadContext.Esp;
+ bp = (WORD)ThreadContext.Ebp;
+ ss = (WORD)ThreadContext.SegSs;
+ ip = (WORD)ThreadContext.Eip;
+ cs = (WORD)ThreadContext.SegCs;
+
+ csBase = GetInfoFromSelector( cs, mode, NULL ) + IntelBase;
+ ssBase = GetInfoFromSelector( ss, mode, NULL ) + IntelBase;
+
+ lines = 10;
+ if (GetNextToken()) {
+ lines = EXPRESSION( lpArgumentString );
+ }
+
+ stack_trace( ss,
+ ssBase,
+ sp,
+ bp,
+ cs,
+ csBase,
+ lines,
+ mode,
+ FALSE,
+ FALSE,
+ FALSE );
+}
+
+VOID
+WalkStackVerbose(
+) {
+ VDMCONTEXT ThreadContext;
+ WORD bp;
+ WORD sp;
+ WORD ss;
+ WORD cs;
+ WORD ip;
+
+ ULONG csBase;
+ ULONG ssBase;
+ int mode;
+ int lines;
+
+ mode = GetContext( &ThreadContext );
+ IntelBase = GetIntelBase();
+
+ sp = (WORD)ThreadContext.Esp;
+ bp = (WORD)ThreadContext.Ebp;
+ ss = (WORD)ThreadContext.SegSs;
+ ip = (WORD)ThreadContext.Eip;
+ cs = (WORD)ThreadContext.SegCs;
+
+ csBase = GetInfoFromSelector( cs, mode, NULL ) + IntelBase;
+ ssBase = GetInfoFromSelector( ss, mode, NULL ) + IntelBase;
+
+ lines = 10;
+ if (GetNextToken()) {
+ lines = EXPRESSION( lpArgumentString );
+ }
+
+ stack_trace( ss,
+ ssBase,
+ sp,
+ bp,
+ cs,
+ csBase,
+ lines,
+ mode,
+ TRUE,
+ FALSE,
+ FALSE );
+}