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

Commit 826680d

Browse files
committed
EVMC tracing for interpreter
1 parent 9c99c5b commit 826680d

File tree

5 files changed

+87
-10
lines changed

5 files changed

+87
-10
lines changed

evmc

Submodule evmc updated from 6743fb9 to 9505981

libevm/EVMC.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,36 @@ EVM::EVM(evmc_instance* _instance) noexcept : m_instance(_instance)
2121
m_instance->set_option(m_instance, pair.first.c_str(), pair.second.c_str());
2222
}
2323

24+
EVMC::EVMC(evmc_instance* _instance) : EVM(_instance)
25+
{
26+
static constexpr auto tracer = [](evmc_tracer_context * context, int depth, int step,
27+
size_t code_offset, evmc_status_code status_code, int64_t gas_left, size_t stack_num_items,
28+
const evmc_uint256be* pushed_stack_item, size_t memory_size,
29+
size_t changed_memory_offset, size_t changed_memory_size,
30+
const uint8_t* changed_memory) noexcept {
31+
32+
EVMC* evmc = reinterpret_cast<EVMC*>(context);
33+
34+
// TODO: It might be easier to just pass instruction from VM.
35+
InstructionInfo instrInfo = instructionInfo(static_cast<Instruction>(evmc->m_code[code_offset]));
36+
37+
std::cerr << "EVMC " << depth << " " << step << " " << code_offset << " " << instrInfo.name << " " << status_code
38+
<< " " << gas_left << " " << stack_num_items;
39+
40+
if (pushed_stack_item)
41+
std::cerr << " +[" << fromEvmC(*pushed_stack_item) << "]";
42+
43+
std::cerr << " " << memory_size << "\n";
44+
45+
(void)changed_memory_offset;
46+
(void)changed_memory_size;
47+
(void)changed_memory_size;
48+
(void)changed_memory;
49+
};
50+
51+
_instance->set_tracer(_instance, tracer, reinterpret_cast<evmc_tracer_context*>(this));
52+
}
53+
2454
owning_bytes_ref EVMC::exec(u256& io_gas, ExtVMFace& _ext, const OnOpFunc& _onOp)
2555
{
2656
assert(_ext.envInfo().number() >= 0);
@@ -35,6 +65,8 @@ owning_bytes_ref EVMC::exec(u256& io_gas, ExtVMFace& _ext, const OnOpFunc& _onOp
3565
assert(_ext.envInfo().gasLimit() <= int64max);
3666
assert(_ext.depth <= static_cast<size_t>(std::numeric_limits<int32_t>::max()));
3767

68+
m_code = bytesConstRef{&_ext.code};
69+
3870
auto gas = static_cast<int64_t>(io_gas);
3971
EVM::Result r = execute(_ext, gas);
4072

libevm/EVMC.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,12 @@ class EVM
9191
class EVMC : public EVM, public VMFace
9292
{
9393
public:
94-
explicit EVMC(evmc_instance* _instance) : EVM(_instance) {}
94+
explicit EVMC(evmc_instance* _instance);
9595

9696
owning_bytes_ref exec(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) final;
97+
98+
private:
99+
bytesConstRef m_code;
97100
};
98101
}
99102
}

libevm/VM.cpp

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,36 @@ VM::VM()
9191
aleth_get_buildinfo()->project_version,
9292
::destroy,
9393
::execute,
94+
setTracer,
9495
nullptr,
9596
}
9697
{}
9798

