From 31dee93e849d79a91f280faf16941806e3cb3c6b Mon Sep 17 00:00:00 2001 From: polaris- Date: Wed, 2 Sep 2015 08:56:38 -0400 Subject: Implement gdbstub --- src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 41 ++++++++++++++++++++------ src/core/arm/skyeye_common/armstate.cpp | 35 ++++++++++++++++++++++ src/core/arm/skyeye_common/armstate.h | 2 ++ 3 files changed, 69 insertions(+), 9 deletions(-) (limited to 'src/core/arm') diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index fbd6f94f9..8293f4c60 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -23,6 +23,8 @@ #include "core/arm/skyeye_common/armsupp.h" #include "core/arm/skyeye_common/vfp/vfp.h" +#include "core/gdbstub/gdbstub.h" + Common::Profiling::TimingCategory profile_execute("DynCom::Execute"); Common::Profiling::TimingCategory profile_decode("DynCom::Decode"); @@ -3548,6 +3550,7 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { CITRA_IGNORE_EXIT(-1); } inst_base = arm_instruction_trans[idx](inst, idx); + translated: phys_addr += inst_size; @@ -3580,6 +3583,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { Common::Profiling::ScopeTimer timer_execute(profile_execute); MICROPROFILE_SCOPE(DynCom_Execute); + int breakpoint_offset = -1; + #undef RM #undef RS @@ -3604,15 +3609,27 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { #define INC_PC(l) ptr += sizeof(arm_inst) + l #define INC_PC_STUB ptr += sizeof(arm_inst) +#define GDB_BP_CHECK \ + cpu->Cpsr &= ~(1 << 5); \ + cpu->Cpsr |= cpu->TFlag << 5; \ + if (GDBStub::g_server_enabled) { \ + if (GDBStub::IsMemoryBreak() || PC == breakpoint_offset) { \ + GDBStub::Break(); \ + goto END; \ + } \ + } + // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a // clunky switch statement. #if defined __GNUC__ || defined __clang__ #define GOTO_NEXT_INST \ + GDB_BP_CHECK; \ if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ num_instrs++; \ goto *InstLabel[inst_base->idx] #else #define GOTO_NEXT_INST \ + GDB_BP_CHECK; \ if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ num_instrs++; \ switch(inst_base->idx) { \ @@ -3878,6 +3895,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { unsigned int addr; unsigned int num_instrs = 0; + int ptr; LOAD_NZCVT; @@ -3903,6 +3921,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { goto END; } + // Find breakpoint if one exists within the block + if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { + breakpoint_offset = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); + } + inst_base = (arm_inst *)&inst_buf[ptr]; GOTO_NEXT_INST; } @@ -4454,7 +4477,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read8(addr); + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); if (BITS(inst_cream->inst, 12, 15) == 15) { INC_PC(sizeof(ldst_inst)); @@ -4472,7 +4495,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read8(addr); + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); if (BITS(inst_cream->inst, 12, 15) == 15) { INC_PC(sizeof(ldst_inst)); @@ -4531,7 +4554,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->SetExclusiveMemoryAddress(read_addr); - RD = Memory::Read8(read_addr); + RD = cpu->ReadMemory8(read_addr); if (inst_cream->Rd == 15) { INC_PC(sizeof(generic_arm_inst)); goto DISPATCH; @@ -4604,7 +4627,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = Memory::Read8(addr); + unsigned int value = cpu->ReadMemory8(addr); if (BIT(value, 7)) { value |= 0xffffff00; } @@ -6027,7 +6050,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; - Memory::Write8(addr, value); + cpu->WriteMemory8(addr, value); } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -6040,7 +6063,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_cream->get_addr(cpu, inst_cream->inst, addr); unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; - Memory::Write8(addr, value); + cpu->WriteMemory8(addr, value); } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -6091,7 +6114,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (cpu->IsExclusiveMemoryAccess(write_addr)) { cpu->UnsetExclusiveMemoryAddress(); - Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); + cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]); RD = 0; } else { // Failed to write due to mutex access @@ -6250,8 +6273,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { swp_inst* inst_cream = (swp_inst*)inst_base->component; addr = RN; - unsigned int value = Memory::Read8(addr); - Memory::Write8(addr, (RM & 0xFF)); + unsigned int value = cpu->ReadMemory8(addr); + cpu->WriteMemory8(addr, (RM & 0xFF)); RD = value; } cpu->Reg[15] += cpu->GetInstructionSize(); diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp index 0491717dc..2d814345a 100644 --- a/src/core/arm/skyeye_common/armstate.cpp +++ b/src/core/arm/skyeye_common/armstate.cpp @@ -7,6 +7,7 @@ #include "core/memory.h" #include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/vfp/vfp.h" +#include "core/gdbstub/gdbstub.h" ARMul_State::ARMul_State(PrivilegeMode initial_mode) { @@ -185,8 +186,25 @@ void ARMul_State::ResetMPCoreCP15Registers() CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; } +static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) +{ + if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) { + LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address); + GDBStub::Break(true); + } +} + +u8 ARMul_State::ReadMemory8(u32 address) const +{ + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); + + return Memory::Read8(address); +} + u16 ARMul_State::ReadMemory16(u32 address) const { + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); + u16 data = Memory::Read16(address); if (InBigEndianMode()) @@ -197,6 +215,8 @@ u16 ARMul_State::ReadMemory16(u32 address) const u32 ARMul_State::ReadMemory32(u32 address) const { + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); + u32 data = Memory::Read32(address); if (InBigEndianMode()) @@ -207,6 +227,8 @@ u32 ARMul_State::ReadMemory32(u32 address) const u64 ARMul_State::ReadMemory64(u32 address) const { + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); + u64 data = Memory::Read64(address); if (InBigEndianMode()) @@ -215,8 +237,17 @@ u64 ARMul_State::ReadMemory64(u32 address) const return data; } +void ARMul_State::WriteMemory8(u32 address, u8 data) +{ + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); + + Memory::Write8(address, data); +} + void ARMul_State::WriteMemory16(u32 address, u16 data) { + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); + if (InBigEndianMode()) data = Common::swap16(data); @@ -225,6 +256,8 @@ void ARMul_State::WriteMemory16(u32 address, u16 data) void ARMul_State::WriteMemory32(u32 address, u32 data) { + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); + if (InBigEndianMode()) data = Common::swap32(data); @@ -233,6 +266,8 @@ void ARMul_State::WriteMemory32(u32 address, u32 data) void ARMul_State::WriteMemory64(u32 address, u64 data) { + CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); + if (InBigEndianMode()) data = Common::swap64(data); diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h index ceb159d14..98dad9b1f 100644 --- a/src/core/arm/skyeye_common/armstate.h +++ b/src/core/arm/skyeye_common/armstate.h @@ -153,9 +153,11 @@ public: // Reads/writes data in big/little endian format based on the // state of the E (endian) bit in the APSR. + u8 ReadMemory8(u32 address) const; u16 ReadMemory16(u32 address) const; u32 ReadMemory32(u32 address) const; u64 ReadMemory64(u32 address) const; + void WriteMemory8(u32 address, u8 data); void WriteMemory16(u32 address, u16 data); void WriteMemory32(u32 address, u32 data); void WriteMemory64(u32 address, u64 data); -- cgit v1.2.3 From 42928659e8d4ff4edffc36acabe3d9040dbc1326 Mon Sep 17 00:00:00 2001 From: polaris- Date: Sun, 4 Oct 2015 11:22:31 -0400 Subject: Use BreakpointAddress struct instead of passing address directly --- src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 6 +++--- src/core/gdbstub/gdbstub.cpp | 13 +++++++++---- src/core/gdbstub/gdbstub.h | 7 ++++++- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/core/arm') diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 8293f4c60..88be27ab2 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -3583,7 +3583,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { Common::Profiling::ScopeTimer timer_execute(profile_execute); MICROPROFILE_SCOPE(DynCom_Execute); - int breakpoint_offset = -1; + GDBStub::BreakpointAddress breakpoint_data; #undef RM #undef RS @@ -3613,7 +3613,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->Cpsr &= ~(1 << 5); \ cpu->Cpsr |= cpu->TFlag << 5; \ if (GDBStub::g_server_enabled) { \ - if (GDBStub::IsMemoryBreak() || PC == breakpoint_offset) { \ + if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && PC == breakpoint_data.address)) { \ GDBStub::Break(); \ goto END; \ } \ @@ -3923,7 +3923,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { // Find breakpoint if one exists within the block if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { - breakpoint_offset = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); + breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); } inst_base = (arm_inst *)&inst_buf[ptr]; diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index ced1c54f5..25ce63b29 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -231,13 +231,18 @@ static void RemoveBreakpoint(BreakpointType type, PAddr addr) { } } -PAddr GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { +BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { std::map& p = GetBreakpointList(type); auto next_breakpoint = p.lower_bound(addr); - u32 breakpoint = -1; + BreakpointAddress breakpoint; - if (next_breakpoint != p.end()) - breakpoint = next_breakpoint->first; + if (next_breakpoint != p.end()) { + breakpoint.address = next_breakpoint->first; + breakpoint.type = type; + } else { + breakpoint.address = 0; + breakpoint.type = BreakpointType::None; + } return breakpoint; } diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index 11ff823c3..da238f349 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h @@ -18,6 +18,11 @@ enum class BreakpointType { Access ///< Access (R/W) Breakpoint }; +struct BreakpointAddress { + PAddr address; + BreakpointType type; +}; + /// If set to false, the server will never be started and no gdbstub-related functions will be executed. extern std::atomic g_server_enabled; @@ -63,7 +68,7 @@ void HandlePacket(); * @param addr Address to search from. * @param type Type of breakpoint. */ -PAddr GetNextBreakpointFromAddress(u32 addr, GDBStub::BreakpointType type); +BreakpointAddress GetNextBreakpointFromAddress(u32 addr, GDBStub::BreakpointType type); /** * Check if a breakpoint of the specified type exists at the given address. -- cgit v1.2.3 From 2b7316a379103edf4d22893e0f4432e6415eabfa Mon Sep 17 00:00:00 2001 From: polaris- Date: Sun, 11 Oct 2015 20:07:58 -0400 Subject: Remove unnecessary new lines, changed Deinit to Shutdown --- src/citra/config.cpp | 2 +- src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 1 - src/core/gdbstub/gdbstub.cpp | 10 +++++----- src/core/gdbstub/gdbstub.h | 2 +- src/core/system.cpp | 4 +--- 5 files changed, 8 insertions(+), 11 deletions(-) (limited to 'src/core/arm') diff --git a/src/citra/config.cpp b/src/citra/config.cpp index af343e9fe..2f13c29a2 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -76,7 +76,7 @@ void Config::ReadValues() { // Miscellaneous Settings::values.log_filter = glfw_config->Get("Miscellaneous", "log_filter", "*:Info"); - // GDBStubebugging + // Debugging Settings::values.use_gdbstub = glfw_config->GetBoolean("Debugging", "use_gdbstub", false); Settings::values.gdbstub_port = glfw_config->GetInteger("Debugging", "gdbstub_port", 24689); } diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 88be27ab2..96c88c83a 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -3895,7 +3895,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { unsigned int addr; unsigned int num_instrs = 0; - int ptr; LOAD_NZCVT; diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 25ce63b29..15e6f36a0 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -186,7 +186,7 @@ static u8 ReadByte() { size_t received_size = recv(gdbserver_socket, reinterpret_cast(&c), 1, MSG_WAITALL); if (received_size != 1) { LOG_ERROR(Debug_GDBStub, "recv failed : %ld", received_size); - Deinit(); + Shutdown(); } return c; @@ -322,7 +322,7 @@ static void SendReply(const char* reply) { int sent_size = send(gdbserver_socket, reinterpret_cast(ptr), left, 0); if (sent_size < 0) { LOG_ERROR(Debug_GDBStub, "gdb: send failed"); - return Deinit(); + return Shutdown(); } left -= sent_size; @@ -773,7 +773,7 @@ void HandlePacket() { HandleSignal(); break; case 'k': - Deinit(); + Shutdown(); LOG_INFO(Debug_GDBStub, "killed by gdb"); return; case 'g': @@ -829,7 +829,7 @@ void ToggleServer(bool status) { else { // Stop server if (IsConnected()) { - Deinit(); + Shutdown(); } g_server_enabled = status; @@ -908,7 +908,7 @@ void Init() { Init(gdbstub_port); } -void Deinit() { +void Shutdown() { if (!g_server_enabled) { return; } diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index da238f349..aff705a32 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h @@ -44,7 +44,7 @@ void ToggleServer(bool status); void Init(); /// Stop gdbstub server. -void Deinit(); +void Shutdown(); /// Returns true if there is an active socket connection. bool IsConnected(); diff --git a/src/core/system.cpp b/src/core/system.cpp index 421fc48a7..7e9c56538 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -24,13 +24,11 @@ void Init(EmuWindow* emu_window) { Kernel::Init(); HLE::Init(); VideoCore::Init(emu_window); - GDBStub::Init(); } void Shutdown() { - GDBStub::Deinit(); - + GDBStub::Shutdown(); VideoCore::Shutdown(); HLE::Shutdown(); Kernel::Shutdown(); -- cgit v1.2.3