Threads displayed.

This commit is contained in:
Ben Vanik
2013-12-25 17:31:53 -08:00
parent d368e0cb74
commit a1da55a006
19 changed files with 468 additions and 131 deletions

View File

@@ -76,6 +76,15 @@ int Debugger::ResumeAllThreads(bool force) {
return result;
}
void Debugger::ForEachThread(std::function<void(ThreadState*)> callback) {
LockMutex(threads_lock_);
for (auto it = threads_.begin(); it != threads_.end(); ++it) {
ThreadState* thread_state = it->second;
callback(thread_state);
}
UnlockMutex(threads_lock_);
}
int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
// Add to breakpoints map.
LockMutex(breakpoints_lock_);

View File

@@ -86,6 +86,8 @@ public:
int ResumeThread(uint32_t thread_id);
int ResumeAllThreads(bool force = false);
void ForEachThread(std::function<void (ThreadState*)> callback);
int AddBreakpoint(Breakpoint* breakpoint);
int RemoveBreakpoint(Breakpoint* breakpoint);
void FindBreakpoints(

View File

@@ -22,7 +22,7 @@ __declspec(thread) ThreadState* thread_state_ = NULL;
ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id) :
runtime_(runtime), memory_(runtime->memory()),
thread_id_(thread_id),
thread_id_(thread_id), name_(0),
backend_data_(0), raw_context_(0) {
if (thread_id_ == UINT_MAX) {
// System thread. Assign the system thread ID with a high bit
@@ -40,6 +40,19 @@ ThreadState::~ThreadState() {
if (thread_state_ == this) {
thread_state_ = NULL;
}
if (name_) {
xe_free(name_);
}
}
void ThreadState::set_name(const char* value) {
if (value == name_) {
return;
}
if (name_) {
xe_free(name_);
}
name_ = xestrdupa(value);
}
void ThreadState::Bind(ThreadState* thread_state) {

View File

@@ -29,6 +29,8 @@ public:
Runtime* runtime() const { return runtime_; }
Memory* memory() const { return memory_; }
uint32_t thread_id() const { return thread_id_; }
const char* name() const { return name_; }
void set_name(const char* value);
void* backend_data() const { return backend_data_; }
void* raw_context() const { return raw_context_; }
@@ -45,6 +47,7 @@ protected:
Runtime* runtime_;
Memory* memory_;
uint32_t thread_id_;
char* name_;
void* backend_data_;
void* raw_context_;
};

View File

@@ -31,6 +31,7 @@ public:
const char* GetString() const;
char* ToString();
char* EncodeBase64();
private:
char* buffer_;

View File

@@ -330,6 +330,17 @@ json_t* Processor::OnDebugRequest(
}
uint64_t address = (uint64_t)json_number_value(address_json);
return DumpFunction(address, succeeded);
} else if (xestrcmpa(command, "get_thread_states") == 0) {
json_t* result = json_object();
runtime_->debugger()->ForEachThread([&](ThreadState* thread_state) {
json_t* state_json = DumpThreadState((XenonThreadState*)thread_state);
char threadIdString[32];
xesnprintfa(
threadIdString, XECOUNT(threadIdString),
"%d", thread_state->thread_id());
json_object_set_new(result, threadIdString, state_json);
});
return result;
} else if (xestrcmpa(command, "add_breakpoints") == 0) {
// breakpoints: [{}]
json_t* breakpoints_json = json_object_get(request, "breakpoints");
@@ -699,6 +710,61 @@ json_t* Processor::DumpFunction(uint64_t address, bool& succeeded) {
return fn_json;
}
json_t* Processor::DumpThreadState(XenonThreadState* thread_state) {
json_t* result = json_object();
json_object_set_integer_new(result, "id", thread_state->thread_id());
json_object_set_string_new(result, "name", thread_state->name());
json_object_set_integer_new(
result, "stackAddress", thread_state->stack_address());
json_object_set_integer_new(
result, "stackSize", thread_state->stack_size());
json_object_set_integer_new(
result, "threadStateAddress", thread_state->thread_state_address());
json_t* context_json = json_object();
auto context = thread_state->context();
json_object_set_new(
context_json, "lr", json_integer(context->lr));
json_object_set_new(
context_json, "ctr", json_integer(context->ctr));
// xer
// cr*
// fpscr
json_t* r_json = json_array();
for (size_t n = 0; n < 32; n++) {
json_array_append_new(r_json, json_integer(context->r[n]));
}
json_object_set_new(context_json, "r", r_json);
json_t* f_json = json_array();
for (size_t n = 0; n < 32; n++) {
json_array_append_new(f_json, json_real(context->f[n]));
}
json_object_set_new(context_json, "f", f_json);
json_t* v_json = json_array();
for (size_t n = 0; n < 128; n++) {
auto& v = context->v[n];
json_t* vec4_json = json_array();
json_array_append_new(vec4_json, json_integer(v.ix));
json_array_append_new(vec4_json, json_integer(v.iy));
json_array_append_new(vec4_json, json_integer(v.iz));
json_array_append_new(vec4_json, json_integer(v.iw));
json_array_append_new(v_json, vec4_json);
}
json_object_set_new(context_json, "v", v_json);
json_object_set_new(result, "context", context_json);
// TODO(benvanik): callstack
return result;
}
Processor::DebugClientState::DebugClientState(XenonRuntime* runtime) :
runtime_(runtime) {
breakpoints_lock_ = xe_mutex_alloc(10000);

View File

@@ -67,6 +67,7 @@ public:
private:
json_t* DumpModule(XexModule* module, bool& succeeded);
json_t* DumpFunction(uint64_t address, bool& succeeded);
json_t* DumpThreadState(XenonThreadState* thread_state);
private:
Emulator* emulator_;

View File

@@ -29,6 +29,9 @@ public:
size_t stack_size, uint64_t thread_state_address);
virtual ~XenonThreadState();
uint64_t stack_address() const { return stack_address_; }
size_t stack_size() const { return stack_size_; }
uint64_t thread_state_address() const { return thread_state_address_; }
PPCContext* context() const { return context_; }
virtual volatile int* suspend_flag_address() const;
@@ -37,11 +40,9 @@ public:
virtual void EnterSuspend();
private:
size_t stack_size_;
uint64_t thread_state_address;
uint32_t thread_id_;
uint64_t stack_address_;
size_t stack_size_;
uint64_t thread_state_address_;
// NOTE: must be 64b aligned for SSE ops.