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.
This commit is contained in:
parent
46b2a4007b
commit
7e0b126f42
|
@ -1,6 +1,6 @@
|
||||||
#![feature(no_std)]
|
#![feature(no_std)]
|
||||||
#![feature(asm, core)]
|
#![feature(asm, core)]
|
||||||
#![feature(libc, page_size)]
|
#![feature(libc)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
48
src/os.rs
48
src/os.rs
|
@ -1,13 +1,12 @@
|
||||||
extern crate libc;
|
|
||||||
extern crate std;
|
extern crate std;
|
||||||
use self::std::prelude::v1::*;
|
use core::prelude::*;
|
||||||
use self::std::env;
|
|
||||||
use self::std::io::Error as IoError;
|
use self::std::io::Error as IoError;
|
||||||
use self::libc::{c_void, size_t};
|
|
||||||
use core::ptr;
|
|
||||||
use stack;
|
use stack;
|
||||||
use valgrind;
|
use valgrind;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
#[path = "os/unix.rs"] mod sys;
|
||||||
|
|
||||||
#[allow(raw_pointer_derive)]
|
#[allow(raw_pointer_derive)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
|
@ -34,32 +33,27 @@ impl stack::Stack for Stack {
|
||||||
|
|
||||||
fn limit(&self) -> *const u8 {
|
fn limit(&self) -> *const u8 {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.ptr.offset(env::page_size() as isize)
|
self.ptr.offset(sys::page_size() as isize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stack {
|
impl Stack {
|
||||||
fn new(size: usize) -> Stack {
|
fn new(size: usize) -> Stack {
|
||||||
let page_size = env::page_size();
|
let page_size = sys::page_size();
|
||||||
|
|
||||||
// round the page size up,
|
// round the page size up,
|
||||||
// using the fact that it is a power of two
|
// using the fact that it is a power of two
|
||||||
let len = (size + page_size - 1) & !(page_size - 1);
|
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 stack = unsafe {
|
||||||
let ptr = libc::mmap(ptr::null_mut(), len as size_t,
|
let ptr = match sys::map_stack(size) {
|
||||||
STACK_PROT, STACK_FLAGS, -1, 0);
|
None => {
|
||||||
|
panic!("mmap for stack of size {} failed: {:?}",
|
||||||
if ptr == libc::MAP_FAILED {
|
len, IoError::last_os_error())
|
||||||
panic!("mmap for stack of size {} failed: {:?}",
|
}
|
||||||
len, IoError::last_os_error())
|
Some(ptr) => ptr
|
||||||
}
|
};
|
||||||
|
|
||||||
let valgrind_id =
|
let valgrind_id =
|
||||||
valgrind::stack_register(ptr as *const _,
|
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 { ptr: ptr as *mut u8, len: len, valgrind_id: valgrind_id }
|
||||||
};
|
};
|
||||||
|
|
||||||
stack.protect();
|
|
||||||
|
|
||||||
stack
|
|
||||||
}
|
|
||||||
|
|
||||||
fn protect(&self) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if libc::mprotect(self.ptr as *mut c_void,
|
if !sys::protect_stack(stack.ptr) {
|
||||||
env::page_size() as libc::size_t,
|
|
||||||
libc::PROT_NONE) != 0 {
|
|
||||||
panic!("mprotect for guard page of stack {:p} failed: {:?}",
|
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) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
valgrind::stack_deregister(self.valgrind_id);
|
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: {:?}",
|
panic!("munmap for stack {:p} of size {} failed: {:?}",
|
||||||
self.ptr, self.len, IoError::last_os_error())
|
self.ptr, self.len, IoError::last_os_error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue