diff --git a/CMakeLists.txt b/CMakeLists.txt index eb086b3..aea9756 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,3 +121,4 @@ endfunction() add_sample(hello_world) add_sample(sum) add_sample(erc20) +add_sample(disassembler) diff --git a/include/eEVM/disassembler.h b/include/eEVM/disassembler.h index a70f4da..f88e29d 100644 --- a/include/eEVM/disassembler.h +++ b/include/eEVM/disassembler.h @@ -71,14 +71,15 @@ namespace eevm inline std::ostream& operator<<(std::ostream& os, const Instr& i) { os << fmt::format( - "{}: {}{} ({:02x} {:02x}); {}", + "{:>5}: {}{} [{:02x}{}]; {}", i.pc, i.op.mnemonic, i.op.has_immediate() ? - fmt::format(" 0x{}", to_lower_hex_str(i.get_immediate())) : + fmt::format(" {}", to_lower_hex_str(i.get_immediate())) : "", (int)i.op.opcode, - fmt::join(i.raw_imm, " "), + i.raw_imm.size() > 0 ? fmt::format(" {:02x}", fmt::join(i.raw_imm, " ")) : + "", i.comment); return os; } @@ -124,7 +125,13 @@ namespace eevm const auto op = getOp((Opcode)opcode); const auto bytes_left = prog.cend() - it; if (bytes_left < op.immediate_bytes) - throw std::out_of_range("Immediate exceeds instruction stream."); + throw std::out_of_range(fmt::format( + "Immediate exceeds instruction stream (op {} at " + "instruction {} wants {} bytes, only {} remain)", + op.mnemonic, + (size_t)(it - prog.cbegin()), + op.immediate_bytes, + bytes_left)); auto instr = std::make_unique( op, pc, std::vector(it, it + op.immediate_bytes)); diff --git a/samples/disassembler/main.cpp b/samples/disassembler/main.cpp new file mode 100644 index 0000000..394329a --- /dev/null +++ b/samples/disassembler/main.cpp @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "eEVM/disassembler.h" + +#include +#include + +int usage(const char* bin_name) +{ + std::cout << fmt::format("Usage: {} hex_bytecode", bin_name) << std::endl; + std::cout << "Prints disassembly of argument" << std::endl; + return 1; +} + +int main(int argc, char** argv) +{ + if (argc != 2) + { + return usage(argv[0]); + } + + const std::vector code = eevm::to_bytes(argv[1]); + + const auto dis = eevm::Disassembler::dis(code); + + std::cout << dis << std::endl; + + return 0; +}