Threads displayed.
This commit is contained in:
@@ -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_);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
|
||||
const char* GetString() const;
|
||||
char* ToString();
|
||||
char* EncodeBase64();
|
||||
|
||||
private:
|
||||
char* buffer_;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user