Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
path = vcpkg
url = https://github.com/Microsoft/vcpkg.git

[submodule "libraries/sys-vm"]
path = libraries/sys-vm
url = https://github.com/Wire-Network/eos-vm
6 changes: 6 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ git clone --recursive https://github.com/Wire-Network/wire-sysio.git

# Enter the repo directory
cd wire-sysio

# Refresh pinned submodules when updating an existing checkout
git submodule update --init --recursive vcpkg libraries/appbase libraries/sys-vm
```

The eos-vm headers are built from the pinned `libraries/sys-vm` submodule. Softfloat and the other
third-party packages continue to come from vcpkg.

# On Host Machine

> **ONLY SUPPORTS:** Ubuntu 24.04 LTS and Ubuntu 25.x (x86_64).
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ sudo apt-get install -y build-essential binutils ccache cmake curl git ninja-bui
openjdk-21-jre-headless

# Initialize required submodules
git submodule update --init --recursive vcpkg libraries/appbase
git submodule update --init --recursive vcpkg libraries/appbase libraries/sys-vm

# Bootstrap vcpkg
./vcpkg/bootstrap-vcpkg.sh
Expand All @@ -122,7 +122,7 @@ rebuilds through CDT, `sys-vm-jit`, `sys-vm-oc`, and `native-module` are out of
# it keg-only, so its bin directory has to be on PATH for CMake's find_package(Java) to see it.
brew install cmake ninja ccache pkgconf autoconf automake libtool openjdk
export PATH="$(brew --prefix openjdk)/bin:$PATH"
git submodule update --init --recursive vcpkg libraries/appbase
git submodule update --init --recursive vcpkg libraries/appbase libraries/sys-vm
./vcpkg/bootstrap-vcpkg.sh

export BUILD_DIR=$PWD/build/macos-arm64
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ include(boost-test-discovery)
add_p_test(NAME boost_test_discovery_test
COMMAND ${CMAKE_COMMAND} -DGENERATOR=${CMAKE_GENERATOR} -DCXX=${CMAKE_CXX_COMPILER} -DCONFIG=$<CONFIG>
-P ${CMAKE_SOURCE_DIR}/cmake/test/boost-test-discovery-test.cmake)
add_p_test(NAME sys_vm_submodule_test
COMMAND ${CMAKE_COMMAND} -DGENERATOR=${CMAKE_GENERATOR} -DCXX=${CMAKE_CXX_COMPILER} -DCONFIG=$<CONFIG>
-DSOURCE_DIR=${CMAKE_SOURCE_DIR} -DWORK_DIR=${CMAKE_BINARY_DIR}/cmake-test/sys-vm-submodule
-DSOFTFLOAT_DIR=${softfloat_DIR} -P ${CMAKE_SOURCE_DIR}/cmake/test/sys-vm-submodule-test.cmake)

set(CLI_CLIENT_EXECUTABLE_NAME clio)
set(NODE_EXECUTABLE_NAME nodeop)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ contract debugging are not part of this support tier yet.
# it keg-only, so its bin directory has to be on PATH for CMake's find_package(Java) to see it.
brew install cmake ninja ccache pkgconf autoconf automake libtool openjdk
export PATH="$(brew --prefix openjdk)/bin:$PATH"
git submodule update --init --recursive vcpkg libraries/appbase
git submodule update --init --recursive vcpkg libraries/appbase libraries/sys-vm
./vcpkg/bootstrap-vcpkg.sh

cmake -B build/macos-arm64 -S . -G Ninja \
Expand Down
53 changes: 53 additions & 0 deletions cmake/add-sys-vm.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Add the pinned VM without changing Sysio's test, tool, compiler, or installation settings.
function(add_sys_vm_submodule SOURCE_DIRECTORY BINARY_DIRECTORY)
if(NOT EXISTS "${SOURCE_DIRECTORY}/CMakeLists.txt")
message(FATAL_ERROR "Missing sys-vm submodule. Run: git submodule update --init libraries/sys-vm")
endif()

# The subproject predates CMP0077; normal variables keep its options local to this function.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(ENABLE_TESTS OFF)
set(ENABLE_TOOLS OFF)
set(ENABLE_CCACHE OFF)
set(ENABLE_PROFILE OFF)
set(ENABLE_GPERFTOOLS OFF)
set(ENABLE_ADDRESS_SANITIZER OFF)
set(ENABLE_UNDEFINED_BEHAVIOR_SANITIZER OFF)
set(ENABLE_INSTALL ON)
set(ENABLE_SOFTFLOAT ON)
set(ENABLE_SOFTFLOAT_INSTALL OFF)
set(FULL_DEBUG_BUILD OFF)
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "${SYSVM_INSTALL_COMPONENT}")

# cmake_dependent_option writes the shared cache even with CMP0077 NEW. Preserve the parent choices.
set(dependent_options ENABLE_SPEC_TESTS ENABLE_FUZZ_TESTS
ENABLE_ADDRESS_SANITIZER ENABLE_UNDEFINED_BEHAVIOR_SANITIZER)
foreach(option IN LISTS dependent_options)
set(${option}_was_cached FALSE)
if(DEFINED CACHE{${option}})
set(${option}_was_cached TRUE)
foreach(property VALUE TYPE HELPSTRING)
get_property(${option}_${property} CACHE ${option} PROPERTY ${property})
endforeach()
endif()
endforeach()

# Both projects have a dependencies.cmake; resolve the VM's modules in its own source tree first.
list(PREPEND CMAKE_MODULE_PATH "${SOURCE_DIRECTORY}/cmake")
add_subdirectory("${SOURCE_DIRECTORY}" "${BINARY_DIRECTORY}")

foreach(option IN LISTS dependent_options)
if(${option}_was_cached)
set(${option} "${${option}_VALUE}" CACHE ${${option}_TYPE} "${${option}_HELPSTRING}" FORCE)
else()
unset(${option} CACHE)
endif()
endforeach()

# The standalone VM relies on global include paths; expose its headers to build and SDK consumers.
target_include_directories(sys-vm SYSTEM INTERFACE
"$<BUILD_INTERFACE:${SOURCE_DIRECTORY}/include>"
"$<INSTALL_INTERFACE:include>")
target_compile_features(sys-vm INTERFACE cxx_std_20)
add_library(sys-vm::sys-vm ALIAS sys-vm)
endfunction()
1 change: 0 additions & 1 deletion cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ find_package(bn256 CONFIG REQUIRED)
find_package(bls12-381 CONFIG REQUIRED)

find_package(CURL 8.16.0 CONFIG REQUIRED)
find_package(sys-vm CONFIG REQUIRED)

# Allocator overrides - linked per-target by apply_malloc_config (cmake/linker-config.cmake).
# vcpkg jemalloc port only ships .a + pkg-config (no CMake config), so find by name when enabled.
Expand Down
7 changes: 6 additions & 1 deletion cmake/licenses.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ configure_file(${CMAKE_SOURCE_DIR}/LICENSE.md licenses/sysio/LICENSE.md COPYONLY

# In-tree dependency licenses
configure_file(${CMAKE_SOURCE_DIR}/libraries/wasm-jit/LICENSE licenses/sysio/LICENSE.wavm COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/sys-vm/LICENSE.md licenses/sysio/LICENSE.wire-sys-vm COPYONLY)

# vcpkg dependency licenses
# Collect copyright files from all vcpkg-installed packages into the licenses directory.
Expand Down Expand Up @@ -50,6 +51,10 @@ foreach(_dir IN LISTS _installed_dirs)
if(_pkg MATCHES "^vcpkg-" OR _pkg STREQUAL "cmake" OR _pkg STREQUAL "doc" OR _pkg STREQUAL "pkgconfig")
continue()
endif()
# A reused vcpkg installation may retain the old VM port; its license now comes from the submodule.
if(_pkg STREQUAL "wire-sys-vm")
continue()
endif()
# Skip if already collected above
if(_pkg IN_LIST _vcpkg_packages)
continue()
Expand All @@ -64,4 +69,4 @@ foreach(_dir IN LISTS _installed_dirs)
endif()
endforeach()
endif()
endforeach()
endforeach()
126 changes: 126 additions & 0 deletions cmake/test/sys-vm-submodule-test.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Exercise the real submodule integration, option isolation, and installed SDK interface.
if(NOT WORK_DIR OR NOT SOURCE_DIR OR NOT SOFTFLOAT_DIR)
message(FATAL_ERROR "WORK_DIR, SOURCE_DIR, and SOFTFLOAT_DIR are required")
endif()
if(NOT GENERATOR)
set(GENERATOR Ninja)
endif()
file(MAKE_DIRECTORY "${WORK_DIR}/source/sentinel-modules" "${WORK_DIR}/consumer")
file(WRITE "${WORK_DIR}/source/sentinel-modules/dependencies.cmake"
"message(FATAL_ERROR \"The VM resolved its parent's dependencies.cmake\")\n")

set(project [=[
cmake_minimum_required(VERSION 3.19)
project(vm_submodule_probe CXX)
include(GNUInstallDirs)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME parent_component)
foreach(option ENABLE_TESTS ENABLE_SPEC_TESTS ENABLE_FUZZ_TESTS ENABLE_TOOLS ENABLE_CCACHE
ENABLE_PROFILE ENABLE_GPERFTOOLS ENABLE_ADDRESS_SANITIZER ENABLE_UNDEFINED_BEHAVIOR_SANITIZER)
set(${option} ON CACHE BOOL "Parent setting that the VM must preserve" FORCE)
endforeach()
get_property(original_launcher GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sentinel-modules")
set(SYSVM_INSTALL_COMPONENT dev)
include("@SOURCE_DIR@/cmake/add-sys-vm.cmake")
if(NOT VM_SOURCE)
set(VM_SOURCE "@SOURCE_DIR@/libraries/sys-vm")
endif()
add_sys_vm_submodule("${VM_SOURCE}" "${CMAKE_CURRENT_BINARY_DIR}/vm")
foreach(option ENABLE_TESTS ENABLE_SPEC_TESTS ENABLE_FUZZ_TESTS ENABLE_TOOLS ENABLE_CCACHE
ENABLE_PROFILE ENABLE_GPERFTOOLS ENABLE_ADDRESS_SANITIZER ENABLE_UNDEFINED_BEHAVIOR_SANITIZER)
get_property(cached CACHE ${option} PROPERTY VALUE)
if(NOT ${option} OR NOT cached)
message(FATAL_ERROR "The VM changed parent setting ${option}")
endif()
endforeach()
get_property(current_launcher GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(NOT CMAKE_CXX_STANDARD EQUAL 23 OR
NOT CMAKE_INSTALL_DEFAULT_COMPONENT_NAME STREQUAL "parent_component" OR
NOT "${current_launcher}" STREQUAL "${original_launcher}")
message(FATAL_ERROR "The VM changed parent compiler or installation settings")
endif()
if(TARGET unit_tests OR TARGET sys_vm_spec_tests OR TARGET sys-vm-interp)
message(FATAL_ERROR "The VM enabled its standalone tests or tools")
endif()
add_executable(vm_probe main.cpp)
target_link_libraries(vm_probe PRIVATE sys-vm::sys-vm)
]=])
string(CONFIGURE "${project}" project @ONLY)
file(WRITE "${WORK_DIR}/source/CMakeLists.txt" "${project}")
file(WRITE "${WORK_DIR}/source/main.cpp" [=[
#include <sysio/vm/config.hpp>
#include <sysio/vm/signals.hpp>
static_assert(sysio::vm::use_softfloat);
/// Verify that both build-tree and installed consumers use the fixed signal disposition handling.
int main() {
auto& previous = sysio::vm::prev_signal_handler<SIGILL>;
previous = {};
previous.sa_handler = SIG_IGN;
previous.sa_flags = SA_SIGINFO;
sysio::vm::chain_previous_signal_handler(SIGILL, nullptr, nullptr);
}
]=])
file(COPY "${WORK_DIR}/source/main.cpp" DESTINATION "${WORK_DIR}/consumer")
file(WRITE "${WORK_DIR}/consumer/CMakeLists.txt" [=[
cmake_minimum_required(VERSION 3.19)
project(vm_sdk_probe CXX)
find_package(softfloat CONFIG REQUIRED)
find_package(sys-vm CONFIG REQUIRED PATHS "${VM_PREFIX}/share/sys-vm" NO_DEFAULT_PATH)
add_executable(vm_probe main.cpp)
target_link_libraries(vm_probe PRIVATE sys-vm::sys-vm)
]=])

# Keep exact configure/build/install diagnostics for failed integration checks.
function(run_checked name)
execute_process(COMMAND ${ARGN} RESULT_VARIABLE result OUTPUT_VARIABLE output ERROR_VARIABLE error)
file(WRITE "${WORK_DIR}/${name}.log" "${output}${error}")
if(NOT result EQUAL 0)
message(FATAL_ERROR "${name} failed (${result}):\n${output}${error}")
endif()
endfunction()

set(configure_options -G "${GENERATOR}" "-Dsoftfloat_DIR=${SOFTFLOAT_DIR}" -DCMAKE_BUILD_TYPE=Release)
if(CXX)
list(APPEND configure_options "-DCMAKE_CXX_COMPILER=${CXX}")
endif()
set(config_options "")
if(CONFIG)
list(APPEND configure_options "-DCMAKE_CONFIGURATION_TYPES=${CONFIG}")
set(config_options --config "${CONFIG}")
endif()
run_checked(configure "${CMAKE_COMMAND}" -S "${WORK_DIR}/source" -B "${WORK_DIR}/build" ${configure_options})
run_checked(build "${CMAKE_COMMAND}" --build "${WORK_DIR}/build" ${config_options})
run_checked(install-dev "${CMAKE_COMMAND}" --install "${WORK_DIR}/build" ${config_options}
--prefix "${WORK_DIR}/sdk" --component dev)
file(SHA256 "${SOURCE_DIR}/libraries/sys-vm/include/sysio/vm/signals.hpp" source_hash)
file(SHA256 "${WORK_DIR}/sdk/include/sysio/vm/signals.hpp" installed_hash)
if(NOT source_hash STREQUAL installed_hash)
message(FATAL_ERROR "The development package does not contain the pinned VM headers")
endif()
run_checked(install-base "${CMAKE_COMMAND}" --install "${WORK_DIR}/build" ${config_options}
--prefix "${WORK_DIR}/base" --component base)
if(EXISTS "${WORK_DIR}/base/include/sysio/vm")
message(FATAL_ERROR "VM development headers leaked into the base component")
endif()
run_checked(consumer-configure "${CMAKE_COMMAND}" -S "${WORK_DIR}/consumer" -B "${WORK_DIR}/consumer-build"
${configure_options} "-DVM_PREFIX=${WORK_DIR}/sdk")
run_checked(consumer-build "${CMAKE_COMMAND}" --build "${WORK_DIR}/consumer-build" ${config_options})
foreach(build IN ITEMS build consumer-build)
set(probe "${WORK_DIR}/${build}/vm_probe")
if(CONFIG AND EXISTS "${WORK_DIR}/${build}/${CONFIG}/vm_probe")
set(probe "${WORK_DIR}/${build}/${CONFIG}/vm_probe")
endif()
run_checked("${build}-run" "${probe}")
endforeach()

# A checkout without the submodule must fail early with an actionable initialization command.
execute_process(COMMAND "${CMAKE_COMMAND}" -S "${WORK_DIR}/source" -B "${WORK_DIR}/missing-build"
${configure_options} "-DVM_SOURCE=${WORK_DIR}/missing"
RESULT_VARIABLE result OUTPUT_VARIABLE output ERROR_VARIABLE error)
file(WRITE "${WORK_DIR}/missing-submodule.log" "${output}${error}")
string(REGEX REPLACE "[ \t\r\n]+" " " diagnostic "${output}${error}")
if(result EQUAL 0 OR NOT diagnostic MATCHES "git submodule update --init libraries/sys-vm")
message(FATAL_ERROR "A missing VM submodule did not produce the expected initialization error")
endif()
message(STATUS "VM submodule, SDK consumers, option isolation, and missing-submodule checks passed")
7 changes: 2 additions & 5 deletions libraries/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
set(APPBASE_INSTALL_COMPONENT "dev")
set(SYSVM_INSTALL_COMPONENT "dev")

include(add-sys-vm)
add_sys_vm_submodule("${CMAKE_CURRENT_SOURCE_DIR}/sys-vm" "${CMAKE_CURRENT_BINARY_DIR}/sys-vm")

add_subdirectory(libfc-lite)
add_subdirectory(libfc)
Expand All @@ -18,8 +20,3 @@ add_subdirectory(opp)
add_subdirectory(testing)
add_subdirectory(version)
add_subdirectory(state_history)

if(sys-vm IN_LIST SYSIO_WASM_RUNTIMES OR sys-vm-jit IN_LIST SYSIO_WASM_RUNTIMES)
find_package(sys-vm REQUIRED)
# add_library(sys-vm ALIAS sys-vm::sys-vm)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <signal.h>

namespace sysio::chain::sysvmoc {

/// Retain a previous signal action's calling convention when an OC fault belongs to another handler.
class chained_signal_handler {
public:
chained_signal_handler() = default;

/// Decode SA_SIGINFO once, retaining only a callable predecessor of the corresponding type.
explicit chained_signal_handler(const struct sigaction& action) noexcept {
if (action.sa_handler == SIG_IGN || action.sa_handler == SIG_DFL)
return;
if (action.sa_flags & SA_SIGINFO)
siginfo_handler = action.sa_sigaction;
else
legacy_handler = action.sa_handler;
}

/// Invoke the predecessor with its original ABI; false leaves default fault handling to the caller.
bool operator()(int sig, siginfo_t* info, void* context) const {
if (siginfo_handler) {
siginfo_handler(sig, info, context);
return true;
}
if (legacy_handler) {
legacy_handler(sig);
return true;
}
return false;
}

private:
void (*siginfo_handler)(int, siginfo_t*, void*) = nullptr;
void (*legacy_handler)(int) = nullptr;
};

} // namespace sysio::chain::sysvmoc
14 changes: 5 additions & 9 deletions libraries/chain/webassembly/runtimes/sys-vm-oc/executor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <sysio/chain/webassembly/sys-vm-oc/executor.hpp>
#include <sysio/chain/webassembly/sys-vm-oc/chained_signal_handler.hpp>
#include <sysio/chain/webassembly/sys-vm-oc/code_cache.hpp>
#include <sysio/chain/webassembly/sys-vm-oc/memory.hpp>
#include <sysio/chain/webassembly/sys-vm-oc/thread_exec_mem.hpp>
Expand Down Expand Up @@ -36,7 +37,7 @@ namespace sysio::chain::sysvmoc {

static constexpr auto signal_sentinel = 0x4D56534F45534559ul;

static void(*chained_handler)(int,siginfo_t*,void*);
static chained_signal_handler chained_handler;
static void segv_handler(int sig, siginfo_t* info, void* ctx) {
control_block* cb_in_main_segment;

Expand Down Expand Up @@ -66,10 +67,8 @@ static void segv_handler(int sig, siginfo_t* info, void* ctx) {
siglongjmp(*cb_in_main_segment->jmp, SYSVMOC_EXIT_SEGV);

notus:
if(chained_handler) {
chained_handler(sig, info, ctx);
if(chained_handler(sig, info, ctx))
return;
}
::signal(sig, SIG_DFL);
::raise(sig);
__builtin_unreachable();
Expand Down Expand Up @@ -150,15 +149,12 @@ static intrinsic check_memcpy_params_intrinsic("sysvmoc_internal.check_memcpy_pa

struct executor_signal_init {
executor_signal_init() {
struct sigaction sig_action, old_sig_action;
struct sigaction sig_action{}, old_sig_action{};
sig_action.sa_sigaction = segv_handler;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = SA_SIGINFO | SA_NODEFER;
sigaction(SIGSEGV, &sig_action, &old_sig_action);
if(old_sig_action.sa_flags & SA_SIGINFO)
chained_handler = old_sig_action.sa_sigaction;
else if(old_sig_action.sa_handler != SIG_IGN && old_sig_action.sa_handler != SIG_DFL)
chained_handler = (void (*)(int,siginfo_t*,void*))old_sig_action.sa_handler;
chained_handler = chained_signal_handler(old_sig_action);
}
};

Expand Down
1 change: 1 addition & 0 deletions libraries/sys-vm
Submodule sys-vm added at 2c8d4b
Loading
Loading