99+
void VM::setTracer(
100+
evmc_instance* _instance, evmc_trace_callback _callback, evmc_tracer_context* _context) noexcept
101+
{
102+
auto vm = static_cast<dev::eth::VM*>(_instance);
103+
vm->m_trace = _callback;
104+
vm->m_traceContext = _context;
105+
}
106+
107+
void VM::trace() noexcept
108+
{
109+
if (m_trace)
110+
{
111+
InstructionMetric const& metric = c_metrics[static_cast<size_t>(m_OP)];
112+
evmc_uint256be topStackItem;
113+
evmc_uint256be const* pushedStackItem = nullptr;
114+
if (metric.ret == 1)
115+
{
116+
topStackItem = toEvmC(m_SPP[0]);
117+
pushedStackItem = &topStackItem;
118+
}
119+
m_trace(m_traceContext, m_message->depth, m_step++, m_PC, EVMC_SUCCESS, m_io_gas,
120+
m_stackEnd - m_SPP, pushedStackItem, m_mem.size(), 0, 0, nullptr);
121+
}
122+
}
123+
98124
uint64_t VM::memNeed(u256 _offset, u256 _size)
99125
{
100126
return toInt63(_size ? u512(_offset) + _size : u512(0));
@@ -387,6 +413,7 @@ void VM::interpretCases()
387413
updateIOGas();
388414

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

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

399426
*(h256*)&m_mem[(unsigned)m_SP[0]] = (h256)m_SP[1];
427+
trace();
400428
}
401429
NEXT
402430

@@ -1530,11 +1558,14 @@ void VM::interpretCases()
15301558
// get val at two-byte offset into const pool and advance pc by one-byte remainder
15311559
TRACE_OP(2, m_PC, m_OP);
15321560
unsigned off;
1533-
++m_PC;
1534-
off = m_code[m_PC++] << 8;
1535-
off |= m_code[m_PC++];
1536-
m_PC += m_code[m_PC];
1561+
uint64_t pc = m_PC;
1562+
++pc;
1563+
off = m_code[pc++] << 8;
1564+
off |= m_code[pc++];
1565+
pc += m_code[pc];
15371566
m_SPP[0] = m_pool[off];
1567+
trace();
1568+
m_PC = pc;
15381569
TRACE_VAL(2, "Retrieved pooled const", m_SPP[0]);
15391570
#else
15401571
throwBadInstruction();
@@ -1546,9 +1577,9 @@ void VM::interpretCases()
15461577
{
15471578
ON_OP();
15481579
updateIOGas();
1549-
++m_PC;
1550-
m_SPP[0] = m_code[m_PC];
1551-
++m_PC;
1580+
m_SPP[0] = m_code[m_PC + 1];
1581+
trace();
1582+
m_PC += 2;
15521583
}
15531584
CONTINUE
15541585

@@ -1594,6 +1625,8 @@ void VM::interpretCases()
15941625
// bytes to handle "out of code" push data here.
15951626
for (++m_PC; numBytes--; ++m_PC)
15961627
m_SPP[0] = (m_SPP[0] << 8) | m_code[m_PC];
1628+
1629+
trace();
15971630
}
15981631
CONTINUE
15991632

@@ -1722,6 +1755,7 @@ void VM::interpretCases()
17221755

17231756
updateSSGas();
17241757
updateIOGas();
1758+
trace();
17251759

17261760
evmc_uint256be key = toEvmC(m_SP[0]);
17271761
evmc_uint256be value = toEvmC(m_SP[1]);

libevm/VM.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ class VM : public evmc_instance
9292
void copyCode(int);
9393
typedef void (VM::*MemFnPtr)();
9494
MemFnPtr m_bounce = nullptr;
95-
uint64_t m_nSteps = 0;
9695

9796
// return bytes
9897
owning_bytes_ref m_output;
@@ -138,6 +137,15 @@ class VM : public evmc_instance
138137
uint64_t m_newMemSize = 0;
139138
uint64_t m_copyMemSize = 0;
140139

140+
// EVMC tracing.
141+
int m_step = 0;
142+
evmc_trace_callback m_trace = nullptr;
143+
evmc_tracer_context* m_traceContext = nullptr;
144+
static void setTracer(evmc_instance* _instance, evmc_trace_callback _callback,
145+
evmc_tracer_context* _context) noexcept;
146+
147+
void trace() noexcept;
148+
141149
// initialize interpreter
142150
void initEntry();
143151
void optimize();

0 commit comments

Comments
 (0)