From d15996fab0389fc453a4600548fd978580a77251 Mon Sep 17 00:00:00 2001 From: cdetrio Date: Mon, 29 Jul 2019 14:45:15 -0400 Subject: [PATCH] add scout host functions --- src/scout/scout.h | 192 +++++++++++++++++++++++++++++++++++++++ src/tools/wasm-interp.cc | 6 ++ 2 files changed, 198 insertions(+) create mode 100644 src/scout/scout.h diff --git a/src/scout/scout.h b/src/scout/scout.h new file mode 100644 index 000000000..ffc3aa49b --- /dev/null +++ b/src/scout/scout.h @@ -0,0 +1,192 @@ +#include "src/interp/interp.h" + +#include + +#include +#include + +#include +#include +#include +#include + +using bytes = std::basic_string; + + +bytes from_hex(std::string_view hex) +{ + if (hex.length() % 2 == 1) + //throw std::length_error{"the length of the input is odd"}; + printf("ERROR: the length of the input is odd\n"); + + bytes bs; + int b = 0; + for (size_t i = 0; i < hex.size(); ++i) + { + auto h = hex[i]; + int v; + if (h >= '0' && h <= '9') + v = h - '0'; + else if (h >= 'a' && h <= 'f') + v = h - 'a' + 10; + else if (h >= 'A' && h <= 'F') + v = h - 'A' + 10; + else + //throw std::out_of_range{"not a hex digit"}; + printf("ERROR: not a hex digit\n"); + + if (i % 2 == 0) + b = v << 4; + else + bs.push_back(static_cast(b | v)); + } + return bs; +} + + + + +using namespace wabt; +using namespace wabt::interp; + + +void AppendScoutFuncs(wabt::interp::Environment* env, wabt::interp::HostModule* host_module_env) { + + + // TODO: read the file name from an argument + std::ifstream blockDataFile{"./test_block_data.hex"}; + std::string blockdata_hex{std::istreambuf_iterator{blockDataFile}, std::istreambuf_iterator{}}; + + blockdata_hex.erase( + std::remove_if(blockdata_hex.begin(), blockdata_hex.end(), [](char x) { return std::isspace(x); }), + blockdata_hex.end()); + + + // bytes is a basic_string + auto blockdata_bytes = std::make_shared(from_hex(blockdata_hex)); + //std::cout << "blockdata bytes length:" << blockdata_bytes->size() << std::endl; + + const unsigned char* blockData = blockdata_bytes->data(); + + //int block_data_size = std::strlen((char*)blockData); + //std::cout << "blockData[] length:" << block_data_size << std::endl; + //printf("blockData: %s\n", blockData); + + //for(int i=0; i < block_data_size; ++i) + // std::cout << std::hex << (int)blockData[i]; + //std::cout << std::endl; + + + host_module_env->AppendFuncExport( + "eth2_loadPreStateRoot", + {{Type::I32}, {}}, + // [env]( // TODO: use to load prestate root from memory + []( + const interp::HostFunc*, + const interp::FuncSignature*, + const interp::TypedValues& args, + interp::TypedValues& results + ) { + // TODO: use env to load prestate root from wasm memory + //printf("eth2_loadPreStateRoot mem_pos: %llu\n", args[0].value.i32); + return interp::Result::Ok; + } + ); + + host_module_env->AppendFuncExport( + "eth2_savePostStateRoot", + {{Type::I32}, {}}, + [env]( + const interp::HostFunc*, + const interp::FuncSignature*, + const interp::TypedValues& args, + interp::TypedValues& results + ) { + //printf("eth2_savePostStateRoot mem_pos: %llu\n", args[0].value.i32); + + wabt::interp::Memory* mem = env->GetMemory(0); + + unsigned char postStateData[32]; + uint32_t ret_offset = args[0].value.i32; + + uint8_t* mem_ptr = reinterpret_cast(&mem->data[ret_offset]); + uint8_t* mem_ptr_end = reinterpret_cast(&mem->data[ret_offset+32]); + + //printf("eth2_savePostStateRoot copying memory...\n"); + std::copy(mem_ptr, mem_ptr_end, postStateData); + + /// print returned state root + char buffer [33]; + buffer[32] = 0; + for(int j = 0; j < 16; j++) + sprintf(&buffer[2*j], "%02X", postStateData[j]); + + //std::cout << "eth2_savePostStateRoot: " << std::hex << buffer << std::endl; + return interp::Result::Ok; + } + ); + + host_module_env->AppendFuncExport( + "eth2_blockDataSize", + {{}, {Type::I32}}, + [blockdata_bytes]( + const interp::HostFunc*, + const interp::FuncSignature*, + const interp::TypedValues& args, + interp::TypedValues& results + ) { + //printf("eth2_blockDataSize\n"); + + int data_size = blockdata_bytes->size(); + + //printf("data_size: %d\n", data_size); + + results[0].set_i32(data_size); + + return interp::Result::Ok; + } + ); + + host_module_env->AppendFuncExport( + "eth2_blockDataCopy", + {{Type::I32, Type::I32, Type::I32}, {}}, + [env, blockData]( + const interp::HostFunc*, + const interp::FuncSignature*, + const interp::TypedValues& args, + interp::TypedValues& + ) { + //printf("eth2_blockDataCopy.\n"); + + wabt::interp::Memory* mem = env->GetMemory(0); + + // arg order: eth2_blockDataCopy(outOffset, srcOffset, length) + uint32_t out_offset = args[0].value.i32; + uint32_t src_offset = args[1].value.i32; + uint32_t copy_len = args[2].value.i32; + + //printf("eth2_blockDataCopy out_offset: %d\n", args[0].value.i32); + //printf("eth2_blockDataCopy src_offset: %d\n", args[1].value.i32); + //printf("eth2_blockDataCopy copy_len: %d\n", args[2].value.i32); + + std::copy(blockData+src_offset, blockData+copy_len, &mem->data[out_offset]); + //std::cout << "eth2_blockDataCopy wrote to mem." << std::endl; + + /* *** debugging helper + // inspect written memory + unsigned char writtenToMem[32]; + uint8_t* mem_ptr = reinterpret_cast(&mem->data[out_offset]); + uint8_t* mem_ptr_end = reinterpret_cast(&mem->data[out_offset+32]); + std::copy(mem_ptr, mem_ptr_end, writtenToMem); + char bufferWrittenMem [33]; + bufferWrittenMem[32] = 0; + for(int j = 0; j < 16; j++) + sprintf(&bufferWrittenMem[2*j], "%02X", writtenToMem[j]); + std::cout << "eth2_blockDataCopy memory after writing:" << std::hex << bufferWrittenMem << std::endl; + */ + + return interp::Result::Ok; + } + ); + +} \ No newline at end of file diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc index c08a4382a..c60ed5114 100644 --- a/src/tools/wasm-interp.cc +++ b/src/tools/wasm-interp.cc @@ -37,6 +37,8 @@ #include "src/wast-lexer.h" #include "src/wast-parser.h" +#include "src/scout/scout.h" + using namespace wabt; using namespace wabt::interp; @@ -200,6 +202,10 @@ static void InitEnvironment(Environment* env) { return true; }; } + + // append scout host functions + HostModule* env_for_scout = env->AppendHostModule("env"); + AppendScoutFuncs(env, env_for_scout); } static wabt::Result ReadAndRunModule(const char* module_filename) {