static void gdb_reply(const char* reply) { u8 chk; u32 left; u8* ptr; int n; if (!gdb_active()) return; memset(cmd_bfr, 0, sizeof cmd_bfr); cmd_len = strlen(reply); if (cmd_len + 4 > sizeof cmd_bfr) ERROR_LOG(GDB_STUB, "cmd_bfr overflow in gdb_reply"); memcpy(cmd_bfr + 1, reply, cmd_len); cmd_len++; chk = gdb_calc_chksum(); cmd_len--; cmd_bfr[0] = GDB_STUB_START; cmd_bfr[cmd_len + 1] = GDB_STUB_END; cmd_bfr[cmd_len + 2] = nibble2hex(chk >> 4); cmd_bfr[cmd_len + 3] = nibble2hex(chk); DEBUG_LOG(GDB_STUB, "gdb: reply (len: %d): %s", cmd_len, cmd_bfr); ptr = cmd_bfr; left = cmd_len + 4; while (left > 0) { n = send(sock, ptr, left, 0); if (n < 0) { ERROR_LOG(GDB_STUB, "gdb: send failed"); return gdb_deinit(); } left -= n; ptr += n; } }
void gdb_handle_exception() { while (gdb_active()) { if (!gdb_data_available()) continue; gdb_read_command(); if (cmd_len == 0) continue; switch (cmd_bfr[0]) { case 'q': gdb_handle_query(); break; case 'H': gdb_handle_set_thread(); break; case '?': gdb_handle_signal(); break; case 'k': gdb_deinit(); INFO_LOG(GDB_STUB, "killed by gdb"); return; case 'g': gdb_read_registers(); break; case 'G': gdb_write_registers(); break; case 'p': gdb_read_register(); break; case 'P': gdb_write_register(); break; case 'm': gdb_read_mem(); break; case 'M': gdb_write_mem(); PowerPC::ppcState.iCache.Reset(); Host_UpdateDisasmDialog(); break; case 's': gdb_step(); return; case 'C': case 'c': gdb_continue(); return; case 'z': gdb_remove_bp(); break; case 'Z': _gdb_add_bp(); break; default: gdb_reply(""); break; } } }
int Interpreter::SingleStepInner() { static UGeckoInstruction instCode; u32 function = HLE::GetFunctionIndex(PC); if (function != 0) { int type = HLE::GetFunctionTypeByIndex(function); if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE) { int flags = HLE::GetFunctionFlagsByIndex(function); if (HLE::IsEnabled(flags)) { HLEFunction(function); if (type == HLE::HLE_HOOK_START) { // Run the original. function = 0; } } else { function = 0; } } } if (function == 0) { #ifdef USE_GDBSTUB if (gdb_active() && gdb_bp_x(PC)) { Host_UpdateDisasmDialog(); gdb_signal(SIGTRAP); gdb_handle_exception(); } #endif NPC = PC + sizeof(UGeckoInstruction); instCode.hex = PowerPC::Read_Opcode(PC); // Uncomment to trace the interpreter //if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) // startTrace = 1; //else // startTrace = 0; if (startTrace) { Trace(instCode); } if (instCode.hex != 0) { UReg_MSR& msr = (UReg_MSR&)MSR; if (msr.FP) //If FPU is enabled, just execute { m_opTable[instCode.OPCD](instCode); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); m_EndBlock = true; } } else { // check if we have to generate a FPU unavailable exception if (!PPCTables::UsesFPU(instCode)) { m_opTable[instCode.OPCD](instCode); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); m_EndBlock = true; } } else { PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; PowerPC::CheckExceptions(); m_EndBlock = true; } } } else { // Memory exception on instruction fetch PowerPC::CheckExceptions(); m_EndBlock = true; } } last_pc = PC; PC = NPC; GekkoOPInfo *opinfo = GetOpInfo(instCode); return opinfo->numCycles; }
int Interpreter::SingleStepInner(void) { static UGeckoInstruction instCode; u32 function = m_EndBlock ? HLE::GetFunctionIndex(PC) : 0; // Check for HLE functions after branches if (function != 0) { int type = HLE::GetFunctionTypeByIndex(function); if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE) { int flags = HLE::GetFunctionFlagsByIndex(function); if (HLE::IsEnabled(flags)) { HLEFunction(function); if (type == HLE::HLE_HOOK_START) { // Run the original. function = 0; } } else { function = 0; } } } if (function == 0) { #ifdef USE_GDBSTUB if (gdb_active() && gdb_bp_x(PC)) { Host_UpdateDisasmDialog(); gdb_signal(SIGTRAP); gdb_handle_exception(); } #endif NPC = PC + sizeof(UGeckoInstruction); instCode.hex = Memory::Read_Opcode(PC); // Uncomment to trace the interpreter //if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) // startTrace = 1; //else // startTrace = 0; if (startTrace) { Trace(instCode); } if (instCode.hex != 0) { UReg_MSR& msr = (UReg_MSR&)MSR; if (msr.FP) //If FPU is enabled, just execute { m_opTable[instCode.OPCD](instCode); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); m_EndBlock = true; } } else { // check if we have to generate a FPU unavailable exception if (!PPCTables::UsesFPU(instCode)) { m_opTable[instCode.OPCD](instCode); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); m_EndBlock = true; } } else { Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE); PowerPC::CheckExceptions(); m_EndBlock = true; } } } else { // Memory exception on instruction fetch PowerPC::CheckExceptions(); m_EndBlock = true; } } last_pc = PC; PC = NPC; #if defined(_DEBUG) || defined(DEBUGFAST) if (PowerPC::ppcState.gpr[1] == 0) { WARN_LOG(POWERPC, "%i Corrupt stack", PowerPC::ppcState.DebugCount); } PowerPC::ppcState.DebugCount++; #endif patches(); GekkoOPInfo *opinfo = GetOpInfo(instCode); return opinfo->numCyclesMinusOne + 1; }
int Interpreter::SingleStepInner() { if (HandleFunctionHooking(PC)) { UpdatePC(); return PPCTables::GetOpInfo(m_prev_inst)->numCycles; } #ifdef USE_GDBSTUB if (gdb_active() && gdb_bp_x(PC)) { Host_UpdateDisasmDialog(); gdb_signal(GDB_SIGTRAP); gdb_handle_exception(); } #endif NPC = PC + sizeof(UGeckoInstruction); m_prev_inst.hex = PowerPC::Read_Opcode(PC); // Uncomment to trace the interpreter // if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) // startTrace = 1; // else // startTrace = 0; if (startTrace) { Trace(m_prev_inst); } if (m_prev_inst.hex != 0) { if (IsInvalidPairedSingleExecution(m_prev_inst)) { GenerateProgramException(); CheckExceptions(); } else if (MSR.FP) { m_op_table[m_prev_inst.OPCD](m_prev_inst); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { CheckExceptions(); } } else { // check if we have to generate a FPU unavailable exception or a program exception. if (PPCTables::UsesFPU(m_prev_inst)) { PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; CheckExceptions(); } else { m_op_table[m_prev_inst.OPCD](m_prev_inst); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { CheckExceptions(); } } } } else { // Memory exception on instruction fetch CheckExceptions(); } UpdatePC(); return PPCTables::GetOpInfo(m_prev_inst)->numCycles; }
int Interpreter::SingleStepInner() { if (!HandleFunctionHooking(PC)) { #ifdef USE_GDBSTUB if (gdb_active() && gdb_bp_x(PC)) { Host_UpdateDisasmDialog(); gdb_signal(SIGTRAP); gdb_handle_exception(); } #endif NPC = PC + sizeof(UGeckoInstruction); m_prev_inst.hex = PowerPC::Read_Opcode(PC); // Uncomment to trace the interpreter // if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) // startTrace = 1; // else // startTrace = 0; if (startTrace) { Trace(m_prev_inst); } if (m_prev_inst.hex != 0) { if (MSR.FP) // If FPU is enabled, just execute { m_op_table[m_prev_inst.OPCD](m_prev_inst); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); m_end_block = true; } } else { // check if we have to generate a FPU unavailable exception if (!PPCTables::UsesFPU(m_prev_inst)) { m_op_table[m_prev_inst.OPCD](m_prev_inst); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); m_end_block = true; } } else { PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; PowerPC::CheckExceptions(); m_end_block = true; } } } else { // Memory exception on instruction fetch PowerPC::CheckExceptions(); m_end_block = true; } } last_pc = PC; PC = NPC; const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst); return opinfo->numCycles; }