mad_trace_how DIGENTRY MITraceOne( mad_trace_data *td, mad_disasm_data *dd, mad_trace_kind tk, mad_registers const *mr, address *brk ) { mad_disasm_control dc; addr_off ra; dc = DisasmControl( dd, mr ); ra = td->ra; td->ra = mr->ppc.iar.u._32[I64LO32] + sizeof( unsigned_32 ); switch( tk ) { case MTRK_OUT: // NYI: this doesn't always work - lr need not contain useful value! memset( brk, 0, sizeof( *brk ) ); brk->mach.offset = ra; return( MTRH_BREAK ); case MTRK_INTO: return( MTRH_STEP ); case MTRK_OVER: switch( dc & MDC_TYPE_MASK ) { case MDC_CALL: /* Handle special case of call to the next instruction, which is used * to get the GOT pointer in position independent code. */ if( dd->ins.op[0].value == sizeof( unsigned_32 ) ) return( MTRH_STEP ); break; case MDC_OPER: case MDC_RET: case MDC_JUMP: return( MTRH_STEP ); } break; } /* break next */ memset( brk, 0, sizeof( *brk ) ); brk->mach.offset = td->ra; return( MTRH_BREAK ); }
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 ); }
mad_disasm_control DIGENTRY MIDisasmControl( mad_disasm_data *dd, const mad_registers *mr ) { return( DisasmControl( dd, mr ) ); }