Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/build.rs b/build.rs
- index e1591d4..716fd73 100644
- --- a/build.rs
- +++ b/build.rs
- @@ -125,17 +125,17 @@ fn ignore(testsuite: &str, name: &str) -> bool {
- return match (testsuite, name) {
- ("spec_testsuite", "address") => true,
- ("spec_testsuite", "align") => true,
- - ("spec_testsuite", "call") => true,
- - ("spec_testsuite", "call_indirect") => true,
- + // ("spec_testsuite", "call") => true, // unwind loops
- + // ("spec_testsuite", "call_indirect") => true, // unwind loops
- ("spec_testsuite", "conversions") => true,
- ("spec_testsuite", "elem") => true,
- - ("spec_testsuite", "fac") => true,
- - ("spec_testsuite", "func_ptrs") => true,
- + // ("spec_testsuite", "fac") => true, // unwind loops
- + // ("spec_testsuite", "func_ptrs") => true, // fails only in release
- ("spec_testsuite", "globals") => true,
- ("spec_testsuite", "i32") => true,
- ("spec_testsuite", "i64") => true,
- - ("spec_testsuite", "f32") => true,
- - ("spec_testsuite", "f64") => true,
- + // ("spec_testsuite", "f32") => true, // fails
- + // ("spec_testsuite", "f64") => true, // fails
- ("spec_testsuite", "if") => true,
- ("spec_testsuite", "imports") => true,
- ("spec_testsuite", "int_exprs") => true,
- @@ -144,13 +144,13 @@ fn ignore(testsuite: &str, name: &str) -> bool {
- ("spec_testsuite", "memory_trap") => true,
- ("spec_testsuite", "resizing") => true,
- ("spec_testsuite", "select") => true,
- - ("spec_testsuite", "skip-stack-guard-page") => true,
- - ("spec_testsuite", "start") => true,
- + // ("spec_testsuite", "skip-stack-guard-page") => true, // unwind loops / stack overflow
- + ("spec_testsuite", "start") => true, // well, it fails... should check error message
- ("spec_testsuite", "traps") => true,
- ("spec_testsuite", "unreachable") => true,
- ("spec_testsuite", "unwind") => true,
- ("misc_testsuite", "misc_traps") => true,
- - ("misc_testsuite", "stack_overflow") => true,
- + // ("misc_testsuite", "stack_overflow") => true, // unwind loops
- (_, _) => false,
- };
- }
- diff --git a/wasmtime-jit/Cargo.toml b/wasmtime-jit/Cargo.toml
- index 9b4b136..49e6c0f 100644
- --- a/wasmtime-jit/Cargo.toml
- +++ b/wasmtime-jit/Cargo.toml
- @@ -25,6 +25,7 @@ failure_derive = { version = "0.1.3", default-features = false }
- target-lexicon = { version = "0.4.0", default-features = false }
- hashbrown = { version = "0.6.0", optional = true }
- wasmparser = "0.35.1"
- +winapi = "0.3.7"
- [features]
- default = ["std"]
- diff --git a/wasmtime-jit/src/code_memory.rs b/wasmtime-jit/src/code_memory.rs
- index 641577a..eb44be0 100644
- --- a/wasmtime-jit/src/code_memory.rs
- +++ b/wasmtime-jit/src/code_memory.rs
- @@ -34,11 +34,21 @@ impl CodeMemory {
- /// TODO: Add an alignment flag.
- fn allocate(&mut self, size: usize) -> Result<&mut [u8], String> {
- if self.current.len() - self.position < size {
- + // For every mapping on Windows, we need an extra information for structured
- + // exception handling. We use the same handler for every function, so just
- + // one record for single mmap is fine.
- + #[cfg(all(target_os = "windows", target_pointer_width = "64"))]
- + let size = size + region::page::size();
- self.mmaps.push(mem::replace(
- &mut self.current,
- Mmap::with_at_least(cmp::max(0x10000, size))?,
- ));
- self.position = 0;
- + #[cfg(all(target_os = "windows", target_pointer_width = "64"))]
- + {
- + host_impl::register_executable_memory(&mut self.current);
- + self.position += region::page::size();
- + }
- }
- let old_position = self.position;
- self.position += size;
- @@ -100,3 +110,151 @@ impl CodeMemory {
- self.published = self.mmaps.len();
- }
- }
- +
- +#[cfg(all(target_os = "windows", target_pointer_width = "64"))]
- +mod host_impl {
- + // Docs:
- + // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019
- + // SpiderMonkey impl:
- + // https://searchfox.org/mozilla-central/source/js/src/jit/ProcessExecutableMemory.cpp#139-227
- + // CppCon 2018 talk about SEH with good example:
- + // https://www.youtube.com/watch?v=COEv2kq_Ht8
- + // https://github.com/CppCon/CppCon2018/blob/master/Presentations/unwinding_the_stack_exploring_how_cpp_exceptions_work_on_windows/unwinding_the_stack_exploring_how_cpp_exceptions_work_on_windows__james_mcnellis__cppcon_2018.pdf
- + // Note:
- + // ARM requires different treatment (not implemented)
- +
- + use region;
- + use std::convert::TryFrom;
- + use std::ptr;
- + use wasmtime_runtime::Mmap;
- + use winapi::ctypes::c_int;
- + use winapi::shared::basetsd::ULONG64;
- + use winapi::shared::minwindef::{BYTE, ULONG};
- + use winapi::shared::ntdef::FALSE;
- + use winapi::um::winnt::RtlAddFunctionTable;
- + use winapi::um::winnt::{
- + PCONTEXT, PDISPATCHER_CONTEXT, PEXCEPTION_RECORD, RUNTIME_FUNCTION, UNW_FLAG_EHANDLER,
- + };
- + use winapi::vc::excpt::{EXCEPTION_CONTINUE_SEARCH, ExceptionContinueSearch, EXCEPTION_DISPOSITION};
- +
- + #[repr(C)]
- + struct ExceptionHandlerRecord {
- + runtime_function: RUNTIME_FUNCTION,
- + unwind_info: UnwindInfo,
- + thunk: [u8; 13],//12],
- + }
- +
- + // Note: this is a bitfield in WinAPI, so some fields are actually merged below
- + #[cfg(not(target_arch = "arm"))]
- + #[repr(C)]
- + struct UnwindInfo {
- + version_and_flags: BYTE,
- + size_of_prologue: BYTE,
- + count_of_unwind_codes: BYTE,
- + frame_register_and_offset: BYTE,
- + exception_handler: ULONG,
- + }
- + #[cfg(not(target_arch = "arm"))]
- + static FLAGS_BIT_OFFSET: u8 = 3;
- +
- + macro_rules! offsetof {
- + ($class:ident, $field:ident) => { unsafe {
- + (&(*(ptr::null::<$class>())).$field) as *const _
- + } as usize };
- + }
- +
- + #[cfg(not(target_arch = "arm"))]
- + pub fn register_executable_memory(mmap: &mut Mmap) {
- + eprintln!(
- + "register_executable_memory() for mmap {:?} -- {:?}",
- + mmap.as_ptr(),
- + unsafe { mmap.as_ptr().add(mmap.len()) },
- + );
- + let r = unsafe { (mmap.as_mut_ptr() as *mut ExceptionHandlerRecord).as_mut() }.unwrap();
- + r.runtime_function.BeginAddress = u32::try_from(region::page::size()).unwrap();
- + r.runtime_function.EndAddress = u32::try_from(mmap.len()).unwrap();
- + *unsafe { r.runtime_function.u.UnwindInfoAddress_mut() } =
- + u32::try_from(offsetof!(ExceptionHandlerRecord, unwind_info)).unwrap();
- +
- + r.unwind_info.version_and_flags = 1; // version
- + r.unwind_info.version_and_flags |=
- + u8::try_from(UNW_FLAG_EHANDLER << FLAGS_BIT_OFFSET).unwrap(); // flags
- + r.unwind_info.size_of_prologue = 0;
- + r.unwind_info.count_of_unwind_codes = 0;
- + r.unwind_info.frame_register_and_offset = 0;
- + r.unwind_info.exception_handler =
- + u32::try_from(offsetof!(ExceptionHandlerRecord, thunk)).unwrap();
- +
- + // mov imm64, rax
- + r.thunk[0] = 0x48;
- + r.thunk[1] = 0xb8;
- + unsafe {
- + ptr::write_unaligned::<usize>(
- + &mut r.thunk[2] as *mut _ as *mut usize,
- + exception_handler as usize,
- + )
- + };
- + r.thunk[10] = 0x90; //0xCC;
- + // jmp rax
- + r.thunk[10+1] = 0xff;
- + r.thunk[11+1] = 0xe0;
- +
- + // println!("--------------- {:?} and {:?}", exception_handler as usize, &exception_handler as *const _ as usize);
- +
- + // // todo probably not needed, but call it just in case
- + // unsafe {
- + // region::protect(
- + // mmap.as_mut_ptr(),
- + // region::page::size(),
- + // region::Protection::ReadExecute,
- + // )
- + // }
- + // .expect("unable to make memory readonly and executable");
- +
- + let res = unsafe {
- + RtlAddFunctionTable(
- + mmap.as_mut_ptr() as *mut _,
- + 1,
- + u64::try_from(mmap.as_ptr() as usize).unwrap(),
- + )
- + };
- + if res == FALSE {
- + panic!("RtlAddFunctionTable() failed");
- + }
- +
- + eprintln!(
- + "register_executable_memory() END for mmap {:?}",
- + mmap.as_ptr()
- + );
- +
- + // Note: our section needs to have read & execute rights for the thunk,
- + // and publish() will do it before executing the JIT code.
- + }
- +
- + // This method should NEVER be called, because we're using vectored exception handlers
- + // which have higher priority. We can do a couple of things:
- + // 1) unreachable!()
- + // 2) call WasmTrapHandler
- + // -- if exception originates from JIT code, should catch the exception and unwind
- + // the stack
- + // 3) return ExceptionContinueSearch, so OS will continue search for exception handlers
- + // -- imported functions should handle their exceptions, and JIT code doesn't raise
- + // its own exceptions
- + extern "C" {
- + fn Unwind();
- + fn _resetstkoflw() -> c_int;
- + }
- + unsafe extern "C" fn exception_handler(
- + _exception_record: PEXCEPTION_RECORD,
- + _establisher_frame: ULONG64,
- + _context_record: PCONTEXT,
- + _dispatcher_context: PDISPATCHER_CONTEXT,
- + ) -> EXCEPTION_DISPOSITION {
- + // eprintln!("buh");
- + // unreachable!("WasmTrapHandler (vectored exception handler) should have already handled the exception");
- + assert_eq!(_resetstkoflw(), 0);
- + Unwind(); // tmp
- + 0 // dumb value
- + // ExceptionContinueSearch
- + }
- +}
- diff --git a/wasmtime-runtime/build.rs b/wasmtime-runtime/build.rs
- index a2db146..34ec0fb 100644
- --- a/wasmtime-runtime/build.rs
- +++ b/wasmtime-runtime/build.rs
- @@ -1,14 +1,14 @@
- fn main() {
- println!("cargo:rerun-if-changed=signalhandlers/SignalHandlers.cpp");
- println!("cargo:rerun-if-changed=signalhandlers/SignalHandlers.hpp");
- - println!("cargo:rerun-if-changed=signalhandlers/Trampolines.cpp");
- + println!("cargo:rerun-if-changed=signalhandlers/Trampolines.c");
- let target = std::env::var("TARGET").unwrap();
- let mut build = cc::Build::new();
- build
- .cpp(true)
- .warnings(false)
- .file("signalhandlers/SignalHandlers.cpp")
- - .file("signalhandlers/Trampolines.cpp");
- + .file("signalhandlers/Trampolines.c");
- if !target.contains("windows") {
- build
- .flag("-std=c++11")
- diff --git a/wasmtime-runtime/signalhandlers/SignalHandlers.cpp b/wasmtime-runtime/signalhandlers/SignalHandlers.cpp
- index 3f3635f..4240e79 100644
- --- a/wasmtime-runtime/signalhandlers/SignalHandlers.cpp
- +++ b/wasmtime-runtime/signalhandlers/SignalHandlers.cpp
- @@ -16,6 +16,7 @@
- # include <windows.h>
- # include <winternl.h>
- +# include <malloc.h>
- #elif defined(USE_APPLE_MACH_PORTS)
- # include <mach/exc.h>
- @@ -404,23 +405,30 @@ static
- __attribute__ ((warn_unused_result))
- #endif
- bool
- -HandleTrap(CONTEXT* context)
- +HandleTrap(CONTEXT* context, bool stackFixRequired)
- {
- assert(sAlreadyHandlingTrap);
- - RecordTrap(ContextToPC(context));
- + RecordTrap(ContextToPC(context)); // todo tmp
- - // Unwind calls longjmp, so it doesn't run the automatic
- - // sAlreadhHanldingTrap cleanups, so reset it manually before doing
- - // a longjmp.
- - sAlreadyHandlingTrap = false;
- + // TODO: maybe the apple mach ports problem above can use the scheduler below.
- + if (stackFixRequired) {
- + FixStackAfterUnwinding();
- + // _resetstkoflw();
- + }
- -#if defined(USE_APPLE_MACH_PORTS)
- +#if defined(USE_APPLE_MACH_PORTS) //|| defined(_WIN32)
- // Reroute the PC to run the Unwind function on the main stack after the
- // handler exits. This doesn't yet work for stack overflow traps, because
- // in that case the main thread doesn't have any space left to run.
- SetContextPC(context, reinterpret_cast<const uint8_t*>(&Unwind));
- #else
- +
- + // Unwind calls longjmp, so it doesn't run the automatic
- + // sAlreadhHanldingTrap cleanups, so reset it manually before doing
- + // a longjmp.
- + // sAlreadyHandlingTrap = false; // tmp
- +
- // For now, just call Unwind directly, rather than redirecting the PC there,
- // so that it runs on the alternate signal handler stack. To run on the main
- // stack, reroute the context PC like this:
- @@ -440,20 +448,28 @@ HandleTrap(CONTEXT* context)
- // Compiled in all user binaries, so should be stable over time.
- static const unsigned sThreadLocalArrayPointerIndex = 11;
- -static LONG WINAPI
- -WasmTrapHandler(LPEXCEPTION_POINTERS exception)
- +// static
- +LONG WINAPI
- +WasmTrapHandlerFilter(LPEXCEPTION_POINTERS exception)
- {
- + // TODO: this fuction should check if PC is within bounds of jit code.
- +
- + printf("WasmTrapHandler 1 -- PC=%p SP=%p\n", (void*)exception->ContextRecord->Rip, (void*)exception->ContextRecord->Rsp); fflush(stdout);
- +
- // Make sure TLS is initialized before reading sAlreadyHandlingTrap.
- if (!NtCurrentTeb()->Reserved1[sThreadLocalArrayPointerIndex]) {
- return EXCEPTION_CONTINUE_SEARCH;
- }
- + printf("WasmTrapHandler 2\n"); fflush(stdout);
- if (sAlreadyHandlingTrap) {
- return EXCEPTION_CONTINUE_SEARCH;
- }
- AutoHandlingTrap aht;
- EXCEPTION_RECORD* record = exception->ExceptionRecord;
- + printf("WasmTrapHandler 3 -- %x\n", record->ExceptionCode); fflush(stdout);
- + // exception codes: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
- if (record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION &&
- record->ExceptionCode != EXCEPTION_ILLEGAL_INSTRUCTION &&
- record->ExceptionCode != EXCEPTION_STACK_OVERFLOW &&
- @@ -463,11 +479,19 @@ WasmTrapHandler(LPEXCEPTION_POINTERS exception)
- return EXCEPTION_CONTINUE_SEARCH;
- }
- - if (!HandleTrap(exception->ContextRecord)) {
- - return EXCEPTION_CONTINUE_SEARCH;
- - }
- + printf("WasmTrapHandler 4\n"); fflush(stdout);
- +
- + return EXCEPTION_EXECUTE_HANDLER;
- - return EXCEPTION_CONTINUE_EXECUTION;
- + // todo code below
- + // if (!HandleTrap(exception->ContextRecord,
- + // record->ExceptionCode == EXCEPTION_STACK_OVERFLOW))
- + // {
- + // return EXCEPTION_CONTINUE_SEARCH;
- + // }
- + // printf("WasmTrapHandler 5\n"); fflush(stdout);
- +
- + // return EXCEPTION_CONTINUE_EXECUTION;
- }
- #elif defined(USE_APPLE_MACH_PORTS)
- @@ -545,7 +569,7 @@ HandleMachException(const ExceptionRequest& request)
- {
- AutoHandlingTrap aht;
- - if (!HandleTrap(&context)) {
- + if (!HandleTrap(&context, false)) {
- return false;
- }
- }
- @@ -628,7 +652,7 @@ WasmTrapHandler(int signum, siginfo_t* info, void* context)
- if (!sAlreadyHandlingTrap) {
- AutoHandlingTrap aht;
- assert(signum == SIGSEGV || signum == SIGBUS || signum == SIGFPE || signum == SIGILL);
- - if (HandleTrap(static_cast<CONTEXT*>(context))) {
- + if (HandleTrap(static_cast<CONTEXT*>(context), false)) {
- return;
- }
- }
- @@ -683,22 +707,22 @@ EnsureEagerSignalHandlers()
- // Install whatever exception/signal handler is appropriate for the OS.
- #if defined(_WIN32)
- -# if defined(MOZ_ASAN)
- - // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
- - // in the first handler position. This requires some coordination with
- - // MemoryProtectionExceptionHandler::isDisabled().
- - const bool firstHandler = false;
- -# else
- - // Otherwise, WasmTrapHandler needs to go first, so that we can recover
- - // from wasm faults and continue execution without triggering handlers
- - // such as MemoryProtectionExceptionHandler that assume we are crashing.
- - const bool firstHandler = true;
- -# endif
- - if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
- - // Windows has all sorts of random security knobs for disabling things
- - // so make this a dynamic failure that disables wasm, not an abort().
- - return false;
- - }
- +// # if defined(MOZ_ASAN)
- +// // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
- +// // in the first handler position. This requires some coordination with
- +// // MemoryProtectionExceptionHandler::isDisabled().
- +// const bool firstHandler = false;
- +// # else
- +// // Otherwise, WasmTrapHandler needs to go first, so that we can recover
- +// // from wasm faults and continue execution without triggering handlers
- +// // such as MemoryProtectionExceptionHandler that assume we are crashing.
- +// const bool firstHandler = true; // todo test with false
- +// # endif
- +// if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
- +// // Windows has all sorts of random security knobs for disabling things
- +// // so make this a dynamic failure that disables wasm, not an abort().
- +// return false;
- +// }
- #elif defined(USE_APPLE_MACH_PORTS)
- // All the Mach setup in EnsureDarwinMachPorts.
- diff --git a/wasmtime-runtime/signalhandlers/SignalHandlers.hpp b/wasmtime-runtime/signalhandlers/SignalHandlers.hpp
- index 3e98065..71c2fa7 100644
- --- a/wasmtime-runtime/signalhandlers/SignalHandlers.hpp
- +++ b/wasmtime-runtime/signalhandlers/SignalHandlers.hpp
- @@ -19,6 +19,9 @@ void LeaveScope(void*);
- void* GetScope(void);
- void Unwind(void);
- +/// Schedules fixing the stack after unwinding
- +void FixStackAfterUnwinding(void);
- +
- // This function performs the low-overhead signal handler initialization that we
- // want to do eagerly to ensure a more-deterministic global process state. This
- // is especially relevant for signal handlers since handler ordering depends on
- @@ -37,6 +40,11 @@ EnsureEagerSignalHandlers(void);
- int
- EnsureDarwinMachPorts(void);
- +// windows only
- +#include <windows.h>
- +LONG WINAPI
- +WasmTrapHandlerFilter(LPEXCEPTION_POINTERS exception);
- +
- #ifdef __cplusplus
- } // extern "C"
- #endif
- diff --git a/wasmtime-runtime/signalhandlers/Trampolines.c b/wasmtime-runtime/signalhandlers/Trampolines.c
- new file mode 100644
- index 0000000..6d05e6c
- --- /dev/null
- +++ b/wasmtime-runtime/signalhandlers/Trampolines.c
- @@ -0,0 +1,97 @@
- +#include <setjmp.h>
- +#include <stdio.h>
- +
- +#include "SignalHandlers.hpp"
- +
- +#if defined(_WIN32) && 0
- +
- +// #include <exception>
- +// class UnwindException : public std::exception {};
- +
- +#include <windows.h>
- +#include <malloc.h>
- +// extern "C"
- +int WasmtimeCallTrampoline(void *vmctx, void (*body)(void*, void*), void *args) {
- + printf("aaaaaaaaaaaaaaaaaaaa\n");
- + __try {
- + // try {
- + body(vmctx, args);
- + }
- + __except(/*WasmTrapHandlerFilter(GetExceptionInformation())*/EXCEPTION_EXECUTE_HANDLER) { // todo use some filter
- + // catch (UnwindException &ex) {
- + printf("unwound\n"); fflush(stdout);
- + // if (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) {
- + // _resetstkoflw();
- + // }
- + return 0;
- + }
- + // body(vmctx, args);
- + return 1;
- +}
- +
- +// extern "C"
- +int WasmtimeCall(void *vmctx, void (*body)(void*)) {
- + abort();
- + // jmp_buf buf;
- + // void *volatile prev;
- + // printf("bbbbbbbbbbbbbbbbbbb\n");
- + // if (setjmp(buf) != 0) {
- + // printf("unwound\n"); fflush(stdout);
- + // LeaveScope(prev);
- + // return 0;
- + // }
- + // prev = EnterScope(&buf); // todo before setjmp?
- + // body(vmctx);
- + // LeaveScope(prev);
- + // return 1;
- +}
- +
- +// extern "C"
- +void Unwind() {
- + printf("unwinding\n"); fflush(stdout);
- + //abort();
- + // throw UnwindException();
- + jmp_buf *buf = (jmp_buf*) GetScope();
- + longjmp(*buf, 1);
- +}
- +
- +#else // not a Windows
- +
- +// extern "C"
- +int WasmtimeCallTrampoline(void *vmctx, void (*body)(void*, void*), void *args) {
- + jmp_buf buf;
- + void *volatile prev;
- + if (setjmp(buf) != 0) {
- + printf("unwound\n"); fflush(stdout);
- + LeaveScope(prev);
- + return 0;
- + }
- + prev = EnterScope(&buf); // todo before setjmp?
- + body(vmctx, args);
- + LeaveScope(prev);
- + return 1;
- +}
- +
- +// extern "C"
- +int WasmtimeCall(void *vmctx, void (*body)(void*)) {
- + jmp_buf buf;
- + void *volatile prev;
- + if (setjmp(buf) != 0) {
- + printf("unwound\n"); fflush(stdout);
- + LeaveScope(prev);
- + return 0;
- + }
- + prev = EnterScope(&buf); // todo before setjmp?
- + body(vmctx);
- + LeaveScope(prev);
- + return 1;
- +}
- +
- +// extern "C"
- +void Unwind() {
- + printf("unwinding\n"); fflush(stdout);
- + jmp_buf *buf = (jmp_buf*) GetScope();
- + longjmp(*buf, 1);
- +}
- +
- +#endif
- diff --git a/wasmtime-runtime/signalhandlers/Trampolines.cpp b/wasmtime-runtime/signalhandlers/Trampolines.cpp
- deleted file mode 100644
- index 4c6bbcc..0000000
- --- a/wasmtime-runtime/signalhandlers/Trampolines.cpp
- +++ /dev/null
- @@ -1,37 +0,0 @@
- -#include <setjmp.h>
- -
- -#include "SignalHandlers.hpp"
- -
- -extern "C"
- -int WasmtimeCallTrampoline(void *vmctx, void (*body)(void*, void*), void *args) {
- - jmp_buf buf;
- - void *volatile prev;
- - if (setjmp(buf) != 0) {
- - LeaveScope(prev);
- - return 0;
- - }
- - prev = EnterScope(&buf);
- - body(vmctx, args);
- - LeaveScope(prev);
- - return 1;
- -}
- -
- -extern "C"
- -int WasmtimeCall(void *vmctx, void (*body)(void*)) {
- - jmp_buf buf;
- - void *volatile prev;
- - if (setjmp(buf) != 0) {
- - LeaveScope(prev);
- - return 0;
- - }
- - prev = EnterScope(&buf);
- - body(vmctx);
- - LeaveScope(prev);
- - return 1;
- -}
- -
- -extern "C"
- -void Unwind() {
- - jmp_buf *buf = (jmp_buf*) GetScope();
- - longjmp(*buf, 1);
- -}
- diff --git a/wasmtime-runtime/src/traphandlers.rs b/wasmtime-runtime/src/traphandlers.rs
- index 360c392..b97e380 100644
- --- a/wasmtime-runtime/src/traphandlers.rs
- +++ b/wasmtime-runtime/src/traphandlers.rs
- @@ -5,6 +5,8 @@ use crate::vmcontext::{VMContext, VMFunctionBody};
- use core::cell::Cell;
- use core::ptr;
- use std::string::String;
- +#[cfg(target_os = "windows")]
- +use winapi::ctypes::c_int;
- extern "C" {
- fn WasmtimeCallTrampoline(
- @@ -13,9 +15,12 @@ extern "C" {
- values_vec: *mut u8,
- ) -> i32;
- fn WasmtimeCall(vmctx: *mut u8, callee: *const VMFunctionBody) -> i32;
- + #[cfg(target_os = "windows")]
- + fn _resetstkoflw() -> c_int;
- }
- thread_local! {
- + static FIX_STACK: Cell<bool> = Cell::new(false);
- static TRAP_PC: Cell<*const u8> = Cell::new(ptr::null());
- static JMP_BUF: Cell<*const u8> = Cell::new(ptr::null());
- }
- @@ -33,21 +38,37 @@ pub extern "C" fn RecordTrap(pc: *const u8) {
- #[allow(non_snake_case)]
- #[no_mangle]
- pub extern "C" fn EnterScope(ptr: *const u8) -> *const u8 {
- - JMP_BUF.with(|buf| buf.replace(ptr))
- + let ret = JMP_BUF.with(|buf| buf.replace(ptr));
- + println!("EnterScope -- got {:?}, ret {:?}", ptr, ret);
- + ret
- }
- #[doc(hidden)]
- #[allow(non_snake_case)]
- #[no_mangle]
- pub extern "C" fn GetScope() -> *const u8 {
- - JMP_BUF.with(|buf| buf.get())
- + let ret = JMP_BUF.with(|buf| buf.get());
- + // println!("GetScope -- ret {:?}", ret);
- + ret
- }
- #[doc(hidden)]
- #[allow(non_snake_case)]
- #[no_mangle]
- +// todo do cleanup here
- pub extern "C" fn LeaveScope(ptr: *const u8) {
- - JMP_BUF.with(|buf| buf.set(ptr))
- + let ret = JMP_BUF.with(|buf| buf.set(ptr));
- + // println!("LeaveScope -- got {:?}, ret {:?}", ptr, ret);
- + ret
- +}
- +
- +/// Schedules fixing the stack after unwinding
- +#[doc(hidden)]
- +#[allow(non_snake_case)]
- +#[no_mangle]
- +pub extern "C" fn FixStackAfterUnwinding() {
- + eprintln!("Scheduling stack fix after unwinding");
- + FIX_STACK.with(|fix_stack| fix_stack.set(true));
- }
- fn trap_message(_vmctx: *mut VMContext) -> String {
- @@ -59,6 +80,24 @@ fn trap_message(_vmctx: *mut VMContext) -> String {
- format!("wasm trap at {:?}", pc)
- }
- +fn run_post_unwind_actions() {
- + FIX_STACK.with(|fix_stack| {
- + if fix_stack.get() {
- + #[cfg(target_os = "windows")]
- + {
- + // We need to restore guard page under stack to handle future stack overflows properly.
- + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/resetstkoflw?view=vs-2019
- + eprintln!("fixing stack");
- + if unsafe { _resetstkoflw() == 0 } {
- + panic!("Failed to fix the stack after unwinding");
- + }
- + eprintln!("fixed stack");
- + }
- + fix_stack.set(false);
- + }
- + })
- +}
- +
- /// Call the wasm function pointed to by `callee`. `values_vec` points to
- /// a buffer which holds the incoming arguments, and to which the outgoing
- /// return values will be written.
- @@ -69,6 +108,7 @@ pub unsafe extern "C" fn wasmtime_call_trampoline(
- values_vec: *mut u8,
- ) -> Result<(), String> {
- if WasmtimeCallTrampoline(vmctx as *mut u8, callee, values_vec) == 0 {
- + run_post_unwind_actions();
- Err(trap_message(vmctx))
- } else {
- Ok(())
- @@ -83,6 +123,7 @@ pub unsafe extern "C" fn wasmtime_call(
- callee: *const VMFunctionBody,
- ) -> Result<(), String> {
- if WasmtimeCall(vmctx as *mut u8, callee) == 0 {
- + run_post_unwind_actions();
- Err(trap_message(vmctx))
- } else {
- Ok(())
Advertisement
Add Comment
Please, Sign In to add comment