forked from M-Labs/libfringe
rewrite platform.rs to use mmap directly
This commit is contained in:
parent
175583e335
commit
a39493d740
|
@ -1,6 +1,6 @@
|
||||||
#![feature(no_std)]
|
#![feature(no_std)]
|
||||||
#![feature(asm, core)]
|
#![feature(asm, core)]
|
||||||
#![feature(os, libc, page_size)]
|
#![feature(libc, page_size)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
108
src/platform.rs
108
src/platform.rs
|
@ -1,58 +1,82 @@
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate std;
|
extern crate std;
|
||||||
use self::std::prelude::v1::*;
|
use self::std::prelude::v1::*;
|
||||||
use self::std::os::{errno, MemoryMap};
|
use self::std::env;
|
||||||
use self::std::env::page_size;
|
use self::std::io::Error as IoError;
|
||||||
use self::std::os::MapOption::{MapReadable, MapWritable, MapNonStandardFlags};
|
use self::libc::{c_void, size_t};
|
||||||
|
use core::ptr;
|
||||||
use stack;
|
use stack;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "lwt_stack_register"]
|
#[link_name = "lwt_stack_register"]
|
||||||
fn stack_register(start: *const u8, end: *const u8) -> libc::c_uint;
|
fn stack_register(start: *const c_void, end: *const c_void) -> libc::c_uint;
|
||||||
#[link_name = "lwt_stack_deregister"]
|
#[link_name = "lwt_stack_deregister"]
|
||||||
fn stack_deregister(id: libc::c_uint);
|
fn stack_deregister(id: libc::c_uint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(raw_pointer_derive)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
buf: MemoryMap,
|
ptr: *mut u8,
|
||||||
|
len: usize,
|
||||||
valgrind_id: libc::c_uint
|
valgrind_id: libc::c_uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl stack::Stack for Stack {
|
||||||
const STACK_FLAGS: libc::c_int = libc::MAP_STACK
|
fn top(&mut self) -> *mut u8 {
|
||||||
| libc::MAP_PRIVATE
|
unsafe {
|
||||||
| libc::MAP_ANON;
|
self.ptr.offset(self.len as isize)
|
||||||
|
}
|
||||||
impl Stack {
|
|
||||||
pub fn new(size: usize) -> Stack {
|
|
||||||
let buf = match MemoryMap::new(size, &[MapReadable, MapWritable,
|
|
||||||
MapNonStandardFlags(STACK_FLAGS)]) {
|
|
||||||
Ok(map) => map,
|
|
||||||
Err(e) => panic!("mmap for stack of size {} failed: {:?}", size, e)
|
|
||||||
};
|
|
||||||
|
|
||||||
if !protect_last_page(&buf) {
|
|
||||||
panic!("Could not memory-protect guard page. stack={:p}, errno={}",
|
|
||||||
buf.data(), errno());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let valgrind_id = unsafe {
|
fn limit(&self) -> *const u8 {
|
||||||
stack_register(buf.data().offset(buf.len() as isize) as *const _,
|
unsafe {
|
||||||
buf.data() as *const _)
|
self.ptr.offset(env::page_size() as isize)
|
||||||
};
|
|
||||||
|
|
||||||
Stack {
|
|
||||||
buf: buf,
|
|
||||||
valgrind_id: valgrind_id
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn protect_last_page(stack: &MemoryMap) -> bool {
|
impl Stack {
|
||||||
|
pub fn new(size: usize) -> Stack {
|
||||||
|
let page_size = env::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 valgrind_id = stack_register(ptr.offset(len as isize), ptr);
|
||||||
|
|
||||||
|
Stack { ptr: ptr as *mut u8, len: len, valgrind_id: valgrind_id }
|
||||||
|
};
|
||||||
|
|
||||||
|
stack.protect();
|
||||||
|
|
||||||
|
stack
|
||||||
|
}
|
||||||
|
|
||||||
|
fn protect(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let last_page = stack.data() as *mut libc::c_void;
|
if libc::mprotect(self.ptr as *mut c_void,
|
||||||
libc::mprotect(last_page, page_size() as libc::size_t,
|
env::page_size() as libc::size_t,
|
||||||
libc::PROT_NONE) != -1
|
libc::PROT_NONE) != 0 {
|
||||||
|
panic!("mprotect for guard page of stack {:p} failed: {:?}",
|
||||||
|
self.ptr, IoError::last_os_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,20 +84,10 @@ impl Drop for Stack {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_deregister(self.valgrind_id);
|
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())
|
||||||
|
}
|
||||||
impl stack::Stack for Stack {
|
|
||||||
fn top(&mut self) -> *mut u8 {
|
|
||||||
unsafe {
|
|
||||||
self.buf.data().offset(self.buf.len() as isize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn limit(&self) -> *const u8 {
|
|
||||||
unsafe {
|
|
||||||
self.buf.data().offset(page_size() as isize) as *const _
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue