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 18, 2018
1 parent 2b69b9e commit 5f0f14e
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 10 deletions.
2 changes: 1 addition & 1 deletion evmc
37 changes: 37 additions & 0 deletions libevm/EVMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,35 @@ 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 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.
char const* name = evmc->m_instructionNames[evmc->m_code[code_offset]];

std::cerr << "EVMC " << " " << step << " " << code_offset << " " << 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,8 +64,16 @@ 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};

// FIXME: EVMC revision found twice.
m_instructionNames = evmc_get_instruction_names_table(toRevision(_ext.evmSchedule()));


auto gas = static_cast<int64_t>(io_gas);
std::cerr << "EVMC message START " << _ext.depth << " " << _ext.caller << " -> " << _ext.myAddress << " gas: " << gas << "\n";
EVM::Result r = execute(_ext, gas);
std::cerr << "EVMC message END " << _ext.depth << " status: " << r.status() << " gas left: " << r.gasLeft() << "\n";

switch (r.status())
{
Expand Down
6 changes: 5 additions & 1 deletion libevm/EVMC.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,13 @@ 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;
char const* const* m_instructionNames = nullptr;
};
}
}
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)
{
auto const& metrics = c_metrics[static_cast<size_t>(m_OP)];
evmc_uint256be topStackItem;
evmc_uint256be const* pushedStackItem = nullptr;
if (metrics.num_stack_returned_items == 1)
{
topStackItem = toEvmC(m_SPP[0]);
pushedStackItem = &topStackItem;
}
m_trace(m_traceContext, 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 @@ -384,6 +410,7 @@ void VM::interpretCases()
updateIOGas();

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

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

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

Expand Down Expand Up @@ -1527,11 +1555,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 @@ -1543,9 +1574,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 @@ -1591,6 +1622,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 @@ -1719,6 +1752,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 @@ -93,7 +93,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 @@ -139,6 +138,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 5f0f14e

Please sign in to comment.