Repository: libbpf/libbpf-rs (language: rust)

Issue:
[libbpf-cargo] Add support for floats
Floating types were added to libbpf but have not yet been updated in libbpf-cargo


Discussion / hints:
Hi,
I'm looking to contribute to this project. I have some bandwidth in the next few weeks so I could take a crack at this problem if I can get some guidance on the tasks that need to get done? Seems like we would need to update `BtfType` and some methods in `btf.rs` to handle `BtfType::FLoat`. Let me know if it's ok to pick this work up. 

Fix patch:
diff --git a/libbpf-cargo/src/btf/btf.rs b/libbpf-cargo/src/btf/btf.rs
index e414066a..e6caa100 100644
--- a/libbpf-cargo/src/btf/btf.rs
+++ b/libbpf-cargo/src/btf/btf.rs
@@ -136,6 +136,7 @@ impl<'a> Btf<'a> {
             BtfType::Enum(t) => t.size,
             BtfType::Var(t) => self.size_of(t.type_id)?,
             BtfType::Datasec(t) => t.size,
+            BtfType::Float(t) => t.size,
             BtfType::Void
             | BtfType::Volatile(_)
             | BtfType::Const(_)
@@ -143,7 +144,8 @@ impl<'a> Btf<'a> {
             | BtfType::Typedef(_)
             | BtfType::FuncProto(_)
             | BtfType::Fwd(_)
-            | BtfType::Func(_) => bail!("Cannot get size of type_id: {}", skipped_type_id),
+            | BtfType::Func(_)
+            | BtfType::DeclTag(_) => bail!("Cannot get size of type_id: {}", skipped_type_id),
         })
     }
 
@@ -165,6 +167,7 @@ impl<'a> Btf<'a> {
             BtfType::Enum(t) => min(self.ptr_size, t.size),
             BtfType::Var(t) => self.align_of(t.type_id)?,
             BtfType::Datasec(t) => t.size,
+            BtfType::Float(t) => min(self.ptr_size, t.size),
             BtfType::Void
             | BtfType::Volatile(_)
             | BtfType::Const(_)
@@ -172,7 +175,8 @@ impl<'a> Btf<'a> {
             | BtfType::Typedef(_)
             | BtfType::FuncProto(_)
             | BtfType::Fwd(_)
-            | BtfType::Func(_) => bail!("Cannot get alignment of type_id: {}", skipped_type_id),
+            | BtfType::Func(_)
+            | BtfType::DeclTag(_) => bail!("Cannot get alignment of type_id: {}", skipped_type_id),
         })
     }
 
@@ -206,6 +210,18 @@ impl<'a> Btf<'a> {
                     btf::BtfIntEncoding::Char | btf::BtfIntEncoding::None => format!("u{}", width),
                 }
             }
+            BtfType::Float(t) => {
+                let width = match t.size {
+                    2 => bail!("Unsupported float width"),
+                    4 => "32",
+                    8 => "64",
+                    12 => bail!("Unsupported float width"),
+                    16 => bail!("Unsupported float width"),
+                    _ => bail!("Invalid float width"),
+                };
+
+                format!("f{}", width)
+            }
             BtfType::Ptr(t) => {
                 let pointee_ty = self.type_declaration(t.pointee_type)?;
 
@@ -231,7 +247,8 @@ impl<'a> Btf<'a> {
             | BtfType::Typedef(_)
             | BtfType::Volatile(_)
             | BtfType::Const(_)
-            | BtfType::Restrict(_) => {
+            | BtfType::Restrict(_)
+            | BtfType::DeclTag(_) => {
                 bail!("Invalid type: {}", ty)
             }
         })
@@ -252,6 +269,7 @@ impl<'a> Btf<'a> {
         Ok(match ty {
             BtfType::Void => "std::ffi::c_void::default()".to_string(),
             BtfType::Int(_) => format!("{}::default()", self.type_declaration(stripped_type_id)?),
+            BtfType::Float(_) => format!("{}::default()", self.type_declaration(stripped_type_id)?),
             BtfType::Ptr(_) => "std::ptr::null_mut()".to_string(),
             BtfType::Array(t) => {
                 let val_ty = self.type_declaration(t.val_type_id)?;
@@ -268,7 +286,8 @@ impl<'a> Btf<'a> {
             | BtfType::Typedef(_)
             | BtfType::Volatile(_)
             | BtfType::Const(_)
-            | BtfType::Restrict(_) => {
+            | BtfType::Restrict(_)
+            | BtfType::DeclTag(_) => {
                 bail!("Invalid type: {}", ty)
             }
         })
@@ -368,7 +387,14 @@ impl<'a> Btf<'a> {
                     BtfType::Const(t) => id = t.type_id,
                     BtfType::Restrict(t) => id = t.type_id,
                     BtfType::Typedef(t) => id = t.type_id,
-                    _ => return Ok(None),
+                    BtfType::DeclTag(t) => id = t.type_id,
+                    BtfType::Void
+                    | BtfType::Int(_)
+                    | BtfType::Float(_)
+                    | BtfType::Fwd(_)
+                    | BtfType::Func(_)
+                    | BtfType::FuncProto(_)
+                    | BtfType::Var(_) => return Ok(None),
                 }
             }
         };
@@ -376,7 +402,20 @@ impl<'a> Btf<'a> {
         let is_terminal = |id| -> Result<bool> {
             match self.type_by_id(id)?.kind() {
                 BtfKind::Struct | BtfKind::Union | BtfKind::Enum | BtfKind::Datasec => Ok(false),
-                _ => Ok(true),
+                BtfKind::Void
+                | BtfKind::Int
+                | BtfKind::Float
+                | BtfKind::Ptr
+                | BtfKind::Array
+                | BtfKind::Fwd
+                | BtfKind::Typedef
+                | BtfKind::Volatile
+                | BtfKind::Const
+                | BtfKind::Restrict
+                | BtfKind::Func
+                | BtfKind::FuncProto
+                | BtfKind::Var
+                | BtfKind::DeclTag => Ok(true),
             }
         };
 
@@ -648,6 +687,7 @@ impl<'a> Btf<'a> {
                 | BtfType::Ptr(_)
                 | BtfType::Func(_)
                 | BtfType::Int(_)
+                | BtfType::Float(_)
                 | BtfType::Array(_)
                 | BtfType::Fwd(_)
                 | BtfType::Typedef(_)
@@ -655,7 +695,8 @@ impl<'a> Btf<'a> {
                 | BtfType::Var(_)
                 | BtfType::Volatile(_)
                 | BtfType::Const(_)
-                | BtfType::Restrict(_) => bail!("Invalid type: {}", ty),
+                | BtfType::Restrict(_)
+                | BtfType::DeclTag(_) => bail!("Invalid type: {}", ty),
             }
         }
 
@@ -669,7 +710,20 @@ impl<'a> Btf<'a> {
                 BtfType::Const(t) => type_id = t.type_id,
                 BtfType::Restrict(t) => type_id = t.type_id,
                 BtfType::Typedef(t) => type_id = t.type_id,
-                _ => return Ok(type_id),
+                BtfType::Void
+                | BtfType::Int(_)
+                | BtfType::Float(_)
+                | BtfType::Ptr(_)
+                | BtfType::Array(_)
+                | BtfType::Struct(_)
+                | BtfType::Union(_)
+                | BtfType::Enum(_)
+                | BtfType::Fwd(_)
+                | BtfType::Func(_)
+                | BtfType::FuncProto(_)
+                | BtfType::Var(_)
+                | BtfType::Datasec(_)
+                | BtfType::DeclTag(_) => return Ok(type_id),
             };
         }
     }
@@ -685,6 +739,7 @@ impl<'a> Btf<'a> {
                 bail!("Cannot load Void type");
             }
             BtfKind::Int => self.load_int(&t, extra),
+            BtfKind::Float => self.load_float(&t),
             BtfKind::Ptr => Ok(BtfType::Ptr(BtfPtr {
                 pointee_type: t.type_id,
             })),
@@ -707,6 +762,7 @@ impl<'a> Btf<'a> {
             BtfKind::FuncProto => self.load_func_proto(&t, extra),
             BtfKind::Var => self.load_var(&t, extra),
             BtfKind::Datasec => self.load_datasec(&t, extra),
+            BtfKind::DeclTag => self.load_decl_tag(&t, extra),
         }
     }
 
@@ -723,6 +779,13 @@ impl<'a> Btf<'a> {
         }))
     }
 
