From 41d5b41523247a11f3c13ff055bdd1e37bec896e Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 27 Nov 2015 23:00:38 -0600 Subject: [PATCH] Automatically install any CPU breakpoints in any newly-defined functions if necessary. --- src/xenia/cpu/backend/backend.h | 2 ++ src/xenia/cpu/backend/x64/x64_backend.cc | 24 +++++++++++++++++++++++- src/xenia/cpu/backend/x64/x64_backend.h | 1 + src/xenia/cpu/function.h | 12 ++++++++++++ src/xenia/cpu/processor.cc | 12 ++++++++++++ src/xenia/cpu/processor.h | 3 +-- 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/xenia/cpu/backend/backend.h b/src/xenia/cpu/backend/backend.h index 86389f2fe..1f0c540a6 100644 --- a/src/xenia/cpu/backend/backend.h +++ b/src/xenia/cpu/backend/backend.h @@ -17,6 +17,7 @@ namespace xe { namespace cpu { class Breakpoint; +class Function; class GuestFunction; class Module; class Processor; @@ -53,6 +54,7 @@ class Backend { Module* module, uint32_t address) = 0; virtual bool InstallBreakpoint(Breakpoint* bp) { return false; } + virtual bool InstallBreakpoint(Breakpoint* bp, Function* func) { return false; } virtual bool UninstallBreakpoint(Breakpoint* bp) { return false; } protected: diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc index dca4addbb..021fe4a13 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.cc +++ b/src/xenia/cpu/backend/x64/x64_backend.cc @@ -133,7 +133,11 @@ bool X64Backend::InstallBreakpoint(Breakpoint* bp) { assert_true(function->is_guest()); auto guest_function = reinterpret_cast(function); auto code = guest_function->MapGuestAddressToMachineCode(bp->address()); - assert_not_zero(code); + if (!code) { + // This should not happen. + assert_always(); + return false; + } auto orig_bytes = xe::load_and_swap(reinterpret_cast(code + 0x0)); @@ -145,6 +149,24 @@ bool X64Backend::InstallBreakpoint(Breakpoint* bp) { return true; } +bool X64Backend::InstallBreakpoint(Breakpoint* bp, Function* func) { + assert_true(func->is_guest()); + auto guest_function = reinterpret_cast(func); + auto code = guest_function->MapGuestAddressToMachineCode(bp->address()); + if (!code) { + assert_always(); + return false; + } + + // Assume we haven't already installed a breakpoint in this spot. + auto orig_bytes = + xe::load_and_swap(reinterpret_cast(code + 0x0)); + bp->backend_data().push_back({code, orig_bytes}); + + xe::store_and_swap(reinterpret_cast(code + 0x0), 0x0F0C); + return true; +} + bool X64Backend::UninstallBreakpoint(Breakpoint* bp) { for (auto pair : bp->backend_data()) { xe::store_and_swap(reinterpret_cast(pair.first), diff --git a/src/xenia/cpu/backend/x64/x64_backend.h b/src/xenia/cpu/backend/x64/x64_backend.h index e1aadd9e1..02748d71f 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.h +++ b/src/xenia/cpu/backend/x64/x64_backend.h @@ -63,6 +63,7 @@ class X64Backend : public Backend { uint32_t address) override; bool InstallBreakpoint(Breakpoint* bp) override; + bool InstallBreakpoint(Breakpoint* bp, Function* func) override; bool UninstallBreakpoint(Breakpoint* bp) override; private: diff --git a/src/xenia/cpu/function.h b/src/xenia/cpu/function.h index 29160c4da..802241133 100644 --- a/src/xenia/cpu/function.h +++ b/src/xenia/cpu/function.h @@ -49,6 +49,18 @@ class Function : public Symbol { void set_behavior(Behavior value) { behavior_ = value; } bool is_guest() const { return behavior_ != Behavior::kBuiltin; } + bool ContainsAddress(uint32_t address) const { + if (!address_ || !end_address_) { + return false; + } + + if (address >= address_ && address < end_address_) { + return true; + } + + return false; + } + virtual bool Call(ThreadState* thread_state, uint32_t return_address) = 0; protected: diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index bd85cfba9..c2a31affa 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -274,6 +274,8 @@ bool Processor::DemandFunction(Function* function) { debugger_->OnFunctionDefined(function); } + BreakpointFunctionDefined(function); + function->set_status(Symbol::Status::kDefined); symbol_status = function->status(); } @@ -402,6 +404,16 @@ void Processor::LowerIrql(Irql old_value) { reinterpret_cast(&irql_)); } +void Processor::BreakpointFunctionDefined(Function* function) { + std::lock_guard lock(breakpoint_lock_); + + for (auto it = breakpoints_.begin(); it != breakpoints_.end(); it++) { + if (function->ContainsAddress((*it)->address())) { + backend_->InstallBreakpoint(*it, function); + } + } +} + bool Processor::InstallBreakpoint(Breakpoint* bp) { std::lock_guard lock(breakpoint_lock_); diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index ef5790dc4..ca5296e99 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -101,8 +101,7 @@ class Processor { std::vector breakpoints() const { return breakpoints_; } private: - static bool ExceptionCallbackThunk(Exception* ex, void* data); - bool ExceptionCallback(Exception* ex); + void BreakpointFunctionDefined(Function* function); bool DemandFunction(Function* function);