diff --git a/src/alloy/runtime/instrument.cc b/src/alloy/runtime/instrument.cc new file mode 100644 index 000000000..5bae5fc98 --- /dev/null +++ b/src/alloy/runtime/instrument.cc @@ -0,0 +1,122 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include +#include +#include + +using namespace alloy; +using namespace alloy::runtime; + + + +Instrument::Instrument(Runtime* runtime) : + runtime_(runtime), + memory_(runtime->memory()), + is_attached_(false) { +} + +Instrument::~Instrument() { + if (is_attached_) { + Detach(); + } +} + +bool Instrument::Attach() { + if (is_attached_) { + return false; + } + //runtime->AttachInstrument(this); + is_attached_ = true; + return true; +} + +bool Instrument::Detach() { + if (!is_attached_) { + return false; + } + is_attached_ = false; + //runtime->DetachInstrument(this); + return true; +} + + +FunctionInstrument::FunctionInstrument( + Runtime* runtime, Function* function) : + target_(function), + Instrument(runtime) { +} + +bool FunctionInstrument::Attach() { + if (!Instrument::Attach()) { + return false; + } + + // Function impl attach: + // - add instrument to list + // IVM: handle in Call() + // JIT: transition to instrumented state + // - rewrite enter/exit to jump to instrumentation thunk + // - some sort of locking required? + + return true; +} + +bool FunctionInstrument::Detach() { + if (!Instrument::Detach()) { + return false; + } + + // + + return true; +} + +void FunctionInstrument::Enter(ThreadState* thread_state) { + // ? Placement new? How to get instance type? +} + +void FunctionInstrument::Exit(ThreadState* thread_state) { + // +} + + +MemoryInstrument::MemoryInstrument( + Runtime* runtime, uint64_t address, uint64_t end_address) : + address_(address), end_address_(end_address), + Instrument(runtime) { +} + +bool MemoryInstrument::Attach() { + if (!Instrument::Attach()) { + return false; + } + + // TODO(benvanik): protect memory page, catch exception + // https://github.com/frida/frida-gum/blob/master/gum/gummemoryaccessmonitor.c + + return true; +} + +bool MemoryInstrument::Detach() { + if (!Instrument::Detach()) { + return false; + } + + // + + return true; +} + +void MemoryInstrument::Access( + ThreadState* thread_state, uint64_t address, AccessType type) { + // TODO(benvanik): get thread local instance +} diff --git a/src/alloy/runtime/instrument.h b/src/alloy/runtime/instrument.h new file mode 100644 index 000000000..2c45fc31c --- /dev/null +++ b/src/alloy/runtime/instrument.h @@ -0,0 +1,149 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef ALLOY_RUNTIME_INSTRUMENT_H_ +#define ALLOY_RUNTIME_INSTRUMENT_H_ + +#include + +XEDECLARECLASS1(alloy, Memory); + + +namespace alloy { +namespace runtime { + +class Function; +class Runtime; +class ThreadState; + + +class Instrument { +public: + Instrument(Runtime* runtime); + virtual ~Instrument(); + + Runtime* runtime() const { return runtime_; } + Memory* memory() const { return memory_; } + bool is_attached() const { return is_attached_; } + + virtual bool Attach(); + virtual bool Detach(); + +private: + Runtime* runtime_; + Memory* memory_; + bool is_attached_; +}; + + +class FunctionInstrument : public Instrument { +public: + FunctionInstrument(Runtime* runtime, Function* function); + virtual ~FunctionInstrument() {} + + Function* target() const { return target_; } + + virtual bool Attach(); + virtual bool Detach(); + +public: + void Enter(ThreadState* thread_state); + void Exit(ThreadState* thread_state); + +protected: + class Instance { + public: + Instance(FunctionInstrument* instrument) : instrument_(instrument) {} + virtual ~Instance() {} + + FunctionInstrument* instrument() const { return instrument_; } + + virtual void OnEnter(ThreadState* thread_state) = 0; + virtual void OnExit(ThreadState* thread_state) = 0; + + // TODO(benvanik): utilities: + // Log(...) + // DebugBreak(type) + // GetArg(N)/GetReturn()/SetReturn(V) ? + // CallSelf() + // Call(target_fn/address) + // Return(opt_value) + + private: + FunctionInstrument* instrument_; + }; + +private: + Function* target_; +}; + + +class MemoryInstrument : public Instrument { +public: + MemoryInstrument(Runtime* runtime, uint64_t address, uint64_t end_address); + virtual ~MemoryInstrument() {} + + uint64_t address() const { return address_; } + uint64_t end_address() const { return end_address_; } + + virtual bool Attach(); + virtual bool Detach(); + +public: + enum AccessType { + ACCESS_READ = (1 << 1), + ACCESS_WRITE = (1 << 2), + }; + void Access(ThreadState* thread_state, uint64_t address, AccessType type); + +protected: + class Instance { + public: + Instance(MemoryInstrument* instrument) : instrument_(instrument) {} + virtual ~Instance() {} + + MemoryInstrument* instrument() const { return instrument_; } + + virtual void OnAccess( + ThreadState* thread_state, uint64_t address, AccessType type) = 0; + + private: + MemoryInstrument* instrument_; + }; + +private: + uint64_t address_; + uint64_t end_address_; +}; + + +// ThreadInstrument +// (v Detach()) +// ThreadInstrumentInstance: +// instrument() +// v OnCreate(context, state_ptr) +// v OnStart(context, state_ptr) +// v OnResume(context, state_ptr) +// v OnSuspend(context, state_ptr) +// v OnExit(context, state_ptr) + +// ModuleInstrument +// (v Detach()) +// ModuleInstrumentInstance: +// instrument() +// v OnLoad(context) +// v OnUnload(context) +// // get proc address? + + +} // namespace runtime +} // namespace alloy + + +#endif // ALLOY_RUNTIME_INSTRUMENT_H_ diff --git a/src/alloy/runtime/sources.gypi b/src/alloy/runtime/sources.gypi index d4ef940ab..be12e8f4e 100644 --- a/src/alloy/runtime/sources.gypi +++ b/src/alloy/runtime/sources.gypi @@ -9,6 +9,8 @@ 'entry_table.h', 'function.cc', 'function.h', + 'instrument.cc', + 'instrument.h', 'module.cc', 'module.h', 'raw_module.cc',