#[cfg(asan)]
mod enabled {
use crate::vm::{VMCommonStackInformation, VMContRef, VMStackChain, VmPtr};
use core::ptr::NonNull;
unsafe fn continuation_from_args(args: *mut crate::vm::VMHostArray) -> *mut VMContRef {
unsafe {
args.cast::<u8>()
.byte_sub(core::mem::offset_of!(VMContRef, args))
.cast()
}
}
unsafe fn parent_csi(contref: *mut VMContRef) -> *mut VMCommonStackInformation {
let parent = unsafe { &mut (*contref).parent_chain };
match parent {
VMStackChain::InitialStack(csi) => csi.as_ptr(),
VMStackChain::Continuation(contref) => unsafe {
core::ptr::addr_of_mut!((*contref.as_ptr()).common_stack_information)
},
VMStackChain::Absent => panic!("a running continuation must have a parent stack"),
}
}
unsafe fn stack_range(csi: *const VMCommonStackInformation) -> (*const u8, usize) {
let csi = unsafe { &*csi };
let bottom = csi
.asan_stack_bottom
.expect("ASan requires the destination stack's bounds");
(bottom.as_ptr(), csi.asan_stack_size)
}
pub unsafe extern "C" fn start_switch_fiber(fake_stack_save: *mut u8, target_csi: *mut u8) {
unsafe {
let (bottom, size) = stack_range(target_csi.cast());
__sanitizer_start_switch_fiber(Some(&mut *fake_stack_save.cast()), bottom, size);
}
}
pub unsafe extern "C" fn finish_switch_fiber(fake_stack: *mut u8) {
unsafe {
let mut bottom = core::ptr::null();
let mut size = 0;
__sanitizer_finish_switch_fiber(fake_stack, &mut bottom, &mut size);
}
}
#[cfg_attr(asan, sanitize(address = "off"))]
#[cfg(all(feature = "stack-switching"))]
pub unsafe fn fiber_start_complete(args: *mut crate::vm::VMHostArray) {
unsafe {
let mut bottom = core::ptr::null();
let mut size = 0;
__sanitizer_finish_switch_fiber(core::ptr::null_mut(), &mut bottom, &mut size);
let parent = &mut *parent_csi(continuation_from_args(args));
parent.asan_stack_bottom = Some(VmPtr::from(
NonNull::new(bottom.cast_mut())
.expect("ASan must report the previous stack's bounds"),
));
parent.asan_stack_size = size;
}
}
#[cfg_attr(asan, sanitize(address = "off"))]
#[cfg(all(feature = "stack-switching"))]
pub unsafe extern "C" fn fiber_exit(args: *mut crate::vm::VMHostArray) {
unsafe {
let parent = parent_csi(continuation_from_args(args));
let (bottom, size) = stack_range(parent);
__sanitizer_start_switch_fiber(None, bottom, size);
}
}
unsafe extern "C" {
fn __sanitizer_start_switch_fiber(
fake_stack_save: Option<&mut *mut u8>,
bottom: *const u8,
size: usize,
);
fn __sanitizer_finish_switch_fiber(
fake_stack: *mut u8,
bottom_old: &mut *const u8,
size_old: &mut usize,
);
}
}
#[cfg(not(asan))]
mod disabled {
#[allow(dead_code, reason = "Used by ASan builds")]
pub unsafe extern "C" fn start_switch_fiber(_fake_stack_save: *mut u8, _target_csi: *mut u8) {}
#[allow(dead_code, reason = "Used by ASan builds")]
pub unsafe extern "C" fn finish_switch_fiber(_fake_stack: *mut u8) {}
}
#[cfg(not(asan))]
#[allow(unused_imports, reason = "Used by ASan builds")]
pub use disabled::*;
#[cfg(asan)]
pub use enabled::*;