Starting debugger rework, adding base async socket, removing flatbuffers.

This commit is contained in:
Ben Vanik 2015-07-22 00:01:36 -07:00
parent a98fa47081
commit d01abd4694
23 changed files with 617 additions and 2817 deletions

3
.gitmodules vendored
View File

@ -7,9 +7,6 @@
[submodule "third_party/imgui"]
path = third_party/imgui
url = https://github.com/ocornut/imgui.git
[submodule "third_party/flatbuffers"]
path = third_party/flatbuffers
url = https://github.com/google/flatbuffers.git
[submodule "third_party/binutils-ppc-cygwin"]
path = third_party/binutils-ppc-cygwin
url = https://github.com/benvanik/binutils-ppc-cygwin

108
src/xenia/base/socket.h Normal file
View File

@ -0,0 +1,108 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_BASE_SOCKET_H_
#define XENIA_BASE_SOCKET_H_
#include <cstdint>
#include <functional>
#include <memory>
#include "xenia/base/threading.h"
namespace xe {
// An asynchronous bidirectional socket.
// Sockets are wait-based and operate in a thread-free manner. Data may be
// read from or written to a socket from any thread with the wait handle as
// a mechanism to efficiently wait until new data is available.
// Consumers should wait on the wait handle and when signalled poll to see
// if the socket is still connected or new data is available. When reading
// data Receive should be called until it returns 0 new bytes and then the
// wait handle should be waited on until new data arrives.
class Socket {
public:
// TODO(benvanik): client socket static Connect method.
virtual ~Socket() = default;
// TODO(benvanik): socket info? remote IP? etc?
// Returns a wait handle that can be used to wait on incoming client data or
// status updates. When this handle is signalled consumers should poll for
// new data and react accordingly.
virtual xe::threading::WaitHandle* wait_handle() = 0;
// Returns true if the client is connected and can send/receive data.
virtual bool is_connected() = 0;
// Closes the socket.
// This will signal the wait handle.
virtual void Close() = 0;
// Receives incoming data up to the given capacity and returns the total
// number of bytes received.
// 0 is returned if there is no data available. -1 is returned if the client
// has been closed.
virtual size_t Receive(void* buffer, size_t buffer_capacity) = 0;
// Asynchronously sends a set of buffers.
// The buffers are copied and may be modified immediately after the function
// returns.
// Returns false if the socket is disconnected or the data cannot be sent.
virtual bool Send(const std::pair<const void*, size_t>* buffers,
size_t buffer_count) = 0;
// Asynchronously sends a set of buffers.
// The buffers are copied and may be modified immediately after the function
// returns.
// Returns false if the socket is disconnected or the data cannot be sent.
bool Send(std::vector<std::pair<const void*, size_t>> buffers) {
return Send(buffers.data(), buffers.size());
}
// Asynchronously sends a buffer of data.
// The buffer is copied and may be modified immediately after the function
// returns.
// Returns false if the socket is disconnected or the data cannot be sent.
bool Send(const void* buffer, size_t buffer_length) {
auto buffer_list = std::make_pair(buffer, buffer_length);
return Send(&buffer_list, 1);
}
// Asynchronously sends a buffer of data.
// The buffer is copied and may be modified immediately after the function
// returns.
// Returns false if the socket is disconnected or the data cannot be sent.
bool Send(const std::vector<uint8_t>& buffer) {
auto buffer_list = std::make_pair(buffer.data(), buffer.size());
return Send(&buffer_list, 1);
}
};
// Runs a socket server on the specified local port.
// The server accepts clients from a background thread until closed (by
// deletion). Clients are not tied to their creating server and the server
// may be closed while clients remain connected.
class SocketServer {
public:
// Creates a new socket server bound to the given local port.
// The accept callback will be called from a random thread when a new client
// connects.
// Returns null if the server cannot be bound to the given port (in use, etc).
static std::unique_ptr<SocketServer> Create(
uint16_t port,
std::function<void(std::unique_ptr<Socket> client)> accept_callback);
virtual ~SocketServer() = default;
};
} // namespace xe
#endif // XENIA_BASE_SOCKET_H_

View File

@ -0,0 +1,249 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/base/socket.h"
#include <mutex>
#include <thread>
#include "xenia/base/logging.h"
// platform_win.h must come first to include Windows headers.
#include "xenia/base/platform_win.h"
#include <mstcpip.h>
#include <winsock2.h>
#include <ws2tcpip.h>
namespace xe {
void InitializeWinsock() {
static bool has_initialized = false;
if (!has_initialized) {
has_initialized = true;
WSADATA wsa_data;
WSAStartup(MAKEWORD(2, 2), &wsa_data);
}
}
class Win32Socket : public Socket {
public:
Win32Socket() = default;
~Win32Socket() override { Close(); }
bool Accept(SOCKET socket) {
std::lock_guard<std::recursive_mutex> lock(mutex_);
socket_ = socket;
// Create event and bind to the socket, waiting for read/close
// notifications.
event_ = xe::threading::Event::CreateManualResetEvent(false);
WSAEventSelect(socket_, event_->native_handle(), FD_READ | FD_CLOSE);
// Keepalive for a looong time, as we may be paused by the debugger/etc.
struct tcp_keepalive alive;
alive.onoff = TRUE;
alive.keepalivetime = 7200000;
alive.keepaliveinterval = 6000;
DWORD bytes_returned;
WSAIoctl(socket_, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), nullptr, 0,
&bytes_returned, nullptr, nullptr);
return true;
}
xe::threading::WaitHandle* wait_handle() override { return event_.get(); }
bool is_connected() override {
std::lock_guard<std::recursive_mutex> lock(mutex_);
return socket_ != INVALID_SOCKET;
}
void Close() override {
std::lock_guard<std::recursive_mutex> lock(mutex_);
if (socket_ != INVALID_SOCKET) {
SOCKET socket = socket_;
socket_ = INVALID_SOCKET;
shutdown(socket, SD_SEND);
closesocket(socket);
}
if (event_) {
// Set event so any future waits will immediately succeed.
event_->Set();
}
}
size_t Receive(void* buffer, size_t buffer_capacity) override {
std::lock_guard<std::recursive_mutex> lock(mutex_);
if (socket_ == INVALID_SOCKET) {
return -1;
}
int ret =
recv(socket_, reinterpret_cast<char*>(buffer), int(buffer_capacity), 0);
if (ret == SOCKET_ERROR) {
int e = WSAGetLastError();
if (e == WSAEWOULDBLOCK) {
// Ok - no more data to read.
// Reset our event so we'll block next time.
event_->Reset();
return 0;
}
XELOGE("Socket send error: %d", e);
Close();
return -1;
} else if (ret == 0) {
// Socket gracefully closed.
Close();
return -1;
}
return ret;
}
bool Send(const std::pair<const void*, size_t>* buffers,
size_t buffer_count) override {
std::lock_guard<std::recursive_mutex> lock(mutex_);
if (socket_ == INVALID_SOCKET) {
return false;
}
std::vector<WSABUF> buffer_data_list;
std::vector<DWORD> buffer_data_sent;
for (size_t i = 0; i < buffer_count; ++i) {
WSABUF buf;
buf.len = ULONG(buffers[i].second);
buf.buf = reinterpret_cast<char*>(const_cast<void*>(buffers[i].first));
buffer_data_list.emplace_back(buf);
buffer_data_sent.emplace_back(0);
}
int ret = WSASend(socket_, buffer_data_list.data(), DWORD(buffer_count),
buffer_data_sent.data(), 0, nullptr, nullptr);
if (ret == SOCKET_ERROR) {
int e = WSAGetLastError();
XELOGE("Socket send error: %d", e);
Close();
return false;
}
return true;
}
private:
std::recursive_mutex mutex_;
SOCKET socket_ = INVALID_SOCKET;
std::unique_ptr<xe::threading::Event> event_;
};
class Win32SocketServer : public SocketServer {
public:
Win32SocketServer(
std::function<void(std::unique_ptr<Socket> client)> accept_callback)
: accept_callback_(std::move(accept_callback)) {}
~Win32SocketServer() override {
if (socket_ != INVALID_SOCKET) {
SOCKET socket = socket_;
socket_ = INVALID_SOCKET;
linger so_linger;
so_linger.l_onoff = TRUE;
so_linger.l_linger = 30;
setsockopt(socket, SOL_SOCKET, SO_LINGER,
reinterpret_cast<const char*>(&so_linger), sizeof(so_linger));
shutdown(socket, SD_SEND);
closesocket(socket);
}
if (accept_thread_) {
// Join thread, which should die because the socket is now invalid.
xe::threading::Wait(accept_thread_.get(), true);
accept_thread_.reset();
}
}
bool Bind(uint16_t port) {
socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socket_ < 1) {
XELOGE("Unable to create listen socket");
return false;
}
struct tcp_keepalive alive;
alive.onoff = TRUE;
alive.keepalivetime = 7200000;
alive.keepaliveinterval = 6000;
DWORD bytes_returned;
WSAIoctl(socket_, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), nullptr, 0,
&bytes_returned, nullptr, nullptr);
int opt_value = 1;
setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<const char*>(&opt_value), sizeof(opt_value));
opt_value = 1;
setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<const char*>(&opt_value), sizeof(opt_value));
sockaddr_in socket_addr = {0};
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
socket_addr.sin_port = htons(port);
if (bind(socket_, reinterpret_cast<sockaddr*>(&socket_addr),
sizeof(socket_addr)) == SOCKET_ERROR) {
int e = WSAGetLastError();
XELOGE("Unable to bind debug socket: %d", e);
return false;
}
if (listen(socket_, 5) == SOCKET_ERROR) {
int e = WSAGetLastError();
XELOGE("Unable to listen on accept socket %d", e);
return false;
}
accept_thread_ = xe::threading::Thread::Create({}, [this, port]() {
xe::threading::set_name(std::string("xe::SocketServer localhost:") +
std::to_string(port));
while (socket_ != INVALID_SOCKET) {
sockaddr_in6 client_addr;
int client_count = sizeof(client_addr);
SOCKET client_socket = accept(
socket_, reinterpret_cast<sockaddr*>(&client_addr), &client_count);
if (client_socket == INVALID_SOCKET) {
continue;
}
auto client = std::make_unique<Win32Socket>();
if (!client->Accept(client_socket)) {
XELOGE("Unable to accept socket; ignoring");
continue;
}
accept_callback_(std::move(client));
}
});
return true;
}
private:
std::function<void(std::unique_ptr<Socket> client)> accept_callback_;
std::unique_ptr<xe::threading::Thread> accept_thread_;
SOCKET socket_ = INVALID_SOCKET;
};
std::unique_ptr<SocketServer> SocketServer::Create(
uint16_t port,
std::function<void(std::unique_ptr<Socket> client)> accept_callback) {
InitializeWinsock();
auto socket_server =
std::make_unique<Win32SocketServer>(std::move(accept_callback));
if (!socket_server->Bind(port)) {
return nullptr;
}
return std::unique_ptr<SocketServer>(socket_server.release());
}
} // namespace xe

View File

