Skip to content

Commit

Permalink
Start code analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Feb 12, 2019
1 parent fc1d18a commit 969295c
Show file tree
Hide file tree
Showing 12 changed files with 459 additions and 0 deletions.
41 changes: 41 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
Language: Cpp
BasedOnStyle: Chromium
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
BinPackParameters: true
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
SplitEmptyFunction: false
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
ColumnLimit: 100
ConstructorInitializerIndentWidth: 2
IncludeCategories:
- Regex: '^".*'
Priority: 1
- Regex: '^<boost.*'
Priority: 98
- Regex: '^<.*\.(h|hpp)>'
Priority: 2
- Regex: '^<.*'
Priority: 99
- Regex: '.*'
Priority: 4
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentWidth: 4
MaxEmptyLinesToKeep: 2
PenaltyBreakAssignment: 1
PenaltyBreakComment: 50
TabWidth: 4
...
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/build
/cmake-build-*
/.idea
35 changes: 35 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# evmone: Ethereum Virtual Machine
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

cmake_minimum_required(VERSION 3.5)

option(EVMONE_TESTING "Build tests and test tools" OFF)

include(cmake/cable/bootstrap.cmake)
include(CableBuildType)
include(CableCompilerSettings)
include(CableToolchains)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

cable_configure_toolchain(DEFAULT cxx17-pic)

if(EVMONE_TESTING)
include(HunterConfig)
endif()

project(evmone)
set(PROJECT_VERSION 0.1.0-dev)

cable_set_build_type(DEFAULT Release CONFIGURATION_TYPES Debug Release)
cable_configure_compiler()

add_subdirectory(evmc)
add_subdirectory(lib)

if(EVMONE_TESTING)
enable_testing()
add_subdirectory(test)
endif()

12 changes: 12 additions & 0 deletions cmake/HunterConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# evmone: Fast Ethereum Virtual Machine implementation
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

set(HUNTER_CONFIGURATION_TYPES Release CACHE STRING "Build type of Hunter packages")

include(HunterGate)

HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.23.64.tar.gz"
SHA1 "a5f3c4999e03173d28b8469c4da4545dea740a41"
)
5 changes: 5 additions & 0 deletions cmake/toolchains/cxx17-pic.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
5 changes: 5 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# evmone: Fast Ethereum Virtual Machine implementation
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

add_subdirectory(evmone)
6 changes: 6 additions & 0 deletions lib/evmone/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# evmone: Fast Ethereum Virtual Machine implementation
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

add_library(evmone analysis.cpp)
target_link_libraries(evmone PRIVATE evmc::instructions)
90 changes: 90 additions & 0 deletions lib/evmone/analysis.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0.

#include "analysis.hpp"

#include <evmc/instructions.h>

namespace evmone
{
namespace
{
bool is_terminator(uint8_t c) noexcept
{
return c == OP_JUMP || c == OP_JUMPI || c == OP_STOP || c == OP_RETURN || c == OP_REVERT ||
c == OP_SELFDESTRUCT;
}
}

int code_analysis::find_jumpdest(int offset) noexcept
{
// TODO: Replace with lower_bound().
for (const auto& d : jumpdest_map)
{
if (d.first == offset)
return d.second;
}
return -1;
}

code_analysis analyze(const exec_fn_table& fns, const uint8_t* code, size_t code_size) noexcept
{
code_analysis analysis;
analysis.instrs.reserve(code_size + 1);

auto* instr_table = evmc_get_instruction_metrics_table(EVMC_BYZANTIUM);

block_info* block = nullptr;
int instr_index = 0;
for (size_t i = 0; i < code_size; ++i, ++instr_index)
{
const auto c = code[i];
auto& instr = analysis.instrs.emplace_back(fns[c]);

const bool jumpdest = c == OP_JUMPDEST;
if (!block || jumpdest)
{
// Create new block.
block = &analysis.blocks.emplace_back();
instr.block_index = static_cast<int>(analysis.blocks.size() - 1);

if (jumpdest)
analysis.jumpdest_map.emplace_back(static_cast<int>(i), instr_index);
}

auto metrics = instr_table[c];
block->gas_cost += metrics.gas_cost;
auto stack_req = metrics.num_stack_arguments - block->stack_diff;
block->stack_diff += (metrics.num_stack_returned_items - metrics.num_stack_arguments);
block->stack_req = std::max(block->stack_req, stack_req);
block->stack_max = std::max(block->stack_max, block->stack_diff);

// Skip PUSH data.
if (c >= OP_PUSH1 && c <= OP_PUSH32)
{
++i;
auto push_size = size_t(c - OP_PUSH1 + 1);
analysis.extra.emplace_back();
auto& extra = analysis.extra.back();

auto leading_zeros = 32 - push_size;
for (auto& b : extra.bytes)
b = 0;
for (size_t j = 0; j < push_size && (i + j) < code_size; ++j)
extra.bytes[leading_zeros + j] = code[i + j];
instr.extra_data_index = static_cast<int>(analysis.extra.size() - 1);
i += push_size - 1;
}
else if (is_terminator(c))
block = nullptr;
}

// Not terminated block.
if (block)
analysis.instrs.emplace_back(nullptr);

return analysis;
}

} // namespace evmone
49 changes: 49 additions & 0 deletions lib/evmone/analysis.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0.

#include <array>
#include <cstdint>
#include <vector>

namespace evmone
{
using exec_fn = void (*)();

using exec_fn_table = std::array<exec_fn, 256>;

struct instr_info
{
exec_fn fn = nullptr;
int extra_data_index = -1;
int block_index = -1;

explicit constexpr instr_info(exec_fn fn) noexcept : fn{fn} {};
};

struct block_info
{
int64_t gas_cost = 0;
int stack_req = 0;
int stack_max = 0;
int stack_diff = 0;
};

struct extra_data
{
uint8_t bytes[32];
};

struct code_analysis
{
std::vector<instr_info> instrs;
std::vector<block_info> blocks;
std::vector<extra_data> extra;
std::vector<std::pair<int, int>> jumpdest_map;

int find_jumpdest(int offset) noexcept;
};

code_analysis analyze(const exec_fn_table& fns, const uint8_t* code, size_t code_size) noexcept;

} // namespace evmone
7 changes: 7 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# evmone: Fast Ethereum Virtual Machine implementation
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

set(evmone_private_include_dir ${PROJECT_SOURCE_DIR}/lib)

add_subdirectory(unittests)
14 changes: 14 additions & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# evmone: Fast Ethereum Virtual Machine implementation
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

hunter_add_package(GTest)
find_package(GTest CONFIG REQUIRED)

add_executable(evmone-unittests
test_analysis.cpp
)

target_link_libraries(evmone-unittests PRIVATE evmone evmc::instructions GTest::gtest GTest::main)
target_include_directories(evmone-unittests PRIVATE ${evmone_private_include_dir})
set_target_properties(evmone-unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
Loading

0 comments on commit 969295c

Please sign in to comment.