forked from M-Labs/artiq-zynq
rpc: Fixed alignment problem.
Fixes issue #42. Previously there was no fix for the variable alignment. We calculate the position of the variable based on the size of the previous variable, so we could break the alignment requirement for variables. For example, having a `i64` after `bool` could break the alignment required for `i64` and trigger DataAbort or data corruption. However, this requires the same data layout and LLVM type for the variables. If this cannot be maintained, this would break the alignment on the other side of the RPC, either from host to kernel or kernel to host.
This commit is contained in:
parent
2e10922715
commit
4457af7277
@ -13,6 +13,18 @@ use crate::proto_core_io::ProtoWrite;
|
|||||||
use crate::proto_async;
|
use crate::proto_async;
|
||||||
use self::tag::{Tag, TagIterator, split_tag};
|
use self::tag::{Tag, TagIterator, split_tag};
|
||||||
|
|
||||||
|
unsafe fn align_ptr<T>(ptr: *const ()) -> *const T {
|
||||||
|
let alignment = core::mem::align_of::<T>() as isize;
|
||||||
|
let fix = (alignment - (ptr as isize) % alignment) % alignment;
|
||||||
|
((ptr as isize) + fix) as *const T
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
|
||||||
|
let alignment = core::mem::align_of::<T>() as isize;
|
||||||
|
let fix = (alignment - (ptr as isize) % alignment) % alignment;
|
||||||
|
((ptr as isize) + fix) as *mut T
|
||||||
|
}
|
||||||
|
|
||||||
#[async_recursion(?Send)]
|
#[async_recursion(?Send)]
|
||||||
async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, data: &mut *mut (),
|
async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, data: &mut *mut (),
|
||||||
alloc: &(impl Fn(usize) -> F + 'async_recursion))
|
alloc: &(impl Fn(usize) -> F + 'async_recursion))
|
||||||
@ -21,7 +33,7 @@ async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, da
|
|||||||
{
|
{
|
||||||
macro_rules! consume_value {
|
macro_rules! consume_value {
|
||||||
($ty:ty, |$ptr:ident| $map:expr) => ({
|
($ty:ty, |$ptr:ident| $map:expr) => ({
|
||||||
let $ptr = (*data) as *mut $ty;
|
let $ptr = align_ptr_mut::<$ty>(*data);
|
||||||
*data = $ptr.offset(1) as *mut ();
|
*data = $ptr.offset(1) as *mut ();
|
||||||
$map
|
$map
|
||||||
})
|
})
|
||||||
@ -108,7 +120,7 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
|
|||||||
{
|
{
|
||||||
macro_rules! consume_value {
|
macro_rules! consume_value {
|
||||||
($ty:ty, |$ptr:ident| $map:expr) => ({
|
($ty:ty, |$ptr:ident| $map:expr) => ({
|
||||||
let $ptr = (*data) as *const $ty;
|
let $ptr = align_ptr::<$ty>(*data);
|
||||||
*data = $ptr.offset(1) as *const ();
|
*data = $ptr.offset(1) as *const ();
|
||||||
$map
|
$map
|
||||||
})
|
})
|
||||||
@ -142,6 +154,7 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Tag::List(it) | Tag::Array(it) => {
|
Tag::List(it) | Tag::Array(it) => {
|
||||||
|
#[repr(C)]
|
||||||
struct List { elements: *const (), length: u32 };
|
struct List { elements: *const (), length: u32 };
|
||||||
consume_value!(List, |ptr| {
|
consume_value!(List, |ptr| {
|
||||||
writer.write_u32((*ptr).length)?;
|
writer.write_u32((*ptr).length)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user