strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", timedat);
log_fio.Fprintf("**** Start of logging CALL TRACE %d steps for %s at %s.%06ld ****\n\n", steps, target->this_device_name, timestr, tv.tv_usec);
}
- int begin_step = (target_debugger->cpu_trace_ptr - steps) & (MAX_CPU_TRACE - 1);
- int max_step = target_debugger->cpu_trace_ptr & (MAX_CPU_TRACE - 1);
+ int begin_step = (target_debugger->cpu_trace_call_ptr - steps) & (MAX_CPU_TRACE - 1);
+ int max_step = target_debugger->cpu_trace_call_ptr & (MAX_CPU_TRACE - 1);
int steps_left = steps;
- if(!(target_debugger->cpu_trace_overwrap)) {
- if(steps_left > max_step) {
- begin_step = 0;
- steps_left = max_step;
- steps = max_step;
- }
- }
for(int i = begin_step; i != max_step; i = ((i + 1) & (MAX_CPU_TRACE - 1)) ) {
int index = i;
if(!(target_debugger->cpu_trace[index] & ~target->get_debug_prog_addr_mask())) {
int len = 0;
bool hit = target->debug_rewind_call_trace(
- target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask(),
+ target_debugger->cpu_trace_call[i] & target->get_debug_prog_addr_mask(),
len,
buffer,
array_length(buffer),
- target_debugger->cpu_trace_userdata[index]);
+ target_debugger->cpu_trace_call_type[i]
+ );
if(hit) {
const _TCHAR *name = my_get_symbol(target, target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
if(name != NULL) {
message("* vm/common_vm")
-SET(THIS_LIB_VERSION 2.26.1)
+SET(THIS_LIB_VERSION 2.26.2)
#include(cotire)
set(s_vm_common_vm_srcs
#define MAX_COMMAND_HISTORY 32
//#define MAX_CPU_TRACE 0x01000000 /* 16Msteps */
#define MAX_CPU_TRACE 0x00100000 /* 1Msteps */
-
-
+#define TRACE_TYPE_CALL 0x00000000
typedef struct {
struct {
uint32_t addr, mask;
memset(cpu_trace_exp, 0x00, sizeof(cpu_trace_exp));
memset(cpu_trace_exp_map, 0x00, sizeof(cpu_trace_exp_map));
memset(cpu_trace_userdata, 0x00, sizeof(cpu_trace_userdata));
+ memset(cpu_trace_call_type, 0x00, sizeof(cpu_trace_call_type));
+ memset(cpu_trace_call, 0x00, sizeof(cpu_trace_call));
exception_happened = false;
stop_on_exception = true;
prev_cpu_trace = 0xffffffff;
cpu_trace_ptr = 0;
+ cpu_trace_call_ptr = 0;
cpu_trace_overwrap = false;
set_device_name(_T("Debugger"));
}
}
first_symbol = last_symbol = NULL;
}
- void add_cpu_trace_exception(uint64_t exception_code)
+ void __FASTCALL add_cpu_trace_exception(uint64_t exception_code)
{
cpu_trace_exp[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] = exception_code;
cpu_trace_exp_map[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] = true;
}
// Userdata should after executing instruction.
- void add_cpu_trace_userdata(uint32_t data, uint32_t mask)
+ void __FASTCALL add_cpu_trace_userdata(uint32_t data, uint32_t mask)
{
cpu_trace_userdata[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] &= ~mask;
cpu_trace_userdata[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] |= (data & mask);
}
+ void __FASTCALL add_cpu_trace_irq(uint32_t pc, uint32_t irq)
+ {
+ cpu_trace_call[cpu_trace_call_ptr] = pc;
+ cpu_trace_call_type[cpu_trace_call_ptr] = ((uint64_t)irq << 32);
+ cpu_trace_call_ptr++;
+ cpu_trace_call_ptr &= (MAX_CPU_TRACE - 1);
+ }
+ void __FASTCALL add_cpu_trace_call(uint32_t pc, uint32_t target)
+ {
+ cpu_trace_call[cpu_trace_call_ptr] = pc;
+ cpu_trace_call_type[cpu_trace_call_ptr] = (uint64_t)target;
+ cpu_trace_call_ptr++;
+ cpu_trace_call_ptr &= (MAX_CPU_TRACE - 1);
+ }
+ void __FASTCALL add_cpu_trace_return(uint32_t pc)
+ {
+ cpu_trace_call[cpu_trace_call_ptr] = pc;
+ cpu_trace_call_type[cpu_trace_call_ptr] = (uint64_t)0x80000000 << 32;
+ cpu_trace_call_ptr++;
+ cpu_trace_call_ptr &= (MAX_CPU_TRACE - 1);
+ }
+
void add_cpu_trace(uint32_t pc)
{
if(prev_cpu_trace != pc) {
uint32_t cpu_trace[MAX_CPU_TRACE], prev_cpu_trace;
uint64_t cpu_trace_exp[MAX_CPU_TRACE];
uint32_t cpu_trace_userdata[MAX_CPU_TRACE]; // ToDo: Is need larger userdata?
+ uint32_t cpu_trace_call[MAX_CPU_TRACE]; // ToDo: Is need larger userdata?
+ uint64_t cpu_trace_call_type[MAX_CPU_TRACE]; // ToDo: Is need larger userdata?
bool cpu_trace_exp_map[MAX_CPU_TRACE];
int cpu_trace_ptr;
+ int cpu_trace_call_ptr;
bool cpu_trace_overwrap;
};
{
return 0;
}
- virtual bool debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint32_t userdata = 0)
+ virtual bool debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint64_t userdata = 0)
{
size = 0;
return false;
CPU_EXEC();
if(nmi_pending) {
CPU_INTERRUPT(2, 0);
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(get_pc(), 2);
+ }
nmi_pending = false;
} else if(irq_pending && CPU_isEI) {
- CPU_INTERRUPT(device_pic->get_intr_ack(), 0);
+ uint32_t intr_level = device_pic->get_intr_ack();
+ CPU_INTERRUPT(intr_level, 0);
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(get_pc(), intr_level);
+ }
irq_pending = false;
device_pic->update_intr();
}
CPU_EXEC();
if(nmi_pending) {
CPU_INTERRUPT(2, 0);
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(get_pc(), 2);
+ }
nmi_pending = false;
} else if(irq_pending && CPU_isEI) {
- CPU_INTERRUPT(device_pic->get_intr_ack(), 0);
+ uint32_t intr_level = device_pic->get_intr_ack();
+ CPU_INTERRUPT(intr_level, 0);
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(get_pc(), intr_level);
+ }
irq_pending = false;
device_pic->update_intr();
}
return true;
}
-bool I386::debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint32_t userdata)
+bool I386::debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint64_t userdata)
{
size = 0;
_TCHAR prefix[128] = {0};
- if((userdata & 0x8000fff0) != 0) { // Maybe call/ret/jmp/intr
- if(userdata & I386_TRACE_DATA_BIT_IRQ) {
- strncpy(prefix, _T("*IRQ HAPPENED*"), 127);
- } else if(userdata & I386_TRACE_DATA_BIT_EXCEPTION) {
- strncpy(prefix, _T("*EXCEPTION HAPPENED*"), 127);
- } else if(userdata & I386_TRACE_DATA_BIT_INT) {
- strncpy(prefix, _T("*INTXX*"), 127);
- } else if(userdata & I386_TRACE_DATA_BIT_RET) {
- strncpy(prefix, _T("*RETURN*"), 127);
- } else if(userdata & I386_TRACE_DATA_BIT_JMP) {
- strncpy(prefix, _T("*JMP*"), 127);
- } else if(userdata & I386_TRACE_DATA_BIT_CALL) {
- strncpy(prefix, _T("*CALL*"), 127);
- } else {
- // Not meanful
- return false;
- }
- _TCHAR dasmbuf[1024] = {0};
- size = debug_dasm_with_userdata(pc, dasmbuf, 1023, userdata);
- if(size <= 0) {
- strncpy(dasmbuf, 1023, _T("**UNDEFINED BEHAVIOR**"));
- }
- my_stprintf_s(buffer, buffer_len, _T("HIT %s @%08X %s\n"),
- prefix, pc, dasmbuf);
- return true;
+ if((userdata & ((uint64_t)0xffffffff << 32)) == ((uint64_t)0x80000000 << 32)) {
+ my_stprintf_s(prefix, 127, _T("*RETURN*"));
+ } else if((userdata & (uint64_t)0xffffffff00000000) != 0) {
+ my_stprintf_s(prefix, 127, _T("*IRQ %X HAPPENED*"), (uint32_t)(userdata >> 32));
+ } else {
+ my_stprintf_s(prefix, 127, _T("*CALL TO %08X*"), (uint32_t)userdata);
+ }
+ _TCHAR dasmbuf[1024] = {0};
+ size = debug_dasm_with_userdata(pc, dasmbuf, 1023, userdata);
+ if(size <= 0) {
+ strncpy(dasmbuf, 1023, _T("**UNDEFINED BEHAVIOR**"));
}
- return false;
+ my_stprintf_s(buffer, buffer_len, _T("HIT %s @%08X %s\n"),
+ prefix, pc, dasmbuf);
+ return true;
}
int I386::debug_dasm_with_userdata(uint32_t pc, _TCHAR *buffer, size_t buffer_len, uint32_t userdata)
{
virtual bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
virtual bool get_debug_regs_description(_TCHAR *buffer, size_t buffer_len);
int debug_dasm_with_userdata(uint32_t pc, _TCHAR *buffer, size_t buffer_len, uint32_t userdata = 0);
- virtual bool debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint32_t userdata = 0);
+ virtual bool debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint64_t userdata = 0);
//#endif
bool process_state(FILEIO* state_fio, bool loading);
{
return 0;
}
-bool DEVICE::debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint32_t userdata = 0)
+bool DEVICE::debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint64_t userdata = 0)
{
size = 0;
return false;
virtual bool get_debug_regs_description(_TCHAR *buffer, size_t buffer_len);
virtual int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len);
virtual int debug_dasm_with_userdata(uint32_t pc, _TCHAR *buffer, size_t buffer_len, uint32_t userdata = 0);
- virtual bool debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint32_t userdata = 0);
+ virtual bool debug_rewind_call_trace(uint32_t pc, int &size, _TCHAR* buffer, size_t buffer_len, uint64_t userdata = 0);
/*
These functions are used for debugging non-cpu device
Insert debugger between standard read/write functions and these functions for checking breakpoints
}
ctx[ctx_index].opbytes = 0;
#endif
+ UINT32 old_eip = CPU_PREV_EIP;
+ UINT32 old_addr = 0;
for (prefix = 0; prefix < MAX_PREFIX; prefix++) {
check_exception(is_debugging);
} else {
switch(op) {
case 0x9a: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + old_eip;
+ }
op_size |= I386_TRACE_DATA_BIT_CALL;
break;
case 0xc2: // RET far
case 0xc3:
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + old_eip;
+ }
op_size |= I386_TRACE_DATA_BIT_RET;
break;
case 0xca: // RET far
case 0xcb:
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + old_eip;
+ }
op_size |= I386_TRACE_DATA_BIT_RET;
break;
- case 0xcc: // INTr
- case 0xcd:
- case 0xce:
- op_size |= I386_TRACE_DATA_BIT_INT;
- break;
case 0xcf:
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + old_eip;
+ }
op_size |= I386_TRACE_DATA_BIT_IRET;
break;
case 0xe8: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + old_eip;
+ }
op_size |= I386_TRACE_DATA_BIT_CALL;
break;
case 0xe9: //JMP
case 0xea: //JMP16
case 0xeb: //JMP
- op_size |= I386_TRACE_DATA_BIT_CALL;
+ op_size |= I386_TRACE_DATA_BIT_JMP;
break;
case 0xe3:
op_size |= I386_TRACE_DATA_BIT_JMP_COND;
/* prefix */
if (insttable_info[op] & INST_PREFIX) {
(*insttable_1byte[0][op])();
+ switch(op) {
+ case 0x9a: //CAll
+ case 0xe8: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ case 0xc2: // RET far
+ case 0xc3:
+ case 0xca: // RET far
+ case 0xcb:
+ case 0xcf: // iRET
+ {
+ // ToDo: Collect intr num.
+ device_debugger->add_cpu_trace_return(old_addr);
+ }
+ break;
+ }
continue;
}
break;
cpu_debug_rep_cont = 0;
#endif
(*insttable_1byte[CPU_INST_OP32][op])();
+ switch(op) {
+ case 0x9a: //CAll
+ case 0xe8: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ case 0xc2: // RET far
+ case 0xc3:
+ case 0xca: // RET far
+ case 0xcb:
+ case 0xcf: // iRET
+ {
+ // ToDo: Collect intr num.
+ device_debugger->add_cpu_trace_return(old_addr);
+ }
+ break;
+ }
check_exception(is_debugging);
return;
}
/* prefix */
if (insttable_info[op] & INST_PREFIX) {
(*insttable_1byte[0][op])();
+ switch(op) {
+ case 0x9a: //CAll
+ case 0xe8: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ case 0xcc: // INTr
+ case 0xcd:
+ case 0xce:
+ case 0xf1:
+ {
+ // ToDo: Collect intr num.
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ case 0xc2: // RET far
+ case 0xc3:
+ case 0xca: // RET far
+ case 0xcb:
+ case 0xcf: // iRET
+ {
+ // ToDo: Collect intr num.
+ device_debugger->add_cpu_trace_return(old_addr);
+ }
+ break;
+ }
continue;
}
break;
cpu_debug_rep_cont = 0;
#endif
(*insttable_1byte[CPU_INST_OP32][op])();
+ switch(op) {
+ case 0x9a: //CAll
+ case 0xe8: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ case 0xcc: // INTr
+ case 0xcd:
+ case 0xce:
+ case 0xf1:
+ {
+ // ToDo: Collect intr num.
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ case 0xc2: // RET far
+ case 0xc3:
+ case 0xca: // RET far
+ case 0xcb:
+ case 0xcf: // iRET
+ {
+ // ToDo: Collect intr num.
+ device_debugger->add_cpu_trace_return(old_addr);
+ }
+ break;
+ }
check_exception(is_debugging);
goto cpucontinue; //continue;
}
{
UINT32 op;
+ UINT32 old_eip = CPU_PREV_EIP;
+ UINT32 old_addr = 0;
GET_PCBYTE(op);
+ UINT32 op_old = op;
+ switch((op >> 3) & 7) {
+ case 2: //CAll
+ case 3: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + old_eip;
+ }
+ break;
+ }
(*insttable_G5Ed[(op >> 3) & 7])(op);
+ switch((op >> 3) & 7) {
+ case 2: //CAll
+ case 3: //CAll
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ uint32_t new_addr = sdp->u.seg.segbase + CPU_EIP;
+ device_debugger->add_cpu_trace_call(old_addr, new_addr);
+ }
+ break;
+ }
}
INT1(void)
{
+ uint32_t old_addr;
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + CPU_PREV_EIP;
+ }
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(old_addr, 1);
+ }
CPU_WORKCLOCK(33);
INTERRUPT(1, INTR_TYPE_SOFTINTR);
}
void
INT6(void)
{
+ uint32_t old_addr;
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + CPU_PREV_EIP;
+ }
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(old_addr, 6);
+ }
CPU_WORKCLOCK(33);
INTERRUPT(6, INTR_TYPE_SOFTINTR);
}
#endif
*/
CPU_WORKCLOCK(33);
+ uint32_t old_addr;
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + CPU_PREV_EIP;
+ }
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(old_addr, 3);
+ }
INTERRUPT(3, INTR_TYPE_SOFTINTR);
}
return;
}
CPU_WORKCLOCK(35);
+ uint32_t old_addr;
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + CPU_PREV_EIP;
+ }
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(old_addr, 4);
+ }
INTERRUPT(4, INTR_TYPE_SOFTINTR);
}
CPU_WORKCLOCK(37);
if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) {
+ uint32_t old_addr;
+ {
+ descriptor_t *sdp = &CPU_CS_DESC;
+ old_addr = sdp->u.seg.segbase + CPU_PREV_EIP;
+ }
GET_PCBYTE(vect);
+ if(device_debugger != NULL) {
+ device_debugger->add_cpu_trace_irq(old_addr, vect);
+ }
#if defined(ENABLE_TRAP)
softinttrap(CPU_CS, CPU_EIP - 2, vect);
#endif