diff --git a/src/arch/or1k.rs b/src/arch/or1k.rs index ab94d0b..c5af1c0 100644 --- a/src/arch/or1k.rs +++ b/src/arch/or1k.rs @@ -40,6 +40,8 @@ // when unwinding as well as returning normally, because LLVM does not do it for us. use stack::Stack; +pub const STACK_ALIGNMENT: usize = 4; + #[derive(Debug, Clone)] pub struct StackPointer(*mut usize); diff --git a/src/arch/x86.rs b/src/arch/x86.rs index 3753506..69e86bf 100644 --- a/src/arch/x86.rs +++ b/src/arch/x86.rs @@ -41,6 +41,8 @@ // when unwinding as well as returning normally, because LLVM does not do it for us. use stack::Stack; +pub const STACK_ALIGNMENT: usize = 16; + #[derive(Debug, Clone)] pub struct StackPointer(*mut usize); diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index b4b4b1b..efa057b 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -45,6 +45,8 @@ // when unwinding as well as returning normally, because LLVM does not do it for us. use stack::Stack; +pub const STACK_ALIGNMENT: usize = 16; + #[derive(Debug, Clone)] pub struct StackPointer(*mut usize); diff --git a/src/lib.rs b/src/lib.rs index 02b12e7..1242efe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. #![feature(asm, naked_functions, cfg_target_vendor)] -#![cfg_attr(feature = "alloc", feature(alloc))] +#![cfg_attr(feature = "alloc", feature(alloc, heap_api))] #![cfg_attr(test, feature(test, thread_local, const_fn))] #![no_std] @@ -45,6 +45,10 @@ pub use owned_stack::OwnedStack; pub use os::Stack as OsStack; mod arch; + +/// Minimum alignment of a stack base address on the target platform. +pub const STACK_ALIGNMENT: usize = arch::STACK_ALIGNMENT; + mod debug; mod context; diff --git a/src/owned_stack.rs b/src/owned_stack.rs index d3db64f..e914690 100644 --- a/src/owned_stack.rs +++ b/src/owned_stack.rs @@ -3,18 +3,22 @@ // See the LICENSE file included in this distribution. extern crate alloc; -use self::alloc::raw_vec::RawVec; +use core::slice; +use self::alloc::heap; use self::alloc::boxed::Box; -/// OwnedStack allocates on heap and owns a non-guarded stack. +/// OwnedStack holds a non-guarded, heap-allocated stack. #[derive(Debug)] pub struct OwnedStack(Box<[u8]>); impl OwnedStack { - /// Allocates a new stack with exactly `size` accessible bytes using - /// the default Rust allocator. + /// Allocates a new stack with exactly `size` accessible bytes and alignment appropriate + /// for the current platform using the default Rust allocator. pub fn new(size: usize) -> OwnedStack { - OwnedStack(unsafe { RawVec::with_capacity(size).into_box() }) + unsafe { + let ptr = heap::allocate(size, ::STACK_ALIGNMENT); + OwnedStack(Box::from_raw(slice::from_raw_parts_mut(ptr, size))) + } } } diff --git a/src/slice_stack.rs b/src/slice_stack.rs index 2ac0a82..0af9502 100644 --- a/src/slice_stack.rs +++ b/src/slice_stack.rs @@ -2,8 +2,10 @@ // Copyright (c) whitequark // See the LICENSE file included in this distribution. -/// SliceStack holds a non-guarded stack allocated elsewhere and provided as a mutable -/// slice. +/// SliceStack holds a non-guarded stack allocated elsewhere and provided as a mutable slice. +/// +/// Any slice used in a SliceStack must adhere to the [Stack contract][contract]. +/// [contract]: trait.Stack.html #[derive(Debug)] pub struct SliceStack<'a>(pub &'a mut [u8]); diff --git a/src/stack.rs b/src/stack.rs index dfd05bc..39afc39 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -11,17 +11,17 @@ /// To preserve memory safety, an implementation of this trait must fulfill /// the following contract: /// -/// * The base of the stack must be aligned to a platform-specific boundary. +/// * The base address of the stack must be aligned to +/// a [`STACK_ALIGNMENT`][align]-byte boundary. /// * Every address between the base and the limit must be readable and writable. /// -/// On any platform supported by libfringe, it is safe to align the stack to a 16-byte boundary. -/// The platform ABI document lists the specific alignment requirement. +/// [align]: constant.STACK_ALIGNMENT.html pub trait Stack { - /// Returns the base of the stack. + /// Returns the base address of the stack. /// On all modern architectures, the stack grows downwards, /// so this is the highest address. fn base(&self) -> *mut u8; - /// Returns the limit of the stack. + /// Returns the limit address of the stack. /// On all modern architectures, the stack grows downwards, /// so this is the lowest address. fn limit(&self) -> *mut u8;