Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Commit

Permalink
EVMC tracing for interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Jun 5, 2018
1 parent 9c99c5b commit 826680d
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 10 deletions.
2 changes: 1 addition & 1 deletion evmc
Submodule evmc updated 1 files
+22 −0 include/evmc/evmc.h
32 changes: 32 additions & 0 deletions libevm/EVMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,36 @@ EVM::EVM(evmc_instance* _instance) noexcept : m_instance(_instance)
m_instance->set_option(m_instance, pair.first.c_str(), pair.second.c_str());
}

EVMC::EVMC(evmc_instance* _instance) : EVM(_instance)
{
static constexpr auto tracer = [](evmc_tracer_context * context, int depth, int step,
size_t code_offset, evmc_status_code status_code, int64_t gas_left, size_t stack_num_items,
const evmc_uint256be* pushed_stack_item, size_t memory_size,
size_t changed_memory_offset, size_t changed_memory_size,
const uint8_t* changed_memory) noexcept {

EVMC* evmc = reinterpret_cast<EVMC*>(context);

// TODO: It might be easier to just pass instruction from VM.
InstructionInfo instrInfo = instructionInfo(static_cast<Instruction>(evmc->m_code[code_offset]));

std::cerr << "EVMC " << depth << " " << step << " " << code_offset << " " << instrInfo.name << " " << status_code
<< " " << gas_left << " " << stack_num_items;

if (pushed_stack_item)
std::cerr << " +[" << fromEvmC(*pushed_stack_item) << "]";

std::cerr << " " << memory_size << "\n";

(void)changed_memory_offset;
(void)changed_memory_size;
(void)changed_memory_size;
(void)changed_memory;
};

_instance->set_tracer(_instance, tracer, reinterpret_cast<evmc_tracer_context*>(this));
}

owning_bytes_ref EVMC::exec(u256& io_gas, ExtVMFace& _ext, const OnOpFunc& _onOp)
{
assert(_ext.envInfo().number() >= 0);
Expand All @@ -35,6 +65,8 @@ owning_bytes_ref EVMC::exec(u256& io_gas, ExtVMFace& _ext, const OnOpFunc& _onOp
assert(_ext.envInfo().gasLimit() <= int64max);
assert(_ext.depth <= static_cast<size_t>(std::numeric_limits<int32_t>::max()));

m_code = bytesConstRef{&_ext.code};

auto gas = static_cast<int64_t>(io_gas);
EVM::Result r = execute(_ext, gas);

Expand Down
5 changes: 4 additions & 1 deletion libevm/EVMC.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,12 @@ class EVM
class EVMC : public EVM, public VMFace
{
public:
explicit EVMC(evmc_instance* _instance) : EVM(_instance) {}
explicit EVMC(evmc_instance* _instance);

owning_bytes_ref exec(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) final;

private:
bytesConstRef m_code;
};
}
}
48 changes: 41 additions & 7 deletions libevm/VM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,36 @@ VM::VM()
aleth_get_buildinfo()->project_version,
::destroy,
::execute,
setTracer,
nullptr,
}
{}

void VM::setTracer(
evmc_instance* _instance, evmc_trace_callback _callback, evmc_tracer_context* _context) noexcept
{
auto vm = static_cast<dev::eth::VM*>(_instance);
vm->m_trace = _callback;
vm->m_traceContext = _context;
}

void VM::trace() noexcept
{
if (m_trace)
{
InstructionMetric const& metric = c_metrics[static_cast<size_t>(m_OP)];
evmc_uint256be topStackItem;
evmc_uint256be const* pushedStackItem = nullptr;
if (metric.ret == 1)
{
topStackItem = toEvmC(m_SPP[0]);
pushedStackItem = &topStackItem;
}
m_trace(m_traceContext, m_message->depth, m_step++, m_PC, EVMC_SUCCESS, m_io_gas,
m_stackEnd - m_SPP, pushedStackItem, m_mem.size(), 0, 0, nullptr);
}
}

uint64_t VM::memNeed(u256 _offset, u256 _size)
{
return toInt63(_size ? u512(_offset) + _size : u512(0));
Expand Down Expand Up @@ -387,6 +413,7 @@ void VM::interpretCases()
updateIOGas();

m_SPP[0] = (u256)*(h256 const*)(m_mem.data() + (unsigned)m_SP[0]);
trace();
}
NEXT

Expand All @@ -397,6 +424,7 @@ void VM::interpretCases()
updateIOGas();

*(h256*)&m_mem[(unsigned)m_SP[0]] = (h256)m_SP[1];
trace();
}
NEXT

Expand Down Expand Up @@ -1530,11 +1558,14 @@ void VM::interpretCases()
// get val at two-byte offset into const pool and advance pc by one-byte remainder
TRACE_OP(2, m_PC, m_OP);
unsigned off;
++m_PC;
off = m_code[m_PC++] << 8;
off |= m_code[m_PC++];
m_PC += m_code[m_PC];
uint64_t pc = m_PC;
++pc;
off = m_code[pc++] << 8;
off |= m_code[pc++];
pc += m_code[pc];
m_SPP[0] = m_pool[off];
trace();
m_PC = pc;
TRACE_VAL(2, "Retrieved pooled const", m_SPP[0]);
#else
throwBadInstruction();
Expand All @@ -1546,9 +1577,9 @@ void VM::interpretCases()
{
ON_OP();
updateIOGas();
++m_PC;
m_SPP[0] = m_code[m_PC];
++m_PC;
m_SPP[0] = m_code[m_PC + 1];
trace();
m_PC += 2;
}
CONTINUE

Expand Down Expand Up @@ -1594,6 +1625,8 @@ void VM::interpretCases()
// bytes to handle "out of code" push data here.
for (++m_PC; numBytes--; ++m_PC)
m_SPP[0] = (m_SPP[0] << 8) | m_code[m_PC];

trace();
}
CONTINUE

Expand Down Expand Up @@ -1722,6 +1755,7 @@ void VM::interpretCases()

updateSSGas();
updateIOGas();
trace();

evmc_uint256be key = toEvmC(m_SP[0]);
evmc_uint256be value = toEvmC(m_SP[1]);
Expand Down
10 changes: 9 additions & 1 deletion libevm/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ class VM : public evmc_instance
void copyCode(int);
typedef void (VM::*MemFnPtr)();
MemFnPtr m_bounce = nullptr;
uint64_t m_nSteps = 0;

// return bytes
owning_bytes_ref m_output;
Expand Down Expand Up @@ -138,6 +137,15 @@ class VM : public evmc_instance
uint64_t m_newMemSize = 0;
uint64_t m_copyMemSize = 0;

// EVMC tracing.
int m_step = 0;
evmc_trace_callback m_trace = nullptr;
evmc_tracer_context* m_traceContext = nullptr;
static void setTracer(evmc_instance* _instance, evmc_trace_callback _callback,
evmc_tracer_context* _context) noexcept;

void trace() noexcept;

// initialize interpreter
void initEntry();
void optimize();
Expand Down

0 comments on commit 826680d

Please sign in to comment.