Automatically install any CPU breakpoints in any newly-defined functions if necessary.
This commit is contained in:
parent
d09e3b7953
commit
41d5b41523
|
@ -17,6 +17,7 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
class Breakpoint;
|
class Breakpoint;
|
||||||
|
class Function;
|
||||||
class GuestFunction;
|
class GuestFunction;
|
||||||
class Module;
|
class Module;
|
||||||
class Processor;
|
class Processor;
|
||||||
|
@ -53,6 +54,7 @@ class Backend {
|
||||||
Module* module, uint32_t address) = 0;
|
Module* module, uint32_t address) = 0;
|
||||||
|
|
||||||
virtual bool InstallBreakpoint(Breakpoint* bp) { return false; }
|
virtual bool InstallBreakpoint(Breakpoint* bp) { return false; }
|
||||||
|
virtual bool InstallBreakpoint(Breakpoint* bp, Function* func) { return false; }
|
||||||
virtual bool UninstallBreakpoint(Breakpoint* bp) { return false; }
|
virtual bool UninstallBreakpoint(Breakpoint* bp) { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -133,7 +133,11 @@ bool X64Backend::InstallBreakpoint(Breakpoint* bp) {
|
||||||
assert_true(function->is_guest());
|
assert_true(function->is_guest());
|
||||||
auto guest_function = reinterpret_cast<cpu::GuestFunction*>(function);
|
auto guest_function = reinterpret_cast<cpu::GuestFunction*>(function);
|
||||||
auto code = guest_function->MapGuestAddressToMachineCode(bp->address());
|
auto code = guest_function->MapGuestAddressToMachineCode(bp->address());
|
||||||
assert_not_zero(code);
|
if (!code) {
|
||||||
|
// This should not happen.
|
||||||
|
assert_always();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto orig_bytes =
|
auto orig_bytes =
|
||||||
xe::load_and_swap<uint16_t>(reinterpret_cast<void*>(code + 0x0));
|
xe::load_and_swap<uint16_t>(reinterpret_cast<void*>(code + 0x0));
|
||||||
|
@ -145,6 +149,24 @@ bool X64Backend::InstallBreakpoint(Breakpoint* bp) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool X64Backend::InstallBreakpoint(Breakpoint* bp, Function* func) {
|
||||||
|
assert_true(func->is_guest());
|
||||||
|
auto guest_function = reinterpret_cast<cpu::GuestFunction*>(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<uint16_t>(reinterpret_cast<void*>(code + 0x0));
|
||||||
|
bp->backend_data().push_back({code, orig_bytes});
|
||||||
|
|
||||||
|
xe::store_and_swap<uint16_t>(reinterpret_cast<void*>(code + 0x0), 0x0F0C);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool X64Backend::UninstallBreakpoint(Breakpoint* bp) {
|
bool X64Backend::UninstallBreakpoint(Breakpoint* bp) {
|
||||||
for (auto pair : bp->backend_data()) {
|
for (auto pair : bp->backend_data()) {
|
||||||
xe::store_and_swap<uint16_t>(reinterpret_cast<void*>(pair.first),
|
xe::store_and_swap<uint16_t>(reinterpret_cast<void*>(pair.first),
|
||||||
|
|
|
@ -63,6 +63,7 @@ class X64Backend : public Backend {
|
||||||
uint32_t address) override;
|
uint32_t address) override;
|
||||||
|
|
||||||
bool InstallBreakpoint(Breakpoint* bp) override;
|
bool InstallBreakpoint(Breakpoint* bp) override;
|
||||||
|
bool InstallBreakpoint(Breakpoint* bp, Function* func) override;
|
||||||
bool UninstallBreakpoint(Breakpoint* bp) override;
|
bool UninstallBreakpoint(Breakpoint* bp) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -49,6 +49,18 @@ class Function : public Symbol {
|
||||||
void set_behavior(Behavior value) { behavior_ = value; }
|
void set_behavior(Behavior value) { behavior_ = value; }
|
||||||
bool is_guest() const { return behavior_ != Behavior::kBuiltin; }
|
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;
|
virtual bool Call(ThreadState* thread_state, uint32_t return_address) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -274,6 +274,8 @@ bool Processor::DemandFunction(Function* function) {
|
||||||
debugger_->OnFunctionDefined(function);
|
debugger_->OnFunctionDefined(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BreakpointFunctionDefined(function);
|
||||||
|
|
||||||
function->set_status(Symbol::Status::kDefined);
|
function->set_status(Symbol::Status::kDefined);
|
||||||
symbol_status = function->status();
|
symbol_status = function->status();
|
||||||
}
|
}
|
||||||
|
@ -402,6 +404,16 @@ void Processor::LowerIrql(Irql old_value) {
|
||||||
reinterpret_cast<volatile uint32_t*>(&irql_));
|
reinterpret_cast<volatile uint32_t*>(&irql_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Processor::BreakpointFunctionDefined(Function* function) {
|
||||||
|
std::lock_guard<std::recursive_mutex> 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) {
|
bool Processor::InstallBreakpoint(Breakpoint* bp) {
|
||||||
std::lock_guard<std::recursive_mutex> lock(breakpoint_lock_);
|
std::lock_guard<std::recursive_mutex> lock(breakpoint_lock_);
|
||||||
|
|
||||||
|
|
|
@ -101,8 +101,7 @@ class Processor {
|
||||||
std::vector<Breakpoint*> breakpoints() const { return breakpoints_; }
|
std::vector<Breakpoint*> breakpoints() const { return breakpoints_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool ExceptionCallbackThunk(Exception* ex, void* data);
|
void BreakpointFunctionDefined(Function* function);
|
||||||
bool ExceptionCallback(Exception* ex);
|
|
||||||
|
|
||||||
bool DemandFunction(Function* function);
|
bool DemandFunction(Function* function);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue