diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index 23f19ac94..03b6ccf2f 100644 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -21,6 +21,7 @@ #include "Instruction.h" +#include #include #include #include @@ -294,27 +295,42 @@ static const std::map c_instructionInfo = { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true, ZeroTier } } }; -string dev::eth::disassemble(bytes const& _mem) +void dev::eth::eachInstruction( + bytes const& _mem, + function const& _onInstruction +) { - stringstream ret; - unsigned numerics = 0; for (auto it = _mem.begin(); it != _mem.end(); ++it) { - byte n = *it; - auto iit = c_instructionInfo.find((Instruction)n); - if (numerics || iit == c_instructionInfo.end() || (byte)iit->first != n) // not an instruction or expecting an argument... + Instruction instr = Instruction(*it); + size_t additional = 0; + if (isValidInstruction(instr)) + additional = instructionInfo(instr).additional; + u256 data; + for (size_t i = 0; i < additional; ++i) { - if (numerics) - numerics--; - ret << "0x" << hex << (int)n << " "; + data <<= 8; + if (it != _mem.end() && ++it != _mem.end()) + data |= *it; } + _onInstruction(instr, data); + } +} + +string dev::eth::disassemble(bytes const& _mem) +{ + stringstream ret; + eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) { + if (!isValidInstruction(_instr)) + ret << "0x" << hex << int(_instr) << " "; else { - auto const& ii = iit->second; - ret << ii.name << " "; - numerics = ii.additional; + InstructionInfo info = instructionInfo(_instr); + ret << info.name << " "; + if (info.additional) + ret << "0x" << hex << _data << " "; } - } + }); return ret.str(); } diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index 07c7b52fd..2ccf5bc34 100644 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include #include @@ -253,6 +254,9 @@ bool isValidInstruction(Instruction _inst); /// Convert from string mnemonic to Instruction type. extern const std::map c_instructions; +/// Iterate through EVM code and call a function on each instruction. +void eachInstruction(bytes const& _mem, std::function const& _onInstruction); + /// Convert from EVM code to simple EVM assembly language. std::string disassemble(bytes const& _mem);