From c2fbafdc285e07bd245e14daf0c0e9337def308e Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 1 Feb 2013 05:37:42 -0800 Subject: [PATCH] Skeleton of the debugger host. --- debugger/debugger.js | 42 +++++++++++ debugger/index.html | 9 +++ include/xenia/dbg/client.h | 38 ++++++++++ include/xenia/dbg/content_source.h | 46 ++++++++++++ include/xenia/dbg/debugger.h | 54 ++++++++++++++ include/xenia/dbg/indexed_content_source.h | 45 +++++++++++ include/xenia/xenia.h | 3 +- src/dbg/client.cc | 27 +++++++ src/dbg/content_source.cc | 27 +++++++ src/dbg/debugger.cc | 80 ++++++++++++++++++++ src/dbg/indexed_content_source.cc | 28 +++++++ src/dbg/listener.cc | 23 ++++++ src/dbg/listener.h | 38 ++++++++++ src/dbg/sources.gypi | 12 +++ src/dbg/ws_client.cc | 29 ++++++++ src/dbg/ws_client.h | 40 ++++++++++ src/dbg/ws_listener.cc | 86 ++++++++++++++++++++++ src/dbg/ws_listener.h | 42 +++++++++++ tools/xenia-run/xenia-run.cc | 11 +++ xenia.gyp | 1 + 20 files changed, 679 insertions(+), 2 deletions(-) create mode 100644 debugger/debugger.js create mode 100644 debugger/index.html create mode 100644 include/xenia/dbg/client.h create mode 100644 include/xenia/dbg/content_source.h create mode 100644 include/xenia/dbg/debugger.h create mode 100644 include/xenia/dbg/indexed_content_source.h create mode 100644 src/dbg/client.cc create mode 100644 src/dbg/content_source.cc create mode 100644 src/dbg/debugger.cc create mode 100644 src/dbg/indexed_content_source.cc create mode 100644 src/dbg/listener.cc create mode 100644 src/dbg/listener.h create mode 100644 src/dbg/sources.gypi create mode 100644 src/dbg/ws_client.cc create mode 100644 src/dbg/ws_client.h create mode 100644 src/dbg/ws_listener.cc create mode 100644 src/dbg/ws_listener.h diff --git a/debugger/debugger.js b/debugger/debugger.js new file mode 100644 index 000000000..37622e73a --- /dev/null +++ b/debugger/debugger.js @@ -0,0 +1,42 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +// TODO(benvanik): closure or something fancy + + +var DebugClient = function(endpoint) { + /** + * Target websocket endpoint. + * @type {string} + * @private + */ + this.endpoint_ = endpoint; + + /** + * Connected socket. + * @type {!WebSocket} + * @private + */ + this.socket_ = new WebSocket(endpoint, []); + + this.socket_.onopen = (function() { + console.log('opened'); + }).bind(this); + + this.socket_.onerror = (function(e) { + console.log('error', e); + }).bind(this); + + this.socket_.onmessage = (function(e) { + console.log('message', e.data); + }).bind(this); +} + + +var client = new DebugClient('ws://127.0.0.1:6200'); diff --git a/debugger/index.html b/debugger/index.html new file mode 100644 index 000000000..6c3502a87 --- /dev/null +++ b/debugger/index.html @@ -0,0 +1,9 @@ + + + + Xenia Debugger + + + + + diff --git a/include/xenia/dbg/client.h b/include/xenia/dbg/client.h new file mode 100644 index 000000000..8853c3a20 --- /dev/null +++ b/include/xenia/dbg/client.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * 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_KERNEL_DBG_CLIENT_H_ +#define XENIA_KERNEL_DBG_CLIENT_H_ + +#include +#include + + +namespace xe { +namespace dbg { + + +class Client { +public: + Client(); + virtual ~Client(); + + void Write(const uint8_t* buffer, const size_t length); + virtual void Write(const uint8_t** buffers, const size_t* lengths, + size_t count) = 0; + +protected: +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_CLIENT_H_ diff --git a/include/xenia/dbg/content_source.h b/include/xenia/dbg/content_source.h new file mode 100644 index 000000000..3a6e8821a --- /dev/null +++ b/include/xenia/dbg/content_source.h @@ -0,0 +1,46 @@ +/** + ****************************************************************************** + * 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_KERNEL_DBG_CONTENT_SOURCE_H_ +#define XENIA_KERNEL_DBG_CONTENT_SOURCE_H_ + +#include +#include + +#include + + +namespace xe { +namespace dbg { + + +class ContentSource { +public: + enum Type { + kTypeIndexed, + }; + + ContentSource(Type type); + virtual ~ContentSource(); + + Type type(); + + virtual int DispatchRequest(Client* client, + const uint8_t* data, size_t length) = 0; + +protected: + Type type_; +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_CONTENT_SOURCE_H_ diff --git a/include/xenia/dbg/debugger.h b/include/xenia/dbg/debugger.h new file mode 100644 index 000000000..a9d75ad63 --- /dev/null +++ b/include/xenia/dbg/debugger.h @@ -0,0 +1,54 @@ +/** + ****************************************************************************** + * 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_KERNEL_DBG_DEBUGGER_H_ +#define XENIA_KERNEL_DBG_DEBUGGER_H_ + +#include +#include + +#include + + +namespace xe { +namespace dbg { + + +class Client; +class ContentSource; +class Listener; + + +class Debugger { +public: + Debugger(xe_pal_ref pal); + virtual ~Debugger(); + + void RegisterContentSource(std::string& name, ContentSource* content_source); + + int Startup(); + +private: + int DispatchRequest(Client* client, const char* source_name, + const uint8_t* data, size_t length); + + friend class Client; + +private: + xe_pal_ref pal_; + auto_ptr listener_; + std::map content_sources_; +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_DEBUGGER_H_ diff --git a/include/xenia/dbg/indexed_content_source.h b/include/xenia/dbg/indexed_content_source.h new file mode 100644 index 000000000..be1d27709 --- /dev/null +++ b/include/xenia/dbg/indexed_content_source.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_KERNEL_DBG_INDEXED_CONTENT_SOURCE_H_ +#define XENIA_KERNEL_DBG_INDEXED_CONTENT_SOURCE_H_ + +#include +#include + +#include + + +namespace xe { +namespace dbg { + + +class Client; + + +class IndexedContentSource : public ContentSource { +public: + IndexedContentSource(); + virtual ~IndexedContentSource(); + + int DispatchRequest(Client* client, const uint8_t* data, size_t length); + +protected: + virtual int RequestIndex(Client* client, uint64_t req_id) = 0; + virtual int RequestRange(Client* client, uint64_t req_id, + uint64_t start_index, uint64_t end_index) = 0; + virtual int RequestEntry(Client* client, uint64_t req_id, uint64_t index) = 0; +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_INDEXED_CONTENT_SOURCE_H_ diff --git a/include/xenia/xenia.h b/include/xenia/xenia.h index 35249b31f..503a4fe95 100644 --- a/include/xenia/xenia.h +++ b/include/xenia/xenia.h @@ -15,7 +15,6 @@ #include #include #include - -int some_function(int x); +#include #endif // XENIA_H_ diff --git a/src/dbg/client.cc b/src/dbg/client.cc new file mode 100644 index 000000000..0ea6e0dd2 --- /dev/null +++ b/src/dbg/client.cc @@ -0,0 +1,27 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::dbg; + + +Client::Client() { +} + +Client::~Client() { +} + +void Client::Write(const uint8_t* buffer, const size_t length) { + const uint8_t* buffers[] = {buffer}; + const size_t lengths[] = {length}; + Write(buffers, lengths, 1); +} diff --git a/src/dbg/content_source.cc b/src/dbg/content_source.cc new file mode 100644 index 000000000..61af4e2e6 --- /dev/null +++ b/src/dbg/content_source.cc @@ -0,0 +1,27 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::dbg; + + +ContentSource::ContentSource(Type type) : + type_(type) { +} + +ContentSource::~ContentSource() { +} + + +ContentSource::Type ContentSource::type() { + return type_; +} diff --git a/src/dbg/debugger.cc b/src/dbg/debugger.cc new file mode 100644 index 000000000..502432cb8 --- /dev/null +++ b/src/dbg/debugger.cc @@ -0,0 +1,80 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include + +#include + +#include + +#include "dbg/ws_listener.h" + + +using namespace xe; +using namespace xe::dbg; + + +DEFINE_bool(wait_for_debugger, false, + "Whether to wait for the debugger to attach before launching."); +DEFINE_int32(remote_debug_port, 6200, + "Websocket port to listen for debugger connections on."); + + +Debugger::Debugger(xe_pal_ref pal) { + pal_ = xe_pal_retain(pal); + + listener_ = auto_ptr(new WsListener( + pal_, FLAGS_remote_debug_port)); +} + +Debugger::~Debugger() { + for (std::map::iterator it = content_sources_.begin(); + it != content_sources_.end(); ++it) { + xe_free(it->first); + delete it->second; + } + content_sources_.clear(); + + xe_pal_release(pal_); +} + +void Debugger::RegisterContentSource(std::string& name, + ContentSource* content_source) { + content_sources_.insert(std::pair( + xestrdupa(name.c_str()), content_source)); +} + +int Debugger::Startup() { + // Start listener. + // This may launch a thread and such. + if (listener_->Setup()) { + return 1; + } + + // If desired, wait until the first client connects. + if (FLAGS_wait_for_debugger) { + XELOGI(XT("Waiting for debugger on port %d..."), FLAGS_remote_debug_port); + if (listener_->WaitForClient()) { + return 1; + } + XELOGI(XT("Debugger attached, continuing...")); + } + + return 0; +} + +int Debugger::DispatchRequest(Client* client, const char* source_name, + const uint8_t* data, size_t length) { + std::map::iterator it = + content_sources_.find((char*)source_name); + if (it == content_sources_.end()) { + return 1; + } + return it->second->DispatchRequest(client, data, length); +} diff --git a/src/dbg/indexed_content_source.cc b/src/dbg/indexed_content_source.cc new file mode 100644 index 000000000..c0fab8d89 --- /dev/null +++ b/src/dbg/indexed_content_source.cc @@ -0,0 +1,28 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::dbg; + + +IndexedContentSource::IndexedContentSource() : + ContentSource(kTypeIndexed) { +} + +IndexedContentSource::~IndexedContentSource() { +} + +int IndexedContentSource::DispatchRequest(Client* client, + const uint8_t* data, size_t length) { + // + return 1; +} diff --git a/src/dbg/listener.cc b/src/dbg/listener.cc new file mode 100644 index 000000000..83686ea6f --- /dev/null +++ b/src/dbg/listener.cc @@ -0,0 +1,23 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include "dbg/listener.h" + + +using namespace xe; +using namespace xe::dbg; + + +Listener::Listener(xe_pal_ref pal) { + pal_ = xe_pal_retain(pal); +} + +Listener::~Listener() { + xe_pal_release(pal_); +} diff --git a/src/dbg/listener.h b/src/dbg/listener.h new file mode 100644 index 000000000..4ce466088 --- /dev/null +++ b/src/dbg/listener.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * 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_KERNEL_DBG_LISTENER_H_ +#define XENIA_KERNEL_DBG_LISTENER_H_ + +#include +#include + + +namespace xe { +namespace dbg { + + +class Listener { +public: + Listener(xe_pal_ref pal); + virtual ~Listener(); + + virtual int Setup() = 0; + virtual int WaitForClient() = 0; + +protected: + xe_pal_ref pal_; +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_LISTENER_H_ diff --git a/src/dbg/sources.gypi b/src/dbg/sources.gypi new file mode 100644 index 000000000..c85b47ad4 --- /dev/null +++ b/src/dbg/sources.gypi @@ -0,0 +1,12 @@ +# Copyright 2013 Ben Vanik. All Rights Reserved. +{ + 'sources': [ + 'client.cc', + 'content_source.cc', + 'debugger.cc', + 'indexed_content_source.cc', + 'listener.cc', + 'ws_client.cc', + 'ws_listener.cc', + ], +} diff --git a/src/dbg/ws_client.cc b/src/dbg/ws_client.cc new file mode 100644 index 000000000..a8b8e9b08 --- /dev/null +++ b/src/dbg/ws_client.cc @@ -0,0 +1,29 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include "dbg/ws_client.h" + + +using namespace xe; +using namespace xe::dbg; + + +WsClient::WsClient(int socket_id) : + Client(), + socket_id_(socket_id) { +} + +WsClient::~WsClient() { + close(socket_id_); +} + +void WsClient::Write(const uint8_t** buffers, const size_t* lengths, + size_t count) { + // +} diff --git a/src/dbg/ws_client.h b/src/dbg/ws_client.h new file mode 100644 index 000000000..76ed73508 --- /dev/null +++ b/src/dbg/ws_client.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * 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_KERNEL_DBG_WS_CLIENT_H_ +#define XENIA_KERNEL_DBG_WS_CLIENT_H_ + +#include +#include + +#include + + +namespace xe { +namespace dbg { + + +class WsClient : public Client { +public: + WsClient(int socket_id); + virtual ~WsClient(); + + virtual void Write(const uint8_t** buffers, const size_t* lengths, + size_t count); + +protected: + int socket_id_; +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_WS_CLIENT_H_ diff --git a/src/dbg/ws_listener.cc b/src/dbg/ws_listener.cc new file mode 100644 index 000000000..9e48812b0 --- /dev/null +++ b/src/dbg/ws_listener.cc @@ -0,0 +1,86 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#include "dbg/ws_listener.h" + +#include +#include +#include + +#include "dbg/ws_client.h" + + +using namespace xe; +using namespace xe::dbg; + + +WsListener::WsListener(xe_pal_ref pal, uint32_t port) : + Listener(pal), + port_(port) { + +} + +WsListener::~WsListener() { + if (socket_id_) { + close(socket_id_); + } +} + +int WsListener::Setup() { + socket_id_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (socket_id_ < 1) { + return 1; + } + + int opt_value; + opt_value = 1; + setsockopt(socket_id_, SOL_SOCKET, SO_KEEPALIVE, + &opt_value, sizeof(opt_value)); + opt_value = 0; + setsockopt(socket_id_, IPPROTO_TCP, TCP_NODELAY, + &opt_value, sizeof(opt_value)); + + struct sockaddr_in socket_addr; + socket_addr.sin_family = AF_INET; + socket_addr.sin_addr.s_addr = htonl(INADDR_ANY); + socket_addr.sin_port = htons(port_); + if (bind(socket_id_, (struct sockaddr*)&socket_addr, + sizeof(socket_addr)) < 0) { + return 1; + } + + if (listen(socket_id_, 5) < 0) { + close(socket_id_); + return 1; + } + + return 0; +} + +int WsListener::WaitForClient() { + // Accept the first connection we get. + struct sockaddr_in client_addr; + socklen_t client_count = sizeof(client_addr); + int client_socket_id = accept(socket_id_, (struct sockaddr*)&client_addr, + &client_count); + if (client_socket_id < 0) { + return 1; + } + + int client_ip = client_addr.sin_addr.s_addr; + char client_ip_str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &client_ip, client_ip_str, XECOUNT(client_ip_str)); + XELOGI(XT("Debugger connected from %s"), client_ip_str); + + //WsClient* client = new WsClient(client_socket_id); + + // TODO(benvanik): add to list for cleanup + + return 0; +} diff --git a/src/dbg/ws_listener.h b/src/dbg/ws_listener.h new file mode 100644 index 000000000..2e46d55bb --- /dev/null +++ b/src/dbg/ws_listener.h @@ -0,0 +1,42 @@ +/** + ****************************************************************************** + * 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_KERNEL_DBG_WS_LISTENER_H_ +#define XENIA_KERNEL_DBG_WS_LISTENER_H_ + +#include +#include + +#include "dbg/listener.h" + + +namespace xe { +namespace dbg { + + +class WsListener : public Listener { +public: + WsListener(xe_pal_ref pal, uint32_t port); + virtual ~WsListener(); + + virtual int Setup(); + virtual int WaitForClient(); + +protected: + uint32_t port_; + + int socket_id_; +}; + + +} // namespace dbg +} // namespace xe + + +#endif // XENIA_KERNEL_DBG_WS_LISTENER_H_ diff --git a/tools/xenia-run/xenia-run.cc b/tools/xenia-run/xenia-run.cc index e2df701f4..e284fd8f5 100644 --- a/tools/xenia-run/xenia-run.cc +++ b/tools/xenia-run/xenia-run.cc @@ -14,6 +14,7 @@ using namespace xe; using namespace xe::cpu; +using namespace xe::dbg; using namespace xe::kernel; @@ -34,6 +35,7 @@ private: xe_memory_ref memory_; shared_ptr processor_; shared_ptr runtime_; + shared_ptr debugger_; }; Run::Run() { @@ -50,6 +52,8 @@ int Run::Setup() { pal_ = xe_pal_create(pal_options); XEEXPECTNOTNULL(pal_); + debugger_ = shared_ptr(new Debugger(pal_)); + xe_memory_options_t memory_options; xe_zero_struct(&memory_options, sizeof(memory_options)); memory_ = xe_memory_create(pal_, memory_options); @@ -86,6 +90,13 @@ int Run::Launch(const xechar_t* path) { return 1; } + // Run the debugger. + // This may pause waiting for connections. + if (debugger_->Startup()) { + XELOGE(XT("Debugger failed to startup")); + return 1; + } + // Launch based on file type. // This is a silly guess based on file extension. // NOTE: the runtime launch routine will wait until the module exits. diff --git a/xenia.gyp b/xenia.gyp index 9cea94ee1..109177c92 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -34,6 +34,7 @@ 'includes': [ 'src/xenia/sources.gypi', 'src/core/sources.gypi', + 'src/dbg/sources.gypi', ], },