@ -22,6 +22,7 @@
#include "xenia/cpu/module.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/cpu/xex_module.h"
#include "xenia/debug/debugger.h"
#include "xenia/profiling.h"
// TODO(benvanik): based on compiler support
@ -32,27 +33,6 @@ namespace cpu {
using PPCContext = xe::cpu::frontend::PPCContext;
void InitializeIfNeeded();
void CleanupOnShutdown();
void InitializeIfNeeded() {
static bool has_initialized = false;
if (has_initialized) {
return;
}
has_initialized = true;
// ppc::RegisterDisasmCategoryAltivec();
// ppc::RegisterDisasmCategoryALU();
// ppc::RegisterDisasmCategoryControl();
// ppc::RegisterDisasmCategoryFPU();
// ppc::RegisterDisasmCategoryMemory();
atexit(CleanupOnShutdown);
}
void CleanupOnShutdown() {}
class BuiltinModule : public Module {
public:
BuiltinModule(Processor* processor) : Module(processor), name_("builtin") {}
@ -67,9 +47,7 @@ class BuiltinModule : public Module {
Processor::Processor(xe::Memory* memory, ExportResolver* export_resolver,
debug::Debugger* debugger)
: memory_(memory), debugger_(debugger), export_resolver_(export_resolver) {
InitializeIfNeeded();
}
: memory_(memory), debugger_(debugger), export_resolver_(export_resolver) {}
Processor::~Processor() {
{

View File

@ -21,9 +21,14 @@
#include "xenia/cpu/function.h"
#include "xenia/cpu/module.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/debug/debugger.h"
#include "xenia/memory.h"
namespace xe {
namespace debug {
class Debugger;
} // namespace debug
} // namespace xe
namespace xe {
namespace cpu {

View File

@ -11,12 +11,6 @@
#include <gflags/gflags.h>
// TODO(benvanik): generic socket implementation in base/.
#include "xenia/base/platform_win.h"
#include <mstcpip.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mutex>
#include "xenia/base/filesystem.h"
@ -26,24 +20,16 @@
#include "xenia/cpu/backend/code_cache.h"
#include "xenia/cpu/function.h"
#include "xenia/cpu/processor.h"
#include "xenia/debug/transport/gdb/gdb_transport.h"
#include "xenia/emulator.h"
#include "xenia/kernel/objects/xkernel_module.h"
#include "xenia/kernel/objects/xmodule.h"
#include "xenia/kernel/objects/xthread.h"
#include "xenia/kernel/objects/xuser_module.h"
// Autogenerated Flatbuffers files:
#include "xenia/debug/proto/breakpoints_generated.h"
#include "xenia/debug/proto/common_generated.h"
#include "xenia/debug/proto/control_generated.h"
#include "xenia/debug/proto/messages_generated.h"
#include "xenia/debug/proto/modules_generated.h"
#include "xenia/debug/proto/threads_generated.h"
DEFINE_string(debug_session_path, "", "Debug output path.");
DEFINE_int32(debug_port, 19000, "Port the debugger listens on.");
DEFINE_bool(wait_for_debugger, false,
"Waits for the debugger to attach before starting the game.");
"Waits for a debugger to attach before starting the game.");
DEFINE_bool(exit_with_debugger, true, "Exit whe the debugger disconnects.");
namespace xe {
@ -58,17 +44,22 @@ Breakpoint::Breakpoint(Type type, uint32_t address)
Breakpoint::~Breakpoint() = default;
Debugger::Debugger(Emulator* emulator)
: emulator_(emulator),
listen_socket_(INVALID_SOCKET),
client_socket_(INVALID_SOCKET) {
WSADATA wsa_data;
WSAStartup(MAKEWORD(2, 2), &wsa_data);
}
Debugger::Debugger(Emulator* emulator) : emulator_(emulator) {}
Debugger::~Debugger() {
if (listen_socket_ != INVALID_SOCKET) {
StopSession();
Debugger::~Debugger() { StopSession(); }
void Debugger::set_attached(bool attached) {
if (is_attached_ && !attached) {
// Debugger detaching.
if (FLAGS_exit_with_debugger) {
XELOGE("Debugger detached, --exit_with_debugger is killing us");
exit(1);
return;
}
}
is_attached_ = attached;
if (is_attached_) {
attach_fence_.Signal();
}
}
@ -87,417 +78,34 @@ bool Debugger::StartSession() {
functions_trace_file_ = ChunkedMappedMemoryWriter::Open(
functions_trace_path_, 32 * 1024 * 1024, true);
listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket_ < 1) {
XELOGE("Failed to create debugger socket");
return false;
}
struct tcp_keepalive alive;
alive.onoff = TRUE;
alive.keepalivetime = 7200000;
alive.keepaliveinterval = 6000;
DWORD bytes_returned;
WSAIoctl(listen_socket_, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), nullptr,
0, &bytes_returned, nullptr, nullptr);
int opt_value = 1;
setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<const char*>(&opt_value), sizeof(opt_value));
opt_value = 1;
setsockopt(listen_socket_, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<const char*>(&opt_value), sizeof(opt_value));
sockaddr_in socket_addr = {0};
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_addr.sin_port = htons(FLAGS_debug_port);
if (bind(listen_socket_, reinterpret_cast<sockaddr*>(&socket_addr),
sizeof(socket_addr)) == SOCKET_ERROR) {
int e = WSAGetLastError();
XELOGE("Unable to bind debug socket: %d", e);
return false;
}
if (listen(listen_socket_, 5) == SOCKET_ERROR) {
XELOGE("Unable to listen on debug socket");
return 1;
// Add default transports.
auto gdb_transport =
std::make_unique<xe::debug::transport::gdb::GdbTransport>(this);
if (gdb_transport->Initialize()) {
transports_.emplace_back(std::move(gdb_transport));
} else {
XELOGE("Unable to initialize GDB debugger transport");
}
return true;
}
void SendResponse(SOCKET client_socket, flatbuffers::FlatBufferBuilder& fbb,
uint32_t request_id, proto::ResponseData response_data_type,
flatbuffers::Offset<void> response_data_offset) {
auto response_offset = proto::CreateResponse(
fbb, request_id, response_data_type, response_data_offset);
fbb.Finish(response_offset);
int buffer_length = fbb.GetSize();
send(client_socket, reinterpret_cast<const char*>(&buffer_length), 4, 0);
send(client_socket, reinterpret_cast<const char*>(fbb.GetBufferPointer()),
fbb.GetSize(), 0);
}
void Debugger::PreLaunch() {
if (!accept_thread_running_) {
accept_thread_running_ = true;
accept_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Server");
while (listen_socket_ != INVALID_SOCKET) {
sockaddr_in6 client_addr;
int client_count = sizeof(client_addr);
SOCKET client_socket_id =
accept(listen_socket_, reinterpret_cast<sockaddr*>(&client_addr),
&client_count);
if (client_socket_id == INVALID_SOCKET) {
XELOGE("Failed to accept socket");
continue;
}
// Only one debugger at a time.
if (client_socket_ != INVALID_SOCKET) {
XELOGW("Ignoring debugger connection as one is already connected");
closesocket(client_socket_id);
continue;
}
// Setup recv thread.
client_socket_ = client_socket_id;
receive_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Connection");
while (client_socket_ != INVALID_SOCKET) {
// Read length prefix.
uint32_t length = 0;
int r = recv(client_socket_, reinterpret_cast<char*>(&length), 4,
MSG_WAITALL);
if (r != 4) {
// Failed?
XELOGE("Failed to recv debug data length - dead connection?");
if (FLAGS_exit_with_debugger) {
exit(1);
}
break;
}
// Read body.
std::vector<uint8_t> body(length);
r = recv(client_socket_, reinterpret_cast<char*>(body.data()),
length, MSG_WAITALL);
if (r != length) {
// Failed?
XELOGE("Failed to recv debug data body - dead connection?");
if (FLAGS_exit_with_debugger) {
exit(1);
}
break;
}
// Read message contents and dispatch.
OnMessage(std::move(body));
}
});
// This will WaitForClient if it was waiting.
}
});
}
if (FLAGS_wait_for_debugger) {
// Wait for the first client.
XELOGI("Waiting for debugger because of --wait_for_debugger...");
accept_fence_.Wait();
attach_fence_.Wait();
XELOGI("Debugger attached, continuing...");
}
}
void Debugger::OnMessage(std::vector<uint8_t> buffer) {
flatbuffers::FlatBufferBuilder fbb;
proto::ResponseData response_data_type;
flatbuffers::Offset<void> response_data_offset;
auto request = flatbuffers::GetRoot<proto::Request>(buffer.data());
switch (request->request_data_type()) {
case proto::RequestData_AttachRequest: {
// Send debug info.
auto code_cache = emulator()->processor()->backend()->code_cache();
response_data_type = proto::ResponseData_AttachResponse;
response_data_offset =
proto::CreateAttachResponse(
fbb, fbb.CreateString(
xe::to_string(emulator()->memory()->file_name())),
fbb.CreateString(xe::to_string(code_cache->file_name())),
code_cache->base_address(), code_cache->total_size(),
fbb.CreateString(xe::to_string(functions_path_)),
fbb.CreateString(xe::to_string(functions_trace_path_)))
.Union();
// Allow continuation if we were blocked waiting for a client.
accept_fence_.Signal();
} break;
case proto::RequestData_ListBreakpointsRequest: {
response_data_type = proto::ResponseData_ListBreakpointsResponse;
auto response_data = proto::ListBreakpointsResponseBuilder(fbb);
//
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_AddBreakpointsRequest: {
response_data_type = proto::ResponseData_RemoveBreakpointsResponse;
auto response_data = proto::AddBreakpointsResponseBuilder(fbb);
//
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_UpdateBreakpointsRequest: {
response_data_type = proto::ResponseData_UpdateBreakpointsResponse;
auto response_data = proto::UpdateBreakpointsResponseBuilder(fbb);
//
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_RemoveBreakpointsRequest: {
response_data_type = proto::ResponseData_AddBreakpointsResponse;
auto response_data = proto::RemoveBreakpointsResponseBuilder(fbb);
//
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_ListModulesRequest: {
response_data_type = proto::ResponseData_ListModulesResponse;
auto modules =
emulator()->kernel_state()->object_table()->GetObjectsByType<XModule>(
XObject::kTypeModule);
std::vector<proto::ListModuleEntry> module_entries;
for (size_t i = 0; i < modules.size(); ++i) {
auto& module = modules[i];
auto processor_module = module->processor_module();
module_entries.emplace_back(
module->handle(),
processor_module ? uint32_t(processor_module->QuerySymbolCount())
: 0);
}
auto module_entries_offset =
fbb.CreateVectorOfStructs<proto::ListModuleEntry>(module_entries);
auto response_data = proto::ListModulesResponseBuilder(fbb);
response_data.add_entry(module_entries_offset);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_GetModuleRequest: {
auto request_data = reinterpret_cast<const proto::GetModuleRequest*>(
request->request_data());
auto module =
emulator()->kernel_state()->object_table()->LookupObject<XModule>(
request_data->module_id());
flatbuffers::Offset<proto::Module> module_offset;
if (module) {
proto::XObject xobject_data(module->handle());
auto module_name_offset = fbb.CreateString(module->name());
auto module_path_offset = fbb.CreateString(module->path());
proto::ModuleBuilder module_builder(fbb);
module_builder.add_object(&xobject_data);
module_builder.add_type(
static_cast<proto::ModuleType>(module->module_type()));
module_builder.add_name(module_name_offset);
module_builder.add_path(module_path_offset);
switch (module->module_type()) {
case XModule::ModuleType::kKernelModule: {
// auto kernel_module =
// reinterpret_cast<XKernelModule*>(module.get());
break;
}
case XModule::ModuleType::kUserModule: {
// auto user_module = reinterpret_cast<XUserModule*>(module.get());
// user_module->xex?
break;
}
default:
assert_unhandled_case(module->module_type());
break;
}
module_offset = module_builder.Finish();
}
response_data_type = proto::ResponseData_GetModuleResponse;
auto response_data = proto::GetModuleResponseBuilder(fbb);
response_data.add_module(module_offset);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_ListFunctionsRequest: {
auto request_data = reinterpret_cast<const proto::ListFunctionsRequest*>(
request->request_data());
auto module =
emulator()->kernel_state()->object_table()->LookupObject<XModule>(
request_data->module_id());
if (!module || !module->processor_module()) {
response_data_type = proto::ResponseData_ListFunctionsResponse;
auto response_data = proto::ListFunctionsResponseBuilder(fbb);
response_data_offset = response_data.Finish().Union();
break;
}
auto processor_module = module->processor_module();
size_t max_function_count = request_data->function_index_end() -
request_data->function_index_start() + 1;
std::vector<flatbuffers::Offset<proto::FunctionEntry>> function_list;
function_list.reserve(max_function_count);
processor_module->ForEachSymbol(
request_data->function_index_start(),
request_data->function_index_end(),
[&](xe::cpu::SymbolInfo* symbol_info) {
if (symbol_info->type() != xe::cpu::SymbolType::kFunction) {
return;
}
auto function_info =
reinterpret_cast<xe::cpu::FunctionInfo*>(symbol_info);
flatbuffers::Offset<flatbuffers::String> name_offset;
if (!function_info->name().empty()) {
name_offset = fbb.CreateString(function_info->name());
}
auto function_entry = proto::FunctionEntryBuilder(fbb);
function_entry.add_identifier(
reinterpret_cast<uintptr_t>(function_info));
function_entry.add_address_start(function_info->address());
function_entry.add_address_end(function_info->end_address());
function_entry.add_name(name_offset);
function_list.push_back(function_entry.Finish());
});
auto function_list_data = fbb.CreateVector(function_list);
response_data_type = proto::ResponseData_ListFunctionsResponse;
auto response_data = proto::ListFunctionsResponseBuilder(fbb);
response_data.add_entry(function_list_data);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_GetFunctionRequest: {
auto request_data = reinterpret_cast<const proto::GetFunctionRequest*>(
request->request_data());
auto function_info =
reinterpret_cast<xe::cpu::FunctionInfo*>(request_data->identifier());
auto function = function_info->function();
if (!function) {
// Attempt to resolve.
emulator_->processor()->ResolveFunction(function_info->address(),
&function);
}
flatbuffers::Offset<flatbuffers::String> name_offset;
if (!function_info->name().empty()) {
name_offset = fbb.CreateString(function_info->name());
}
flatbuffers::Offset<flatbuffers::String> disasm_hir_raw_offset;
flatbuffers::Offset<flatbuffers::String> disasm_hir_opt_offset;
if (function && function->debug_info()) {
auto debug_info = function->debug_info();
if (debug_info->raw_hir_disasm()) {
disasm_hir_raw_offset =
fbb.CreateString(debug_info->raw_hir_disasm());
}
if (debug_info->hir_disasm()) {
disasm_hir_opt_offset = fbb.CreateString(debug_info->hir_disasm());
}
}
auto function_data = proto::FunctionBuilder(fbb);
function_data.add_identifier(request_data->identifier());
function_data.add_address_start(function_info->address());
function_data.add_address_end(function_info->end_address());
function_data.add_name(name_offset);
if (function) {
function_data.add_machine_code_start(
uint32_t(uintptr_t(function->machine_code())));
function_data.add_machine_code_end(uint32_t(uintptr_t(
function->machine_code() + function->machine_code_length())));
}
function_data.add_disasm_hir_raw(disasm_hir_raw_offset);
function_data.add_disasm_hir_opt(disasm_hir_opt_offset);
auto function_offset = function_data.Finish();
response_data_type = proto::ResponseData_GetFunctionResponse;
auto response_data = proto::GetFunctionResponseBuilder(fbb);
response_data.add_function(function_offset);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_ListThreadsRequest: {
response_data_type = proto::ResponseData_ListThreadsResponse;
auto threads =
emulator()->kernel_state()->object_table()->GetObjectsByType<XThread>(
XObject::kTypeThread);
std::vector<flatbuffers::Offset<proto::Thread>> thread_list;
for (size_t i = 0; i < threads.size(); ++i) {
auto& thread = threads[i];
auto thread_name_string = fbb.CreateString(thread->name());
auto thread_builder = proto::ThreadBuilder(fbb);
// thread_builder.add_type();
// thread_builder.add_stack_size();
// thread_builder.add_xapi_thread_startup();
// thread_builder.add_start_address();
// thread_builder.add_start_context();
// thread_builder.add_creation_flags();
thread_builder.add_tls_address(thread->tls_ptr());
thread_builder.add_pcr_address(thread->pcr_ptr());
thread_builder.add_thread_id(thread->thread_id());
thread_builder.add_name(thread_name_string);
thread_builder.add_priority(thread->priority());
thread_builder.add_affinity(thread->affinity());
// thread_builder.add_state(thread->);
thread_list.push_back(thread_builder.Finish());
}
auto threads_offset = fbb.CreateVector(thread_list);
auto response_data = proto::ListThreadsResponseBuilder(fbb);
response_data.add_thread(threads_offset);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_StopRequest: {
response_data_type = proto::ResponseData_StopResponse;
auto response_data = proto::StopResponseBuilder(fbb);
// TODO(benvanik): gracefully die?
exit(1);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_BreakRequest: {
response_data_type = proto::ResponseData_BreakResponse;
auto response_data = proto::BreakResponseBuilder(fbb);
//
SuspendAllThreads();
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_ContinueRequest: {
response_data_type = proto::ResponseData_ContinueResponse;
auto response_data = proto::ContinueResponseBuilder(fbb);
//
ResumeAllThreads();
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_StepRequest: {
response_data_type = proto::ResponseData_StepResponse;
auto response_data = proto::StepResponseBuilder(fbb);
//
response_data_offset = response_data.Finish().Union();
} break;
default:
assert_unhandled_case(request->request_data_type());
break;
}
SendResponse(client_socket_, fbb, request->id(), response_data_type,
response_data_offset);
// TODO(benvanik): notify transports?
}
void Debugger::StopSession() {
FlushSession();
if (client_socket_ != INVALID_SOCKET) {
shutdown(client_socket_, SD_SEND);
closesocket(client_socket_);
client_socket_ = INVALID_SOCKET;
}
linger so_linger;
so_linger.l_onoff = TRUE;
so_linger.l_linger = 30;
setsockopt(listen_socket_, SOL_SOCKET, SO_LINGER,
reinterpret_cast<const char*>(&so_linger), sizeof(so_linger));
shutdown(listen_socket_, SD_SEND);
closesocket(listen_socket_);
listen_socket_ = INVALID_SOCKET;
if (accept_thread_.joinable()) {
accept_thread_.join();
}
// Kill all transports.
transports_.clear();
functions_file_.reset();
functions_trace_file_.reset();
@ -631,11 +239,11 @@ void Debugger::FindBreakpoints(uint32_t address,
}
void Debugger::OnThreadCreated(ThreadState* thread_state) {
//
// TODO(benvanik): notify transports.
}
void Debugger::OnThreadDestroyed(ThreadState* thread_state) {
//
// TODO(benvanik): notify transports.
}
void Debugger::OnFunctionDefined(cpu::FunctionInfo* symbol_info,
@ -670,9 +278,7 @@ void Debugger::OnBreakpointHit(ThreadState* thread_state,
// Suspend all threads immediately.
SuspendAllThreads();
// Notify listeners.
BreakpointHitEvent e(this, thread_state, breakpoint);
breakpoint_hit(e);
// TODO(benvanik): notify transports.
// Note that we stay suspended.
}

View File

@ -14,12 +14,12 @@
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
#include "xenia/base/delegate.h"
#include "xenia/base/mapped_memory.h"
#include "xenia/base/threading.h"
#include "xenia/cpu/processor.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/debug/breakpoint.h"
@ -27,44 +27,10 @@ namespace xe {
class Emulator;
} // namespace xe
namespace xe {
namespace cpu {
class Function;
class FunctionInfo;
class Processor;
} // namespace cpu
} // namespace xe
namespace xe {
namespace debug {
class Debugger;
class DebugEvent {
public:
DebugEvent(Debugger* debugger) : debugger_(debugger) {}
virtual ~DebugEvent() = default;
Debugger* debugger() const { return debugger_; }
protected:
Debugger* debugger_;
};
class BreakpointHitEvent : public DebugEvent {
public:
BreakpointHitEvent(Debugger* debugger, cpu::ThreadState* thread_state,
Breakpoint* breakpoint)
: DebugEvent(debugger),
thread_state_(thread_state),
breakpoint_(breakpoint) {}
~BreakpointHitEvent() override = default;
cpu::ThreadState* thread_state() const { return thread_state_; }
Breakpoint* breakpoint() const { return breakpoint_; }
protected:
cpu::ThreadState* thread_state_;
Breakpoint* breakpoint_;
};
class Transport;
class Debugger {
public:
@ -81,7 +47,8 @@ class Debugger {
uint8_t* AllocateFunctionData(size_t size);
uint8_t* AllocateFunctionTraceData(size_t size);
bool is_attached() const { return client_socket_ != ~0; }
bool is_attached() const { return is_attached_; }
void set_attached(bool attached);
bool SuspendAllThreads();
bool ResumeThread(uint32_t thread_id);
@ -102,20 +69,14 @@ class Debugger {
void OnBreakpointHit(cpu::ThreadState* thread_state, Breakpoint* breakpoint);
public:
Delegate<BreakpointHitEvent> breakpoint_hit;
private:
void OnMessage(std::vector<uint8_t> buffer);
Emulator* emulator_ = nullptr;
uintptr_t listen_socket_ = ~0u;
bool accept_thread_running_ = false;
std::thread accept_thread_;
xe::threading::Fence accept_fence_;
uintptr_t client_socket_ = ~0u;
std::thread receive_thread_;
std::vector<std::unique_ptr<Transport>> transports_;
bool is_attached_ = false;
xe::threading::Fence attach_fence_;
std::wstring functions_path_;
std::unique_ptr<ChunkedMappedMemoryWriter> functions_file_;

View File

@ -1,31 +0,0 @@
include "common.fbs";
namespace xe.debug.proto;
struct Breakpoint {
breakpoint_id:uint;
}
table ListBreakpointsRequest {
}
table ListBreakpointsResponse {
breakpoints:[Breakpoint];
}
table AddBreakpointsRequest {
breakpoints:[Breakpoint];
}
table AddBreakpointsResponse {
}
table UpdateBreakpointsRequest {
breakpoints:[Breakpoint];
}
table UpdateBreakpointsResponse {
}
table RemoveBreakpointsRequest {
breakpoints:[Breakpoint];
}
table RemoveBreakpointsResponse {
}

View File

@ -1,330 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_BREAKPOINTS_XE_DEBUG_PROTO_H_
#define FLATBUFFERS_GENERATED_BREAKPOINTS_XE_DEBUG_PROTO_H_
#include "flatbuffers/flatbuffers.h"
namespace xe {
namespace debug {
namespace proto {
struct XObject;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct Breakpoint;
struct ListBreakpointsRequest;
struct ListBreakpointsResponse;
struct AddBreakpointsRequest;
struct AddBreakpointsResponse;
struct UpdateBreakpointsRequest;
struct UpdateBreakpointsResponse;
struct RemoveBreakpointsRequest;
struct RemoveBreakpointsResponse;
MANUALLY_ALIGNED_STRUCT(4) Breakpoint FLATBUFFERS_FINAL_CLASS {
private:
uint32_t breakpoint_id_;
public:
Breakpoint(uint32_t breakpoint_id)
: breakpoint_id_(flatbuffers::EndianScalar(breakpoint_id)) {}
uint32_t breakpoint_id() const {
return flatbuffers::EndianScalar(breakpoint_id_);
}
};
STRUCT_END(Breakpoint, 4);
struct ListBreakpointsRequest FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct ListBreakpointsRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
ListBreakpointsRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListBreakpointsRequestBuilder& operator=(
const ListBreakpointsRequestBuilder&);
flatbuffers::Offset<ListBreakpointsRequest> Finish() {
auto o =
flatbuffers::Offset<ListBreakpointsRequest>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<ListBreakpointsRequest> CreateListBreakpointsRequest(
flatbuffers::FlatBufferBuilder& _fbb) {
ListBreakpointsRequestBuilder builder_(_fbb);
return builder_.Finish();
}
struct ListBreakpointsResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<const Breakpoint*>* breakpoints() const {
return GetPointer<const flatbuffers::Vector<const Breakpoint*>*>(4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* breakpoints */) &&
verifier.Verify(breakpoints()) && verifier.EndTable();
}
};
struct ListBreakpointsResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_breakpoints(
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints) {
fbb_.AddOffset(4, breakpoints);
}
ListBreakpointsResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListBreakpointsResponseBuilder& operator=(
const ListBreakpointsResponseBuilder&);
flatbuffers::Offset<ListBreakpointsResponse> Finish() {
auto o =
flatbuffers::Offset<ListBreakpointsResponse>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<ListBreakpointsResponse>
CreateListBreakpointsResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints =
0) {
ListBreakpointsResponseBuilder builder_(_fbb);
builder_.add_breakpoints(breakpoints);
return builder_.Finish();
}
struct AddBreakpointsRequest FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<const Breakpoint*>* breakpoints() const {
return GetPointer<const flatbuffers::Vector<const Breakpoint*>*>(4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* breakpoints */) &&
verifier.Verify(breakpoints()) && verifier.EndTable();
}
};
struct AddBreakpointsRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_breakpoints(
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints) {
fbb_.AddOffset(4, breakpoints);
}
AddBreakpointsRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
AddBreakpointsRequestBuilder& operator=(const AddBreakpointsRequestBuilder&);
flatbuffers::Offset<AddBreakpointsRequest> Finish() {
auto o =
flatbuffers::Offset<AddBreakpointsRequest>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<AddBreakpointsRequest> CreateAddBreakpointsRequest(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints =
0) {
AddBreakpointsRequestBuilder builder_(_fbb);
builder_.add_breakpoints(breakpoints);
return builder_.Finish();
}
struct AddBreakpointsResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct AddBreakpointsResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
AddBreakpointsResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
AddBreakpointsResponseBuilder& operator=(
const AddBreakpointsResponseBuilder&);
flatbuffers::Offset<AddBreakpointsResponse> Finish() {
auto o =
flatbuffers::Offset<AddBreakpointsResponse>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<AddBreakpointsResponse> CreateAddBreakpointsResponse(
flatbuffers::FlatBufferBuilder& _fbb) {
AddBreakpointsResponseBuilder builder_(_fbb);
return builder_.Finish();
}
struct UpdateBreakpointsRequest FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<const Breakpoint*>* breakpoints() const {
return GetPointer<const flatbuffers::Vector<const Breakpoint*>*>(4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* breakpoints */) &&
verifier.Verify(breakpoints()) && verifier.EndTable();
}
};
struct UpdateBreakpointsRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_breakpoints(
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints) {
fbb_.AddOffset(4, breakpoints);
}
UpdateBreakpointsRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
UpdateBreakpointsRequestBuilder& operator=(
const UpdateBreakpointsRequestBuilder&);
flatbuffers::Offset<UpdateBreakpointsRequest> Finish() {
auto o =
flatbuffers::Offset<UpdateBreakpointsRequest>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<UpdateBreakpointsRequest>
CreateUpdateBreakpointsRequest(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints =
0) {
UpdateBreakpointsRequestBuilder builder_(_fbb);
builder_.add_breakpoints(breakpoints);
return builder_.Finish();
}
struct UpdateBreakpointsResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct UpdateBreakpointsResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
UpdateBreakpointsResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
UpdateBreakpointsResponseBuilder& operator=(
const UpdateBreakpointsResponseBuilder&);
flatbuffers::Offset<UpdateBreakpointsResponse> Finish() {
auto o = flatbuffers::Offset<UpdateBreakpointsResponse>(
fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<UpdateBreakpointsResponse>
CreateUpdateBreakpointsResponse(flatbuffers::FlatBufferBuilder& _fbb) {
UpdateBreakpointsResponseBuilder builder_(_fbb);
return builder_.Finish();
}
struct RemoveBreakpointsRequest FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<const Breakpoint*>* breakpoints() const {
return GetPointer<const flatbuffers::Vector<const Breakpoint*>*>(4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* breakpoints */) &&
verifier.Verify(breakpoints()) && verifier.EndTable();
}
};
struct RemoveBreakpointsRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_breakpoints(
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints) {
fbb_.AddOffset(4, breakpoints);
}
RemoveBreakpointsRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
RemoveBreakpointsRequestBuilder& operator=(
const RemoveBreakpointsRequestBuilder&);
flatbuffers::Offset<RemoveBreakpointsRequest> Finish() {
auto o =
flatbuffers::Offset<RemoveBreakpointsRequest>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<RemoveBreakpointsRequest>
CreateRemoveBreakpointsRequest(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<const Breakpoint*>> breakpoints =
0) {
RemoveBreakpointsRequestBuilder builder_(_fbb);
builder_.add_breakpoints(breakpoints);
return builder_.Finish();
}
struct RemoveBreakpointsResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct RemoveBreakpointsResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
RemoveBreakpointsResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
RemoveBreakpointsResponseBuilder& operator=(
const RemoveBreakpointsResponseBuilder&);
flatbuffers::Offset<RemoveBreakpointsResponse> Finish() {
auto o = flatbuffers::Offset<RemoveBreakpointsResponse>(
fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<RemoveBreakpointsResponse>
CreateRemoveBreakpointsResponse(flatbuffers::FlatBufferBuilder& _fbb) {
RemoveBreakpointsResponseBuilder builder_(_fbb);
return builder_.Finish();
}
} // namespace proto
} // namespace debug
} // namespace xe
#endif // FLATBUFFERS_GENERATED_BREAKPOINTS_XE_DEBUG_PROTO_H_

View File

@ -1,5 +0,0 @@
namespace xe.debug.proto;
struct XObject {
handle:uint;
}

View File

@ -1,29 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_COMMON_XE_DEBUG_PROTO_H_
#define FLATBUFFERS_GENERATED_COMMON_XE_DEBUG_PROTO_H_
#include "flatbuffers/flatbuffers.h"
namespace xe {
namespace debug {
namespace proto {
struct XObject;
MANUALLY_ALIGNED_STRUCT(4) XObject FLATBUFFERS_FINAL_CLASS {
private:
uint32_t handle_;
public:
XObject(uint32_t handle) : handle_(flatbuffers::EndianScalar(handle)) {}
uint32_t handle() const { return flatbuffers::EndianScalar(handle_); }
};
STRUCT_END(XObject, 4);
} // namespace proto
} // namespace debug
} // namespace xe
#endif // FLATBUFFERS_GENERATED_COMMON_XE_DEBUG_PROTO_H_

View File

@ -1,49 +0,0 @@
include "common.fbs";
namespace xe.debug.proto;
table StopRequest {
}
table StopResponse {
}
table BreakRequest {
}
table BreakResponse {
}
enum ContinueAction:byte {
Continue,
ContinueTo,
}
table ContinueRequest {
action:ContinueAction;
target_address:uint;
}
table ContinueResponse {
}
enum StepAction:byte {
StepIn,
StepOver,
StepOut,
}
table StepRequest {
action:StepAction;
thread_id:uint;
}
table StepResponse {
}
table BreakpointEvent {
thread_id:uint;
breakpoint_id:uint;
}
table AccessViolationEvent {
thread_id:uint;
target_address:uint;
}

View File

@ -1,378 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_CONTROL_XE_DEBUG_PROTO_H_
#define FLATBUFFERS_GENERATED_CONTROL_XE_DEBUG_PROTO_H_
#include "flatbuffers/flatbuffers.h"
namespace xe {
namespace debug {
namespace proto {
struct XObject;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct StopRequest;
struct StopResponse;
struct BreakRequest;
struct BreakResponse;
struct ContinueRequest;
struct ContinueResponse;
struct StepRequest;
struct StepResponse;
struct BreakpointEvent;
struct AccessViolationEvent;
enum ContinueAction {
ContinueAction_Continue = 0,
ContinueAction_ContinueTo = 1
};
inline const char** EnumNamesContinueAction() {
static const char* names[] = {"Continue", "ContinueTo", nullptr};
return names;
}
inline const char* EnumNameContinueAction(ContinueAction e) {
return EnumNamesContinueAction()[e];
}
enum StepAction {
StepAction_StepIn = 0,
StepAction_StepOver = 1,
StepAction_StepOut = 2
};
inline const char** EnumNamesStepAction() {
static const char* names[] = {"StepIn", "StepOver", "StepOut", nullptr};
return names;
}
inline const char* EnumNameStepAction(StepAction e) {
return EnumNamesStepAction()[e];
}
struct StopRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct StopRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
StopRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
StopRequestBuilder& operator=(const StopRequestBuilder&);
flatbuffers::Offset<StopRequest> Finish() {
auto o = flatbuffers::Offset<StopRequest>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<StopRequest> CreateStopRequest(
flatbuffers::FlatBufferBuilder& _fbb) {
StopRequestBuilder builder_(_fbb);
return builder_.Finish();
}
struct StopResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct StopResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
StopResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
StopResponseBuilder& operator=(const StopResponseBuilder&);
flatbuffers::Offset<StopResponse> Finish() {
auto o = flatbuffers::Offset<StopResponse>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<StopResponse> CreateStopResponse(
flatbuffers::FlatBufferBuilder& _fbb) {
StopResponseBuilder builder_(_fbb);
return builder_.Finish();
}
struct BreakRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct BreakRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
BreakRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
BreakRequestBuilder& operator=(const BreakRequestBuilder&);
flatbuffers::Offset<BreakRequest> Finish() {
auto o = flatbuffers::Offset<BreakRequest>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<BreakRequest> CreateBreakRequest(
flatbuffers::FlatBufferBuilder& _fbb) {
BreakRequestBuilder builder_(_fbb);
return builder_.Finish();
}
struct BreakResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct BreakResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
BreakResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
BreakResponseBuilder& operator=(const BreakResponseBuilder&);
flatbuffers::Offset<BreakResponse> Finish() {
auto o = flatbuffers::Offset<BreakResponse>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<BreakResponse> CreateBreakResponse(
flatbuffers::FlatBufferBuilder& _fbb) {
BreakResponseBuilder builder_(_fbb);
return builder_.Finish();
}
struct ContinueRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
ContinueAction action() const {
return static_cast<ContinueAction>(GetField<int8_t>(4, 0));
}
uint32_t target_address() const { return GetField<uint32_t>(6, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int8_t>(verifier, 4 /* action */) &&
VerifyField<uint32_t>(verifier, 6 /* target_address */) &&
verifier.EndTable();
}
};
struct ContinueRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_action(ContinueAction action) {
fbb_.AddElement<int8_t>(4, static_cast<int8_t>(action), 0);
}
void add_target_address(uint32_t target_address) {
fbb_.AddElement<uint32_t>(6, target_address, 0);
}
ContinueRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ContinueRequestBuilder& operator=(const ContinueRequestBuilder&);
flatbuffers::Offset<ContinueRequest> Finish() {
auto o = flatbuffers::Offset<ContinueRequest>(fbb_.EndTable(start_, 2));
return o;
}
};
inline flatbuffers::Offset<ContinueRequest> CreateContinueRequest(
flatbuffers::FlatBufferBuilder& _fbb,
ContinueAction action = ContinueAction_Continue,
uint32_t target_address = 0) {
ContinueRequestBuilder builder_(_fbb);
builder_.add_target_address(target_address);
builder_.add_action(action);
return builder_.Finish();
}
struct ContinueResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct ContinueResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
ContinueResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ContinueResponseBuilder& operator=(const ContinueResponseBuilder&);
flatbuffers::Offset<ContinueResponse> Finish() {
auto o = flatbuffers::Offset<ContinueResponse>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<ContinueResponse> CreateContinueResponse(
flatbuffers::FlatBufferBuilder& _fbb) {
ContinueResponseBuilder builder_(_fbb);
return builder_.Finish();
}
struct StepRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
StepAction action() const {
return static_cast<StepAction>(GetField<int8_t>(4, 0));
}
uint32_t thread_id() const { return GetField<uint32_t>(6, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int8_t>(verifier, 4 /* action */) &&
VerifyField<uint32_t>(verifier, 6 /* thread_id */) &&
verifier.EndTable();
}
};
struct StepRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_action(StepAction action) {
fbb_.AddElement<int8_t>(4, static_cast<int8_t>(action), 0);
}
void add_thread_id(uint32_t thread_id) {
fbb_.AddElement<uint32_t>(6, thread_id, 0);
}
StepRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
StepRequestBuilder& operator=(const StepRequestBuilder&);
flatbuffers::Offset<StepRequest> Finish() {
auto o = flatbuffers::Offset<StepRequest>(fbb_.EndTable(start_, 2));
return o;
}
};
inline flatbuffers::Offset<StepRequest> CreateStepRequest(
flatbuffers::FlatBufferBuilder& _fbb, StepAction action = StepAction_StepIn,
uint32_t thread_id = 0) {
StepRequestBuilder builder_(_fbb);
builder_.add_thread_id(thread_id);
builder_.add_action(action);
return builder_.Finish();
}
struct StepResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct StepResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
StepResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
StepResponseBuilder& operator=(const StepResponseBuilder&);
flatbuffers::Offset<StepResponse> Finish() {
auto o = flatbuffers::Offset<StepResponse>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<StepResponse> CreateStepResponse(
flatbuffers::FlatBufferBuilder& _fbb) {
StepResponseBuilder builder_(_fbb);
return builder_.Finish();
}
struct BreakpointEvent FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint32_t thread_id() const { return GetField<uint32_t>(4, 0); }
uint32_t breakpoint_id() const { return GetField<uint32_t>(6, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, 4 /* thread_id */) &&
VerifyField<uint32_t>(verifier, 6 /* breakpoint_id */) &&
verifier.EndTable();
}
};
struct BreakpointEventBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_thread_id(uint32_t thread_id) {
fbb_.AddElement<uint32_t>(4, thread_id, 0);
}
void add_breakpoint_id(uint32_t breakpoint_id) {
fbb_.AddElement<uint32_t>(6, breakpoint_id, 0);
}
BreakpointEventBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
BreakpointEventBuilder& operator=(const BreakpointEventBuilder&);
flatbuffers::Offset<BreakpointEvent> Finish() {
auto o = flatbuffers::Offset<BreakpointEvent>(fbb_.EndTable(start_, 2));
return o;
}
};
inline flatbuffers::Offset<BreakpointEvent> CreateBreakpointEvent(
flatbuffers::FlatBufferBuilder& _fbb, uint32_t thread_id = 0,
uint32_t breakpoint_id = 0) {
BreakpointEventBuilder builder_(_fbb);
builder_.add_breakpoint_id(breakpoint_id);
builder_.add_thread_id(thread_id);
return builder_.Finish();
}
struct AccessViolationEvent FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
uint32_t thread_id() const { return GetField<uint32_t>(4, 0); }
uint32_t target_address() const { return GetField<uint32_t>(6, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, 4 /* thread_id */) &&
VerifyField<uint32_t>(verifier, 6 /* target_address */) &&
verifier.EndTable();
}
};
struct AccessViolationEventBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_thread_id(uint32_t thread_id) {
fbb_.AddElement<uint32_t>(4, thread_id, 0);
}
void add_target_address(uint32_t target_address) {
fbb_.AddElement<uint32_t>(6, target_address, 0);
}
AccessViolationEventBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
AccessViolationEventBuilder& operator=(const AccessViolationEventBuilder&);
flatbuffers::Offset<AccessViolationEvent> Finish() {
auto o =
flatbuffers::Offset<AccessViolationEvent>(fbb_.EndTable(start_, 2));
return o;
}
};
inline flatbuffers::Offset<AccessViolationEvent> CreateAccessViolationEvent(
flatbuffers::FlatBufferBuilder& _fbb, uint32_t thread_id = 0,
uint32_t target_address = 0) {
AccessViolationEventBuilder builder_(_fbb);
builder_.add_target_address(target_address);
builder_.add_thread_id(thread_id);
return builder_.Finish();
}
} // namespace proto
} // namespace debug
} // namespace xe
#endif // FLATBUFFERS_GENERATED_CONTROL_XE_DEBUG_PROTO_H_

View File

@ -1,74 +0,0 @@
include "breakpoints.fbs";
include "common.fbs";
include "control.fbs";
include "modules.fbs";
include "threads.fbs";
namespace xe.debug.proto;
table AttachRequest {
//
}
table AttachResponse {
memory_file:string;
code_cache_file:string;
code_cache_base:uint;
code_cache_size:uint;
functions_file:string;
functions_trace_file:string;
}
union RequestData {
AttachRequest,
ListBreakpointsRequest,
AddBreakpointsRequest,
UpdateBreakpointsRequest,
RemoveBreakpointsRequest,
ListModulesRequest,
GetModuleRequest,
ListFunctionsRequest,
GetFunctionRequest,
ListThreadsRequest,
StopRequest,
BreakRequest,
ContinueRequest,
StepRequest,
}
table Request {
id:uint;
request_data:RequestData;
}
union ResponseData {
AttachResponse,
ListBreakpointsResponse,
AddBreakpointsResponse,
UpdateBreakpointsResponse,
RemoveBreakpointsResponse,
ListModulesResponse,
GetModuleResponse,
ListFunctionsResponse,
GetFunctionResponse,
ListThreadsResponse,
StopResponse,
BreakResponse,
ContinueResponse,
StepResponse,
BreakpointEvent,
AccessViolationEvent,
}
table Response {
id:uint;
response_data:ResponseData;
}

View File

@ -1,519 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_MESSAGES_XE_DEBUG_PROTO_H_
#define FLATBUFFERS_GENERATED_MESSAGES_XE_DEBUG_PROTO_H_
#include "flatbuffers/flatbuffers.h"
namespace xe {
namespace debug {
namespace proto {
struct XObject;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct Breakpoint;
struct ListBreakpointsRequest;
struct ListBreakpointsResponse;
struct AddBreakpointsRequest;
struct AddBreakpointsResponse;
struct UpdateBreakpointsRequest;
struct UpdateBreakpointsResponse;
struct RemoveBreakpointsRequest;
struct RemoveBreakpointsResponse;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct StopRequest;
struct StopResponse;
struct BreakRequest;
struct BreakResponse;
struct ContinueRequest;
struct ContinueResponse;
struct StepRequest;
struct StepResponse;
struct BreakpointEvent;
struct AccessViolationEvent;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct Module;
struct ListModulesRequest;
struct ListModuleEntry;
struct ListModulesResponse;
struct GetModuleRequest;
struct GetModuleResponse;
struct FunctionEntry;
struct Function;
struct ListFunctionsRequest;
struct ListFunctionsResponse;
struct GetFunctionRequest;
struct GetFunctionResponse;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct Thread;
struct ListThreadsRequest;
struct ListThreadsResponse;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct AttachRequest;
struct AttachResponse;
struct Request;
struct Response;
enum RequestData {
RequestData_NONE = 0,
RequestData_AttachRequest = 1,
RequestData_ListBreakpointsRequest = 2,
RequestData_AddBreakpointsRequest = 3,
RequestData_UpdateBreakpointsRequest = 4,
RequestData_RemoveBreakpointsRequest = 5,
RequestData_ListModulesRequest = 6,
RequestData_GetModuleRequest = 7,
RequestData_ListFunctionsRequest = 8,
RequestData_GetFunctionRequest = 9,
RequestData_ListThreadsRequest = 10,
RequestData_StopRequest = 11,
RequestData_BreakRequest = 12,
RequestData_ContinueRequest = 13,
RequestData_StepRequest = 14
};
inline const char** EnumNamesRequestData() {
static const char* names[] = {"NONE",
"AttachRequest",
"ListBreakpointsRequest",
"AddBreakpointsRequest",
"UpdateBreakpointsRequest",
"RemoveBreakpointsRequest",
"ListModulesRequest",
"GetModuleRequest",
"ListFunctionsRequest",
"GetFunctionRequest",
"ListThreadsRequest",
"StopRequest",
"BreakRequest",
"ContinueRequest",
"StepRequest",
nullptr};
return names;
}
inline const char* EnumNameRequestData(RequestData e) {
return EnumNamesRequestData()[e];
}
inline bool VerifyRequestData(flatbuffers::Verifier& verifier,
const void* union_obj, RequestData type);
enum ResponseData {
ResponseData_NONE = 0,
ResponseData_AttachResponse = 1,
ResponseData_ListBreakpointsResponse = 2,
ResponseData_AddBreakpointsResponse = 3,
ResponseData_UpdateBreakpointsResponse = 4,
ResponseData_RemoveBreakpointsResponse = 5,
ResponseData_ListModulesResponse = 6,
ResponseData_GetModuleResponse = 7,
ResponseData_ListFunctionsResponse = 8,
ResponseData_GetFunctionResponse = 9,
ResponseData_ListThreadsResponse = 10,
ResponseData_StopResponse = 11,
ResponseData_BreakResponse = 12,
ResponseData_ContinueResponse = 13,
ResponseData_StepResponse = 14,
ResponseData_BreakpointEvent = 15,
ResponseData_AccessViolationEvent = 16
};
inline const char** EnumNamesResponseData() {
static const char* names[] = {"NONE",
"AttachResponse",
"ListBreakpointsResponse",
"AddBreakpointsResponse",
"UpdateBreakpointsResponse",
"RemoveBreakpointsResponse",
"ListModulesResponse",
"GetModuleResponse",
"ListFunctionsResponse",
"GetFunctionResponse",
"ListThreadsResponse",
"StopResponse",
"BreakResponse",
"ContinueResponse",
"StepResponse",
"BreakpointEvent",
"AccessViolationEvent",
nullptr};
return names;
}
inline const char* EnumNameResponseData(ResponseData e) {
return EnumNamesResponseData()[e];
}
inline bool VerifyResponseData(flatbuffers::Verifier& verifier,
const void* union_obj, ResponseData type);
struct AttachRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct AttachRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
AttachRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
AttachRequestBuilder& operator=(const AttachRequestBuilder&);
flatbuffers::Offset<AttachRequest> Finish() {
auto o = flatbuffers::Offset<AttachRequest>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<AttachRequest> CreateAttachRequest(
flatbuffers::FlatBufferBuilder& _fbb) {
AttachRequestBuilder builder_(_fbb);
return builder_.Finish();
}
struct AttachResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String* memory_file() const {
return GetPointer<const flatbuffers::String*>(4);
}
const flatbuffers::String* code_cache_file() const {
return GetPointer<const flatbuffers::String*>(6);
}
uint32_t code_cache_base() const { return GetField<uint32_t>(8, 0); }
uint32_t code_cache_size() const { return GetField<uint32_t>(10, 0); }
const flatbuffers::String* functions_file() const {
return GetPointer<const flatbuffers::String*>(12);
}
const flatbuffers::String* functions_trace_file() const {
return GetPointer<const flatbuffers::String*>(14);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* memory_file */) &&
verifier.Verify(memory_file()) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
6 /* code_cache_file */) &&
verifier.Verify(code_cache_file()) &&
VerifyField<uint32_t>(verifier, 8 /* code_cache_base */) &&
VerifyField<uint32_t>(verifier, 10 /* code_cache_size */) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
12 /* functions_file */) &&
verifier.Verify(functions_file()) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
14 /* functions_trace_file */) &&
verifier.Verify(functions_trace_file()) && verifier.EndTable();
}
};
struct AttachResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_memory_file(flatbuffers::Offset<flatbuffers::String> memory_file) {
fbb_.AddOffset(4, memory_file);
}
void add_code_cache_file(
flatbuffers::Offset<flatbuffers::String> code_cache_file) {
fbb_.AddOffset(6, code_cache_file);
}
void add_code_cache_base(uint32_t code_cache_base) {
fbb_.AddElement<uint32_t>(8, code_cache_base, 0);
}
void add_code_cache_size(uint32_t code_cache_size) {
fbb_.AddElement<uint32_t>(10, code_cache_size, 0);
}
void add_functions_file(
flatbuffers::Offset<flatbuffers::String> functions_file) {
fbb_.AddOffset(12, functions_file);
}
void add_functions_trace_file(
flatbuffers::Offset<flatbuffers::String> functions_trace_file) {
fbb_.AddOffset(14, functions_trace_file);
}
AttachResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
AttachResponseBuilder& operator=(const AttachResponseBuilder&);
flatbuffers::Offset<AttachResponse> Finish() {
auto o = flatbuffers::Offset<AttachResponse>(fbb_.EndTable(start_, 6));
return o;
}
};
inline flatbuffers::Offset<AttachResponse> CreateAttachResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::String> memory_file = 0,
flatbuffers::Offset<flatbuffers::String> code_cache_file = 0,
uint32_t code_cache_base = 0, uint32_t code_cache_size = 0,
flatbuffers::Offset<flatbuffers::String> functions_file = 0,
flatbuffers::Offset<flatbuffers::String> functions_trace_file = 0) {
AttachResponseBuilder builder_(_fbb);
builder_.add_functions_trace_file(functions_trace_file);
builder_.add_functions_file(functions_file);
builder_.add_code_cache_size(code_cache_size);
builder_.add_code_cache_base(code_cache_base);
builder_.add_code_cache_file(code_cache_file);
builder_.add_memory_file(memory_file);
return builder_.Finish();
}
struct Request FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint32_t id() const { return GetField<uint32_t>(4, 0); }
RequestData request_data_type() const {
return static_cast<RequestData>(GetField<uint8_t>(6, 0));
}
const void* request_data() const { return GetPointer<const void*>(8); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, 4 /* id */) &&
VerifyField<uint8_t>(verifier, 6 /* request_data_type */) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
8 /* request_data */) &&
VerifyRequestData(verifier, request_data(), request_data_type()) &&
verifier.EndTable();
}
};
struct RequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_id(uint32_t id) { fbb_.AddElement<uint32_t>(4, id, 0); }
void add_request_data_type(RequestData request_data_type) {
fbb_.AddElement<uint8_t>(6, static_cast<uint8_t>(request_data_type), 0);
}
void add_request_data(flatbuffers::Offset<void> request_data) {
fbb_.AddOffset(8, request_data);
}
RequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
RequestBuilder& operator=(const RequestBuilder&);
flatbuffers::Offset<Request> Finish() {
auto o = flatbuffers::Offset<Request>(fbb_.EndTable(start_, 3));
return o;
}
};
inline flatbuffers::Offset<Request> CreateRequest(
flatbuffers::FlatBufferBuilder& _fbb, uint32_t id = 0,
RequestData request_data_type = RequestData_NONE,
flatbuffers::Offset<void> request_data = 0) {
RequestBuilder builder_(_fbb);
builder_.add_request_data(request_data);
builder_.add_id(id);
builder_.add_request_data_type(request_data_type);
return builder_.Finish();
}
struct Response FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint32_t id() const { return GetField<uint32_t>(4, 0); }
ResponseData response_data_type() const {
return static_cast<ResponseData>(GetField<uint8_t>(6, 0));
}
const void* response_data() const { return GetPointer<const void*>(8); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, 4 /* id */) &&
VerifyField<uint8_t>(verifier, 6 /* response_data_type */) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
8 /* response_data */) &&
VerifyResponseData(verifier, response_data(),
response_data_type()) &&
verifier.EndTable();
}
};
struct ResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_id(uint32_t id) { fbb_.AddElement<uint32_t>(4, id, 0); }
void add_response_data_type(ResponseData response_data_type) {
fbb_.AddElement<uint8_t>(6, static_cast<uint8_t>(response_data_type), 0);
}
void add_response_data(flatbuffers::Offset<void> response_data) {
fbb_.AddOffset(8, response_data);
}
ResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ResponseBuilder& operator=(const ResponseBuilder&);
flatbuffers::Offset<Response> Finish() {
auto o = flatbuffers::Offset<Response>(fbb_.EndTable(start_, 3));
return o;
}
};
inline flatbuffers::Offset<Response> CreateResponse(
flatbuffers::FlatBufferBuilder& _fbb, uint32_t id = 0,
ResponseData response_data_type = ResponseData_NONE,
flatbuffers::Offset<void> response_data = 0) {
ResponseBuilder builder_(_fbb);
builder_.add_response_data(response_data);
builder_.add_id(id);
builder_.add_response_data_type(response_data_type);
return builder_.Finish();
}
inline bool VerifyRequestData(flatbuffers::Verifier& verifier,
const void* union_obj, RequestData type) {
switch (type) {
case RequestData_NONE:
return true;
case RequestData_AttachRequest:
return verifier.VerifyTable(
reinterpret_cast<const AttachRequest*>(union_obj));
case RequestData_ListBreakpointsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListBreakpointsRequest*>(
union_obj));
case RequestData_AddBreakpointsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::AddBreakpointsRequest*>(
union_obj));
case RequestData_UpdateBreakpointsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::UpdateBreakpointsRequest*>(
union_obj));
case RequestData_RemoveBreakpointsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::RemoveBreakpointsRequest*>(
union_obj));
case RequestData_ListModulesRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListModulesRequest*>(
union_obj));
case RequestData_GetModuleRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::GetModuleRequest*>(
union_obj));
case RequestData_ListFunctionsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListFunctionsRequest*>(
union_obj));
case RequestData_GetFunctionRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::GetFunctionRequest*>(
union_obj));
case RequestData_ListThreadsRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListThreadsRequest*>(
union_obj));
case RequestData_StopRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::StopRequest*>(union_obj));
case RequestData_BreakRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::BreakRequest*>(union_obj));
case RequestData_ContinueRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ContinueRequest*>(
union_obj));
case RequestData_StepRequest:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::StepRequest*>(union_obj));
default:
return false;
}
}
inline bool VerifyResponseData(flatbuffers::Verifier& verifier,
const void* union_obj, ResponseData type) {
switch (type) {
case ResponseData_NONE:
return true;
case ResponseData_AttachResponse:
return verifier.VerifyTable(
reinterpret_cast<const AttachResponse*>(union_obj));
case ResponseData_ListBreakpointsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListBreakpointsResponse*>(
union_obj));
case ResponseData_AddBreakpointsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::AddBreakpointsResponse*>(
union_obj));
case ResponseData_UpdateBreakpointsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::UpdateBreakpointsResponse*>(
union_obj));
case ResponseData_RemoveBreakpointsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::RemoveBreakpointsResponse*>(
union_obj));
case ResponseData_ListModulesResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListModulesResponse*>(
union_obj));
case ResponseData_GetModuleResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::GetModuleResponse*>(
union_obj));
case ResponseData_ListFunctionsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListFunctionsResponse*>(
union_obj));
case ResponseData_GetFunctionResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::GetFunctionResponse*>(
union_obj));
case ResponseData_ListThreadsResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ListThreadsResponse*>(
union_obj));
case ResponseData_StopResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::StopResponse*>(union_obj));
case ResponseData_BreakResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::BreakResponse*>(union_obj));
case ResponseData_ContinueResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::ContinueResponse*>(
union_obj));
case ResponseData_StepResponse:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::StepResponse*>(union_obj));
case ResponseData_BreakpointEvent:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::BreakpointEvent*>(
union_obj));
case ResponseData_AccessViolationEvent:
return verifier.VerifyTable(
reinterpret_cast<const xe::debug::proto::AccessViolationEvent*>(
union_obj));
default:
return false;
}
}
} // namespace proto
} // namespace debug
} // namespace xe
#endif // FLATBUFFERS_GENERATED_MESSAGES_XE_DEBUG_PROTO_H_

