move Valgrind handling into Context

fix #3
This takes all Valgrind functionality private again.
Valgrind stack registrations are now associated with a Context, not with
a Stack. This makes sense, since it's only actually a stack when a
Context is running on it. Perhaps Valgrind will even be able to detect
early stack frees now.
This commit is contained in:
edef 2015-04-16 02:30:10 -04:00
parent a04117f955
commit 2760a0a7aa
7 changed files with 33 additions and 16 deletions

View File

@ -1,5 +1,5 @@
extern crate gcc; extern crate gcc;
fn main() { fn main() {
gcc::compile_library("libvalgrind.a", &["src/valgrind.c"]); gcc::compile_library("libvalgrind.a", &["src/debug/valgrind.c"]);
} }

View File

@ -1,9 +1,11 @@
use core::prelude::*; use core::prelude::*;
use arch::Registers; use arch::Registers;
use stack; use stack;
use debug::StackId;
pub struct Context<Stack: stack::Stack> { pub struct Context<Stack: stack::Stack> {
regs: Registers, regs: Registers,
_stack_id: StackId,
stack: Stack stack: Stack
} }
@ -11,9 +13,11 @@ impl<Stack> Context<Stack> where Stack: stack::Stack {
#[inline] #[inline]
pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<Stack> pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<Stack>
where F: FnOnce() + Send + 'static { where F: FnOnce() + Send + 'static {
let stack_id = StackId::register(&mut stack);
let regs = Registers::new(&mut stack, f); let regs = Registers::new(&mut stack, f);
Context { Context {
regs: regs, regs: regs,
_stack_id: stack_id,
stack: stack stack: stack
} }
} }

24
src/debug/mod.rs Normal file
View File

@ -0,0 +1,24 @@
use core::prelude::*;
use stack;
mod valgrind;
pub struct StackId(valgrind::stack_id_t);
impl StackId {
#[inline(always)]
pub fn register<Stack: stack::Stack>(stack: &mut Stack) -> StackId {
StackId(unsafe {
valgrind::stack_register(stack.limit(), stack.top())
})
}
}
impl Drop for StackId {
#[inline(always)]
fn drop(&mut self) {
unsafe {
valgrind::stack_deregister(self.0)
}
}
}

View File

@ -12,11 +12,6 @@ extern "C" {
/// `start < end`. /// `start < end`.
pub fn stack_register(start: *const u8, end: *const u8) -> stack_id_t; pub fn stack_register(start: *const u8, end: *const u8) -> stack_id_t;
#[link_name = "valgrind_stack_change"]
/// Change the size or location of a stack registered with Valgrind.
/// `start < end`.
pub fn stack_change(id: stack_id_t, start: *const u8, end: *const u8) -> stack_id_t;
#[link_name = "valgrind_stack_deregister"] #[link_name = "valgrind_stack_deregister"]
/// Deregister a stack from Valgrind. Takes the integer ID that was returned /// Deregister a stack from Valgrind. Takes the integer ID that was returned
/// on registration. /// on registration.

View File

@ -18,7 +18,8 @@ mod std { pub use core::*; }
pub mod context; pub mod context;
pub mod stack; pub mod stack;
pub mod valgrind;
mod debug;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
mod arch; mod arch;

View File

@ -2,7 +2,6 @@ extern crate std;
use core::prelude::*; use core::prelude::*;
use self::std::io::Error as IoError; use self::std::io::Error as IoError;
use stack; use stack;
use valgrind;
#[cfg(unix)] #[cfg(unix)]
#[path = "os/unix.rs"] mod sys; #[path = "os/unix.rs"] mod sys;
@ -11,8 +10,7 @@ use valgrind;
#[derive(Debug)] #[derive(Debug)]
pub struct Stack { pub struct Stack {
ptr: *mut u8, ptr: *mut u8,
len: usize, len: usize
valgrind_id: valgrind::stack_id_t
} }
pub struct StackSource; pub struct StackSource;
@ -55,11 +53,7 @@ impl Stack {
Some(ptr) => ptr Some(ptr) => ptr
}; };
let valgrind_id = Stack { ptr: ptr as *mut u8, len: len }
valgrind::stack_register(ptr as *const _,
ptr.offset(len as isize) as *const _);
Stack { ptr: ptr as *mut u8, len: len, valgrind_id: valgrind_id }
}; };
unsafe { unsafe {
@ -76,7 +70,6 @@ impl Stack {
impl Drop for Stack { impl Drop for Stack {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
valgrind::stack_deregister(self.valgrind_id);
if !sys::unmap_stack(self.ptr, self.len) { 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())