From a631ada0f7b48e3e35a7da32e68a81a12953bb71 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 22 Dec 2013 00:51:50 -0800 Subject: [PATCH] Routing messages to debug targets. --- src/xenia/cpu/processor.cc | 15 +++++++- src/xenia/cpu/processor.h | 8 +++- src/xenia/debug/debug_server.cc | 19 ++++++++++ src/xenia/debug/debug_server.h | 7 ++++ src/xenia/debug/debug_target.h | 45 +++++++++++++++++++++++ src/xenia/debug/protocols/ws/ws_client.cc | 24 +++++++----- src/xenia/debug/sources.gypi | 1 + 7 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 src/xenia/debug/debug_target.h diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 4064062f5..e1a09624d 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -9,6 +9,8 @@ #include +#include + #include #include #include @@ -51,11 +53,16 @@ Processor::Processor(Emulator* emulator) : emulator_(emulator), export_resolver_(emulator->export_resolver()), runtime_(0), memory_(emulator->memory()), interrupt_thread_lock_(NULL), interrupt_thread_state_(NULL), - interrupt_thread_block_(0) { + interrupt_thread_block_(0), + DebugTarget(emulator->debug_server()) { InitializeIfNeeded(); + + emulator_->debug_server()->AddTarget("cpu", this); } Processor::~Processor() { + emulator_->debug_server()->RemoveTarget("cpu"); + if (interrupt_thread_block_) { memory_->HeapFree(interrupt_thread_block_, 2048); delete interrupt_thread_state_; @@ -158,3 +165,9 @@ uint64_t Processor::ExecuteInterrupt( xe_mutex_unlock(interrupt_thread_lock_); return result; } + +json_t* Processor::OnDebugRequest( + const char* command, json_t* request, bool& succeeded) { + succeeded = true; + return json_null(); +} diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 254419a33..2fb378495 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -10,8 +10,9 @@ #ifndef XENIA_CPU_PROCESSOR_H_ #define XENIA_CPU_PROCESSOR_H_ -#include #include +#include +#include #include @@ -31,7 +32,7 @@ using RegisterReadCallback = alloy::runtime::RegisterReadCallback; using RegisterWriteCallback = alloy::runtime::RegisterWriteCallback; -class Processor { +class Processor : public debug::DebugTarget { public: Processor(Emulator* emulator); ~Processor(); @@ -55,6 +56,9 @@ public: uint64_t ExecuteInterrupt( uint32_t cpu, uint64_t address, uint64_t arg0, uint64_t arg1); + virtual json_t* OnDebugRequest( + const char* command, json_t* request, bool& succeeded); + private: Emulator* emulator_; ExportResolver* export_resolver_; diff --git a/src/xenia/debug/debug_server.cc b/src/xenia/debug/debug_server.cc index 811e679fd..fc2546182 100644 --- a/src/xenia/debug/debug_server.cc +++ b/src/xenia/debug/debug_server.cc @@ -106,6 +106,25 @@ void DebugServer::Shutdown() { xe_mutex_unlock(lock_); } +void DebugServer::AddTarget(const char* name, DebugTarget* target) { + xe_mutex_lock(lock_); + targets_[name] = target; + xe_mutex_unlock(lock_); +} + +void DebugServer::RemoveTarget(const char* name) { + xe_mutex_lock(lock_); + targets_[name] = NULL; + xe_mutex_unlock(lock_); +} + +DebugTarget* DebugServer::GetTarget(const char* name) { + xe_mutex_lock(lock_); + DebugTarget* target = targets_[name]; + xe_mutex_unlock(lock_); + return target; +} + int DebugServer::WaitForClient() { while (!has_clients()) { WaitForSingleObject(client_event_, INFINITE); diff --git a/src/xenia/debug/debug_server.h b/src/xenia/debug/debug_server.h index a1c272a53..0780f4f2e 100644 --- a/src/xenia/debug/debug_server.h +++ b/src/xenia/debug/debug_server.h @@ -18,6 +18,7 @@ XEDECLARECLASS1(xe, Emulator); XEDECLARECLASS2(xe, debug, DebugClient); +XEDECLARECLASS2(xe, debug, DebugTarget); XEDECLARECLASS2(xe, debug, Protocol); @@ -38,6 +39,10 @@ public: int BeforeEntry(); void Shutdown(); + void AddTarget(const char* name, DebugTarget* target); + void RemoveTarget(const char* name); + DebugTarget* GetTarget(const char* name); + int WaitForClient(); private: @@ -51,6 +56,8 @@ private: std::vector protocols_; xe_mutex_t* lock_; + typedef std::unordered_map TargetMap; + TargetMap targets_; std::vector clients_; HANDLE client_event_; }; diff --git a/src/xenia/debug/debug_target.h b/src/xenia/debug/debug_target.h new file mode 100644 index 000000000..4a95f805f --- /dev/null +++ b/src/xenia/debug/debug_target.h @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_DEBUG_DEBUG_TARGET_H_ +#define XENIA_DEBUG_DEBUG_TARGET_H_ + +#include +#include +#include + + +struct json_t; + + +namespace xe { +namespace debug { + + +class DebugTarget { +public: + DebugTarget(DebugServer* debug_server) : + debug_server_(debug_server) {} + virtual ~DebugTarget() {} + + DebugServer* debug_server() const { return debug_server_; } + + virtual json_t* OnDebugRequest( + const char* command, json_t* request, bool& succeeded) = 0; + +protected: + DebugServer* debug_server_; +}; + + +} // namespace debug +} // namespace xe + + +#endif // XENIA_DEBUG_DEBUG_TARGET_H_ diff --git a/src/xenia/debug/protocols/ws/ws_client.cc b/src/xenia/debug/protocols/ws/ws_client.cc index 71b1b3645..e00261daf 100644 --- a/src/xenia/debug/protocols/ws/ws_client.cc +++ b/src/xenia/debug/protocols/ws/ws_client.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -494,17 +495,22 @@ json_t* WSClient::HandleMessage(const char* command, json_t* request, // Get target. char target_name[16] = { 0 }; const char* dot = xestrchra(command, '.'); - if (dot) { - if (dot - command > XECOUNT(target_name)) { - return NULL; - } - xestrncpya(target_name, XECOUNT(target_name), - command, dot - command); + if (!dot) { + return json_string("No debug target specified."); } + if (dot - command > XECOUNT(target_name)) { + return NULL; + } + xestrncpya(target_name, XECOUNT(target_name), + command, dot - command); const char* sub_command = command + (dot - command + 1); - // Lookup target and dispatch. + // Lookup target. + DebugTarget* target = debug_server_->GetTarget(target_name); + if (!target) { + return json_string("Unknown debug target prefix."); + } - succeeded = true; - return json_null(); + // Dispatch. + return target->OnDebugRequest(sub_command, request, succeeded); } diff --git a/src/xenia/debug/sources.gypi b/src/xenia/debug/sources.gypi index abaf1d60a..af6968004 100644 --- a/src/xenia/debug/sources.gypi +++ b/src/xenia/debug/sources.gypi @@ -5,6 +5,7 @@ 'debug_client.h', 'debug_server.cc', 'debug_server.h', + 'debug_target.h', 'protocol.cc', 'protocol.h', ],