View File

@ -1,69 +0,0 @@
include "common.fbs";
namespace xe.debug.proto;
enum ModuleType:byte {
Kernel = 0,
User = 1,
}
table Module {
object:XObject;
type:ModuleType;
name:string;
path:string;
// TODO(benvanik): xex info/etc?
}
table ListModulesRequest {
}
struct ListModuleEntry {
handle:uint;
function_count:uint;
}
table ListModulesResponse {
entry:[ListModuleEntry];
}
table GetModuleRequest {
module_id:uint;
}
table GetModuleResponse {
module:Module;
}
table FunctionEntry {
identifier:ulong;
address_start:uint;
address_end:uint;
name:string;
}
table Function {
identifier:ulong;
address_start:uint;
address_end:uint;
name:string;
machine_code_start:uint;
machine_code_end:uint;
disasm_hir_raw:string;
disasm_hir_opt:string;
}
table ListFunctionsRequest {
module_id:uint;
function_index_start:uint;
function_index_end:uint;
}
table ListFunctionsResponse {
entry:[FunctionEntry];
}
table GetFunctionRequest {
identifier:ulong;
}
table GetFunctionResponse {
function:Function;
}

View File

@ -1,560 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_MODULES_XE_DEBUG_PROTO_H_
#define FLATBUFFERS_GENERATED_MODULES_XE_DEBUG_PROTO_H_
#include "flatbuffers/flatbuffers.h"
namespace xe {
namespace debug {
namespace proto {
struct XObject;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct Module;
struct ListModulesRequest;
struct ListModuleEntry;
struct ListModulesResponse;
struct GetModuleRequest;
struct GetModuleResponse;
struct FunctionEntry;
struct Function;
struct ListFunctionsRequest;
struct ListFunctionsResponse;
struct GetFunctionRequest;
struct GetFunctionResponse;
enum ModuleType { ModuleType_Kernel = 0, ModuleType_User = 1 };
inline const char** EnumNamesModuleType() {
static const char* names[] = {"Kernel", "User", nullptr};
return names;
}
inline const char* EnumNameModuleType(ModuleType e) {
return EnumNamesModuleType()[e];
}
MANUALLY_ALIGNED_STRUCT(4) ListModuleEntry FLATBUFFERS_FINAL_CLASS {
private:
uint32_t handle_;
uint32_t function_count_;
public:
ListModuleEntry(uint32_t handle, uint32_t function_count)
: handle_(flatbuffers::EndianScalar(handle)),
function_count_(flatbuffers::EndianScalar(function_count)) {}
uint32_t handle() const { return flatbuffers::EndianScalar(handle_); }
uint32_t function_count() const {
return flatbuffers::EndianScalar(function_count_);
}
};
STRUCT_END(ListModuleEntry, 8);
struct Module FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const xe::debug::proto::XObject* object() const {
return GetStruct<const xe::debug::proto::XObject*>(4);
}
ModuleType type() const {
return static_cast<ModuleType>(GetField<int8_t>(6, 0));
}
const flatbuffers::String* name() const {
return GetPointer<const flatbuffers::String*>(8);
}
const flatbuffers::String* path() const {
return GetPointer<const flatbuffers::String*>(10);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<xe::debug::proto::XObject>(verifier, 4 /* object */) &&
VerifyField<int8_t>(verifier, 6 /* type */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 8 /* name */) &&
verifier.Verify(name()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 10 /* path */) &&
verifier.Verify(path()) && verifier.EndTable();
}
};
struct ModuleBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_object(const xe::debug::proto::XObject* object) {
fbb_.AddStruct(4, object);
}
void add_type(ModuleType type) {
fbb_.AddElement<int8_t>(6, static_cast<int8_t>(type), 0);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(8, name);
}
void add_path(flatbuffers::Offset<flatbuffers::String> path) {
fbb_.AddOffset(10, path);
}
ModuleBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ModuleBuilder& operator=(const ModuleBuilder&);
flatbuffers::Offset<Module> Finish() {
auto o = flatbuffers::Offset<Module>(fbb_.EndTable(start_, 4));
return o;
}
};
inline flatbuffers::Offset<Module> CreateModule(
flatbuffers::FlatBufferBuilder& _fbb,
const xe::debug::proto::XObject* object = 0,
ModuleType type = ModuleType_Kernel,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::String> path = 0) {
ModuleBuilder builder_(_fbb);
builder_.add_path(path);
builder_.add_name(name);
builder_.add_object(object);
builder_.add_type(type);
return builder_.Finish();
}
struct ListModulesRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct ListModulesRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
ListModulesRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListModulesRequestBuilder& operator=(const ListModulesRequestBuilder&);
flatbuffers::Offset<ListModulesRequest> Finish() {
auto o = flatbuffers::Offset<ListModulesRequest>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<ListModulesRequest> CreateListModulesRequest(
flatbuffers::FlatBufferBuilder& _fbb) {
ListModulesRequestBuilder builder_(_fbb);
return builder_.Finish();
}
struct ListModulesResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<const ListModuleEntry*>* entry() const {
return GetPointer<const flatbuffers::Vector<const ListModuleEntry*>*>(4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* entry */) &&
verifier.Verify(entry()) && verifier.EndTable();
}
};
struct ListModulesResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_entry(
flatbuffers::Offset<flatbuffers::Vector<const ListModuleEntry*>> entry) {
fbb_.AddOffset(4, entry);
}
ListModulesResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListModulesResponseBuilder& operator=(const ListModulesResponseBuilder&);
flatbuffers::Offset<ListModulesResponse> Finish() {
auto o = flatbuffers::Offset<ListModulesResponse>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<ListModulesResponse> CreateListModulesResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<const ListModuleEntry*>> entry =
0) {
ListModulesResponseBuilder builder_(_fbb);
builder_.add_entry(entry);
return builder_.Finish();
}
struct GetModuleRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint32_t module_id() const { return GetField<uint32_t>(4, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, 4 /* module_id */) &&
verifier.EndTable();
}
};
struct GetModuleRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_module_id(uint32_t module_id) {
fbb_.AddElement<uint32_t>(4, module_id, 0);
}
GetModuleRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
GetModuleRequestBuilder& operator=(const GetModuleRequestBuilder&);
flatbuffers::Offset<GetModuleRequest> Finish() {
auto o = flatbuffers::Offset<GetModuleRequest>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<GetModuleRequest> CreateGetModuleRequest(
flatbuffers::FlatBufferBuilder& _fbb, uint32_t module_id = 0) {
GetModuleRequestBuilder builder_(_fbb);
builder_.add_module_id(module_id);
return builder_.Finish();
}
struct GetModuleResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const Module* module() const { return GetPointer<const Module*>(4); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* module */) &&
verifier.VerifyTable(module()) && verifier.EndTable();
}
};
struct GetModuleResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_module(flatbuffers::Offset<Module> module) {
fbb_.AddOffset(4, module);
}
GetModuleResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
GetModuleResponseBuilder& operator=(const GetModuleResponseBuilder&);
flatbuffers::Offset<GetModuleResponse> Finish() {
auto o = flatbuffers::Offset<GetModuleResponse>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<GetModuleResponse> CreateGetModuleResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<Module> module = 0) {
GetModuleResponseBuilder builder_(_fbb);
builder_.add_module(module);
return builder_.Finish();
}
struct FunctionEntry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint64_t identifier() const { return GetField<uint64_t>(4, 0); }
uint32_t address_start() const { return GetField<uint32_t>(6, 0); }
uint32_t address_end() const { return GetField<uint32_t>(8, 0); }
const flatbuffers::String* name() const {
return GetPointer<const flatbuffers::String*>(10);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(verifier, 4 /* identifier */) &&
VerifyField<uint32_t>(verifier, 6 /* address_start */) &&
VerifyField<uint32_t>(verifier, 8 /* address_end */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 10 /* name */) &&
verifier.Verify(name()) && verifier.EndTable();
}
};
struct FunctionEntryBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_identifier(uint64_t identifier) {
fbb_.AddElement<uint64_t>(4, identifier, 0);
}
void add_address_start(uint32_t address_start) {
fbb_.AddElement<uint32_t>(6, address_start, 0);
}
void add_address_end(uint32_t address_end) {
fbb_.AddElement<uint32_t>(8, address_end, 0);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(10, name);
}
FunctionEntryBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
FunctionEntryBuilder& operator=(const FunctionEntryBuilder&);
flatbuffers::Offset<FunctionEntry> Finish() {
auto o = flatbuffers::Offset<FunctionEntry>(fbb_.EndTable(start_, 4));
return o;
}
};
inline flatbuffers::Offset<FunctionEntry> CreateFunctionEntry(
flatbuffers::FlatBufferBuilder& _fbb, uint64_t identifier = 0,
uint32_t address_start = 0, uint32_t address_end = 0,
flatbuffers::Offset<flatbuffers::String> name = 0) {
FunctionEntryBuilder builder_(_fbb);
builder_.add_identifier(identifier);
builder_.add_name(name);
builder_.add_address_end(address_end);
builder_.add_address_start(address_start);
return builder_.Finish();
}
struct Function FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint64_t identifier() const { return GetField<uint64_t>(4, 0); }
uint32_t address_start() const { return GetField<uint32_t>(6, 0); }
uint32_t address_end() const { return GetField<uint32_t>(8, 0); }
const flatbuffers::String* name() const {
return GetPointer<const flatbuffers::String*>(10);
}
uint32_t machine_code_start() const { return GetField<uint32_t>(12, 0); }
uint32_t machine_code_end() const { return GetField<uint32_t>(14, 0); }
const flatbuffers::String* disasm_hir_raw() const {
return GetPointer<const flatbuffers::String*>(16);
}
const flatbuffers::String* disasm_hir_opt() const {
return GetPointer<const flatbuffers::String*>(18);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(verifier, 4 /* identifier */) &&
VerifyField<uint32_t>(verifier, 6 /* address_start */) &&
VerifyField<uint32_t>(verifier, 8 /* address_end */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 10 /* name */) &&
verifier.Verify(name()) &&
VerifyField<uint32_t>(verifier, 12 /* machine_code_start */) &&
VerifyField<uint32_t>(verifier, 14 /* machine_code_end */) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
16 /* disasm_hir_raw */) &&
verifier.Verify(disasm_hir_raw()) &&
VerifyField<flatbuffers::uoffset_t>(verifier,
18 /* disasm_hir_opt */) &&
verifier.Verify(disasm_hir_opt()) && verifier.EndTable();
}
};
struct FunctionBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_identifier(uint64_t identifier) {
fbb_.AddElement<uint64_t>(4, identifier, 0);
}
void add_address_start(uint32_t address_start) {
fbb_.AddElement<uint32_t>(6, address_start, 0);
}
void add_address_end(uint32_t address_end) {
fbb_.AddElement<uint32_t>(8, address_end, 0);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(10, name);
}
void add_machine_code_start(uint32_t machine_code_start) {
fbb_.AddElement<uint32_t>(12, machine_code_start, 0);
}
void add_machine_code_end(uint32_t machine_code_end) {
fbb_.AddElement<uint32_t>(14, machine_code_end, 0);
}
void add_disasm_hir_raw(
flatbuffers::Offset<flatbuffers::String> disasm_hir_raw) {
fbb_.AddOffset(16, disasm_hir_raw);
}
void add_disasm_hir_opt(
flatbuffers::Offset<flatbuffers::String> disasm_hir_opt) {
fbb_.AddOffset(18, disasm_hir_opt);
}
FunctionBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
FunctionBuilder& operator=(const FunctionBuilder&);
flatbuffers::Offset<Function> Finish() {
auto o = flatbuffers::Offset<Function>(fbb_.EndTable(start_, 8));
return o;
}
};
inline flatbuffers::Offset<Function> CreateFunction(
flatbuffers::FlatBufferBuilder& _fbb, uint64_t identifier = 0,
uint32_t address_start = 0, uint32_t address_end = 0,
flatbuffers::Offset<flatbuffers::String> name = 0,
uint32_t machine_code_start = 0, uint32_t machine_code_end = 0,
flatbuffers::Offset<flatbuffers::String> disasm_hir_raw = 0,
flatbuffers::Offset<flatbuffers::String> disasm_hir_opt = 0) {
FunctionBuilder builder_(_fbb);
builder_.add_identifier(identifier);
builder_.add_disasm_hir_opt(disasm_hir_opt);
builder_.add_disasm_hir_raw(disasm_hir_raw);
builder_.add_machine_code_end(machine_code_end);
builder_.add_machine_code_start(machine_code_start);
builder_.add_name(name);
builder_.add_address_end(address_end);
builder_.add_address_start(address_start);
return builder_.Finish();
}
struct ListFunctionsRequest FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
uint32_t module_id() const { return GetField<uint32_t>(4, 0); }
uint32_t function_index_start() const { return GetField<uint32_t>(6, 0); }
uint32_t function_index_end() const { return GetField<uint32_t>(8, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, 4 /* module_id */) &&
VerifyField<uint32_t>(verifier, 6 /* function_index_start */) &&
VerifyField<uint32_t>(verifier, 8 /* function_index_end */) &&
verifier.EndTable();
}
};
struct ListFunctionsRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_module_id(uint32_t module_id) {
fbb_.AddElement<uint32_t>(4, module_id, 0);
}
void add_function_index_start(uint32_t function_index_start) {
fbb_.AddElement<uint32_t>(6, function_index_start, 0);
}
void add_function_index_end(uint32_t function_index_end) {
fbb_.AddElement<uint32_t>(8, function_index_end, 0);
}
ListFunctionsRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListFunctionsRequestBuilder& operator=(const ListFunctionsRequestBuilder&);
flatbuffers::Offset<ListFunctionsRequest> Finish() {
auto o =
flatbuffers::Offset<ListFunctionsRequest>(fbb_.EndTable(start_, 3));
return o;
}
};
inline flatbuffers::Offset<ListFunctionsRequest> CreateListFunctionsRequest(
flatbuffers::FlatBufferBuilder& _fbb, uint32_t module_id = 0,
uint32_t function_index_start = 0, uint32_t function_index_end = 0) {
ListFunctionsRequestBuilder builder_(_fbb);
builder_.add_function_index_end(function_index_end);
builder_.add_function_index_start(function_index_start);
builder_.add_module_id(module_id);
return builder_.Finish();
}
struct ListFunctionsResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<FunctionEntry>>* entry() const {
return GetPointer<
const flatbuffers::Vector<flatbuffers::Offset<FunctionEntry>>*>(4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* entry */) &&
verifier.Verify(entry()) && verifier.VerifyVectorOfTables(entry()) &&
verifier.EndTable();
}
};
struct ListFunctionsResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_entry(
flatbuffers::Offset<
flatbuffers::Vector<flatbuffers::Offset<FunctionEntry>>> entry) {
fbb_.AddOffset(4, entry);
}
ListFunctionsResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListFunctionsResponseBuilder& operator=(const ListFunctionsResponseBuilder&);
flatbuffers::Offset<ListFunctionsResponse> Finish() {
auto o =
flatbuffers::Offset<ListFunctionsResponse>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<ListFunctionsResponse> CreateListFunctionsResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FunctionEntry>>>
entry = 0) {
ListFunctionsResponseBuilder builder_(_fbb);
builder_.add_entry(entry);
return builder_.Finish();
}
struct GetFunctionRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint64_t identifier() const { return GetField<uint64_t>(4, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(verifier, 4 /* identifier */) &&
verifier.EndTable();
}
};
struct GetFunctionRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_identifier(uint64_t identifier) {
fbb_.AddElement<uint64_t>(4, identifier, 0);
}
GetFunctionRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
GetFunctionRequestBuilder& operator=(const GetFunctionRequestBuilder&);
flatbuffers::Offset<GetFunctionRequest> Finish() {
auto o = flatbuffers::Offset<GetFunctionRequest>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<GetFunctionRequest> CreateGetFunctionRequest(
flatbuffers::FlatBufferBuilder& _fbb, uint64_t identifier = 0) {
GetFunctionRequestBuilder builder_(_fbb);
builder_.add_identifier(identifier);
return builder_.Finish();
}
struct GetFunctionResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const Function* function() const { return GetPointer<const Function*>(4); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* function */) &&
verifier.VerifyTable(function()) && verifier.EndTable();
}
};
struct GetFunctionResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_function(flatbuffers::Offset<Function> function) {
fbb_.AddOffset(4, function);
}
GetFunctionResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
GetFunctionResponseBuilder& operator=(const GetFunctionResponseBuilder&);
flatbuffers::Offset<GetFunctionResponse> Finish() {
auto o = flatbuffers::Offset<GetFunctionResponse>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<GetFunctionResponse> CreateGetFunctionResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<Function> function = 0) {
GetFunctionResponseBuilder builder_(_fbb);
builder_.add_function(function);
return builder_.Finish();
}
} // namespace proto
} // namespace debug
} // namespace xe
#endif // FLATBUFFERS_GENERATED_MODULES_XE_DEBUG_PROTO_H_

