From 7e0b126f4214b83de398d8e235f3c50c483afe78 Mon Sep 17 00:00:00 2001 From: edef Date: Thu, 16 Apr 2015 02:04:06 -0400 Subject: [PATCH] separate all the libc interaction out per OS We're now handling more of this ourselves, and leaving less to libstd. Hopefully, we'll eventually break free of libstd, leaving a highly-focused low-level library that retains all its conveniences in freestanding environments. --- src/lib.rs | 2 +- src/os.rs | 48 ++++++++++++++++++------------------------------ src/os/unix.rs | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 src/os/unix.rs diff --git a/src/lib.rs b/src/lib.rs index 0cf7d3e..f2fdacb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(no_std)] #![feature(asm, core)] -#![feature(libc, page_size)] +#![feature(libc)] #![no_std] #[macro_use] diff --git a/src/os.rs b/src/os.rs index 3d00dae..06860c3 100644 --- a/src/os.rs +++ b/src/os.rs @@ -1,13 +1,12 @@ -extern crate libc; extern crate std; -use self::std::prelude::v1::*; -use self::std::env; +use core::prelude::*; use self::std::io::Error as IoError; -use self::libc::{c_void, size_t}; -use core::ptr; use stack; use valgrind; +#[cfg(unix)] +#[path = "os/unix.rs"] mod sys; + #[allow(raw_pointer_derive)] #[derive(Debug)] pub struct Stack { @@ -34,32 +33,27 @@ impl stack::Stack for Stack { fn limit(&self) -> *const u8 { unsafe { - self.ptr.offset(env::page_size() as isize) + self.ptr.offset(sys::page_size() as isize) } } } impl Stack { fn new(size: usize) -> Stack { - let page_size = env::page_size(); + let page_size = sys::page_size(); // round the page size up, // using the fact that it is a power of two let len = (size + page_size - 1) & !(page_size - 1); - const STACK_PROT: libc::c_int = libc::PROT_READ | libc::PROT_WRITE; - const STACK_FLAGS: libc::c_int = libc::MAP_STACK - | libc::MAP_PRIVATE - | libc::MAP_ANON; - let stack = unsafe { - let ptr = libc::mmap(ptr::null_mut(), len as size_t, - STACK_PROT, STACK_FLAGS, -1, 0); - - if ptr == libc::MAP_FAILED { - panic!("mmap for stack of size {} failed: {:?}", - len, IoError::last_os_error()) - } + let ptr = match sys::map_stack(size) { + None => { + panic!("mmap for stack of size {} failed: {:?}", + len, IoError::last_os_error()) + } + Some(ptr) => ptr + }; let valgrind_id = valgrind::stack_register(ptr as *const _, @@ -68,20 +62,14 @@ impl Stack { Stack { ptr: ptr as *mut u8, len: len, valgrind_id: valgrind_id } }; - stack.protect(); - - stack - } - - fn protect(&self) { unsafe { - if libc::mprotect(self.ptr as *mut c_void, - env::page_size() as libc::size_t, - libc::PROT_NONE) != 0 { + if !sys::protect_stack(stack.ptr) { panic!("mprotect for guard page of stack {:p} failed: {:?}", - self.ptr, IoError::last_os_error()); + stack.ptr, IoError::last_os_error()); } } + + stack } } @@ -89,7 +77,7 @@ impl Drop for Stack { fn drop(&mut self) { unsafe { valgrind::stack_deregister(self.valgrind_id); - if libc::munmap(self.ptr as *mut c_void, self.len as size_t) != 0 { + if !sys::unmap_stack(self.ptr, self.len) { panic!("munmap for stack {:p} of size {} failed: {:?}", self.ptr, self.len, IoError::last_os_error()) } diff --git a/src/os/unix.rs b/src/os/unix.rs new file mode 100644 index 0000000..3bf5fc9 --- /dev/null +++ b/src/os/unix.rs @@ -0,0 +1,39 @@ +extern crate libc; +use core::prelude::*; +pub use self::libc::{c_void, c_int, size_t}; +pub use self::libc::{mmap, mprotect, munmap}; +pub use self::libc::MAP_FAILED; + +use core::ptr; + +pub fn page_size() -> usize { + unsafe { + libc::sysconf(libc::_SC_PAGESIZE) as usize + } +} + +pub const GUARD_PROT: c_int = libc::PROT_NONE; +pub const STACK_PROT: c_int = libc::PROT_READ + | libc::PROT_WRITE; +pub const STACK_FLAGS: c_int = libc::MAP_STACK + | libc::MAP_PRIVATE + | libc::MAP_ANON; + +pub unsafe fn map_stack(len: usize) -> Option<*mut u8> { + let ptr = mmap(ptr::null_mut(), len as size_t, + STACK_PROT, STACK_FLAGS, -1, 0); + if ptr != MAP_FAILED { + Some(ptr as *mut u8) + } + else { + None + } +} + +pub unsafe fn protect_stack(ptr: *mut u8) -> bool { + mprotect(ptr as *mut c_void, page_size() as size_t, GUARD_PROT) == 0 +} + +pub unsafe fn unmap_stack(ptr: *mut u8, len: usize) -> bool { + munmap(ptr as *mut c_void, len as size_t) == 0 +}