mad_status DIGENTRY MITraceSimulate( mad_trace_data *td, mad_disasm_data *dd, const mad_registers *in, mad_registers *out ) { address sp; word value; td = td; switch( dd->ins.type ) { case DI_X86_into: if( !( in->x86.cpu.efl & FLG_O ) ) { out->x86 = in->x86; out->x86.cpu.eip += dd->ins.size; return( MS_OK ); } /* fall through */ case DI_X86_int: /* only in real mode */ if( !( dd->characteristics & X86AC_REAL ) ) break; out->x86 = in->x86; sp = GetRegSP( out ); sp.mach.offset -= sizeof( word ); value = out->x86.cpu.efl; MCWriteMem( sp, sizeof( value ), &value ); out->x86.cpu.efl &= ~FLG_I; value = out->x86.cpu.cs; MCWriteMem( sp, sizeof( value ), &value ); value = out->x86.cpu.eip; MCWriteMem( sp, sizeof( value ), &value ); out->x86.cpu.esp = sp.mach.offset; return( MS_OK ); default: break; } return( MS_UNSUPPORTED ); }
mad_status MADIMPENTRY( CallBuildFrame )( mad_string call, address ret, address rtn, const mad_registers *in, mad_registers *out ) { unsigned dec; unsigned_32 value; address sp; dec = BIG_SEG( rtn ) ? 4 : 2; if( call == MAD_MSTR_NIL ) { call = (dec == 2) ? MAD_MSTR_FAR : MAD_MSTR_NEAR; } out->x86 = in->x86; sp = GetRegSP( out ); switch( call ) { case MAD_MSTR_INTERRUPT: sp.mach.offset -= dec; value = out->x86.cpu.efl; MCWriteMem( sp, dec, &value ); /* fall through */ case MAD_MSTR_FAR: sp.mach.offset -= dec; value = ret.mach.segment; MCWriteMem( sp, dec, &value ); /* fall through */ case MAD_MSTR_NEAR: sp.mach.offset -= dec; value = ret.mach.offset; MCWriteMem( sp, dec, &value ); break; } out->x86.cpu.esp = sp.mach.offset; out->x86.cpu.cs = rtn.mach.segment; out->x86.cpu.eip = rtn.mach.offset; return( MS_OK ); }
static void BreakRet( mad_trace_data *td, mad_disasm_data *dd, const mad_registers *mr ) { address sp; union { addr32_off off32; addr48_off off48; } off; sp = GetRegSP( mr ); switch( dd->ins.type ) { case DI_X86_iret: MCReadMem( sp, sizeof( off.off32 ), &off.off32 ); sp.mach.offset += sizeof( off.off32 ); td->brk.mach.offset = off.off32; MCReadMem( sp, sizeof( td->brk.mach.segment ), &td->brk.mach.segment ); sp.mach.offset += sizeof( td->brk.mach.segment ); break; case DI_X86_iretd: MCReadMem( sp, sizeof( off.off48 ), &off.off48 ); sp.mach.offset += sizeof( off.off48 ); td->brk.mach.offset = off.off48; MCReadMem( sp, sizeof( td->brk.mach.segment ), &td->brk.mach.segment ); sp.mach.offset += sizeof( td->brk.mach.segment ); break; default: if( dd->characteristics & X86AC_BIG ) { MCReadMem( sp, sizeof( off.off48 ), &off.off48 ); sp.mach.offset += sizeof( off.off48 ); td->brk.mach.offset = off.off48; } else { MCReadMem( sp, sizeof( off.off32 ), &off.off32 ); sp.mach.offset += sizeof( off.off32 ); td->brk.mach.offset = off.off32; } switch( td->prev_ins_type ) { case DI_X86_call: case DI_X86_call2: case DI_X86_ret: case DI_X86_ret2: td->brk.mach.segment = mr->x86.cpu.cs; break; case DI_X86_call3: case DI_X86_call4: case DI_X86_int: case DI_X86_into: case DI_X86_iret: case DI_X86_iretd: case DI_X86_retf: case DI_X86_retf2: MCReadMem( sp, sizeof( td->brk.mach.segment ), &td->brk.mach.segment ); sp.mach.offset += sizeof( td->brk.mach.segment ); break; default: break; } } MCAddrSection( &td->brk ); }
static void InitImageInfo( image_entry *image ) { if( !FindNullSym( image->dip_handle, &image->def_addr_space ) ) { image->def_addr_space = GetRegSP(); image->def_addr_space.mach.offset = 0; } SetWDPresent( image->dip_handle ); VarReMapScopes( image ); ReMapPoints( image ); }
walk_result DoDisasmMemRefWalk( mad_disasm_data *dd, MEMREF_WALKER *wk, const mad_registers *mr, void *d ) { walk_result wr; mad_type_handle th; int i; th = (mad_type_handle)-1; switch( dd->ins.type ) { case DI_X86_ret: case DI_X86_ret2: th = (dd->ins.flags.u.x86 & DIF_X86_OPND_LONG) ? X86T_N32_PTR : X86T_N16_PTR; break; case DI_X86_retf: case DI_X86_retf2: th = (dd->ins.flags.u.x86 & DIF_X86_OPND_LONG) ? X86T_F32_PTR : X86T_F16_PTR; break; case DI_X86_iret: case DI_X86_iretd: th = (dd->ins.flags.u.x86 & DIF_X86_OPND_LONG) ? X86T_IRET32 : X86T_IRET16; break; case DI_X86_pop: case DI_X86_pop2: case DI_X86_pop3d: case DI_X86_pop3e: case DI_X86_pop3s: case DI_X86_pop4f: case DI_X86_pop4g: case DI_X86_popf: case DI_X86_popfd: case DI_X86_leave: th = (dd->ins.flags.u.x86 & DIF_X86_OPND_LONG) ? X86T_DWORD : X86T_WORD; break; case DI_X86_popa: case DI_X86_popad: th = (dd->ins.flags.u.x86 & DIF_X86_OPND_LONG) ? X86T_POPAD : X86T_POPA; break; default: break; } if( th != (mad_type_handle)-1 ) { wr = wk( GetRegSP( mr ), th, MMK_VOLATILE|MMK_IMPLICIT|MMK_READ, d ); if( wr != WR_CONTINUE ) { return( wr ); } } for( i = 0; i < dd->ins.num_ops; i++ ) { if( ( dd->ins.op[i].type & ( DO_MASK | DO_HIDDEN ) ) == DO_MEMORY_ABS ) { wr = MemReference( i, dd, wk, mr, d ); if( wr != WR_CONTINUE ) { return( wr ); } } } return( WR_CONTINUE ); }
mad_status MADIMPENTRY( UnexpectedBreak )( mad_registers *mr, char *buff, size_t *buff_size_p ) { address a; union { byte b[9]; addr32_ptr a32; addr48_ptr a48; } data; size_t buff_size; size_t len; buff_size = *buff_size_p; *buff_size_p = 0; if( buff_size > 0 ) buff[0] = '\0'; a = GetRegIP( mr ); memset( &data, 0, sizeof( data ) ); MCReadMem( a, sizeof( data.b ), data.b ); if( data.b[0] != BRK_POINT ) return( MS_FAIL ); mr->x86.cpu.eip += 1; if( data.b[1] != JMP_SHORT ) return( MS_OK ); if( memcmp( data.b + 3, "WVIDEO", 6 ) != 0 ) return( MS_OK ); a = GetRegSP( mr ); MCReadMem( a, sizeof( addr_ptr ), &data ); if( BIG_SEG( a ) ) { a.mach = data.a48; } else { ConvAddr32ToAddr48( data.a32, a.mach ); } len = 0; while( MCReadMem( a, sizeof( data.b[0] ), data.b ) != 0 ) { a.mach.offset++; if( len + 1 < buff_size ) buff[len] = data.b[0]; if( data.b[0] == '\0' ) break; ++len; } *buff_size_p = len; if( buff_size > 0 ) { --buff_size; if( buff_size > len ) buff_size = len; buff[buff_size] = '\0'; } return( MS_OK ); }
address DefAddrSpaceForMod( mod_handle mh ) { image_entry *image; address def_addr; image = ImageEntry( mh ); if( image == NULL ) image = ImagePrimary(); if( image != NULL ) { return( image->def_addr_space ); } def_addr = GetRegSP(); def_addr.mach.offset = 0; return( def_addr ); }
mad_status DIGENTRY MIUnexpectedBreak( mad_registers *mr, unsigned *maxp, char *buff ) { address a; union { byte b[9]; addr32_ptr a32; addr48_ptr a48; } data; unsigned max; unsigned len; max = *maxp; *maxp = 0; if( max > 0 ) buff[0] = '\0'; a = GetRegIP( mr ); memset( &data, 0, sizeof( data ) ); MCReadMem( a, sizeof( data.b ), &data ); if( data.b[0] != BRK_POINT ) return( MS_FAIL ); mr->x86.cpu.eip += 1; if( data.b[1] != JMP_SHORT ) return( MS_OK ); if( memcmp( &data.b[3], "WVIDEO", 6 ) != 0 ) return( MS_OK ); a = GetRegSP( mr ); MCReadMem( a, sizeof( addr_ptr ), &data ); if( BIG_SEG( a ) ) { a.mach = data.a48; } else { ConvAddr32ToAddr48( data.a32, a.mach ); } len = 0; for( ;; ) { if( MCReadMem( a, sizeof( data.b[0] ), &data.b[0] ) == 0 ) break; a.mach.offset++; if( len < max ) buff[len] = data.b[0]; if( data.b[0] == '\0' ) break; ++len; } if( max > 0 ) buff[max] = '\0'; *maxp = len; return( MS_OK ); }
static bool CallRoutine( void ) { unsigned trap; address sp; sp = GetRegSP(); for( ;; ) { trap = ExecProg( FALSE, TRUE, FALSE ); if( !(trap & COND_BREAK) ) { ReportTrap( trap, FALSE ); return( FALSE ); } if( MADTraceHaveRecursed( sp, &DbgRegs->mr ) != MS_OK ) { return( TRUE ); } } }
bool PerformExplicitCall( address start, mad_string ctype, unsigned num_parms ) { bool ret; stack_entry *src; address stack; unsigned align; unsigned long amount; mad_type_info mti; stack = GetRegSP(); GetMADTypeDefaultAt( stack, MTK_INTEGER, &mti ); align = mti.b.bits / BITS_PER_BYTE; for( ; num_parms != 0; --num_parms ) { if( ExprSP->v.loc.e[0].type!=LT_ADDR && ExprSP->v.loc.e[0].u.p==NULL ) { /* push item */ src = StkEntry( 1 ); amount = (src->info.size + (align-1)) & -align; if( _IsOff( SW_STACK_GROWS_UP ) ) { stack.mach.offset -= amount; } LocationCreate( &ExprSP->v.loc, LT_ADDR, &stack ); if( _IsOn( SW_STACK_GROWS_UP ) ) { stack.mach.offset += amount; } ExprSP->info = src->info; ExprSP->flags |= SF_LOCATION; ExprSP->th = NULL; } SwapStack( 1 ); DoAssign(); PopEntry(); } AddrFix( &start ); SetRegSP( stack ); MADCallBuildFrame( ctype, start, start, &DbgRegs->mr, &DbgRegs->mr ); DbgTmpBrk.loc.addr = start; NullStatus( &DbgTmpBrk ); DbgTmpBrk.status.b.active = TRUE; ret = CallRoutine(); NullStatus( &DbgTmpBrk ); return( ret ); }
mad_status DIGENTRY MIDisasmInsNext( mad_disasm_data *dd, const mad_registers *mr, address *next ) { mad_disasm_control dc; *next = GetRegIP( mr ); next->mach.offset += dd->ins.size; dc = DisasmControl( dd, mr ); if( (dc & MDC_TAKEN_MASK) == MDC_TAKEN_NOT ) { return( MS_OK ); } switch( dc & MDC_TYPE_MASK ) { case MDC_SYSCALL: return( MS_FAIL ); case MDC_JUMP: case MDC_CALL: switch( dd->ins.op[ OP_1 ].type & DO_MASK ) { case DO_ABSOLUTE: next->mach.segment = dd->ins.op[ OP_1 ].extra; /* fall through */ case DO_RELATIVE: next->mach.offset = dd->ins.op[ OP_1 ].value; break; case DO_REG: next->mach.offset = RegValue( mr, dd->ins.op[ OP_1 ].base ); break; default: /* memory indirect jump/call */ DoDisasmMemRefWalk( dd, FindCallTarget, mr, &DbgAddr ); if( dd->ins.flags.u.x86 & DIF_X86_OPND_LONG ) { next->mach.offset = GetDataLong(); if( dd->ins.op[ OP_1 ].ref_type == DRT_X86_FARPTR48 ) { next->mach.segment = (unsigned_16)GetDataWord(); } } else { next->mach.offset = (unsigned_16)GetDataWord(); if( dd->ins.op[ OP_1 ].ref_type == DRT_X86_FARPTR32 ) { next->mach.segment = (unsigned_16)GetDataWord(); } } break; } break; case MDC_SYSRET: case MDC_RET: DbgAddr = GetRegSP( mr ); if( dd->ins.flags.u.x86 & DIF_X86_OPND_LONG ) { next->mach.offset = GetDataLong(); } else { next->mach.offset = (unsigned_16)GetDataWord(); } switch( dd->ins.type ) { case DI_X86_retf: case DI_X86_retf2: next->mach.segment = (unsigned_16)GetDataWord(); break; default: break; } break; } return( MS_OK ); }