mad_status GetDisasmPrev( address *a ) { mad_disasm_data dd; addr_off start; addr_off curr_off; addr_off prev; unsigned backup; int big; DbgAddr = *a; big = BIG_SEG( DbgAddr ); backup = ( big ) ? 0x40 : 0x20; curr_off = DbgAddr.mach.offset; DbgAddr.mach.offset = (curr_off <= backup) ? 0 : (curr_off - backup); InitCache( DbgAddr, curr_off - DbgAddr.mach.offset ); for( start = DbgAddr.mach.offset; start < curr_off; ++start ) { DbgAddr.mach.offset = start; for( ;; ) { prev = DbgAddr.mach.offset; DoCode( &dd, big ); if( dd.ins.size == 0 ) break; /* invalid address */ DbgAddr.mach.offset += dd.ins.size; if( DbgAddr.mach.offset == curr_off ) { a->mach.offset = prev; return( MS_OK ); } if( DbgAddr.mach.offset > curr_off ) break; if( DbgAddr.mach.offset < start ) break; /* wrapped around segment */ } } /* Couldn't sync instruction stream */ return( MS_FAIL ); }
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 ); }
const mad_reg_info *MADIMPENTRY( CallReturnReg )( mad_string call, address rtn ) { /* unused parameters */ (void)call; if( BIG_SEG( rtn ) ) { return( &CPU_eax.info ); } else { return( &CPU_ax.info ); } }
char *ToSegStr( addr_off value, addr_seg seg, addr_off addr ) { address memaddr; mad_type_handle th; addr = addr; memaddr.mach.segment = seg; memaddr.mach.offset = value; MCAddrSection( &memaddr ); th = BIG_SEG( memaddr ) ? X86T_F32_PTR : X86T_F16_PTR; MCAddrToString( memaddr, th, MLK_MEMORY, sizeof( ScratchBuff ) - 1, ScratchBuff ); return( ScratchBuff ); }
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 ); }
void MADIMPENTRY( AddrAdd )( address *a, long b, mad_address_format af ) { unsigned over; a->mach.offset += b; if( !BIG_SEG( *a ) ) { if( a->mach.offset > 0xffff ) { if( af != MAF_OFFSET ) { over = a->mach.offset >> (16 - MCSystemConfig()->huge_shift); a->mach.segment += (addr_seg)over; } a->mach.offset &= 0xffff; } }
mad_type_handle DIGENTRY MITypeDefault( mad_type_kind tk, mad_address_format af, const mad_registers *mr, const address *ap ) { int big; if( tk & MAS_IO ) { switch( tk & MTK_ALL ) { case MTK_BASIC: case MTK_INTEGER: return( X86T_BYTE ); case MTK_ADDRESS: return( X86T_N16_PTR ); } return( MAD_NIL_TYPE_HANDLE ); } if( ap != NULL ) { big = BIG_SEG( *ap ); } else if( mr != NULL ) { big = BIG_SEG( GetRegIP( mr ) ); } else { big = ( ( MCSystemConfig()->cpu & X86_CPU_MASK ) >= X86_386); } switch( tk & MTK_ALL ) { case MTK_BASIC: return( X86T_BYTE ); case MTK_INTEGER: return( big ? X86T_DWORD : X86T_WORD ); case MTK_ADDRESS: if( big ) { return( (af == MAF_OFFSET) ? X86T_N32_PTR : X86T_F32_PTR ); } else { return( (af == MAF_OFFSET) ? X86T_N16_PTR : X86T_F16_PTR ); } case MTK_FLOAT: return( X86T_DOUBLE ); } return( MAD_NIL_TYPE_HANDLE ); }
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 ); }
char *JmpLabel( unsigned long addr, addr_off off ) { address memaddr; mad_type_handle th; char *p; off = off; memaddr = DbgAddr; memaddr.mach.offset = addr; th = ( BIG_SEG( memaddr ) ) ? X86T_N32_PTR : X86T_N16_PTR; #define PREFIX_STR "CS:" #define PREFIX_LEN (sizeof(PREFIX_STR)-1) p = &ScratchBuff[ PREFIX_LEN ]; if( MCAddrToString( memaddr, th, MLK_CODE, sizeof( ScratchBuff ) - 1 - PREFIX_LEN, p ) != MS_OK ) { p -= PREFIX_LEN; memcpy( p, PREFIX_STR, PREFIX_LEN ); } return( p ); }
mad_status MADIMPENTRY( CallUpStackLevel )( mad_call_up_data *cud, const address *startp, unsigned rtn_characteristics, long return_disp, const mad_registers *in, address *execution, address *frame, address *stack, mad_registers **out ) { address prev_sp_value; address start; /* unused parameters */ (void)cud; (void)in; *out = NULL; Is32BitSegment = BIG_SEG( *execution ); start = *startp; if( MCSystemConfig()->os == MAD_OS_WINDOWS && !Is32BitSegment ) { memset( &start, 0, sizeof( start ) ); } prev_sp_value = *stack; if( start.mach.segment == 0 && start.mach.offset == 0 ) { if( Is32BitSegment ) return( MS_FAIL ); if( !BPTraceBack( execution, frame, stack ) ) return( MS_FAIL ); } else { if( return_disp != -1L ) { SymbolicTraceBack( &start, rtn_characteristics, return_disp, execution, frame, stack ); } else { if( !HeuristicTraceBack( &prev_sp_value, &start, execution, frame, stack ) ) return( MS_FAIL ); } } if( stack->mach.offset <= prev_sp_value.mach.offset ) return( MS_FAIL ); return( MS_OK ); }