Breakpoint hits reaching all the way to UI.

Nasty json only hackery right now, but fixable to support other protocols.
This commit is contained in:
Ben Vanik
2013-12-23 14:01:13 -08:00
parent a0256fac45
commit 475ddc1fcf
19 changed files with 284 additions and 9 deletions

View File

@@ -16,7 +16,7 @@
typedef struct xe_mutex xe_mutex_t;
xe_mutex_t* xe_mutex_alloc(uint32_t spin_count);
xe_mutex_t* xe_mutex_alloc(uint32_t spin_count = 10000);
void xe_mutex_free(xe_mutex_t* mutex);
int xe_mutex_lock(xe_mutex_t* mutex);

View File

@@ -59,18 +59,23 @@ Processor::Processor(Emulator* emulator) :
DebugTarget(emulator->debug_server()) {
InitializeIfNeeded();
debug_client_states_lock_ = xe_mutex_alloc();
emulator_->debug_server()->AddTarget("cpu", this);
}
Processor::~Processor() {
emulator_->debug_server()->RemoveTarget("cpu");
xe_mutex_lock(debug_client_states_lock_);
for (auto it = debug_client_states_.begin();
it != debug_client_states_.end(); ++it) {
DebugClientState* client_state = it->second;
delete client_state;
}
debug_client_states_.clear();
xe_mutex_unlock(debug_client_states_lock_);
xe_mutex_free(debug_client_states_lock_);
if (interrupt_thread_block_) {
memory_->HeapFree(interrupt_thread_block_, 2048);
@@ -99,6 +104,31 @@ int Processor::Setup() {
return result;
}
// Setup debugger events.
auto debugger = runtime_->debugger();
auto debug_server = emulator_->debug_server();
debugger->breakpoint_hit.AddListener(
[debug_server](BreakpointHitEvent& e) {
const char* breakpoint_id = e.breakpoint()->id();
if (!breakpoint_id) {
// This is not a breakpoint we know about. Ignore.
return;
}
json_t* event_json = json_object();
json_t* type_json = json_string("breakpoint");
json_object_set_new(event_json, "type", type_json);
json_t* thread_id_json = json_integer(e.thread_state()->thread_id());
json_object_set_new(event_json, "threadId", thread_id_json);
json_t* breakpoint_id_json = json_string(breakpoint_id);
json_object_set_new(event_json, "breakpointId", breakpoint_id_json);
debug_server->BroadcastEvent(event_json);
json_decref(event_json);
});
interrupt_thread_lock_ = xe_mutex_alloc(10000);
interrupt_thread_state_ = new XenonThreadState(
runtime_, 0, 16 * 1024, 0);
@@ -177,19 +207,26 @@ uint64_t Processor::ExecuteInterrupt(
void Processor::OnDebugClientConnected(uint32_t client_id) {
DebugClientState* client_state = new DebugClientState(runtime_);
xe_mutex_lock(debug_client_states_lock_);
debug_client_states_[client_id] = client_state;
xe_mutex_unlock(debug_client_states_lock_);
}
void Processor::OnDebugClientDisconnected(uint32_t client_id) {
DebugClientState* client_state = debug_client_states_[client_id];
xe_mutex_lock(debug_client_states_lock_);
debug_client_states_.erase(client_id);
xe_mutex_unlock(debug_client_states_lock_);
delete client_state;
}
json_t* Processor::OnDebugRequest(
uint32_t client_id, const char* command, json_t* request,
bool& succeeded) {
xe_mutex_lock(debug_client_states_lock_);
DebugClientState* client_state = debug_client_states_[client_id];
xe_mutex_unlock(debug_client_states_lock_);
XEASSERTNOTNULL(client_state);
succeeded = true;
if (xestrcmpa(command, "get_module_list") == 0) {
@@ -343,6 +380,7 @@ json_t* Processor::OnDebugRequest(
Breakpoint* breakpoint = new Breakpoint(
type, address);
breakpoint->set_id(breakpoint_id);
if (client_state->AddBreakpoint(breakpoint_id, breakpoint)) {
succeeded = false;
return json_string("Error adding breakpoint");

View File

@@ -91,6 +91,7 @@ private:
typedef std::unordered_map<std::string, alloy::runtime::Breakpoint*> BreakpointMap;
BreakpointMap breakpoints_;
};
xe_mutex_t* debug_client_states_lock_;
typedef std::unordered_map<uint32_t, DebugClientState*> DebugClientStateMap;
DebugClientStateMap debug_client_states_;
};

View File

@@ -46,12 +46,24 @@ XenonThreadState::XenonThreadState(
alloy::tracing::WriteEvent(EventType::ThreadInit({
}));
runtime_->debugger()->OnThreadCreated(this);
}
XenonThreadState::~XenonThreadState() {
runtime_->debugger()->OnThreadDestroyed(this);
alloy::tracing::WriteEvent(EventType::ThreadDeinit({
}));
xe_free_aligned(context_);
memory_->HeapFree(stack_address_, stack_size_);
}
int XenonThreadState::Suspend(uint32_t timeout_ms) {
return 0;
}
int XenonThreadState::Resume() {
return 0;
}

View File

@@ -31,6 +31,9 @@ public:
PPCContext* context() const { return context_; }
virtual int Suspend(uint32_t timeout_ms = UINT_MAX);
virtual int Resume();
private:
size_t stack_size_;
uint64_t thread_state_address;

View File

@@ -16,6 +16,8 @@
XEDECLARECLASS2(xe, debug, DebugServer);
struct json_t;
namespace xe {
namespace debug {
@@ -31,6 +33,8 @@ public:
virtual int Setup() = 0;
virtual void Close() = 0;
virtual void SendEvent(json_t* event_json) = 0;
protected:
void MakeReady();

View File

@@ -126,6 +126,15 @@ DebugTarget* DebugServer::GetTarget(const char* name) {
return target;
}
void DebugServer::BroadcastEvent(json_t* event_json) {
// TODO(benvanik): avoid lock somehow?
xe_mutex_lock(lock_);
for (auto client : clients_) {
client->SendEvent(event_json);
}
xe_mutex_unlock(lock_);
}
int DebugServer::WaitForClient() {
while (!has_clients()) {
WaitForSingleObject(client_event_, INFINITE);

View File

@@ -21,6 +21,8 @@ XEDECLARECLASS2(xe, debug, DebugClient);
XEDECLARECLASS2(xe, debug, DebugTarget);
XEDECLARECLASS2(xe, debug, Protocol);
struct json_t;
namespace xe {
namespace debug {
@@ -43,6 +45,8 @@ public:
void RemoveTarget(const char* name);
DebugTarget* GetTarget(const char* name);
void BroadcastEvent(json_t* event_json);
int WaitForClient();
private:

View File

@@ -37,6 +37,8 @@ public:
virtual int Setup();
virtual void Close();
virtual void SendEvent(json_t* event_json) {}
private:
static void StartCallback(void* param);

View File

@@ -371,7 +371,12 @@ void WSClient::EventThread() {
delete this;
}
void WSClient::Write(const char* value) {
void WSClient::SendEvent(json_t* event_json) {
char* str = json_dumps(event_json, 0);
Write(str);
}
void WSClient::Write(char* value) {
const uint8_t* buffers[] = {
(uint8_t*)value,
};
@@ -475,7 +480,8 @@ void WSClient::OnMessage(const uint8_t* data, size_t length) {
json_object_set_new(response, "result", result_json);
// Encode response to string and send back.
const char* response_string = json_dumps(response, JSON_INDENT(2));
// String freed by Write.
char* response_string = json_dumps(response, JSON_INDENT(2));
Write(response_string);
json_decref(request);

View File

@@ -38,7 +38,9 @@ public:
virtual int Setup();
virtual void Close();
void Write(const char* value);
virtual void SendEvent(json_t* event_json);
void Write(char* value);
void Write(const uint8_t** buffers, size_t* lengths, size_t count,
bool binary = true);