diff --git a/circle.yml b/circle.yml index 61d890eb8..fa31f559b 100644 --- a/circle.yml +++ b/circle.yml @@ -135,9 +135,8 @@ defaults: run: name: "Test shared Hera (binaryen)" command: | - export ASAN_OPTIONS=detect_leaks=0 SO=$([ $(uname) = Darwin ] && echo dylib || echo so) - if [[ $PRELOAD_ASAN ]]; then export LD_PRELOAD=/usr/lib/clang/8/lib/linux/libclang_rt.asan-x86_64.so; fi + export DYLD_INSERT_LIBRARIES=/Applications/Xcode-10.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib testeth --version testeth -t GeneralStateTests/stEWASMTests -- --testpath tests --vm ~/build/src/libhera.$SO --singlenet Byzantium --evmc engine=binaryen $TESTETH_OPTIONS @@ -299,7 +298,7 @@ jobs: - CXX: c++ - GENERATOR: Unix Makefiles - BUILD_PARALLEL_JOBS: 4 - - CMAKE_OPTIONS: -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WABT=ON + - CMAKE_OPTIONS: -DHERA_DEBUGGING=ON -DHERA_BINARYEN=ON -DHERA_WABT=ON -DSANITIZE=address macos: xcode: "10.1.0" steps: @@ -354,24 +353,7 @@ workflows: version: 2 hera: jobs: - - lint - - linux-clang-shared-asan - - linux-gcc-shared-coverage - - linux-gcc-static-debug - - linux-clang-shared-release: - filters: - tags: - only: /.*/ - macos: filters: tags: only: /.*/ - - deploy: - requires: - - linux-clang-shared-release - - macos - filters: - branches: - ignore: /.*/ - tags: - only: /^v[0-9].*/ diff --git a/cmake/ProjectBinaryen.cmake b/cmake/ProjectBinaryen.cmake index bbe989839..caba17849 100644 --- a/cmake/ProjectBinaryen.cmake +++ b/cmake/ProjectBinaryen.cmake @@ -29,25 +29,33 @@ set(binaryen_other_libraries ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}wasm${CMAKE_STATIC_LIBRARY_SUFFIX} ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}asmjs${CMAKE_STATIC_LIBRARY_SUFFIX} ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}passes${CMAKE_STATIC_LIBRARY_SUFFIX} + ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}wasm${CMAKE_STATIC_LIBRARY_SUFFIX} ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}cfg${CMAKE_STATIC_LIBRARY_SUFFIX} ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}ir${CMAKE_STATIC_LIBRARY_SUFFIX} ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}emscripten-optimizer${CMAKE_STATIC_LIBRARY_SUFFIX} ${binary_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}support${CMAKE_STATIC_LIBRARY_SUFFIX} ) +set(binaryen_cxx_flags ${CMAKE_CXX_FLAGS}) +if (SANITIZE) + set(binaryen_cxx_flags "${binaryen_cxx_flags} -fsanitize=${SANITIZE}") +endif() + ExternalProject_Add(binaryen PREFIX ${prefix} - DOWNLOAD_NAME binaryen-1.37.35.tar.gz + DOWNLOAD_NAME binaryen-1.39.1.tar.gz DOWNLOAD_DIR ${prefix}/downloads SOURCE_DIR ${source_dir} BINARY_DIR ${binary_dir} - URL https://github.com/WebAssembly/binaryen/archive/1.37.35.tar.gz - URL_HASH SHA256=19439e41dc576446eaae0c4a8e07d4cd4c40aea7dfb0a6475b925686852f8006 + URL https://github.com/WebAssembly/binaryen/archive/1.39.1.tar.gz + URL_HASH SHA256=4852a676c383efffa368e58f2abf3108fcf02f0e8b6cd3923b0cdc35bc0ee8c9 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= -DCMAKE_INSTALL_LIBDIR=lib - -DCMAKE_BUILD_TYPE=Release + -DCMAKE_BUILD_TYPE=Debug -DBUILD_STATIC_LIB=ON + -DCMAKE_CXX_FLAGS=${binaryen_cxx_flags} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} ${build_command} ${install_command} BUILD_BYPRODUCTS ${binaryen_library} ${binaryen_other_libraries} @@ -63,7 +71,6 @@ set_target_properties( IMPORTED_LOCATION_RELEASE ${binaryen_library} INTERFACE_INCLUDE_DIRECTORIES ${binaryen_include_dir} INTERFACE_LINK_LIBRARIES "${binaryen_other_libraries}" - ) add_dependencies(binaryen::binaryen binaryen) diff --git a/src/binaryen.cpp b/src/binaryen.cpp index ff42a1a9e..d147f4b3a 100644 --- a/src/binaryen.cpp +++ b/src/binaryen.cpp @@ -49,9 +49,9 @@ class BinaryenEthereumInterface : public wasm::ShellExternalInterface, EthereumI { } protected: - wasm::Literal callImport(wasm::Import *import, wasm::LiteralList& arguments) override; + wasm::Literal callImport(wasm::Function* import, wasm::LiteralList& arguments) override; #if HERA_DEBUGGING - wasm::Literal callDebugImport(wasm::Import *import, wasm::LiteralList& arguments); + wasm::Literal callDebugImport(wasm::Function* import, wasm::LiteralList& arguments); #endif void importGlobals(map& globals, wasm::Module& wasm) override; @@ -77,7 +77,7 @@ class BinaryenEthereumInterface : public wasm::ShellExternalInterface, EthereumI } #if HERA_DEBUGGING - wasm::Literal BinaryenEthereumInterface::callDebugImport(wasm::Import *import, wasm::LiteralList& arguments) { + wasm::Literal BinaryenEthereumInterface::callDebugImport(wasm::Function *import, wasm::LiteralList& arguments) { heraAssert(import->module == wasm::Name("debug"), "Import namespace error."); if (import->base == wasm::Name("print32")) { @@ -138,7 +138,7 @@ class BinaryenEthereumInterface : public wasm::ShellExternalInterface, EthereumI } #endif - wasm::Literal BinaryenEthereumInterface::callImport(wasm::Import *import, wasm::LiteralList& arguments) { + wasm::Literal BinaryenEthereumInterface::callImport(wasm::Function* import, wasm::LiteralList& arguments) { #if HERA_DEBUGGING if (import->module == wasm::Name("debug")) // Reroute to debug namespace @@ -505,9 +505,7 @@ ExecutionResult BinaryenEngine::execute( executionStarted(); try { - wasm::Name main = wasm::Name("main"); - wasm::LiteralList args; - instance.callExport(main, args); + instance.callExport(wasm::Name("main"), wasm::LiteralList{}); } catch (EndExecution const&) { // This exception is ignored here because we consider it to be a success. // It is only a clutch for POSIX style exit() @@ -635,7 +633,11 @@ void BinaryenEngine::verifyContract(wasm::Module & module) { wasm::Name("selfDestruct"), createFunctionType({ wasm::Type::i32 }, wasm::Type::none) } }; - for (auto const& import: module.imports) { + for (auto const& import: module.functions) { + + if (!import->imported()) // Only check imported functions. + continue; + #if HERA_DEBUGGING if (import->module == wasm::Name("debug")) continue; @@ -655,7 +657,7 @@ void BinaryenEngine::verifyContract(wasm::Module & module) // NOTE: needs to be a copy by value due to `structuralComparison` requiring a non-const input wasm::FunctionType eei_function_type = eei_signatures.at(import->base); - wasm::FunctionType* function_type = module.getFunctionTypeOrNull(import->functionType); + wasm::FunctionType* function_type = module.getFunctionTypeOrNull(import->type); ensureCondition( function_type, ContractValidationFailure, diff --git a/src/shell-interface.h b/src/shell-interface.h index 556417291..09f82126a 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -51,7 +51,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { Memory& operator=(const Memory&) = delete; public: - Memory() {} + Memory() = default; // Gives no guarantee about the length of the memory. Caller needs to ensure that. char* rawpointer(size_t offset) { return &memory[offset]; @@ -94,26 +94,12 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { std::vector table; ShellExternalInterface() : memory() {} + virtual ~ShellExternalInterface() = default; void init(Module& wasm, ModuleInstance& instance) override { + (void)instance; memory.resize(wasm.memory.initial * wasm::Memory::kPageSize); - // apply memory segments - for (auto& segment : wasm.memory.segments) { - Address offset = static_cast(ConstantExpressionRunner(instance.globals).visit(segment.offset).value.geti32()); - assert(offset + segment.data.size() <= wasm.memory.initial * wasm::Memory::kPageSize); - for (size_t i = 0; i != segment.data.size(); ++i) { - memory.set(offset + i, segment.data[i]); - } - } - table.resize(wasm.table.initial); - for (auto& segment : wasm.table.segments) { - Address offset = static_cast(ConstantExpressionRunner(instance.globals).visit(segment.offset).value.geti32()); - assert(offset + segment.data.size() <= wasm.table.initial); - for (size_t i = 0; i != segment.data.size(); ++i) { - table[offset + i] = segment.data[i]; - } - } } void importGlobals(std::map& globals, Module& wasm) override { @@ -122,7 +108,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { trap("No globals supported."); } - Literal callImport(Import *import, LiteralList& arguments) override { + Literal callImport(Function* import, LiteralList& arguments) override { (void)import; (void)arguments; trap("No imports supported."); @@ -142,7 +128,11 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { if (func->result != result) { trap("callIndirect: bad result type"); } - return instance.callFunctionInternal(func->name, arguments); + if (func->imported()) { + return callImport(func, arguments); + } else { + return instance.callFunctionInternal(func->name, arguments); + } } int8_t load8s(Address addr) override { return memory.get(addr); } @@ -153,11 +143,19 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { uint32_t load32u(Address addr) override { return memory.get(addr); } int64_t load64s(Address addr) override { return memory.get(addr); } uint64_t load64u(Address addr) override { return memory.get(addr); } + std::array load128(Address addr) override { + return memory.get>(addr); + } void store8(Address addr, int8_t value) override { memory.set(addr, value); } void store16(Address addr, int16_t value) override { memory.set(addr, value); } void store32(Address addr, int32_t value) override { memory.set(addr, value); } void store64(Address addr, int64_t value) override { memory.set(addr, value); } + void store128(Address addr, const std::array& value) override { + memory.set>(addr, value); + } + + void tableStore(Address addr, Name entry) override { table[addr] = entry; } void growMemory(Address /*oldSize*/, Address newSize) override { memory.resize(newSize);