2014-12-24 14:07:25 +08:00
|
|
|
extern crate libc;
|
2014-12-24 14:28:21 +08:00
|
|
|
extern crate std;
|
2015-01-10 05:45:39 +08:00
|
|
|
use self::std::prelude::v1::*;
|
2015-03-27 14:52:25 +08:00
|
|
|
use self::std::env;
|
|
|
|
use self::std::io::Error as IoError;
|
|
|
|
use self::libc::{c_void, size_t};
|
|
|
|
use core::ptr;
|
2015-01-14 15:31:17 +08:00
|
|
|
use stack;
|
2014-12-24 13:12:39 +08:00
|
|
|
|
|
|
|
extern "C" {
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_stack_register"]
|
2015-03-27 14:52:25 +08:00
|
|
|
fn stack_register(start: *const c_void, end: *const c_void) -> libc::c_uint;
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_stack_deregister"]
|
2014-12-24 14:07:25 +08:00
|
|
|
fn stack_deregister(id: libc::c_uint);
|
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
#[allow(raw_pointer_derive)]
|
|
|
|
#[derive(Debug)]
|
2014-12-24 14:07:25 +08:00
|
|
|
pub struct Stack {
|
2015-03-27 14:52:25 +08:00
|
|
|
ptr: *mut u8,
|
|
|
|
len: usize,
|
2014-12-24 14:07:25 +08:00
|
|
|
valgrind_id: libc::c_uint
|
|
|
|
}
|
|
|
|
|
2015-04-16 03:56:57 +08:00
|
|
|
pub struct StackSource;
|
|
|
|
|
|
|
|
impl stack::StackSource for StackSource {
|
|
|
|
type Output = Stack;
|
|
|
|
fn get_stack(size: usize) -> Stack {
|
|
|
|
Stack::new(size)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
impl stack::Stack for Stack {
|
|
|
|
fn top(&mut self) -> *mut u8 {
|
|
|
|
unsafe {
|
|
|
|
self.ptr.offset(self.len as isize)
|
|
|
|
}
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
fn limit(&self) -> *const u8 {
|
|
|
|
unsafe {
|
|
|
|
self.ptr.offset(env::page_size() as isize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
|
|
|
|
impl Stack {
|
2015-04-16 03:56:57 +08:00
|
|
|
fn new(size: usize) -> Stack {
|
2015-03-27 14:52:25 +08:00
|
|
|
let page_size = env::page_size();
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
// 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;
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
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 valgrind_id = stack_register(ptr.offset(len as isize), ptr);
|
|
|
|
|
|
|
|
Stack { ptr: ptr as *mut u8, len: len, valgrind_id: valgrind_id }
|
2014-12-24 14:07:25 +08:00
|
|
|
};
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
stack.protect();
|
2014-12-24 14:07:25 +08:00
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
stack
|
2014-12-24 14:07:25 +08:00
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
fn protect(&self) {
|
2014-12-24 14:07:25 +08:00
|
|
|
unsafe {
|
2015-03-27 14:52:25 +08:00
|
|
|
if libc::mprotect(self.ptr as *mut c_void,
|
|
|
|
env::page_size() as libc::size_t,
|
|
|
|
libc::PROT_NONE) != 0 {
|
|
|
|
panic!("mprotect for guard page of stack {:p} failed: {:?}",
|
|
|
|
self.ptr, IoError::last_os_error());
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-27 14:52:25 +08:00
|
|
|
impl Drop for Stack {
|
|
|
|
fn drop(&mut self) {
|
2014-12-24 14:07:25 +08:00
|
|
|
unsafe {
|
2015-03-27 14:52:25 +08:00
|
|
|
stack_deregister(self.valgrind_id);
|
|
|
|
if libc::munmap(self.ptr as *mut c_void, self.len as size_t) != 0 {
|
|
|
|
panic!("munmap for stack {:p} of size {} failed: {:?}",
|
|
|
|
self.ptr, self.len, IoError::last_os_error())
|
|
|
|
}
|
2014-12-24 14:07:25 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-24 13:12:39 +08:00
|
|
|
}
|