#include #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 ); }