Debugger can pause/resume threads.
This commit is contained in:
parent
8dc20eb5cd
commit
d482885378
|
@ -45,10 +45,6 @@ class ThreadState {
|
||||||
uint32_t pcr_address() const { return pcr_address_; }
|
uint32_t pcr_address() const { return pcr_address_; }
|
||||||
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
||||||
|
|
||||||
bool Suspend() { return Suspend(~0); }
|
|
||||||
bool Suspend(uint32_t timeout_ms) { return false; }
|
|
||||||
bool Resume(bool force = false) { return false; }
|
|
||||||
|
|
||||||
static void Bind(ThreadState* thread_state);
|
static void Bind(ThreadState* thread_state);
|
||||||
static ThreadState* Get();
|
static ThreadState* Get();
|
||||||
static uint32_t GetThreadID();
|
static uint32_t GetThreadID();
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "xenia/emulator.h"
|
#include "xenia/emulator.h"
|
||||||
#include "xenia/kernel/objects/xkernel_module.h"
|
#include "xenia/kernel/objects/xkernel_module.h"
|
||||||
#include "xenia/kernel/objects/xmodule.h"
|
#include "xenia/kernel/objects/xmodule.h"
|
||||||
|
#include "xenia/kernel/objects/xthread.h"
|
||||||
#include "xenia/kernel/objects/xuser_module.h"
|
#include "xenia/kernel/objects/xuser_module.h"
|
||||||
|
|
||||||
// Autogenerated Flatbuffers files:
|
// Autogenerated Flatbuffers files:
|
||||||
|
@ -127,6 +128,8 @@ void SendResponse(SOCKET client_socket, flatbuffers::FlatBufferBuilder& fbb,
|
||||||
|
|
||||||
void Debugger::PreLaunch() {
|
void Debugger::PreLaunch() {
|
||||||
accept_thread_ = std::thread([this]() {
|
accept_thread_ = std::thread([this]() {
|
||||||
|
xe::threading::set_name("Debugger Server");
|
||||||
|
|
||||||
while (listen_socket_ != INVALID_SOCKET) {
|
while (listen_socket_ != INVALID_SOCKET) {
|
||||||
sockaddr_in6 client_addr;
|
sockaddr_in6 client_addr;
|
||||||
int client_count = sizeof(client_addr);
|
int client_count = sizeof(client_addr);
|
||||||
|
@ -148,6 +151,8 @@ void Debugger::PreLaunch() {
|
||||||
// Setup recv thread.
|
// Setup recv thread.
|
||||||
client_socket_ = client_socket_id;
|
client_socket_ = client_socket_id;
|
||||||
receive_thread_ = std::thread([this]() {
|
receive_thread_ = std::thread([this]() {
|
||||||
|
xe::threading::set_name("Debugger Connection");
|
||||||
|
|
||||||
while (client_socket_ != INVALID_SOCKET) {
|
while (client_socket_ != INVALID_SOCKET) {
|
||||||
// Read length prefix.
|
// Read length prefix.
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
|
@ -471,51 +476,36 @@ uint8_t* Debugger::AllocateFunctionTraceData(size_t size) {
|
||||||
return functions_trace_file_->Allocate(size);
|
return functions_trace_file_->Allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Debugger::SuspendAllThreads(uint32_t timeout_ms) {
|
bool Debugger::SuspendAllThreads() {
|
||||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
auto threads =
|
||||||
|
emulator_->kernel_state()->object_table()->GetObjectsByType<XThread>(
|
||||||
int result = 0;
|
XObject::kTypeThread);
|
||||||
for (auto thread_state : threads_) {
|
for (auto& thread : threads) {
|
||||||
if (thread_state.second->Suspend(timeout_ms)) {
|
if (!XSUCCEEDED(thread->Suspend(nullptr))) {
|
||||||
result = 1;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Debugger::ResumeThread(uint32_t thread_id) {
|
bool Debugger::ResumeThread(uint32_t thread_id) {
|
||||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
auto thread = emulator_->kernel_state()->GetThreadByID(thread_id);
|
||||||
|
if (!thread) {
|
||||||
auto it = threads_.find(thread_id);
|
return false;
|
||||||
if (it == threads_.end()) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
return XSUCCEEDED(thread->Resume());
|
||||||
// Found thread. Note that it could be deleted as soon as we unlock.
|
|
||||||
ThreadState* thread_state = it->second;
|
|
||||||
int result = thread_state->Resume();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Debugger::ResumeAllThreads(bool force) {
|
bool Debugger::ResumeAllThreads() {
|
||||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
auto threads =
|
||||||
|
emulator_->kernel_state()->object_table()->GetObjectsByType<XThread>(
|
||||||
int result = 0;
|
XObject::kTypeThread);
|
||||||
for (auto thread_state : threads_) {
|
for (auto& thread : threads) {
|
||||||
if (thread_state.second->Resume(force)) {
|
if (!XSUCCEEDED(thread->Resume())) {
|
||||||
result = 1;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
void Debugger::ForEachThread(std::function<void(ThreadState*)> callback) {
|
|
||||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
|
||||||
|
|
||||||
for (auto thread_state : threads_) {
|
|
||||||
callback(thread_state.second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
|
int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
|
||||||
|
@ -591,16 +581,11 @@ void Debugger::FindBreakpoints(uint32_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::OnThreadCreated(ThreadState* thread_state) {
|
void Debugger::OnThreadCreated(ThreadState* thread_state) {
|
||||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
//
|
||||||
threads_[thread_state->thread_id()] = thread_state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::OnThreadDestroyed(ThreadState* thread_state) {
|
void Debugger::OnThreadDestroyed(ThreadState* thread_state) {
|
||||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
//
|
||||||
auto it = threads_.find(thread_state->thread_id());
|
|
||||||
if (it != threads_.end()) {
|
|
||||||
threads_.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::OnFunctionDefined(cpu::FunctionInfo* symbol_info,
|
void Debugger::OnFunctionDefined(cpu::FunctionInfo* symbol_info,
|
||||||
|
|
|
@ -81,11 +81,9 @@ class Debugger {
|
||||||
uint8_t* AllocateFunctionData(size_t size);
|
uint8_t* AllocateFunctionData(size_t size);
|
||||||
uint8_t* AllocateFunctionTraceData(size_t size);
|
uint8_t* AllocateFunctionTraceData(size_t size);
|
||||||
|
|
||||||
int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX);
|
bool SuspendAllThreads();
|
||||||
int ResumeThread(uint32_t thread_id);
|
bool ResumeThread(uint32_t thread_id);
|
||||||
int ResumeAllThreads(bool force = false);
|
bool ResumeAllThreads();
|
||||||
|
|
||||||
void ForEachThread(std::function<void(cpu::ThreadState*)> callback);
|
|
||||||
|
|
||||||
int AddBreakpoint(Breakpoint* breakpoint);
|
int AddBreakpoint(Breakpoint* breakpoint);
|
||||||
int RemoveBreakpoint(Breakpoint* breakpoint);
|
int RemoveBreakpoint(Breakpoint* breakpoint);
|
||||||
|
@ -121,9 +119,6 @@ class Debugger {
|
||||||
std::wstring functions_trace_path_;
|
std::wstring functions_trace_path_;
|
||||||
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
|
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
|
||||||
|
|
||||||
std::mutex threads_lock_;
|
|
||||||
std::unordered_map<uint32_t, cpu::ThreadState*> threads_;
|
|
||||||
|
|
||||||
std::mutex breakpoints_lock_;
|
std::mutex breakpoints_lock_;
|
||||||
std::multimap<uint32_t, Breakpoint*> breakpoints_;
|
std::multimap<uint32_t, Breakpoint*> breakpoints_;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue