Guest User

unwind info patch

a guest
Aug 21st, 2019
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 25.58 KB | None | 0 0
  1. diff --git a/build.rs b/build.rs
  2. index e1591d4..716fd73 100644
  3. --- a/build.rs
  4. +++ b/build.rs
  5. @@ -125,17 +125,17 @@ fn ignore(testsuite: &str, name: &str) -> bool {
  6.          return match (testsuite, name) {
  7.              ("spec_testsuite", "address") => true,
  8.              ("spec_testsuite", "align") => true,
  9. -            ("spec_testsuite", "call") => true,
  10. -            ("spec_testsuite", "call_indirect") => true,
  11. +            // ("spec_testsuite", "call") => true, // unwind loops
  12. +            // ("spec_testsuite", "call_indirect") => true, // unwind loops
  13.              ("spec_testsuite", "conversions") => true,
  14.              ("spec_testsuite", "elem") => true,
  15. -            ("spec_testsuite", "fac") => true,
  16. -            ("spec_testsuite", "func_ptrs") => true,
  17. +            // ("spec_testsuite", "fac") => true, // unwind loops
  18. +            // ("spec_testsuite", "func_ptrs") => true, // fails only in release
  19.              ("spec_testsuite", "globals") => true,
  20.              ("spec_testsuite", "i32") => true,
  21.              ("spec_testsuite", "i64") => true,
  22. -            ("spec_testsuite", "f32") => true,
  23. -            ("spec_testsuite", "f64") => true,
  24. +            // ("spec_testsuite", "f32") => true, // fails
  25. +            // ("spec_testsuite", "f64") => true, // fails
  26.              ("spec_testsuite", "if") => true,
  27.              ("spec_testsuite", "imports") => true,
  28.              ("spec_testsuite", "int_exprs") => true,
  29. @@ -144,13 +144,13 @@ fn ignore(testsuite: &str, name: &str) -> bool {
  30.              ("spec_testsuite", "memory_trap") => true,
  31.              ("spec_testsuite", "resizing") => true,
  32.              ("spec_testsuite", "select") => true,
  33. -            ("spec_testsuite", "skip-stack-guard-page") => true,
  34. -            ("spec_testsuite", "start") => true,
  35. +            // ("spec_testsuite", "skip-stack-guard-page") => true, // unwind loops / stack overflow
  36. +            ("spec_testsuite", "start") => true, // well, it fails... should check error message
  37.              ("spec_testsuite", "traps") => true,
  38.              ("spec_testsuite", "unreachable") => true,
  39.              ("spec_testsuite", "unwind") => true,
  40.              ("misc_testsuite", "misc_traps") => true,
  41. -            ("misc_testsuite", "stack_overflow") => true,
  42. +            // ("misc_testsuite", "stack_overflow") => true, // unwind loops
  43.              (_, _) => false,
  44.          };
  45.      }
  46. diff --git a/wasmtime-jit/Cargo.toml b/wasmtime-jit/Cargo.toml
  47. index 9b4b136..49e6c0f 100644
  48. --- a/wasmtime-jit/Cargo.toml
  49. +++ b/wasmtime-jit/Cargo.toml
  50. @@ -25,6 +25,7 @@ failure_derive = { version = "0.1.3", default-features = false }
  51.  target-lexicon = { version = "0.4.0", default-features = false }
  52.  hashbrown = { version = "0.6.0", optional = true }
  53.  wasmparser = "0.35.1"
  54. +winapi = "0.3.7"
  55.  
  56.  [features]
  57.  default = ["std"]
  58. diff --git a/wasmtime-jit/src/code_memory.rs b/wasmtime-jit/src/code_memory.rs
  59. index 641577a..eb44be0 100644
  60. --- a/wasmtime-jit/src/code_memory.rs
  61. +++ b/wasmtime-jit/src/code_memory.rs
  62. @@ -34,11 +34,21 @@ impl CodeMemory {
  63.      /// TODO: Add an alignment flag.
  64.      fn allocate(&mut self, size: usize) -> Result<&mut [u8], String> {
  65.          if self.current.len() - self.position < size {
  66. +            // For every mapping on Windows, we need an extra information for structured
  67. +            // exception handling. We use the same handler for every function, so just
  68. +            // one record for single mmap is fine.
  69. +                #[cfg(all(target_os = "windows", target_pointer_width = "64"))]
  70. +                let size = size + region::page::size();
  71.              self.mmaps.push(mem::replace(
  72.                  &mut self.current,
  73.                  Mmap::with_at_least(cmp::max(0x10000, size))?,
  74.              ));
  75.              self.position = 0;
  76. +                #[cfg(all(target_os = "windows", target_pointer_width = "64"))]
  77. +                {
  78. +                    host_impl::register_executable_memory(&mut self.current);
  79. +                    self.position += region::page::size();
  80. +                }
  81.          }
  82.          let old_position = self.position;
  83.          self.position += size;
  84. @@ -100,3 +110,151 @@ impl CodeMemory {
  85.          self.published = self.mmaps.len();
  86.      }
  87.  }
  88. +
  89. +#[cfg(all(target_os = "windows", target_pointer_width = "64"))]
  90. +mod host_impl {
  91. +    // Docs:
  92. +    //    https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019
  93. +    // SpiderMonkey impl:
  94. +    //    https://searchfox.org/mozilla-central/source/js/src/jit/ProcessExecutableMemory.cpp#139-227
  95. +    // CppCon 2018 talk about SEH with good example:
  96. +    //    https://www.youtube.com/watch?v=COEv2kq_Ht8
  97. +    //    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
  98. +    // Note:
  99. +    //    ARM requires different treatment (not implemented)
  100. +
  101. +    use region;
  102. +    use std::convert::TryFrom;
  103. +    use std::ptr;
  104. +    use wasmtime_runtime::Mmap;
  105. +    use winapi::ctypes::c_int;
  106. +    use winapi::shared::basetsd::ULONG64;
  107. +    use winapi::shared::minwindef::{BYTE, ULONG};
  108. +    use winapi::shared::ntdef::FALSE;
  109. +    use winapi::um::winnt::RtlAddFunctionTable;
  110. +    use winapi::um::winnt::{
  111. +        PCONTEXT, PDISPATCHER_CONTEXT, PEXCEPTION_RECORD, RUNTIME_FUNCTION, UNW_FLAG_EHANDLER,
  112. +    };
  113. +    use winapi::vc::excpt::{EXCEPTION_CONTINUE_SEARCH, ExceptionContinueSearch, EXCEPTION_DISPOSITION};
  114. +
  115. +    #[repr(C)]
  116. +    struct ExceptionHandlerRecord {
  117. +        runtime_function: RUNTIME_FUNCTION,
  118. +        unwind_info: UnwindInfo,
  119. +        thunk: [u8; 13],//12],
  120. +    }
  121. +
  122. +    // Note: this is a bitfield in WinAPI, so some fields are actually merged below
  123. +    #[cfg(not(target_arch = "arm"))]
  124. +    #[repr(C)]
  125. +    struct UnwindInfo {
  126. +        version_and_flags: BYTE,
  127. +        size_of_prologue: BYTE,
  128. +        count_of_unwind_codes: BYTE,
  129. +        frame_register_and_offset: BYTE,
  130. +        exception_handler: ULONG,
  131. +    }
  132. +    #[cfg(not(target_arch = "arm"))]
  133. +    static FLAGS_BIT_OFFSET: u8 = 3;
  134. +
  135. +    macro_rules! offsetof {
  136. +        ($class:ident, $field:ident) => { unsafe {
  137. +            (&(*(ptr::null::<$class>())).$field) as *const _
  138. +        } as usize };
  139. +    }
  140. +
  141. +    #[cfg(not(target_arch = "arm"))]
  142. +    pub fn register_executable_memory(mmap: &mut Mmap) {
  143. +        eprintln!(
  144. +            "register_executable_memory() for mmap {:?}  --  {:?}",
  145. +            mmap.as_ptr(),
  146. +            unsafe { mmap.as_ptr().add(mmap.len()) },
  147. +        );
  148. +        let r = unsafe { (mmap.as_mut_ptr() as *mut ExceptionHandlerRecord).as_mut() }.unwrap();
  149. +        r.runtime_function.BeginAddress = u32::try_from(region::page::size()).unwrap();
  150. +        r.runtime_function.EndAddress = u32::try_from(mmap.len()).unwrap();
  151. +        *unsafe { r.runtime_function.u.UnwindInfoAddress_mut() } =
  152. +            u32::try_from(offsetof!(ExceptionHandlerRecord, unwind_info)).unwrap();
  153. +
  154. +        r.unwind_info.version_and_flags = 1; // version
  155. +        r.unwind_info.version_and_flags |=
  156. +            u8::try_from(UNW_FLAG_EHANDLER << FLAGS_BIT_OFFSET).unwrap(); // flags
  157. +        r.unwind_info.size_of_prologue = 0;
  158. +        r.unwind_info.count_of_unwind_codes = 0;
  159. +        r.unwind_info.frame_register_and_offset = 0;
  160. +        r.unwind_info.exception_handler =
  161. +            u32::try_from(offsetof!(ExceptionHandlerRecord, thunk)).unwrap();
  162. +
  163. +        // mov imm64, rax
  164. +        r.thunk[0] = 0x48;
  165. +        r.thunk[1] = 0xb8;
  166. +        unsafe {
  167. +            ptr::write_unaligned::<usize>(
  168. +                &mut r.thunk[2] as *mut _ as *mut usize,
  169. +                exception_handler as usize,
  170. +            )
  171. +        };
  172. +        r.thunk[10] = 0x90; //0xCC;
  173. +        // jmp rax
  174. +        r.thunk[10+1] = 0xff;
  175. +        r.thunk[11+1] = 0xe0;
  176. +
  177. +        // println!("--------------- {:?} and {:?}", exception_handler as usize, &exception_handler as *const _ as usize);
  178. +
  179. +        // // todo probably not needed, but call it just in case
  180. +        // unsafe {
  181. +        //     region::protect(
  182. +        //         mmap.as_mut_ptr(),
  183. +        //         region::page::size(),
  184. +        //         region::Protection::ReadExecute,
  185. +        //     )
  186. +        // }
  187. +        // .expect("unable to make memory readonly and executable");
  188. +
  189. +        let res = unsafe {
  190. +            RtlAddFunctionTable(
  191. +                mmap.as_mut_ptr() as *mut _,
  192. +                1,
  193. +                u64::try_from(mmap.as_ptr() as usize).unwrap(),
  194. +            )
  195. +        };
  196. +        if res == FALSE {
  197. +            panic!("RtlAddFunctionTable() failed");
  198. +        }
  199. +
  200. +        eprintln!(
  201. +            "register_executable_memory() END for mmap {:?}",
  202. +            mmap.as_ptr()
  203. +        );
  204. +
  205. +        // Note: our section needs to have read & execute rights for the thunk,
  206. +        //       and publish() will do it before executing the JIT code.
  207. +    }
  208. +
  209. +    // This method should NEVER be called, because we're using vectored exception handlers
  210. +    // which have higher priority. We can do a couple of things:
  211. +    // 1) unreachable!()
  212. +    // 2) call WasmTrapHandler
  213. +    //    -- if exception originates from JIT code, should catch the exception and unwind
  214. +    //       the stack
  215. +    // 3) return ExceptionContinueSearch, so OS will continue search for exception handlers
  216. +    //    -- imported functions should handle their exceptions, and JIT code doesn't raise
  217. +    //       its own exceptions
  218. +    extern "C" {
  219. +        fn Unwind();
  220. +        fn _resetstkoflw() -> c_int;
  221. +    }
  222. +    unsafe extern "C" fn exception_handler(
  223. +        _exception_record: PEXCEPTION_RECORD,
  224. +        _establisher_frame: ULONG64,
  225. +        _context_record: PCONTEXT,
  226. +        _dispatcher_context: PDISPATCHER_CONTEXT,
  227. +    ) -> EXCEPTION_DISPOSITION {
  228. +        // eprintln!("buh");
  229. +        // unreachable!("WasmTrapHandler (vectored exception handler) should have already handled the exception");
  230. +        assert_eq!(_resetstkoflw(), 0);
  231. +        Unwind(); // tmp
  232. +        0 // dumb value
  233. +        // ExceptionContinueSearch
  234. +    }
  235. +}
  236. diff --git a/wasmtime-runtime/build.rs b/wasmtime-runtime/build.rs
  237. index a2db146..34ec0fb 100644
  238. --- a/wasmtime-runtime/build.rs
  239. +++ b/wasmtime-runtime/build.rs
  240. @@ -1,14 +1,14 @@
  241.  fn main() {
  242.      println!("cargo:rerun-if-changed=signalhandlers/SignalHandlers.cpp");
  243.      println!("cargo:rerun-if-changed=signalhandlers/SignalHandlers.hpp");
  244. -    println!("cargo:rerun-if-changed=signalhandlers/Trampolines.cpp");
  245. +    println!("cargo:rerun-if-changed=signalhandlers/Trampolines.c");
  246.      let target = std::env::var("TARGET").unwrap();
  247.      let mut build = cc::Build::new();
  248.      build
  249.          .cpp(true)
  250.          .warnings(false)
  251.          .file("signalhandlers/SignalHandlers.cpp")
  252. -        .file("signalhandlers/Trampolines.cpp");
  253. +        .file("signalhandlers/Trampolines.c");
  254.      if !target.contains("windows") {
  255.          build
  256.              .flag("-std=c++11")
  257. diff --git a/wasmtime-runtime/signalhandlers/SignalHandlers.cpp b/wasmtime-runtime/signalhandlers/SignalHandlers.cpp
  258. index 3f3635f..4240e79 100644
  259. --- a/wasmtime-runtime/signalhandlers/SignalHandlers.cpp
  260. +++ b/wasmtime-runtime/signalhandlers/SignalHandlers.cpp
  261. @@ -16,6 +16,7 @@
  262.  
  263.  # include <windows.h>
  264.  # include <winternl.h>
  265. +# include <malloc.h>
  266.  
  267.  #elif defined(USE_APPLE_MACH_PORTS)
  268.  # include <mach/exc.h>
  269. @@ -404,23 +405,30 @@ static
  270.  __attribute__ ((warn_unused_result))
  271.  #endif
  272.  bool
  273. -HandleTrap(CONTEXT* context)
  274. +HandleTrap(CONTEXT* context, bool stackFixRequired)
  275.  {
  276.      assert(sAlreadyHandlingTrap);
  277.  
  278. -    RecordTrap(ContextToPC(context));
  279. +    RecordTrap(ContextToPC(context)); // todo tmp
  280.  
  281. -    // Unwind calls longjmp, so it doesn't run the automatic
  282. -    // sAlreadhHanldingTrap cleanups, so reset it manually before doing
  283. -    // a longjmp.
  284. -    sAlreadyHandlingTrap = false;
  285. +    // TODO: maybe the apple mach ports problem above can use the scheduler below.
  286. +    if (stackFixRequired) {
  287. +        FixStackAfterUnwinding();
  288. +        // _resetstkoflw();
  289. +    }
  290.  
  291. -#if defined(USE_APPLE_MACH_PORTS)
  292. +#if defined(USE_APPLE_MACH_PORTS) //|| defined(_WIN32)
  293.      // Reroute the PC to run the Unwind function on the main stack after the
  294.      // handler exits. This doesn't yet work for stack overflow traps, because
  295.      // in that case the main thread doesn't have any space left to run.
  296.      SetContextPC(context, reinterpret_cast<const uint8_t*>(&Unwind));
  297.  #else
  298. +
  299. +    // Unwind calls longjmp, so it doesn't run the automatic
  300. +    // sAlreadhHanldingTrap cleanups, so reset it manually before doing
  301. +    // a longjmp.
  302. +    // sAlreadyHandlingTrap = false; // tmp
  303. +
  304.      // For now, just call Unwind directly, rather than redirecting the PC there,
  305.      // so that it runs on the alternate signal handler stack. To run on the main
  306.      // stack, reroute the context PC like this:
  307. @@ -440,20 +448,28 @@ HandleTrap(CONTEXT* context)
  308.  // Compiled in all user binaries, so should be stable over time.
  309.  static const unsigned sThreadLocalArrayPointerIndex = 11;
  310.  
  311. -static LONG WINAPI
  312. -WasmTrapHandler(LPEXCEPTION_POINTERS exception)
  313. +// static
  314. +LONG WINAPI
  315. +WasmTrapHandlerFilter(LPEXCEPTION_POINTERS exception)
  316.  {
  317. +    // TODO: this fuction should check if PC is within bounds of jit code.
  318. +
  319. +    printf("WasmTrapHandler 1 -- PC=%p  SP=%p\n", (void*)exception->ContextRecord->Rip, (void*)exception->ContextRecord->Rsp); fflush(stdout);
  320. +
  321.      // Make sure TLS is initialized before reading sAlreadyHandlingTrap.
  322.      if (!NtCurrentTeb()->Reserved1[sThreadLocalArrayPointerIndex]) {
  323.          return EXCEPTION_CONTINUE_SEARCH;
  324.      }
  325.  
  326. +    printf("WasmTrapHandler 2\n"); fflush(stdout);
  327.      if (sAlreadyHandlingTrap) {
  328.          return EXCEPTION_CONTINUE_SEARCH;
  329.      }
  330.      AutoHandlingTrap aht;
  331.  
  332.      EXCEPTION_RECORD* record = exception->ExceptionRecord;
  333. +    printf("WasmTrapHandler 3 -- %x\n", record->ExceptionCode); fflush(stdout);
  334. +    // exception codes: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
  335.      if (record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION &&
  336.          record->ExceptionCode != EXCEPTION_ILLEGAL_INSTRUCTION &&
  337.          record->ExceptionCode != EXCEPTION_STACK_OVERFLOW &&
  338. @@ -463,11 +479,19 @@ WasmTrapHandler(LPEXCEPTION_POINTERS exception)
  339.          return EXCEPTION_CONTINUE_SEARCH;
  340.      }
  341.  
  342. -    if (!HandleTrap(exception->ContextRecord)) {
  343. -        return EXCEPTION_CONTINUE_SEARCH;
  344. -    }
  345. +    printf("WasmTrapHandler 4\n"); fflush(stdout);
  346. +
  347. +    return EXCEPTION_EXECUTE_HANDLER;
  348.  
  349. -    return EXCEPTION_CONTINUE_EXECUTION;
  350. +    // todo code below
  351. +    // if (!HandleTrap(exception->ContextRecord,
  352. +    //                 record->ExceptionCode == EXCEPTION_STACK_OVERFLOW))
  353. +    // {
  354. +    //     return EXCEPTION_CONTINUE_SEARCH;
  355. +    // }
  356. +    // printf("WasmTrapHandler 5\n"); fflush(stdout);
  357. +
  358. +    // return EXCEPTION_CONTINUE_EXECUTION;
  359.  }
  360.  
  361.  #elif defined(USE_APPLE_MACH_PORTS)
  362. @@ -545,7 +569,7 @@ HandleMachException(const ExceptionRequest& request)
  363.  
  364.      {
  365.          AutoHandlingTrap aht;
  366. -        if (!HandleTrap(&context)) {
  367. +        if (!HandleTrap(&context, false)) {
  368.              return false;
  369.          }
  370.      }
  371. @@ -628,7 +652,7 @@ WasmTrapHandler(int signum, siginfo_t* info, void* context)
  372.      if (!sAlreadyHandlingTrap) {
  373.          AutoHandlingTrap aht;
  374.          assert(signum == SIGSEGV || signum == SIGBUS || signum == SIGFPE || signum == SIGILL);
  375. -        if (HandleTrap(static_cast<CONTEXT*>(context))) {
  376. +        if (HandleTrap(static_cast<CONTEXT*>(context), false)) {
  377.              return;
  378.          }
  379.      }
  380. @@ -683,22 +707,22 @@ EnsureEagerSignalHandlers()
  381.      // Install whatever exception/signal handler is appropriate for the OS.
  382.  #if defined(_WIN32)
  383.  
  384. -# if defined(MOZ_ASAN)
  385. -    // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
  386. -    // in the first handler position. This requires some coordination with
  387. -    // MemoryProtectionExceptionHandler::isDisabled().
  388. -    const bool firstHandler = false;
  389. -# else
  390. -    // Otherwise, WasmTrapHandler needs to go first, so that we can recover
  391. -    // from wasm faults and continue execution without triggering handlers
  392. -    // such as MemoryProtectionExceptionHandler that assume we are crashing.
  393. -    const bool firstHandler = true;
  394. -# endif
  395. -    if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
  396. -        // Windows has all sorts of random security knobs for disabling things
  397. -        // so make this a dynamic failure that disables wasm, not an abort().
  398. -        return false;
  399. -    }
  400. +// # if defined(MOZ_ASAN)
  401. +//     // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
  402. +//     // in the first handler position. This requires some coordination with
  403. +//     // MemoryProtectionExceptionHandler::isDisabled().
  404. +//     const bool firstHandler = false;
  405. +// # else
  406. +//     // Otherwise, WasmTrapHandler needs to go first, so that we can recover
  407. +//     // from wasm faults and continue execution without triggering handlers
  408. +//     // such as MemoryProtectionExceptionHandler that assume we are crashing.
  409. +//     const bool firstHandler = true; // todo test with false
  410. +// # endif
  411. +//     if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
  412. +//         // Windows has all sorts of random security knobs for disabling things
  413. +//         // so make this a dynamic failure that disables wasm, not an abort().
  414. +//         return false;
  415. +//     }
  416.  
  417.  #elif defined(USE_APPLE_MACH_PORTS)
  418.      // All the Mach setup in EnsureDarwinMachPorts.
  419. diff --git a/wasmtime-runtime/signalhandlers/SignalHandlers.hpp b/wasmtime-runtime/signalhandlers/SignalHandlers.hpp
  420. index 3e98065..71c2fa7 100644
  421. --- a/wasmtime-runtime/signalhandlers/SignalHandlers.hpp
  422. +++ b/wasmtime-runtime/signalhandlers/SignalHandlers.hpp
  423. @@ -19,6 +19,9 @@ void LeaveScope(void*);
  424.  void* GetScope(void);
  425.  void Unwind(void);
  426.  
  427. +/// Schedules fixing the stack after unwinding
  428. +void FixStackAfterUnwinding(void);
  429. +
  430.  // This function performs the low-overhead signal handler initialization that we
  431.  // want to do eagerly to ensure a more-deterministic global process state. This
  432.  // is especially relevant for signal handlers since handler ordering depends on
  433. @@ -37,6 +40,11 @@ EnsureEagerSignalHandlers(void);
  434.  int
  435.  EnsureDarwinMachPorts(void);
  436.  
  437. +// windows only
  438. +#include <windows.h>
  439. +LONG WINAPI
  440. +WasmTrapHandlerFilter(LPEXCEPTION_POINTERS exception);
  441. +
  442.  #ifdef __cplusplus
  443.  } // extern "C"
  444.  #endif
  445. diff --git a/wasmtime-runtime/signalhandlers/Trampolines.c b/wasmtime-runtime/signalhandlers/Trampolines.c
  446. new file mode 100644
  447. index 0000000..6d05e6c
  448. --- /dev/null
  449. +++ b/wasmtime-runtime/signalhandlers/Trampolines.c
  450. @@ -0,0 +1,97 @@
  451. +#include <setjmp.h>
  452. +#include <stdio.h>
  453. +
  454. +#include "SignalHandlers.hpp"
  455. +
  456. +#if defined(_WIN32) && 0
  457. +
  458. +// #include <exception>
  459. +// class UnwindException : public std::exception {};
  460. +
  461. +#include <windows.h>
  462. +#include <malloc.h>
  463. +// extern "C"
  464. +int WasmtimeCallTrampoline(void *vmctx, void (*body)(void*, void*), void *args) {
  465. +  printf("aaaaaaaaaaaaaaaaaaaa\n");
  466. +  __try {
  467. +  // try {
  468. +    body(vmctx, args);
  469. +  }
  470. +  __except(/*WasmTrapHandlerFilter(GetExceptionInformation())*/EXCEPTION_EXECUTE_HANDLER) { // todo use some filter
  471. +  // catch (UnwindException &ex) {
  472. +    printf("unwound\n"); fflush(stdout);
  473. +    // if (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) {
  474. +    //   _resetstkoflw();
  475. +    // }
  476. +    return 0;
  477. +  }
  478. +  // body(vmctx, args);
  479. +  return 1;
  480. +}
  481. +
  482. +// extern "C"
  483. +int WasmtimeCall(void *vmctx, void (*body)(void*)) {
  484. +  abort();
  485. +  // jmp_buf buf;
  486. +  // void *volatile prev;
  487. +  // printf("bbbbbbbbbbbbbbbbbbb\n");
  488. +  // if (setjmp(buf) != 0) {
  489. +  //   printf("unwound\n"); fflush(stdout);
  490. +  //   LeaveScope(prev);
  491. +  //   return 0;
  492. +  // }
  493. +  // prev = EnterScope(&buf); // todo before setjmp?
  494. +  // body(vmctx);
  495. +  // LeaveScope(prev);
  496. +  // return 1;
  497. +}
  498. +
  499. +// extern "C"
  500. +void Unwind() {
  501. +  printf("unwinding\n"); fflush(stdout);
  502. +  //abort();
  503. +  // throw UnwindException();
  504. +  jmp_buf *buf = (jmp_buf*) GetScope();
  505. +  longjmp(*buf, 1);
  506. +}
  507. +
  508. +#else // not a Windows
  509. +
  510. +// extern "C"
  511. +int WasmtimeCallTrampoline(void *vmctx, void (*body)(void*, void*), void *args) {
  512. +  jmp_buf buf;
  513. +  void *volatile prev;
  514. +  if (setjmp(buf) != 0) {
  515. +    printf("unwound\n"); fflush(stdout);
  516. +    LeaveScope(prev);
  517. +    return 0;
  518. +  }
  519. +  prev = EnterScope(&buf); // todo before setjmp?
  520. +  body(vmctx, args);
  521. +  LeaveScope(prev);
  522. +  return 1;
  523. +}
  524. +
  525. +// extern "C"
  526. +int WasmtimeCall(void *vmctx, void (*body)(void*)) {
  527. +  jmp_buf buf;
  528. +  void *volatile prev;
  529. +  if (setjmp(buf) != 0) {
  530. +    printf("unwound\n"); fflush(stdout);
  531. +    LeaveScope(prev);
  532. +    return 0;
  533. +  }
  534. +  prev = EnterScope(&buf); // todo before setjmp?
  535. +  body(vmctx);
  536. +  LeaveScope(prev);
  537. +  return 1;
  538. +}
  539. +
  540. +// extern "C"
  541. +void Unwind() {
  542. +  printf("unwinding\n"); fflush(stdout);
  543. +  jmp_buf *buf = (jmp_buf*) GetScope();
  544. +  longjmp(*buf, 1);
  545. +}
  546. +
  547. +#endif
  548. diff --git a/wasmtime-runtime/signalhandlers/Trampolines.cpp b/wasmtime-runtime/signalhandlers/Trampolines.cpp
  549. deleted file mode 100644
  550. index 4c6bbcc..0000000
  551. --- a/wasmtime-runtime/signalhandlers/Trampolines.cpp
  552. +++ /dev/null
  553. @@ -1,37 +0,0 @@
  554. -#include <setjmp.h>
  555. -
  556. -#include "SignalHandlers.hpp"
  557. -
  558. -extern "C"
  559. -int WasmtimeCallTrampoline(void *vmctx, void (*body)(void*, void*), void *args) {
  560. -  jmp_buf buf;
  561. -  void *volatile prev;
  562. -  if (setjmp(buf) != 0) {
  563. -    LeaveScope(prev);
  564. -    return 0;
  565. -  }
  566. -  prev = EnterScope(&buf);
  567. -  body(vmctx, args);
  568. -  LeaveScope(prev);
  569. -  return 1;
  570. -}
  571. -
  572. -extern "C"
  573. -int WasmtimeCall(void *vmctx, void (*body)(void*)) {
  574. -  jmp_buf buf;
  575. -  void *volatile prev;
  576. -  if (setjmp(buf) != 0) {
  577. -    LeaveScope(prev);
  578. -    return 0;
  579. -  }
  580. -  prev = EnterScope(&buf);
  581. -  body(vmctx);
  582. -  LeaveScope(prev);
  583. -  return 1;
  584. -}
  585. -
  586. -extern "C"
  587. -void Unwind() {
  588. -  jmp_buf *buf = (jmp_buf*) GetScope();
  589. -  longjmp(*buf, 1);
  590. -}
  591. diff --git a/wasmtime-runtime/src/traphandlers.rs b/wasmtime-runtime/src/traphandlers.rs
  592. index 360c392..b97e380 100644
  593. --- a/wasmtime-runtime/src/traphandlers.rs
  594. +++ b/wasmtime-runtime/src/traphandlers.rs
  595. @@ -5,6 +5,8 @@ use crate::vmcontext::{VMContext, VMFunctionBody};
  596.  use core::cell::Cell;
  597.  use core::ptr;
  598.  use std::string::String;
  599. +#[cfg(target_os = "windows")]
  600. +use winapi::ctypes::c_int;
  601.  
  602.  extern "C" {
  603.      fn WasmtimeCallTrampoline(
  604. @@ -13,9 +15,12 @@ extern "C" {
  605.          values_vec: *mut u8,
  606.      ) -> i32;
  607.      fn WasmtimeCall(vmctx: *mut u8, callee: *const VMFunctionBody) -> i32;
  608. +    #[cfg(target_os = "windows")]
  609. +    fn _resetstkoflw() -> c_int;
  610.  }
  611.  
  612.  thread_local! {
  613. +    static FIX_STACK: Cell<bool> = Cell::new(false);
  614.      static TRAP_PC: Cell<*const u8> = Cell::new(ptr::null());
  615.      static JMP_BUF: Cell<*const u8> = Cell::new(ptr::null());
  616.  }
  617. @@ -33,21 +38,37 @@ pub extern "C" fn RecordTrap(pc: *const u8) {
  618.  #[allow(non_snake_case)]
  619.  #[no_mangle]
  620.  pub extern "C" fn EnterScope(ptr: *const u8) -> *const u8 {
  621. -    JMP_BUF.with(|buf| buf.replace(ptr))
  622. +    let ret = JMP_BUF.with(|buf| buf.replace(ptr));
  623. +    println!("EnterScope -- got {:?}, ret {:?}", ptr, ret);
  624. +    ret
  625.  }
  626.  
  627.  #[doc(hidden)]
  628.  #[allow(non_snake_case)]
  629.  #[no_mangle]
  630.  pub extern "C" fn GetScope() -> *const u8 {
  631. -    JMP_BUF.with(|buf| buf.get())
  632. +    let ret = JMP_BUF.with(|buf| buf.get());
  633. +    // println!("GetScope -- ret {:?}", ret);
  634. +    ret
  635.  }
  636.  
  637.  #[doc(hidden)]
  638.  #[allow(non_snake_case)]
  639.  #[no_mangle]
  640. +// todo do cleanup here
  641.  pub extern "C" fn LeaveScope(ptr: *const u8) {
  642. -    JMP_BUF.with(|buf| buf.set(ptr))
  643. +    let ret = JMP_BUF.with(|buf| buf.set(ptr));
  644. +    // println!("LeaveScope -- got {:?}, ret {:?}", ptr, ret);
  645. +    ret
  646. +}
  647. +
  648. +/// Schedules fixing the stack after unwinding
  649. +#[doc(hidden)]
  650. +#[allow(non_snake_case)]
  651. +#[no_mangle]
  652. +pub extern "C" fn FixStackAfterUnwinding() {
  653. +    eprintln!("Scheduling stack fix after unwinding");
  654. +    FIX_STACK.with(|fix_stack| fix_stack.set(true));
  655.  }
  656.  
  657.  fn trap_message(_vmctx: *mut VMContext) -> String {
  658. @@ -59,6 +80,24 @@ fn trap_message(_vmctx: *mut VMContext) -> String {
  659.      format!("wasm trap at {:?}", pc)
  660.  }
  661.  
  662. +fn run_post_unwind_actions() {
  663. +    FIX_STACK.with(|fix_stack| {
  664. +        if fix_stack.get() {
  665. +            #[cfg(target_os = "windows")]
  666. +            {
  667. +                // We need to restore guard page under stack to handle future stack overflows properly.
  668. +                // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/resetstkoflw?view=vs-2019
  669. +                eprintln!("fixing stack");
  670. +                if unsafe { _resetstkoflw() == 0 } {
  671. +                    panic!("Failed to fix the stack after unwinding");
  672. +                }
  673. +                eprintln!("fixed stack");
  674. +            }
  675. +            fix_stack.set(false);
  676. +        }
  677. +    })
  678. +}
  679. +
  680.  /// Call the wasm function pointed to by `callee`. `values_vec` points to
  681.  /// a buffer which holds the incoming arguments, and to which the outgoing
  682.  /// return values will be written.
  683. @@ -69,6 +108,7 @@ pub unsafe extern "C" fn wasmtime_call_trampoline(
  684.      values_vec: *mut u8,
  685.  ) -> Result<(), String> {
  686.      if WasmtimeCallTrampoline(vmctx as *mut u8, callee, values_vec) == 0 {
  687. +        run_post_unwind_actions();
  688.          Err(trap_message(vmctx))
  689.      } else {
  690.          Ok(())
  691. @@ -83,6 +123,7 @@ pub unsafe extern "C" fn wasmtime_call(
  692.      callee: *const VMFunctionBody,
  693.  ) -> Result<(), String> {
  694.      if WasmtimeCall(vmctx as *mut u8, callee) == 0 {
  695. +        run_post_unwind_actions();
  696.          Err(trap_message(vmctx))
  697.      } else {
  698.          Ok(())
Advertisement
Add Comment
Please, Sign In to add comment