+    fn load_float(&self, t: &btf_type) -> Result<BtfType<'a>> {
+        Ok(BtfType::Float(BtfFloat {
+            name: self.get_btf_str(t.name_off as usize)?,
+            size: t.type_id,
+        }))
+    }
+
     fn load_array(&self, extra: &'a [u8]) -> Result<BtfType<'a>> {
         let info = extra.pread::<btf_array>(0)?;
         Ok(BtfType::Array(BtfArray {
@@ -874,6 +937,15 @@ impl<'a> Btf<'a> {
         }))
     }
 
+    fn load_decl_tag(&self, t: &btf_type, extra: &'a [u8]) -> Result<BtfType<'a>> {
+        let decl_tag = extra.pread::<btf_decl_tag>(0)?;
+        Ok(BtfType::DeclTag(BtfDeclTag {
+            name: self.get_btf_str(t.name_off as usize)?,
+            type_id: t.type_id,
+            component_idx: decl_tag.component_idx,
+        }))
+    }
+
     /// Returns size of type on disk in .BTF section
     fn type_size(t: &BtfType) -> usize {
         let common = size_of::<btf_type>();
@@ -885,7 +957,8 @@ impl<'a> Btf<'a> {
             | BtfType::Volatile(_)
             | BtfType::Const(_)
             | BtfType::Restrict(_)
-            | BtfType::Func(_) => common,
+            | BtfType::Func(_)
+            | BtfType::Float(_) => common,
             BtfType::Int(_) | BtfType::Var(_) => common + size_of::<u32>(),
             BtfType::Array(_) => common + size_of::<btf_array>(),
             BtfType::Struct(t) => common + t.members.len() * size_of::<btf_member>(),
@@ -893,6 +966,7 @@ impl<'a> Btf<'a> {
             BtfType::Enum(t) => common + t.values.len() * size_of::<btf_enum>(),
             BtfType::FuncProto(t) => common + t.params.len() * size_of::<btf_param>(),
             BtfType::Datasec(t) => common + t.vars.len() * size_of::<btf_datasec_var>(),
+            BtfType::DeclTag(_) => common + size_of::<btf_decl_tag>(),
         }
     }
 
diff --git a/libbpf-cargo/src/btf/c_types.rs b/libbpf-cargo/src/btf/c_types.rs
index e297fcbf..0ca27021 100644
--- a/libbpf-cargo/src/btf/c_types.rs
+++ b/libbpf-cargo/src/btf/c_types.rs
@@ -62,3 +62,9 @@ pub struct btf_datasec_var {
     pub offset: u32,
     pub size: u32,
 }
+
+#[repr(C)]
+#[derive(Debug, Clone, DerivePread, Pwrite, IOread, SizeWith)]
+pub struct btf_decl_tag {
+    pub component_idx: i32,
+}
diff --git a/libbpf-cargo/src/btf/types.rs b/libbpf-cargo/src/btf/types.rs
index 374e4a78..436cda44 100644
--- a/libbpf-cargo/src/btf/types.rs
+++ b/libbpf-cargo/src/btf/types.rs
@@ -21,6 +21,8 @@ pub enum BtfKind {
     FuncProto = 13,
     Var = 14,
     Datasec = 15,
+    Float = 16,
+    DeclTag = 17,
 }
 
 #[derive(Debug, Copy, Clone, TryFromPrimitive, PartialEq)]
@@ -161,6 +163,19 @@ pub struct BtfDatasec<'a> {
     pub vars: Vec<BtfDatasecVar>,
 }
 
+#[derive(Debug)]
+pub struct BtfFloat<'a> {
+    pub name: &'a str,
+    pub size: u32,
+}
+
+#[derive(Debug)]
+pub struct BtfDeclTag<'a> {
+    pub name: &'a str,
+    pub type_id: u32,
+    pub component_idx: i32,
+}
+
 pub enum BtfType<'a> {
     Void,
     Int(BtfInt<'a>),
@@ -178,6 +193,8 @@ pub enum BtfType<'a> {
     FuncProto(BtfFuncProto<'a>),
     Var(BtfVar<'a>),
     Datasec(BtfDatasec<'a>),
+    Float(BtfFloat<'a>),
+    DeclTag(BtfDeclTag<'a>),
 }
 
 impl<'a> BtfType<'a> {
@@ -199,6 +216,8 @@ impl<'a> BtfType<'a> {
             BtfType::Enum(_) => BtfKind::Enum,
             BtfType::FuncProto(_) => BtfKind::FuncProto,
             BtfType::Datasec(_) => BtfKind::Datasec,
+            BtfType::Float(_) => BtfKind::Float,
+            BtfType::DeclTag(_) => BtfKind::DeclTag,
         }
     }
 }
@@ -222,6 +241,8 @@ impl<'a> fmt::Display for BtfType<'a> {
             BtfType::Enum(_) => write!(f, "enum"),
             BtfType::FuncProto(_) => write!(f, "funcproto"),
             BtfType::Datasec(_) => write!(f, "datasec"),
+            BtfType::Float(_) => write!(f, "float"),
+            BtfType::DeclTag(_) => write!(f, "decltag"),
         }
     }
 }


Test patch: