@@ -951,6 +951,44 @@ fn gen_skel_contents(_debug: bool, raw_obj_name: &str, obj_file_path: &Path) ->
951951 write ! (
952952 skel,
953953 "\
954+ struct OwnedRef<'obj, O> {{
955+ object: Option<&'obj mut std::mem::MaybeUninit<O>>,
956+ }}
957+
958+ impl<'obj, O> OwnedRef<'obj, O> {{
959+ /// # Safety
960+ /// The object has to be initialized.
961+ unsafe fn new(object: &'obj mut std::mem::MaybeUninit<O>) -> Self {{
962+ Self {{
963+ object: Some(object),
964+ }}
965+ }}
966+
967+ fn as_ref(&self) -> &O {{
968+ // SAFETY: As per the contract during construction, the
969+ // object has to be initialized.
970+ unsafe {{ self.object.as_ref().unwrap().assume_init_ref() }}
971+ }}
972+
973+ fn as_mut(&mut self) -> &mut O {{
974+ // SAFETY: As per the contract during construction, the
975+ // object has to be initialized.
976+ unsafe {{ self.object.as_mut().unwrap().assume_init_mut() }}
977+ }}
978+
979+ fn take(mut self) -> &'obj mut std::mem::MaybeUninit<O> {{
980+ self.object.take().unwrap()
981+ }}
982+ }}
983+
984+ impl<O> Drop for OwnedRef<'_, O> {{
985+ fn drop(&mut self) {{
986+ if let Some(object) = &mut self.object {{
987+ unsafe {{ object.assume_init_drop() }}
988+ }}
989+ }}
990+ }}
991+
954992 #[derive(Default)]
955993 pub struct {name}SkelBuilder {{
956994 pub obj_builder: libbpf_rs::ObjectBuilder,
@@ -980,17 +1018,23 @@ fn gen_skel_contents(_debug: bool, raw_obj_name: &str, obj_file_path: &Path) ->
9801018 return Err(libbpf_rs::Error::from_raw_os_error(-ret));
9811019 }}
9821020
1021+ // SAFETY: `skel_ptr` points to a valid object after the
1022+ // open call.
9831023 let obj_ptr = unsafe {{ *skel_ptr.as_ref().obj }};
9841024 // SANITY: `bpf_object__open_skeleton` should have
9851025 // allocated the object.
9861026 let obj_ptr = std::ptr::NonNull::new(obj_ptr).unwrap();
1027+ // SAFETY: `obj_ptr` points to an opened object after
1028+ // skeleton open.
9871029 let obj = unsafe {{ libbpf_rs::OpenObject::from_ptr(obj_ptr) }};
988- let obj_ref = object.write(obj);
1030+ let _obj = object.write(obj);
1031+ // SAFETY: We just wrote initialized data to `object`.
1032+ let mut obj_ref = unsafe {{ OwnedRef::new(object) }};
9891033
9901034 #[allow(unused_mut)]
9911035 let mut skel = Open{name}Skel {{
992- maps: unsafe {{ Open{name}Maps::new(&skel_config, obj_ref)? }},
993- progs: unsafe {{ Open{name}Progs::new(obj_ref)? }},
1036+ maps: unsafe {{ Open{name}Maps::new(&skel_config, obj_ref.as_mut() )? }},
1037+ progs: unsafe {{ Open{name}Progs::new(obj_ref.as_mut() )? }},
9941038 obj: obj_ref,
9951039 // SAFETY: Our `struct_ops` type contains only pointers,
9961040 // which are allowed to be NULL.
@@ -1057,7 +1101,7 @@ pub struct StructOps {{}}
10571101 skel,
10581102 "\
10591103 pub struct Open{name}Skel<'obj> {{
1060- obj: & 'obj mut libbpf_rs::OpenObject,
1104+ obj: OwnedRef< 'obj, libbpf_rs::OpenObject> ,
10611105 pub maps: Open{name}Maps<'obj>,
10621106 pub progs: Open{name}Progs<'obj>,
10631107 pub struct_ops: StructOps,
@@ -1074,22 +1118,25 @@ pub struct StructOps {{}}
10741118 return Err(libbpf_rs::Error::from_raw_os_error(-ret));
10751119 }}
10761120
1077- let obj_ref = unsafe {{
1078- std::mem::transmute::<
1079- &'obj mut libbpf_rs::OpenObject,
1080- &'obj mut std::mem::MaybeUninit<libbpf_rs::OpenObject>,
1081- >(self.obj)
1082- }};
1121+ let obj_ref = self.obj.take();
10831122 let open_obj = std::mem::replace(obj_ref, std::mem::MaybeUninit::uninit());
1084- let obj = unsafe {{ libbpf_rs::Object::from_ptr(open_obj.assume_init().take_ptr()) }};
1085-
1123+ // SAFETY: `open_obj` is guaranteed to be properly
1124+ // initialized as it came from an `OwnedRef`.
1125+ let obj_ptr = unsafe {{ open_obj.assume_init().take_ptr() }};
1126+ // SAFETY: `obj_ptr` points to a loaded object after
1127+ // skeleton load.
1128+ let obj = unsafe {{ libbpf_rs::Object::from_ptr(obj_ptr) }};
1129+ // SAFETY: `OpenObject` and `Object` are guaranteed to
1130+ // have the same memory layout.
10861131 let obj_ref = unsafe {{
10871132 std::mem::transmute::<
10881133 &'obj mut std::mem::MaybeUninit<libbpf_rs::OpenObject>,
10891134 &'obj mut std::mem::MaybeUninit<libbpf_rs::Object>,
10901135 >(obj_ref)
10911136 }};
1092- let obj_ref = obj_ref.write(obj);
1137+ let _obj = obj_ref.write(obj);
1138+ // SAFETY: We just wrote initialized data to `obj_ref`.
1139+ let obj_ref = unsafe {{ OwnedRef::new(obj_ref) }};
10931140
10941141 Ok({name}Skel {{
10951142 obj: obj_ref,
@@ -1102,11 +1149,11 @@ pub struct StructOps {{}}
11021149 }}
11031150
11041151 fn open_object(&self) -> &libbpf_rs::OpenObject {{
1105- self.obj
1152+ self.obj.as_ref()
11061153 }}
11071154
11081155 fn open_object_mut(&mut self) -> &mut libbpf_rs::OpenObject {{
1109- self.obj
1156+ self.obj.as_mut()
11101157 }}
11111158 " ,
11121159 name = & obj_name,
@@ -1124,7 +1171,7 @@ pub struct StructOps {{}}
11241171 skel,
11251172 "\
11261173 pub struct {name}Skel<'obj> {{
1127- obj: & 'obj mut libbpf_rs::Object,
1174+ obj: OwnedRef< 'obj, libbpf_rs::Object> ,
11281175 pub maps: {name}Maps<'obj>,
11291176 pub progs: {name}Progs<'obj>,
11301177 struct_ops: StructOps,
@@ -1143,11 +1190,11 @@ pub struct StructOps {{}}
11431190
11441191 impl<'obj> Skel<'obj> for {name}Skel<'obj> {{
11451192 fn object(&self) -> &libbpf_rs::Object {{
1146- self.obj
1193+ self.obj.as_ref()
11471194 }}
11481195
11491196 fn object_mut(&mut self) -> &mut libbpf_rs::Object {{
1150- self.obj
1197+ self.obj.as_mut()
11511198 }}
11521199 " ,
11531200 name = & obj_name,
0 commit comments