@@ -22,6 +22,9 @@ use libbpf_rs::Btf;
2222use libbpf_rs:: HasSize ;
2323use libbpf_rs:: ReferencesType ;
2424
25+ use super :: canonicalize_internal_map_name;
26+ use super :: InternalMapType ;
27+
2528const ANON_PREFIX : & str = "__anon_" ;
2629
2730/// Check whether the provided type is "unsafe" to use.
@@ -377,11 +380,148 @@ impl<'s> GenBtf<'s> {
377380 Ok ( def)
378381 }
379382
383+ pub fn struct_ops_type_definition ( & self , processed : & mut HashSet < TypeId > ) -> Result < String > {
384+ let mut def = String :: new ( ) ;
385+ let mut dependent_types = vec ! [ ] ;
386+ let mut vars = vec ! [ ] ;
387+
388+ // Take all the struct_ops datasec entries and collect their variables
389+ // (and dependent types).
390+ for ty in self . type_by_kind :: < types:: DataSec < ' _ > > ( ) {
391+ let name = match ty. name ( ) {
392+ Some ( s) => s. to_str ( ) ?,
393+ None => "" ,
394+ } ;
395+
396+ if !matches ! (
397+ canonicalize_internal_map_name( name) ,
398+ Some ( InternalMapType :: StructOps )
399+ ) {
400+ continue ;
401+ }
402+
403+ for var in ty. iter ( ) {
404+ let var = self
405+ . type_by_id :: < types:: Var < ' _ > > ( var. ty )
406+ . ok_or_else ( || anyhow ! ( "datasec type does not point to a variable" ) ) ?;
407+
408+ if var. linkage ( ) == types:: Linkage :: Static {
409+ // do not output Static Var
410+ continue ;
411+ }
412+
413+ let ( ) = vars. push ( * var) ;
414+
415+ if let Some ( next_ty) = next_type ( * var) ? {
416+ let ( ) = dependent_types. push ( next_ty) ;
417+ }
418+ }
419+ }
420+
421+ // Emit a single struct_ops definition containing all variables
422+ // discovered earlier.
423+ write ! (
424+ def,
425+ r#"
426+ #[derive(Debug, Clone)]
427+ #[repr(C)]
428+ pub struct struct_ops {{
429+ "#
430+ ) ?;
431+
432+ for var in vars. iter ( ) {
433+ writeln ! (
434+ def,
435+ r#" pub {var_name}: *mut {var_type},"# ,
436+ var_name = var. name( ) . unwrap( ) . to_string_lossy( ) ,
437+ var_type = self . type_declaration( * var) ?
438+ ) ?;
439+ }
440+
441+ writeln ! ( def, "}}" ) ?;
442+
443+ write ! (
444+ def,
445+ r#"
446+ impl struct_ops {{
447+ "#
448+ ) ?;
449+
450+ for var in vars. iter ( ) {
451+ write ! (
452+ def,
453+ r#"
454+ pub fn {var_name}(&self) -> &{var_type} {{
455+ // SAFETY: The library ensures that the member is pointing to
456+ // valid data.
457+ unsafe {{ self.{var_name}.as_ref() }}.unwrap()
458+ }}
459+
460+ pub fn {var_name}_mut(&mut self) -> &mut {var_type} {{
461+ // SAFETY: The library ensures that the member is pointing to
462+ // valid data.
463+ unsafe {{ self.{var_name}.as_mut() }}.unwrap()
464+ }}
465+ "# ,
466+ var_name = var. name( ) . unwrap( ) . to_string_lossy( ) ,
467+ var_type = self . type_declaration( * var) ?
468+ ) ?;
469+ }
470+
471+ writeln ! ( def, "}}" ) ?;
472+
473+ let vars = vars
474+ . into_iter ( )
475+ . map ( |ty| ty. next_type ( ) . unwrap ( ) . type_id ( ) )
476+ . collect :: < HashSet < _ > > ( ) ;
477+
478+ while !dependent_types. is_empty ( ) {
479+ let ty = dependent_types. remove ( 0 ) ;
480+ if !processed. insert ( ty. type_id ( ) ) {
481+ continue ;
482+ }
483+
484+ btf_type_match ! ( match ty {
485+ BtfKind :: Composite ( t) => {
486+ if vars. contains( & ty. type_id( ) ) {
487+ let opts = TypeDeclOpts {
488+ func_type: "libbpf_rs::libbpf_sys::bpf_program" ,
489+ } ;
490+ self . type_definition_for_composites_with_opts(
491+ & mut def,
492+ & mut dependent_types,
493+ t,
494+ & opts,
495+ ) ?
496+ } else {
497+ self . type_definition_for_composites( & mut def, & mut dependent_types, t) ?
498+ }
499+ }
500+ BtfKind :: Enum ( t) => self . type_definition_for_enums( & mut def, t) ?,
501+ _ => bail!( "Invalid type: {:?}" , ty. kind( ) ) ,
502+ } ) ;
503+ }
504+
505+ Ok ( def)
506+ }
380507 fn type_definition_for_composites < ' a > (
381508 & ' a self ,
382509 def : & mut String ,
383510 dependent_types : & mut Vec < BtfType < ' a > > ,
384511 t : types:: Composite < ' _ > ,
512+ ) -> Result < ( ) > {
513+ let opts = TypeDeclOpts {
514+ func_type : "std::ffi::c_void" ,
515+ } ;
516+ self . type_definition_for_composites_with_opts ( def, dependent_types, t, & opts)
517+ }
518+
519+ fn type_definition_for_composites_with_opts < ' a > (
520+ & ' a self ,
521+ def : & mut String ,
522+ dependent_types : & mut Vec < BtfType < ' a > > ,
523+ t : types:: Composite < ' _ > ,
524+ opts : & TypeDeclOpts ,
385525 ) -> Result < ( ) > {
386526 let packed = is_struct_packed ( & t, & self . btf ) ?;
387527
@@ -476,7 +616,7 @@ impl<'s> GenBtf<'s> {
476616 // Set `offset` to end of current var
477617 offset = ( member_offset / 8 ) as usize + size_of_type ( field_ty, & self . btf ) ?;
478618
479- let field_ty_str = self . type_declaration ( field_ty) ?;
619+ let field_ty_str = type_declaration_impl ( field_ty, & self . anon_types , opts ) ?;
480620 let field_ty_str = if is_unsafe ( field_ty) {
481621 Cow :: Owned ( format ! ( "std::mem::MaybeUninit<{field_ty_str}>" ) )
482622 } else {
0 commit comments