Experimenting with instrument API. Not quite right.

This commit is contained in:
Ben Vanik 2014-01-16 23:27:11 -08:00
parent 7641a5bfed
commit af4e107905
3 changed files with 273 additions and 0 deletions

View File

@ -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 <alloy/runtime/instrument.h>
#include <alloy/memory.h>
#include <alloy/runtime/function.h>
#include <alloy/runtime/runtime.h>
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
}

View File

@ -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 <alloy/core.h>
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_

View File

@ -9,6 +9,8 @@
'entry_table.h',
'function.cc',
'function.h',
'instrument.cc',
'instrument.h',
'module.cc',
'module.h',
'raw_module.cc',