mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-22 21:21:33 +00:00
Add (hopefully-working) support for windows
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1145,6 +1145,7 @@ dependencies = [
|
|||||||
"page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-clif-backend 0.1.0",
|
"wasmer-clif-backend 0.1.0",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -6,7 +6,10 @@ use std::mem;
|
|||||||
use std::ptr::{write_unaligned, NonNull};
|
use std::ptr::{write_unaligned, NonNull};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
self,
|
self,
|
||||||
backend::{self, Mmap, Protect},
|
backend::{
|
||||||
|
self,
|
||||||
|
sys::{Memory, Protect},
|
||||||
|
},
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
structures::Map,
|
structures::Map,
|
||||||
types::LocalFuncIndex,
|
types::LocalFuncIndex,
|
||||||
@ -49,7 +52,7 @@ impl FuncResolverBuilder {
|
|||||||
trap_sinks.push(trap_sink);
|
trap_sinks.push(trap_sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut memory = Mmap::with_size(total_size)
|
let mut memory = Memory::with_size(total_size)
|
||||||
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
||||||
unsafe {
|
unsafe {
|
||||||
memory
|
memory
|
||||||
@ -176,7 +179,7 @@ impl FuncResolverBuilder {
|
|||||||
/// Resolves a function index to a function address.
|
/// Resolves a function index to a function address.
|
||||||
pub struct FuncResolver {
|
pub struct FuncResolver {
|
||||||
map: Map<LocalFuncIndex, usize>,
|
map: Map<LocalFuncIndex, usize>,
|
||||||
memory: Mmap,
|
memory: Memory,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncResolver {
|
impl FuncResolver {
|
||||||
|
@ -10,6 +10,11 @@ hashbrown = "0.1"
|
|||||||
libffi = "0.6.4"
|
libffi = "0.6.4"
|
||||||
nix = "0.12.0"
|
nix = "0.12.0"
|
||||||
page_size = "0.4.1"
|
page_size = "0.4.1"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
winapi = { version = "0.3", features = ["memoryapi"] }
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
errno = "0.2.4"
|
errno = "0.2.4"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::{error::CompileResult, module::ModuleInner, types::LocalFuncIndex, vm};
|
use crate::{error::CompileResult, module::ModuleInner, types::LocalFuncIndex, vm};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub use crate::mmap::{Mmap, Protect};
|
pub mod sys {
|
||||||
|
pub use crate::sys::*;
|
||||||
|
}
|
||||||
pub use crate::sig_registry::SigRegistry;
|
pub use crate::sig_registry::SigRegistry;
|
||||||
|
|
||||||
pub trait Compiler {
|
pub trait Compiler {
|
||||||
|
@ -12,12 +12,12 @@ pub mod export;
|
|||||||
pub mod import;
|
pub mod import;
|
||||||
pub mod instance;
|
pub mod instance;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
mod mmap;
|
|
||||||
pub mod module;
|
pub mod module;
|
||||||
mod recovery;
|
mod recovery;
|
||||||
mod sig_registry;
|
mod sig_registry;
|
||||||
mod sighandler;
|
mod sighandler;
|
||||||
pub mod structures;
|
pub mod structures;
|
||||||
|
mod sys;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mmap::{Mmap, Protect},
|
sys,
|
||||||
types::{LocalMemoryIndex, Memory},
|
types::{LocalMemoryIndex, Memory},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
@ -10,7 +10,7 @@ use crate::{
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LinearMemory {
|
pub struct LinearMemory {
|
||||||
/// The actual memory allocation.
|
/// The actual memory allocation.
|
||||||
mmap: Mmap,
|
memory: sys::Memory,
|
||||||
|
|
||||||
/// The current number of wasm pages.
|
/// The current number of wasm pages.
|
||||||
current: u32,
|
current: u32,
|
||||||
@ -66,21 +66,22 @@ impl LinearMemory {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mmap = Mmap::with_size(mmap_size).unwrap();
|
let mut memory = sys::Memory::with_size(mmap_size).unwrap();
|
||||||
|
|
||||||
// map initial pages as readwrite since the inital mmap is mapped as not accessible.
|
// map initial pages as readwrite since the inital mmap is mapped as not accessible.
|
||||||
if initial_pages != 0 {
|
if initial_pages != 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
mmap.protect(
|
memory
|
||||||
0..(initial_pages as usize * Self::PAGE_SIZE as usize),
|
.protect(
|
||||||
Protect::ReadWrite,
|
0..(initial_pages as usize * Self::PAGE_SIZE as usize),
|
||||||
)
|
sys::Protect::ReadWrite,
|
||||||
.expect("unable to make memory accessible");
|
)
|
||||||
|
.expect("unable to make memory accessible");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
mmap,
|
memory,
|
||||||
current: initial_pages,
|
current: initial_pages,
|
||||||
max: mem.max,
|
max: mem.max,
|
||||||
offset_guard_size,
|
offset_guard_size,
|
||||||
@ -90,7 +91,7 @@ impl LinearMemory {
|
|||||||
|
|
||||||
/// Returns an base address of this linear memory.
|
/// Returns an base address of this linear memory.
|
||||||
fn base(&mut self) -> *mut u8 {
|
fn base(&mut self) -> *mut u8 {
|
||||||
self.mmap.as_ptr()
|
self.memory.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size in bytes
|
/// Returns the size in bytes
|
||||||
@ -146,21 +147,23 @@ impl LinearMemory {
|
|||||||
|
|
||||||
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
|
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
|
||||||
|
|
||||||
if new_bytes > self.mmap.size() - self.offset_guard_size {
|
if new_bytes > self.memory.size() - self.offset_guard_size {
|
||||||
let mmap_size = new_bytes.checked_add(self.offset_guard_size)?;
|
let memory_size = new_bytes.checked_add(self.offset_guard_size)?;
|
||||||
let mut new_mmap = Mmap::with_size(mmap_size).ok()?;
|
let mut new_memory = sys::Memory::with_size(memory_size).ok()?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
new_mmap.protect(0..new_bytes, Protect::ReadWrite).ok()?;
|
new_memory
|
||||||
|
.protect(0..new_bytes, sys::Protect::ReadWrite)
|
||||||
|
.ok()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let copy_size = self.mmap.size() - self.offset_guard_size;
|
let copy_size = self.memory.size() - self.offset_guard_size;
|
||||||
unsafe {
|
unsafe {
|
||||||
new_mmap.as_slice_mut()[..copy_size]
|
new_memory.as_slice_mut()[..copy_size]
|
||||||
.copy_from_slice(&self.mmap.as_slice()[..copy_size]);
|
.copy_from_slice(&self.memory.as_slice()[..copy_size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mmap = new_mmap;
|
self.memory = new_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current = new_pages;
|
self.current = new_pages;
|
||||||
@ -197,8 +200,8 @@ impl LinearMemory {
|
|||||||
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
|
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.mmap
|
self.memory
|
||||||
.protect(prev_bytes..new_bytes, Protect::ReadWrite)
|
.protect(prev_bytes..new_bytes, sys::Protect::ReadWrite)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,12 +214,12 @@ impl LinearMemory {
|
|||||||
impl Deref for LinearMemory {
|
impl Deref for LinearMemory {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
fn deref(&self) -> &[u8] {
|
fn deref(&self) -> &[u8] {
|
||||||
unsafe { self.mmap.as_slice() }
|
unsafe { self.memory.as_slice() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for LinearMemory {
|
impl DerefMut for LinearMemory {
|
||||||
fn deref_mut(&mut self) -> &mut [u8] {
|
fn deref_mut(&mut self) -> &mut [u8] {
|
||||||
unsafe { self.mmap.as_slice_mut() }
|
unsafe { self.memory.as_slice_mut() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
lib/runtime/src/sys/mod.rs
Normal file
11
lib/runtime/src/sys/mod.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#[cfg(unix)]
|
||||||
|
mod unix;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod windows;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub use self::unix::*;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub use self::windows::*;
|
@ -5,12 +5,12 @@ use std::ops::Range;
|
|||||||
use std::{ptr, slice};
|
use std::{ptr, slice};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Mmap {
|
pub struct Memory {
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
size: usize,
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mmap {
|
impl Memory {
|
||||||
pub fn with_size(size: usize) -> Result<Self, String> {
|
pub fn with_size(size: usize) -> Result<Self, String> {
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
@ -43,6 +43,7 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn protect(&mut self, range: Range<usize>, protect: Protect) -> Result<(), String> {
|
pub unsafe fn protect(&mut self, range: Range<usize>, protect: Protect) -> Result<(), String> {
|
||||||
|
let protect = protect.to_protect_const();
|
||||||
let page_size = page_size::get();
|
let page_size = page_size::get();
|
||||||
let start = self
|
let start = self
|
||||||
.ptr
|
.ptr
|
||||||
@ -75,7 +76,7 @@ impl Mmap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Mmap {
|
impl Drop for Memory {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.ptr.is_null() {
|
if !self.ptr.is_null() {
|
||||||
let success = unsafe { libc::munmap(self.ptr as _, self.size) };
|
let success = unsafe { libc::munmap(self.ptr as _, self.size) };
|
||||||
@ -87,12 +88,21 @@ impl Drop for Mmap {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum Protect {
|
pub enum Protect {
|
||||||
None = 0,
|
None,
|
||||||
Read = 1,
|
Read,
|
||||||
Write = 2,
|
ReadWrite,
|
||||||
ReadWrite = 1 | 2,
|
ReadExec,
|
||||||
Exec = 4,
|
}
|
||||||
ReadExec = 1 | 4,
|
|
||||||
|
impl Protect {
|
||||||
|
fn to_protect_const(self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Protect::None => 0,
|
||||||
|
Protect::Read => 1,
|
||||||
|
Protect::ReadWrite => 1 | 2,
|
||||||
|
Protect::ReadExec => 1 | 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Round `size` up to the nearest multiple of `page_size`.
|
/// Round `size` up to the nearest multiple of `page_size`.
|
3
lib/runtime/src/sys/unix/mod.rs
Normal file
3
lib/runtime/src/sys/unix/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod memory;
|
||||||
|
|
||||||
|
pub use self::memory::{Memory, Protect};
|
124
lib/runtime/src/sys/windows/memory.rs
Normal file
124
lib/runtime/src/sys/windows/memory.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
use winapi::um::memoryapi::{
|
||||||
|
VirtualAlloc,
|
||||||
|
MEM_RESERVE, MEM_COMMIT,
|
||||||
|
PAGE_NOACCESS, PAGE_EXECUTE_READ, PAGE_READWRITE, PAGE_READONLY,
|
||||||
|
};
|
||||||
|
use page_size;
|
||||||
|
use std::ops::Range;
|
||||||
|
use std::{ptr, slice};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Memory {
|
||||||
|
ptr: *mut u8,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Memory {
|
||||||
|
pub fn with_size(size: usize) -> Result<Self, String> {
|
||||||
|
if size == 0 {
|
||||||
|
return Ok(Self {
|
||||||
|
ptr: ptr::null_mut(),
|
||||||
|
size: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = round_up_to_page_size(size, page_size::get());
|
||||||
|
|
||||||
|
let ptr = unsafe {
|
||||||
|
VirtualAlloc(
|
||||||
|
ptr::null_mut(),
|
||||||
|
size,
|
||||||
|
MEM_RESERVE,
|
||||||
|
PAGE_NOACCESS,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if ptr.is_null() {
|
||||||
|
Err("unable to allocate memory")
|
||||||
|
} else {
|
||||||
|
Ok(Self {
|
||||||
|
ptr: ptr as *mut u8,
|
||||||
|
size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn protect(&mut self, range: Range<usize>, protect: Protect) -> Result<(), String> {
|
||||||
|
let protect = protect.to_protect_const();
|
||||||
|
let page_size = page_size::get();
|
||||||
|
let start = self
|
||||||
|
.ptr
|
||||||
|
.add(round_down_to_page_size(range.start, page_size));
|
||||||
|
let size = round_up_to_page_size(range.end - range.start, page_size);
|
||||||
|
assert!(size <= self.size);
|
||||||
|
|
||||||
|
// Commit the virtual memory.
|
||||||
|
let ptr = VirtualAlloc(
|
||||||
|
start as _,
|
||||||
|
size,
|
||||||
|
MEM_COMMIT,
|
||||||
|
protect,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ptr.is_null() {
|
||||||
|
Err("unable to protect memory")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> usize {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn as_slice(&self) -> &[u8] {
|
||||||
|
slice::from_raw_parts(self.ptr, self.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||||
|
slice::from_raw_parts_mut(self.ptr, self.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ptr(&self) -> *mut u8 {
|
||||||
|
self.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Memory {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if !self.ptr.is_null() {
|
||||||
|
let success = unsafe { libc::munmap(self.ptr as _, self.size) };
|
||||||
|
assert_eq!(success, 0, "failed to unmap memory: {}", errno::errno());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum Protect {
|
||||||
|
None,
|
||||||
|
Read,
|
||||||
|
ReadWrite,
|
||||||
|
ReadExec,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Protect {
|
||||||
|
fn to_protect_const(self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Protect::None => PAGE_NOACCESS,
|
||||||
|
Protect::Read => PAGE_READONLY,
|
||||||
|
Protect::ReadWrite => PAGE_READWRITE,
|
||||||
|
Protect::ReadExec => PAGE_EXECUTE_READ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Round `size` up to the nearest multiple of `page_size`.
|
||||||
|
fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
|
||||||
|
(size + (page_size - 1)) & !(page_size - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Round `size` down to the nearest multiple of `page_size`.
|
||||||
|
fn round_down_to_page_size(size: usize, page_size: usize) -> usize {
|
||||||
|
size & !(page_size - 1)
|
||||||
|
}
|
1
lib/runtime/src/sys/windows/mod.rs
Normal file
1
lib/runtime/src/sys/windows/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub use self::memory::{Memory, Protect};
|
@ -572,8 +572,8 @@ mod vm_ctx_tests {
|
|||||||
impl FuncResolver for Placeholder {
|
impl FuncResolver for Placeholder {
|
||||||
fn get(
|
fn get(
|
||||||
&self,
|
&self,
|
||||||
module: &ModuleInner,
|
_module: &ModuleInner,
|
||||||
local_func_index: LocalFuncIndex,
|
_local_func_index: LocalFuncIndex,
|
||||||
) -> Option<NonNull<Func>> {
|
) -> Option<NonNull<Func>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user