Splitting up debugger.h.
This commit is contained in:
parent
07ba1be7f5
commit
16c97189dd
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2016 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_DEBUG_DEBUG_LISTENER_H_
|
||||||
|
#define XENIA_DEBUG_DEBUG_LISTENER_H_
|
||||||
|
|
||||||
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
#include "xenia/debug/breakpoint.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
class XThread;
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace debug {
|
||||||
|
|
||||||
|
// Debug event listener interface.
|
||||||
|
// Implementations will receive calls from arbitrary threads and must marshal
|
||||||
|
// them as required.
|
||||||
|
class DebugListener {
|
||||||
|
public:
|
||||||
|
// Handles request for debugger focus (such as when the user requests the
|
||||||
|
// debugger be brought to the front).
|
||||||
|
virtual void OnFocus() = 0;
|
||||||
|
|
||||||
|
// Handles the debugger detaching from the target.
|
||||||
|
// This will be called on shutdown or when the user requests the debug session
|
||||||
|
// end.
|
||||||
|
virtual void OnDetached() = 0;
|
||||||
|
|
||||||
|
// Handles execution being interrupted and transitioning to
|
||||||
|
// ExceutionState::kPaused.
|
||||||
|
virtual void OnExecutionPaused() = 0;
|
||||||
|
// Handles execution continuing when transitioning to
|
||||||
|
// ExecutionState::kRunning or ExecutionState::kStepping.
|
||||||
|
virtual void OnExecutionContinued() = 0;
|
||||||
|
// Handles execution ending when transitioning to ExecutionState::kEnded.
|
||||||
|
virtual void OnExecutionEnded() = 0;
|
||||||
|
|
||||||
|
// Handles step completion events when a requested step operation completes.
|
||||||
|
// The thread is the one that hit its step target. Note that because multiple
|
||||||
|
// threads could be stepping simultaneously (such as a run-to-cursor) use the
|
||||||
|
// thread passed instead of keeping any other state.
|
||||||
|
virtual void OnStepCompleted(xe::kernel::XThread* thread) = 0;
|
||||||
|
|
||||||
|
// Handles breakpoint events as they are hit per-thread.
|
||||||
|
// Breakpoints may be hit during stepping.
|
||||||
|
virtual void OnBreakpointHit(Breakpoint* breakpoint,
|
||||||
|
xe::kernel::XThread* thread) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace debug
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_DEBUG_DEBUG_LISTENER_H_
|
|
@ -26,6 +26,8 @@
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
#include "xenia/debug/breakpoint.h"
|
#include "xenia/debug/breakpoint.h"
|
||||||
|
#include "xenia/debug/debug_listener.h"
|
||||||
|
#include "xenia/debug/thread_execution_info.h"
|
||||||
|
|
||||||
DECLARE_bool(debug);
|
DECLARE_bool(debug);
|
||||||
|
|
||||||
|
@ -53,118 +55,6 @@ enum class ExecutionState {
|
||||||
kEnded,
|
kEnded,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Per-XThread structure holding debugger state and a cache of the sampled call
|
|
||||||
// stack.
|
|
||||||
//
|
|
||||||
// In most cases debug consumers should rely only on data in this structure as
|
|
||||||
// it is never removed (even when a thread is destroyed) and always available
|
|
||||||
// even when running.
|
|
||||||
struct ThreadExecutionInfo {
|
|
||||||
ThreadExecutionInfo();
|
|
||||||
~ThreadExecutionInfo();
|
|
||||||
|
|
||||||
enum class State {
|
|
||||||
// Thread is alive and running.
|
|
||||||
kAlive,
|
|
||||||
// Thread is in a wait state.
|
|
||||||
kWaiting,
|
|
||||||
// Thread has exited but not yet been killed.
|
|
||||||
kExited,
|
|
||||||
// Thread has been killed.
|
|
||||||
kZombie,
|
|
||||||
};
|
|
||||||
|
|
||||||
// XThread::thread_id(), unique to the thread for the run of the emulator.
|
|
||||||
uint32_t thread_id = 0;
|
|
||||||
// XThread::handle() of the thread.
|
|
||||||
// This will be invalidated when the thread dies.
|
|
||||||
uint32_t thread_handle = 0;
|
|
||||||
// Target XThread, if it has not been destroyed.
|
|
||||||
// TODO(benvanik): hold a ref here to keep zombie threads around?
|
|
||||||
kernel::XThread* thread = nullptr;
|
|
||||||
// Current state of the thread.
|
|
||||||
State state = State::kAlive;
|
|
||||||
// Whether the debugger has forcefully suspended this thread.
|
|
||||||
bool suspended = false;
|
|
||||||
|
|
||||||
// A breakpoint managed by the stepping system, installed as required to
|
|
||||||
// trigger a break at the next instruction.
|
|
||||||
std::unique_ptr<StepBreakpoint> step_breakpoint;
|
|
||||||
// A breakpoint managed by the stepping system, installed as required to
|
|
||||||
// trigger after a step over a disabled breakpoint.
|
|
||||||
// When this breakpoint is hit the breakpoint referenced in
|
|
||||||
// restore_original_breakpoint will be reinstalled.
|
|
||||||
// Breakpoint restore_step_breakpoint;
|
|
||||||
// If the thread is stepping over a disabled breakpoint this will point to
|
|
||||||
// that breakpoint so it can be restored.
|
|
||||||
// Breakpoint* restore_original_breakpoint = nullptr;
|
|
||||||
|
|
||||||
// Last-sampled PPC context.
|
|
||||||
// This is updated whenever the debugger stops.
|
|
||||||
xe::cpu::ppc::PPCContext guest_context;
|
|
||||||
// Last-sampled host x64 context.
|
|
||||||
// This is updated whenever the debugger stops and must be used instead of any
|
|
||||||
// value taken from the StackWalker as it properly respects exception stacks.
|
|
||||||
X64Context host_context;
|
|
||||||
|
|
||||||
// A single frame in a call stack.
|
|
||||||
struct Frame {
|
|
||||||
// PC of the current instruction in host code.
|
|
||||||
uint64_t host_pc = 0;
|
|
||||||
// Base of the function the current host_pc is located within.
|
|
||||||
uint64_t host_function_address = 0;
|
|
||||||
// PC of the current instruction in guest code.
|
|
||||||
// 0 if not a guest address or not known.
|
|
||||||
uint32_t guest_pc = 0;
|
|
||||||
// Base of the function the current guest_pc is located within.
|
|
||||||
uint32_t guest_function_address = 0;
|
|
||||||
// Function the current guest_pc is located within.
|
|
||||||
cpu::Function* guest_function = nullptr;
|
|
||||||
// Name of the function, if known.
|
|
||||||
// TODO(benvanik): string table?
|
|
||||||
char name[256] = {0};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Last-sampled call stack.
|
|
||||||
// This is updated whenever the debugger stops.
|
|
||||||
std::vector<Frame> frames;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Debug event listener interface.
|
|
||||||
// Implementations will receive calls from arbitrary threads and must marshal
|
|
||||||
// them as required.
|
|
||||||
class DebugListener {
|
|
||||||
public:
|
|
||||||
// Handles request for debugger focus (such as when the user requests the
|
|
||||||
// debugger be brought to the front).
|
|
||||||
virtual void OnFocus() = 0;
|
|
||||||
|
|
||||||
// Handles the debugger detaching from the target.
|
|
||||||
// This will be called on shutdown or when the user requests the debug session
|
|
||||||
// end.
|
|
||||||
virtual void OnDetached() = 0;
|
|
||||||
|
|
||||||
// Handles execution being interrupted and transitioning to
|
|
||||||
// ExceutionState::kPaused.
|
|
||||||
virtual void OnExecutionPaused() = 0;
|
|
||||||
// Handles execution continuing when transitioning to
|
|
||||||
// ExecutionState::kRunning or ExecutionState::kStepping.
|
|
||||||
virtual void OnExecutionContinued() = 0;
|
|
||||||
// Handles execution ending when transitioning to ExecutionState::kEnded.
|
|
||||||
virtual void OnExecutionEnded() = 0;
|
|
||||||
|
|
||||||
// Handles step completion events when a requested step operation completes.
|
|
||||||
// The thread is the one that hit its step target. Note that because multiple
|
|
||||||
// threads could be stepping simultaneously (such as a run-to-cursor) use the
|
|
||||||
// thread passed instead of keeping any other state.
|
|
||||||
virtual void OnStepCompleted(xe::kernel::XThread* thread) = 0;
|
|
||||||
|
|
||||||
// Handles breakpoint events as they are hit per-thread.
|
|
||||||
// Breakpoints may be hit during stepping.
|
|
||||||
virtual void OnBreakpointHit(Breakpoint* breakpoint,
|
|
||||||
xe::kernel::XThread* thread) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Debugger {
|
class Debugger {
|
||||||
public:
|
public:
|
||||||
explicit Debugger(Emulator* emulator);
|
explicit Debugger(Emulator* emulator);
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2016 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/debug/thread_execution_info.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace debug {
|
||||||
|
|
||||||
|
ThreadExecutionInfo::ThreadExecutionInfo() = default;
|
||||||
|
|
||||||
|
ThreadExecutionInfo::~ThreadExecutionInfo() = default;
|
||||||
|
|
||||||
|
} // namespace debug
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2016 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_DEBUG_THREAD_EXECUTION_INFO_H_
|
||||||
|
#define XENIA_DEBUG_THREAD_EXECUTION_INFO_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "xenia/base/x64_context.h"
|
||||||
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
#include "xenia/debug/breakpoint.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
class XThread;
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace debug {
|
||||||
|
|
||||||
|
// Per-XThread structure holding debugger state and a cache of the sampled call
|
||||||
|
// stack.
|
||||||
|
//
|
||||||
|
// In most cases debug consumers should rely only on data in this structure as
|
||||||
|
// it is never removed (even when a thread is destroyed) and always available
|
||||||
|
// even when running.
|
||||||
|
struct ThreadExecutionInfo {
|
||||||
|
ThreadExecutionInfo();
|
||||||
|
~ThreadExecutionInfo();
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
// Thread is alive and running.
|
||||||
|
kAlive,
|
||||||
|
// Thread is in a wait state.
|
||||||
|
kWaiting,
|
||||||
|
// Thread has exited but not yet been killed.
|
||||||
|
kExited,
|
||||||
|
// Thread has been killed.
|
||||||
|
kZombie,
|
||||||
|
};
|
||||||
|
|
||||||
|
// XThread::thread_id(), unique to the thread for the run of the emulator.
|
||||||
|
uint32_t thread_id = 0;
|
||||||
|
// XThread::handle() of the thread.
|
||||||
|
// This will be invalidated when the thread dies.
|
||||||
|
uint32_t thread_handle = 0;
|
||||||
|
// Target XThread, if it has not been destroyed.
|
||||||
|
// TODO(benvanik): hold a ref here to keep zombie threads around?
|
||||||
|
kernel::XThread* thread = nullptr;
|
||||||
|
// Current state of the thread.
|
||||||
|
State state = State::kAlive;
|
||||||
|
// Whether the debugger has forcefully suspended this thread.
|
||||||
|
bool suspended = false;
|
||||||
|
|
||||||
|
// A breakpoint managed by the stepping system, installed as required to
|
||||||
|
// trigger a break at the next instruction.
|
||||||
|
std::unique_ptr<StepBreakpoint> step_breakpoint;
|
||||||
|
// A breakpoint managed by the stepping system, installed as required to
|
||||||
|
// trigger after a step over a disabled breakpoint.
|
||||||
|
// When this breakpoint is hit the breakpoint referenced in
|
||||||
|
// restore_original_breakpoint will be reinstalled.
|
||||||
|
// Breakpoint restore_step_breakpoint;
|
||||||
|
// If the thread is stepping over a disabled breakpoint this will point to
|
||||||
|
// that breakpoint so it can be restored.
|
||||||
|
// Breakpoint* restore_original_breakpoint = nullptr;
|
||||||
|
|
||||||
|
// Last-sampled PPC context.
|
||||||
|
// This is updated whenever the debugger stops.
|
||||||
|
xe::cpu::ppc::PPCContext guest_context;
|
||||||
|
// Last-sampled host x64 context.
|
||||||
|
// This is updated whenever the debugger stops and must be used instead of any
|
||||||
|
// value taken from the StackWalker as it properly respects exception stacks.
|
||||||
|
X64Context host_context;
|
||||||
|
|
||||||
|
// A single frame in a call stack.
|
||||||
|
struct Frame {
|
||||||
|
// PC of the current instruction in host code.
|
||||||
|
uint64_t host_pc = 0;
|
||||||
|
// Base of the function the current host_pc is located within.
|
||||||
|
uint64_t host_function_address = 0;
|
||||||
|
// PC of the current instruction in guest code.
|
||||||
|
// 0 if not a guest address or not known.
|
||||||
|
uint32_t guest_pc = 0;
|
||||||
|
// Base of the function the current guest_pc is located within.
|
||||||
|
uint32_t guest_function_address = 0;
|
||||||
|
// Function the current guest_pc is located within.
|
||||||
|
cpu::Function* guest_function = nullptr;
|
||||||
|
// Name of the function, if known.
|
||||||
|
// TODO(benvanik): string table?
|
||||||
|
char name[256] = {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Last-sampled call stack.
|
||||||
|
// This is updated whenever the debugger stops.
|
||||||
|
std::vector<Frame> frames;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace debug
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_DEBUG_THREAD_EXECUTION_INFO_H_
|
Loading…
Reference in New Issue