View File

@ -1,38 +0,0 @@
include "common.fbs";
namespace xe.debug.proto;
enum ThreadType:byte {
Kernel,
User,
}
table Thread {
object:XObject;
type:ThreadType;
// module_id:uint;
// creation callstack
stack_size:uint;
xapi_thread_startup:uint;
start_address:uint;
start_context:uint;
creation_flags:uint;
tls_address:uint;
pcr_address:uint;
thread_state_address:uint;
thread_id:uint;
name:string;
priority:uint;
affinity:uint;
state:uint;
}
table ListThreadsRequest {
}
table ListThreadsResponse {
thread:[Thread];
}

View File

@ -1,234 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_THREADS_XE_DEBUG_PROTO_H_
#define FLATBUFFERS_GENERATED_THREADS_XE_DEBUG_PROTO_H_
#include "flatbuffers/flatbuffers.h"
namespace xe {
namespace debug {
namespace proto {
struct XObject;
} // namespace proto
} // namespace debug
} // namespace xe
namespace xe {
namespace debug {
namespace proto {
struct Thread;
struct ListThreadsRequest;
struct ListThreadsResponse;
enum ThreadType { ThreadType_Kernel = 0, ThreadType_User = 1 };
inline const char** EnumNamesThreadType() {
static const char* names[] = {"Kernel", "User", nullptr};
return names;
}
inline const char* EnumNameThreadType(ThreadType e) {
return EnumNamesThreadType()[e];
}
struct Thread FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const xe::debug::proto::XObject* object() const {
return GetStruct<const xe::debug::proto::XObject*>(4);
}
ThreadType type() const {
return static_cast<ThreadType>(GetField<int8_t>(6, 0));
}
uint32_t stack_size() const { return GetField<uint32_t>(8, 0); }
uint32_t xapi_thread_startup() const { return GetField<uint32_t>(10, 0); }
uint32_t start_address() const { return GetField<uint32_t>(12, 0); }
uint32_t start_context() const { return GetField<uint32_t>(14, 0); }
uint32_t creation_flags() const { return GetField<uint32_t>(16, 0); }
uint32_t tls_address() const { return GetField<uint32_t>(18, 0); }
uint32_t pcr_address() const { return GetField<uint32_t>(20, 0); }
uint32_t thread_state_address() const { return GetField<uint32_t>(22, 0); }
uint32_t thread_id() const { return GetField<uint32_t>(24, 0); }
const flatbuffers::String* name() const {
return GetPointer<const flatbuffers::String*>(26);
}
uint32_t priority() const { return GetField<uint32_t>(28, 0); }
uint32_t affinity() const { return GetField<uint32_t>(30, 0); }
uint32_t state() const { return GetField<uint32_t>(32, 0); }
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<xe::debug::proto::XObject>(verifier, 4 /* object */) &&
VerifyField<int8_t>(verifier, 6 /* type */) &&
VerifyField<uint32_t>(verifier, 8 /* stack_size */) &&
VerifyField<uint32_t>(verifier, 10 /* xapi_thread_startup */) &&
VerifyField<uint32_t>(verifier, 12 /* start_address */) &&
VerifyField<uint32_t>(verifier, 14 /* start_context */) &&
VerifyField<uint32_t>(verifier, 16 /* creation_flags */) &&
VerifyField<uint32_t>(verifier, 18 /* tls_address */) &&
VerifyField<uint32_t>(verifier, 20 /* pcr_address */) &&
VerifyField<uint32_t>(verifier, 22 /* thread_state_address */) &&
VerifyField<uint32_t>(verifier, 24 /* thread_id */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 26 /* name */) &&
verifier.Verify(name()) &&
VerifyField<uint32_t>(verifier, 28 /* priority */) &&
VerifyField<uint32_t>(verifier, 30 /* affinity */) &&
VerifyField<uint32_t>(verifier, 32 /* state */) &&
verifier.EndTable();
}
};
struct ThreadBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_object(const xe::debug::proto::XObject* object) {
fbb_.AddStruct(4, object);
}
void add_type(ThreadType type) {
fbb_.AddElement<int8_t>(6, static_cast<int8_t>(type), 0);
}
void add_stack_size(uint32_t stack_size) {
fbb_.AddElement<uint32_t>(8, stack_size, 0);
}
void add_xapi_thread_startup(uint32_t xapi_thread_startup) {
fbb_.AddElement<uint32_t>(10, xapi_thread_startup, 0);
}
void add_start_address(uint32_t start_address) {
fbb_.AddElement<uint32_t>(12, start_address, 0);
}
void add_start_context(uint32_t start_context) {
fbb_.AddElement<uint32_t>(14, start_context, 0);
}
void add_creation_flags(uint32_t creation_flags) {
fbb_.AddElement<uint32_t>(16, creation_flags, 0);
}
void add_tls_address(uint32_t tls_address) {
fbb_.AddElement<uint32_t>(18, tls_address, 0);
}
void add_pcr_address(uint32_t pcr_address) {
fbb_.AddElement<uint32_t>(20, pcr_address, 0);
}
void add_thread_state_address(uint32_t thread_state_address) {
fbb_.AddElement<uint32_t>(22, thread_state_address, 0);
}
void add_thread_id(uint32_t thread_id) {
fbb_.AddElement<uint32_t>(24, thread_id, 0);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(26, name);
}
void add_priority(uint32_t priority) {
fbb_.AddElement<uint32_t>(28, priority, 0);
}
void add_affinity(uint32_t affinity) {
fbb_.AddElement<uint32_t>(30, affinity, 0);
}
void add_state(uint32_t state) { fbb_.AddElement<uint32_t>(32, state, 0); }
ThreadBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ThreadBuilder& operator=(const ThreadBuilder&);
flatbuffers::Offset<Thread> Finish() {
auto o = flatbuffers::Offset<Thread>(fbb_.EndTable(start_, 15));
return o;
}
};
inline flatbuffers::Offset<Thread> CreateThread(
flatbuffers::FlatBufferBuilder& _fbb,
const xe::debug::proto::XObject* object = 0,
ThreadType type = ThreadType_Kernel, uint32_t stack_size = 0,
uint32_t xapi_thread_startup = 0, uint32_t start_address = 0,
uint32_t start_context = 0, uint32_t creation_flags = 0,
uint32_t tls_address = 0, uint32_t pcr_address = 0,
uint32_t thread_state_address = 0, uint32_t thread_id = 0,
flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t priority = 0,
uint32_t affinity = 0, uint32_t state = 0) {
ThreadBuilder builder_(_fbb);
builder_.add_state(state);
builder_.add_affinity(affinity);
builder_.add_priority(priority);
builder_.add_name(name);
builder_.add_thread_id(thread_id);
builder_.add_thread_state_address(thread_state_address);
builder_.add_pcr_address(pcr_address);
builder_.add_tls_address(tls_address);
builder_.add_creation_flags(creation_flags);
builder_.add_start_context(start_context);
builder_.add_start_address(start_address);
builder_.add_xapi_thread_startup(xapi_thread_startup);
builder_.add_stack_size(stack_size);
builder_.add_object(object);
builder_.add_type(type);
return builder_.Finish();
}
struct ListThreadsRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) && verifier.EndTable();
}
};
struct ListThreadsRequestBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
ListThreadsRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListThreadsRequestBuilder& operator=(const ListThreadsRequestBuilder&);
flatbuffers::Offset<ListThreadsRequest> Finish() {
auto o = flatbuffers::Offset<ListThreadsRequest>(fbb_.EndTable(start_, 0));
return o;
}
};
inline flatbuffers::Offset<ListThreadsRequest> CreateListThreadsRequest(
flatbuffers::FlatBufferBuilder& _fbb) {
ListThreadsRequestBuilder builder_(_fbb);
return builder_.Finish();
}
struct ListThreadsResponse FLATBUFFERS_FINAL_CLASS
: private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<Thread>>* thread() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Thread>>*>(
4);
}
bool Verify(flatbuffers::Verifier& verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* thread */) &&
verifier.Verify(thread()) &&
verifier.VerifyVectorOfTables(thread()) && verifier.EndTable();
}
};
struct ListThreadsResponseBuilder {
flatbuffers::FlatBufferBuilder& fbb_;
flatbuffers::uoffset_t start_;
void add_thread(flatbuffers::Offset<
flatbuffers::Vector<flatbuffers::Offset<Thread>>> thread) {
fbb_.AddOffset(4, thread);
}
ListThreadsResponseBuilder(flatbuffers::FlatBufferBuilder& _fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ListThreadsResponseBuilder& operator=(const ListThreadsResponseBuilder&);
flatbuffers::Offset<ListThreadsResponse> Finish() {
auto o = flatbuffers::Offset<ListThreadsResponse>(fbb_.EndTable(start_, 1));
return o;
}
};
inline flatbuffers::Offset<ListThreadsResponse> CreateListThreadsResponse(
flatbuffers::FlatBufferBuilder& _fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Thread>>>
thread = 0) {
ListThreadsResponseBuilder builder_(_fbb);
builder_.add_thread(thread);
return builder_.Finish();
}
} // namespace proto
} // namespace debug
} // namespace xe
#endif // FLATBUFFERS_GENERATED_THREADS_XE_DEBUG_PROTO_H_

View File

@ -0,0 +1,48 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_TRANSPORT_H_
#define XENIA_DEBUG_TRANSPORT_H_
#include "xenia/cpu/function.h"
#include "xenia/cpu/processor.h"
#include "xenia/debug/breakpoint.h"
namespace xe {
namespace debug {
class Debugger;
class Transport {
public:
virtual ~Transport() = default;
Debugger* debugger() const { return debugger_; }
virtual bool Initialize() = 0;
// break/resume state
// TODO(benvanik): better thread type (XThread?)
// virtual void OnThreadCreated(ThreadState* thread_state) = 0;
// virtual void OnThreadDestroyed(ThreadState* thread_state) = 0;
/*virtual void OnBreakpointHit(xe::cpu::ThreadState* thread_state,
Breakpoint* breakpoint) = 0;*/
protected:
Transport(Debugger* debugger) : debugger_(debugger) {}
Debugger* debugger_ = nullptr;
};
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_TRANSPORT_H_

View File

@ -0,0 +1,118 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/transport/gdb/gdb_transport.h"
#include <gflags/gflags.h>
#include "xenia/base/logging.h"
#include "xenia/debug/debugger.h"
DEFINE_int32(gdb_port, 9000, "Debugger GDB server TCP port.");
namespace xe {
namespace debug {
namespace transport {
namespace gdb {
constexpr size_t kReceiveBufferSize = 2 * 1024 * 1024;
GdbTransport::GdbTransport(Debugger* debugger) : Transport(debugger) {
receive_buffer_.resize(kReceiveBufferSize);
}
GdbTransport::~GdbTransport() = default;
bool GdbTransport::Initialize() {
socket_server_ = SocketServer::Create(uint16_t(FLAGS_gdb_port),
[this](std::unique_ptr<Socket> client) {
AcceptClient(std::move(client));
});
if (!socket_server_) {
XELOGE("Unable to create GDB socket server - port in use?");
return false;
}
return true;
}
void GdbTransport::AcceptClient(std::unique_ptr<Socket> client) {
// If we have an existing client, kill it and join its thread.
if (client_) {
// TODO(benvanik): GDB say goodbye?
client_->Close();
xe::threading::Wait(client_thread_.get(), true);
client_thread_.reset();
}
// Take ownership of the new one.
client_ = std::move(client);
// Create a thread to manage the connection.
client_thread_ = xe::threading::Thread::Create({}, [this]() {
// TODO(benvanik): GDB protocol stuff? Do we say hi?
// TODO(benvanik): move hello to thread
// Let the debugger know we are present.
debugger_->set_attached(true);
// Main loop.
bool running = true;
while (running) {
auto wait_result = xe::threading::Wait(client_->wait_handle(), true);
switch (wait_result) {
case xe::threading::WaitResult::kSuccess:
// Event (read or close).
running = HandleClientEvent();
continue;
case xe::threading::WaitResult::kAbandoned:
case xe::threading::WaitResult::kFailed:
// Error - kill the thread.
running = false;
continue;
default:
// Eh. Continue.
continue;
}
}
// Kill client (likely already disconnected).
client_.reset();
// Notify debugger we are no longer attached.
debugger_->set_attached(false);
});
}
bool GdbTransport::HandleClientEvent() {
if (!client_->is_connected()) {
// Known-disconnected.
return false;
}
// Attempt to read into our buffer.
size_t bytes_read =
client_->Receive(receive_buffer_.data(), receive_buffer_.capacity());
if (bytes_read == -1) {
// Disconnected.
return false;
} else if (bytes_read == 0) {
// No data available. Wait again.
return true;
}
// TODO(benvanik): process incoming command.
return true;
}
} // namespace gdb
} // namespace transport
} // namespace debug
} // namespace xe

View File

@ -0,0 +1,47 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_TRANSPORT_GDB_GDB_TRANSPORT_H_
#define XENIA_DEBUG_TRANSPORT_GDB_GDB_TRANSPORT_H_
#include <memory>
#include "xenia/base/socket.h"
#include "xenia/base/threading.h"
#include "xenia/debug/transport.h"
namespace xe {
namespace debug {
namespace transport {
namespace gdb {
class GdbTransport : public Transport {
public:
GdbTransport(Debugger* debugger);
~GdbTransport() override;
bool Initialize() override;
private:
void AcceptClient(std::unique_ptr<Socket> client);
bool HandleClientEvent();
std::unique_ptr<SocketServer> socket_server_;
std::unique_ptr<Socket> client_;
std::unique_ptr<xe::threading::Thread> client_thread_;
std::vector<uint8_t> receive_buffer_;
};
} // namespace gdb
} // namespace transport
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_TRANSPORT_GDB_GDB_TRANSPORT_H_

@ -1 +0,0 @@
Subproject commit ecb27817cab429925f311832cffb277df30a9908