Messages in this thread | | | From | Andreas Hindborg <> | Subject | Re: [PATCH v1 2/7] rust: add offset_of! macro | Date | Tue, 30 May 2023 10:40:03 +0200 |
| |
Gary Guo <gary@garyguo.net> writes:
> On Wed, 17 May 2023 20:31:14 +0000 > Alice Ryhl <aliceryhl@google.com> wrote: > >> From: Wedson Almeida Filho <walmeida@microsoft.com> >> >> This macro is used to compute the offset of a field in a struct. >> >> This commit enables two unstable features that are necessary for using >> the macro in a constant. However, this is not a problem as the macro >> will become available from the Rust standard library soon [1]. The >> unstable features can be disabled again once that happens. >> >> The macro in this patch does not support sub-fields. That is, you cannot >> write `offset_of!(MyStruct, field.sub_field)` to get the offset of >> `sub_field` with `field`'s type being a struct with a field called >> `sub_field`. This is because `field` might be a `Box<SubStruct>`, which >> means that you would be trying to compute the offset to something in an >> entirely different allocation. There's no easy way to fix the current >> macro to support subfields, but the version being added to the standard >> library should support it, so the limitation is temporary and not a big >> deal. >> >> Link: https://github.com/rust-lang/rust/issues/106655 [1] >> Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com> >> Co-developed-by: Alice Ryhl <aliceryhl@google.com> >> Signed-off-by: Alice Ryhl <aliceryhl@google.com> >> --- >> rust/kernel/lib.rs | 35 +++++++++++++++++++++++++++++++++++ >> scripts/Makefile.build | 2 +- >> 2 files changed, 36 insertions(+), 1 deletion(-) >> >> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs >> index c718524056a6..cdf9fe999328 100644 >> --- a/rust/kernel/lib.rs >> +++ b/rust/kernel/lib.rs >> @@ -14,6 +14,8 @@ >> #![no_std] >> #![feature(allocator_api)] >> #![feature(coerce_unsized)] >> +#![feature(const_ptr_offset_from)] >> +#![feature(const_refs_to_cell)] >> #![feature(core_ffi_c)] >> #![feature(dispatch_from_dyn)] >> #![feature(explicit_generic_args_with_impl_trait)] >> @@ -102,3 +104,36 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! { >> // instead of `!`. See <https://github.com/rust-lang/rust-bindgen/issues/2094>. >> loop {} >> } >> + >> +/// Calculates the offset of a field from the beginning of the struct it belongs to. >> +/// >> +/// # Examples >> +/// >> +/// ``` >> +/// #[repr(C)] >> +/// struct Test { >> +/// a: u64, >> +/// b: u32, >> +/// } >> +/// >> +/// assert_eq!(kernel::offset_of!(Test, b), 8); >> +/// ``` >> +#[macro_export] >> +macro_rules! offset_of { >> + ($type:ty, $field:ident) => {{ >> + let tmp = ::core::mem::MaybeUninit::<$type>::uninit(); >> + let outer = tmp.as_ptr(); >> + // To avoid warnings when nesting `unsafe` blocks. >> + #[allow(unused_unsafe)] >> + // SAFETY: The pointer is valid and aligned, just not initialised; `addr_of` ensures that >> + // we don't actually read from `outer` (which would be UB) nor create an intermediate >> + // reference. >> + let inner = unsafe { ::core::ptr::addr_of!((*outer).$field) } as *const u8; >> + // To avoid warnings when nesting `unsafe` blocks. >> + #[allow(unused_unsafe)] >> + // SAFETY: The two pointers are within the same allocation block. >> + unsafe { >> + inner.offset_from(outer as *const u8) as usize >> + } > > This has no protection against using `Deref`. The memoffset crate has a > > let $type { $field: _, .. }; > > line to ensure that the field is a direct member of type and deref is > not happening.
Good catch 👍
> >> + }}; >> +} >> diff --git a/scripts/Makefile.build b/scripts/Makefile.build >> index 9f94fc83f086..ec583d13dde2 100644 >> --- a/scripts/Makefile.build >> +++ b/scripts/Makefile.build >> @@ -277,7 +277,7 @@ $(obj)/%.lst: $(src)/%.c FORCE >> # Compile Rust sources (.rs) >> # --------------------------------------------------------------------------- >> >> -rust_allowed_features := core_ffi_c,explicit_generic_args_with_impl_trait,new_uninit,pin_macro >> +rust_allowed_features := const_ptr_offset_from,const_refs_to_cell,core_ffi_c,explicit_generic_args_with_impl_trait,new_uninit,pin_macro > > Side note: once we bump our compiler to 1.71, we should switch to the > built-in `offset_of!` macro and get rid of these unstable features. > > Best, > Gary
| |