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:
parent
a04117f955
commit
2760a0a7aa
2
build.rs
2
build.rs
|
@ -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"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.
|
|
@ -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;
|
||||||
|
|
11
src/os.rs
11
src/os.rs
|
@ -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())
|
||||||
|
|
Loading…
Reference in New Issue