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