Browse Source

Merge pull request #285 from dave-tucker/btf-redux

aya: Improved BTF Type API
Dave Tucker 2 years ago
parent
commit
66b4f79eca
5 changed files with 1474 additions and 712 deletions
  1. 280 220
      aya/src/obj/btf/btf.rs
  2. 58 57
      aya/src/obj/btf/relocation.rs
  3. 1061 367
      aya/src/obj/btf/types.rs
  4. 37 34
      aya/src/obj/mod.rs
  5. 38 34
      aya/src/sys/bpf.rs

+ 280 - 220
aya/src/obj/btf/btf.rs

@@ -1,7 +1,8 @@
 use std::{
     borrow::Cow,
     collections::HashMap,
-    ffi::{c_void, CStr, CString},
+    convert::TryInto,
+    ffi::{CStr, CString},
     fs, io, mem,
     path::{Path, PathBuf},
     ptr,
@@ -14,17 +15,17 @@ use object::Endianness;
 use thiserror::Error;
 
 use crate::{
-    generated::{btf_enum, btf_ext_header, btf_func_linkage, btf_header, btf_member},
-    obj::btf::{relocation::Relocation, BtfKind, BtfType},
+    generated::{btf_ext_header, btf_header},
+    obj::btf::{
+        info::{FuncSecInfo, LineSecInfo},
+        relocation::Relocation,
+        Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int,
+        IntEncoding, LineInfo, Struct, Typedef, VarLinkage,
+    },
     util::bytes_of,
     Features,
 };
 
-use super::{
-    info::{FuncSecInfo, LineSecInfo},
-    type_vlen, FuncInfo, LineInfo,
-};
-
 pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
 pub(crate) const MAX_SPEC_LEN: usize = 64;
 
@@ -198,16 +199,16 @@ impl Btf {
 
     pub(crate) fn add_string(&mut self, name: String) -> u32 {
         let str = CString::new(name).unwrap();
-        let name_off = self.strings.len();
+        let name_offset = self.strings.len();
         self.strings.extend(str.as_c_str().to_bytes_with_nul());
         self.header.str_len = self.strings.len() as u32;
-        name_off as u32
+        name_offset as u32
     }
 
-    pub(crate) fn add_type(&mut self, type_: BtfType) -> u32 {
-        let size = type_.type_info_size() as u32;
+    pub(crate) fn add_type(&mut self, btf_type: BtfType) -> u32 {
+        let size = btf_type.type_info_size() as u32;
         let type_id = self.types.len();
-        self.types.push(type_);
+        self.types.push(btf_type);
         self.header.type_len += size;
         self.header.str_off += size;
         type_id as u32
@@ -315,35 +316,23 @@ impl Btf {
         self.types.resolve_type(root_type_id)
     }
 
-    pub(crate) fn type_name(&self, ty: &BtfType) -> Result<Option<Cow<'_, str>>, BtfError> {
-        ty.name_offset().map(|off| self.string_at(off)).transpose()
+    pub(crate) fn type_name(&self, ty: &BtfType) -> Result<Cow<'_, str>, BtfError> {
+        self.string_at(ty.name_offset())
     }
 
     pub(crate) fn err_type_name(&self, ty: &BtfType) -> Option<String> {
-        ty.name_offset()
-            .and_then(|off| self.string_at(off).ok().map(String::from))
+        self.string_at(ty.name_offset()).ok().map(String::from)
     }
 
     pub(crate) fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> {
         for (type_id, ty) in self.types().enumerate() {
-            match ty.kind()? {
-                Some(k) => {
-                    if k != kind {
-                        continue;
-                    }
-                }
-                None => continue,
+            if ty.kind() != kind {
+                continue;
             }
-
-            match self.type_name(ty)? {
-                Some(ty_name) => {
-                    if ty_name == name {
-                        return Ok(type_id as u32);
-                    }
-                    continue;
-                }
-                None => continue,
+            if self.type_name(ty)? == name {
+                return Ok(type_id as u32);
             }
+            continue;
         }
 
         Err(BtfError::UnknownBtfTypeName {
@@ -356,41 +345,24 @@ impl Btf {
         let mut n_elems = 1;
         for _ in 0..MAX_RESOLVE_DEPTH {
             let ty = self.types.type_by_id(type_id)?;
-
-            use BtfType::*;
             let size = match ty {
-                Int(ty, _)
-                | Struct(ty, _)
-                | Union(ty, _)
-                | Enum(ty, _)
-                | DataSec(ty, _)
-                | Float(ty) => {
-                    // Safety: union
-                    unsafe { ty.__bindgen_anon_1.size as usize }
-                }
-                Ptr(_) => mem::size_of::<*const c_void>(), // FIXME
-                Typedef(ty)
-                | Volatile(ty)
-                | Const(ty)
-                | Restrict(ty)
-                | Var(ty, _)
-                | DeclTag(ty, _)
-                | TypeTag(ty) => {
-                    // Safety: union
-                    type_id = unsafe { ty.__bindgen_anon_1.type_ };
+                BtfType::Array(Array { array, .. }) => {
+                    n_elems = array.len;
+                    type_id = array.element_type;
                     continue;
                 }
-                Array(_, array) => {
-                    n_elems *= array.nelems as usize;
-                    type_id = array.type_;
-                    continue;
-                }
-                Unknown | Fwd(_) | Func(_) | FuncProto(_, _) => {
-                    return Err(BtfError::UnexpectedBtfType { type_id })
+                other => {
+                    if let Some(size) = other.size() {
+                        size
+                    } else if let Some(next) = other.btf_type() {
+                        type_id = next;
+                        continue;
+                    } else {
+                        return Err(BtfError::UnexpectedBtfType { type_id });
+                    }
                 }
             };
-
-            return Ok(size * n_elems);
+            return Ok((size * n_elems) as usize);
         }
 
         Err(BtfError::MaximumTypeDepthReached {
@@ -416,56 +388,55 @@ impl Btf {
         let mut types = mem::take(&mut self.types);
         for i in 0..types.types.len() {
             let t = &types.types[i];
-            let kind = t.kind()?.unwrap_or_default();
+            let kind = t.kind();
             match t {
                 // Fixup PTR for Rust
                 // LLVM emits names for Rust pointer types, which the kernel doesn't like
                 // While I figure out if this needs fixing in the Kernel or LLVM, we'll
                 // do a fixup here
-                BtfType::Ptr(ty) => {
-                    let mut fixed_ty = *ty;
-                    fixed_ty.name_off = 0;
+                BtfType::Ptr(ptr) => {
+                    let mut fixed_ty = ptr.clone();
+                    fixed_ty.name_offset = 0;
                     types.types[i] = BtfType::Ptr(fixed_ty)
                 }
                 // Sanitize VAR if they are not supported
-                BtfType::Var(ty, _) if !features.btf_datasec => {
-                    types.types[i] = BtfType::new_int(ty.name_off, 1, 0, 0);
+                BtfType::Var(v) if !features.btf_datasec => {
+                    types.types[i] = BtfType::Int(Int::new(v.name_offset, 1, IntEncoding::None, 0));
                 }
                 // Sanitize DATASEC if they are not supported
-                BtfType::DataSec(ty, data) if !features.btf_datasec => {
+                BtfType::DataSec(d) if !features.btf_datasec => {
                     debug!("{}: not supported. replacing with STRUCT", kind);
                     let mut members = vec![];
-                    for member in data {
-                        let mt = types.type_by_id(member.type_).unwrap();
-                        members.push(btf_member {
-                            name_off: mt.btf_type().unwrap().name_off,
-                            type_: member.type_,
+                    for member in d.entries.iter() {
+                        let mt = types.type_by_id(member.btf_type).unwrap();
+                        members.push(BtfMember {
+                            name_offset: mt.name_offset(),
+                            btf_type: member.btf_type,
                             offset: member.offset * 8,
                         })
                     }
-                    types.types[i] = BtfType::new_struct(ty.name_off, members, 0);
+                    types.types[i] = BtfType::Struct(Struct::new(t.name_offset(), members, 0));
                 }
                 // Fixup DATASEC
                 // DATASEC sizes aren't always set by LLVM
                 // we need to fix them here before loading the btf to the kernel
-                BtfType::DataSec(ty, data) if features.btf_datasec => {
+                BtfType::DataSec(d) if features.btf_datasec => {
                     // Start DataSec Fixups
-                    let sec_name = self.string_at(ty.name_off)?;
+                    let sec_name = self.string_at(d.name_offset)?;
                     let name = sec_name.to_string();
 
-                    let mut fixed_ty = *ty;
-                    let mut fixed_data = data.clone();
+                    let mut fixed_ty = d.clone();
 
                     // Handle any "/" characters in section names
                     // Example: "maps/hashmap"
                     let fixed_name = name.replace('/', ".");
                     if fixed_name != name {
-                        fixed_ty.name_off = self.add_string(fixed_name);
+                        fixed_ty.name_offset = self.add_string(fixed_name);
                     }
 
                     // There are some cases when the compiler does indeed populate the
                     // size
-                    if unsafe { ty.__bindgen_anon_1.size > 0 } {
+                    if t.size().unwrap() > 0 {
                         debug!("{} {}: size fixup not required", kind, name);
                     } else {
                         // We need to get the size of the section from the ELF file
@@ -477,19 +448,19 @@ impl Btf {
                             }
                         })?;
                         debug!("{} {}: fixup size to {}", kind, name, size);
-                        fixed_ty.__bindgen_anon_1.size = *size as u32;
+                        fixed_ty.size = *size as u32;
 
                         // The Vec<btf_var_secinfo> contains BTF_KIND_VAR sections
                         // that need to have their offsets adjusted. To do this,
                         // we need to get the offset from the ELF file.
                         // This was also cached during initial parsing and
                         // we can query by name in symbol_offsets
-                        for d in &mut fixed_data {
-                            let var_type = types.type_by_id(d.type_)?;
-                            let var_kind = var_type.kind()?.unwrap();
-                            if let BtfType::Var(vty, var) = var_type {
-                                let var_name = self.string_at(vty.name_off)?.to_string();
-                                if var.linkage == btf_func_linkage::BTF_FUNC_STATIC as u32 {
+                        for d in &mut fixed_ty.entries.iter_mut() {
+                            let var_type = types.type_by_id(d.btf_type)?;
+                            let var_kind = var_type.kind();
+                            if let BtfType::Var(var) = var_type {
+                                let var_name = self.string_at(var.name_offset)?.to_string();
+                                if var.linkage == VarLinkage::Static {
                                     debug!(
                                         "{} {}: {} {}: fixup not required",
                                         kind, name, var_kind, var_name
@@ -512,68 +483,66 @@ impl Btf {
                             }
                         }
                     }
-                    types.types[i] = BtfType::DataSec(fixed_ty, fixed_data);
+                    types.types[i] = BtfType::DataSec(fixed_ty);
                 }
                 // Fixup FUNC_PROTO
-                BtfType::FuncProto(ty, params) if features.btf_func => {
-                    let mut params = params.clone();
-                    for (i, mut param) in params.iter_mut().enumerate() {
-                        if param.name_off == 0 && param.type_ != 0 {
-                            param.name_off = self.add_string(format!("param{}", i));
+                BtfType::FuncProto(ty) if features.btf_func => {
+                    let mut ty = ty.clone();
+                    for (i, mut param) in ty.params.iter_mut().enumerate() {
+                        if param.name_offset == 0 && param.btf_type != 0 {
+                            param.name_offset = self.add_string(format!("param{}", i));
                         }
                     }
-                    types.types[i] = BtfType::FuncProto(*ty, params);
+                    types.types[i] = BtfType::FuncProto(ty);
                 }
                 // Sanitize FUNC_PROTO
-                BtfType::FuncProto(ty, vars) if !features.btf_func => {
+                BtfType::FuncProto(ty) if !features.btf_func => {
                     debug!("{}: not supported. replacing with ENUM", kind);
-                    let members: Vec<btf_enum> = vars
+                    let members: Vec<BtfEnum> = ty
+                        .params
                         .iter()
-                        .map(|p| btf_enum {
-                            name_off: p.name_off,
-                            val: p.type_ as i32,
+                        .map(|p| BtfEnum {
+                            name_offset: p.name_offset,
+                            value: p.btf_type as i32,
                         })
                         .collect();
-                    let enum_type = BtfType::new_enum(ty.name_off, members);
+                    let enum_type = BtfType::Enum(Enum::new(ty.name_offset, members));
                     types.types[i] = enum_type;
                 }
                 // Sanitize FUNC
                 BtfType::Func(ty) if !features.btf_func => {
                     debug!("{}: not supported. replacing with TYPEDEF", kind);
-                    let typedef_type =
-                        BtfType::new_typedef(ty.name_off, unsafe { ty.__bindgen_anon_1.type_ });
+                    let typedef_type = BtfType::Typedef(Typedef::new(ty.name_offset, ty.btf_type));
                     types.types[i] = typedef_type;
                 }
                 // Sanitize BTF_FUNC_GLOBAL
                 BtfType::Func(ty) if !features.btf_func_global => {
-                    let mut fixed_ty = *ty;
-                    if type_vlen(ty) == btf_func_linkage::BTF_FUNC_GLOBAL as usize {
+                    let mut fixed_ty = ty.clone();
+                    if ty.linkage() == FuncLinkage::Global {
                         debug!(
                             "{}: BTF_FUNC_GLOBAL not supported. replacing with BTF_FUNC_STATIC",
                             kind
                         );
-                        fixed_ty.info = (ty.info & 0xFFFF0000)
-                            | (btf_func_linkage::BTF_FUNC_STATIC as u32) & 0xFFFF;
+                        fixed_ty.set_linkage(FuncLinkage::Static);
                     }
                     types.types[i] = BtfType::Func(fixed_ty);
                 }
                 // Sanitize FLOAT
                 BtfType::Float(ty) if !features.btf_float => {
                     debug!("{}: not supported. replacing with STRUCT", kind);
-                    let struct_ty =
-                        BtfType::new_struct(0, vec![], unsafe { ty.__bindgen_anon_1.size });
+                    let struct_ty = BtfType::Struct(Struct::new(0, vec![], ty.size));
                     types.types[i] = struct_ty;
                 }
                 // Sanitize DECL_TAG
-                BtfType::DeclTag(ty, _) if !features.btf_decl_tag => {
+                BtfType::DeclTag(ty) if !features.btf_decl_tag => {
                     debug!("{}: not supported. replacing with INT", kind);
-                    let int_type = BtfType::new_int(ty.name_off, 1, 0, 0);
+                    let int_type = BtfType::Int(Int::new(ty.name_offset, 1, IntEncoding::None, 0));
                     types.types[i] = int_type;
                 }
                 // Sanitize TYPE_TAG
                 BtfType::TypeTag(ty) if !features.btf_type_tag => {
                     debug!("{}: not supported. replacing with CONST", kind);
-                    let const_type = BtfType::new_const(unsafe { ty.__bindgen_anon_1.type_ });
+                    let const_type = BtfType::Const(Const::new(ty.btf_type));
                     types.types[i] = const_type;
                 }
                 // The type does not need fixing up or sanitization
@@ -670,12 +639,12 @@ impl BtfExt {
             SecInfoIter::new(ext.func_info_data(), ext.func_info_rec_size, endianness)
                 .map(move |sec| {
                     let name = btf
-                        .string_at(sec.sec_name_off)
+                        .string_at(sec.name_offset)
                         .ok()
                         .map(String::from)
                         .unwrap();
                     let info = FuncSecInfo::parse(
-                        sec.sec_name_off,
+                        sec.name_offset,
                         sec.num_info,
                         func_info_rec_size,
                         sec.data,
@@ -691,12 +660,12 @@ impl BtfExt {
             SecInfoIter::new(ext.line_info_data(), ext.line_info_rec_size, endianness)
                 .map(move |sec| {
                     let name = btf
-                        .string_at(sec.sec_name_off)
+                        .string_at(sec.name_offset)
                         .ok()
                         .map(String::from)
                         .unwrap();
                     let info = LineSecInfo::parse(
-                        sec.sec_name_off,
+                        sec.name_offset,
                         sec.num_info,
                         line_info_rec_size,
                         sec.data,
@@ -717,7 +686,7 @@ impl BtfExt {
                         .enumerate()
                         .map(|(n, rec)| unsafe { Relocation::parse(rec, n) })
                         .collect::<Result<Vec<_>, _>>()?;
-                    Ok((sec.sec_name_off, relos))
+                    Ok((sec.name_offset, relos))
                 })
                 .collect::<Result<Vec<_>, _>>()?,
         );
@@ -793,7 +762,7 @@ impl<'a> Iterator for SecInfoIter<'a> {
         } else {
             u32::from_be_bytes
         };
-        let sec_name_off = read_u32(data[self.offset..self.offset + 4].try_into().unwrap());
+        let name_offset = read_u32(data[self.offset..self.offset + 4].try_into().unwrap());
         self.offset += 4;
         let num_info = u32::from_ne_bytes(data[self.offset..self.offset + 4].try_into().unwrap());
         self.offset += 4;
@@ -802,7 +771,7 @@ impl<'a> Iterator for SecInfoIter<'a> {
         self.offset += self.rec_size * num_info as usize;
 
         Some(SecInfo {
-            sec_name_off,
+            name_offset,
             num_info,
             data,
         })
@@ -829,7 +798,7 @@ impl BtfTypes {
         let mut buf = vec![];
         for t in self.types.iter().skip(1) {
             let b = t.to_bytes();
-            buf.put(b.as_slice())
+            buf.extend(b)
         }
         buf
     }
@@ -855,9 +824,24 @@ impl BtfTypes {
 
             use BtfType::*;
             match ty {
-                Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) | TypeTag(ty) => {
-                    // Safety: union
-                    type_id = unsafe { ty.__bindgen_anon_1.type_ };
+                Volatile(ty) => {
+                    type_id = ty.btf_type;
+                    continue;
+                }
+                Const(ty) => {
+                    type_id = ty.btf_type;
+                    continue;
+                }
+                Restrict(ty) => {
+                    type_id = ty.btf_type;
+                    continue;
+                }
+                Typedef(ty) => {
+                    type_id = ty.btf_type;
+                    continue;
+                }
+                TypeTag(ty) => {
+                    type_id = ty.btf_type;
                     continue;
                 }
                 _ => return Ok(type_id),
@@ -872,15 +856,15 @@ impl BtfTypes {
 
 #[derive(Debug)]
 pub(crate) struct SecInfo<'a> {
-    sec_name_off: u32,
+    name_offset: u32,
     num_info: u32,
     data: &'a [u8],
 }
 
 #[cfg(test)]
 mod tests {
-    use crate::generated::{
-        btf_param, btf_var_secinfo, BTF_INT_SIGNED, BTF_VAR_GLOBAL_EXTERN, BTF_VAR_STATIC,
+    use crate::obj::btf::{
+        BtfParam, DataSec, DataSecEntry, DeclTag, Float, Func, FuncProto, Ptr, TypeTag, Var,
     };
 
     use super::*;
@@ -976,11 +960,11 @@ mod tests {
     fn test_write_btf() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+        let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
         btf.add_type(int_type);
 
         let name_offset = btf.add_string("widget".to_string());
-        let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+        let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
         btf.add_type(int_type);
 
         let btf_bytes = btf.to_bytes();
@@ -1002,10 +986,15 @@ mod tests {
     fn test_fixup_ptr() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let name_offset = btf.add_string("&mut int".to_string());
-        let ptr_type_id = btf.add_type(BtfType::new_ptr(name_offset, int_type_id));
+        let ptr_type_id = btf.add_type(BtfType::Ptr(Ptr::new(name_offset, int_type_id)));
 
         let features = Features {
             ..Default::default()
@@ -1015,9 +1004,9 @@ mod tests {
             .unwrap();
         if let BtfType::Ptr(fixed) = btf.type_by_id(ptr_type_id).unwrap() {
             assert!(
-                fixed.name_off == 0,
+                fixed.name_offset == 0,
                 "expected offset 0, got {}",
-                fixed.name_off
+                fixed.name_offset
             )
         } else {
             panic!("not a ptr")
@@ -1031,10 +1020,19 @@ mod tests {
     fn test_sanitize_var() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let name_offset = btf.add_string("&mut int".to_string());
-        let var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC));
+        let var_type_id = btf.add_type(BtfType::Var(Var::new(
+            name_offset,
+            int_type_id,
+            VarLinkage::Static,
+        )));
 
         let features = Features {
             btf_datasec: false,
@@ -1043,8 +1041,8 @@ mod tests {
 
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
-        if let BtfType::Int(fixed, _) = btf.type_by_id(var_type_id).unwrap() {
-            assert!(fixed.name_off == name_offset)
+        if let BtfType::Int(fixed) = btf.type_by_id(var_type_id).unwrap() {
+            assert!(fixed.name_offset == name_offset)
         } else {
             panic!("not an int")
         }
@@ -1057,18 +1055,28 @@ mod tests {
     fn test_sanitize_datasec() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let name_offset = btf.add_string("foo".to_string());
-        let var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC));
+        let var_type_id = btf.add_type(BtfType::Var(Var::new(
+            name_offset,
+            int_type_id,
+            VarLinkage::Static,
+        )));
 
         let name_offset = btf.add_string(".data".to_string());
-        let variables = vec![btf_var_secinfo {
-            type_: var_type_id,
+        let variables = vec![DataSecEntry {
+            btf_type: var_type_id,
             offset: 0,
             size: 4,
         }];
-        let datasec_type_id = btf.add_type(BtfType::new_datasec(name_offset, variables, 0));
+        let datasec_type_id =
+            btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
 
         let features = Features {
             btf_datasec: false,
@@ -1077,11 +1085,11 @@ mod tests {
 
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
-        if let BtfType::Struct(fixed, members) = btf.type_by_id(datasec_type_id).unwrap() {
-            assert!(fixed.name_off == name_offset);
-            assert!(members.len() == 1);
-            assert!(members[0].type_ == var_type_id);
-            assert!(members[0].offset == 0)
+        if let BtfType::Struct(fixed) = btf.type_by_id(datasec_type_id).unwrap() {
+            assert!(fixed.name_offset == name_offset);
+            assert!(fixed.members.len() == 1);
+            assert!(fixed.members[0].btf_type == var_type_id);
+            assert!(fixed.members[0].offset == 0)
         } else {
             panic!("not a struct")
         }
@@ -1094,22 +1102,28 @@ mod tests {
     fn test_fixup_datasec() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let name_offset = btf.add_string("foo".to_string());
-        let var_type_id = btf.add_type(BtfType::new_var(
+        let var_type_id = btf.add_type(BtfType::Var(Var::new(
             name_offset,
             int_type_id,
-            BTF_VAR_GLOBAL_EXTERN,
-        ));
+            VarLinkage::Global,
+        )));
 
         let name_offset = btf.add_string(".data/foo".to_string());
-        let variables = vec![btf_var_secinfo {
-            type_: var_type_id,
+        let variables = vec![DataSecEntry {
+            btf_type: var_type_id,
             offset: 0,
             size: 4,
         }];
-        let datasec_type_id = btf.add_type(BtfType::new_datasec(name_offset, variables, 0));
+        let datasec_type_id =
+            btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
 
         let features = Features {
             btf_datasec: true,
@@ -1123,17 +1137,17 @@ mod tests {
         )
         .unwrap();
 
-        if let BtfType::DataSec(fixed, sec_info) = btf.type_by_id(datasec_type_id).unwrap() {
-            assert!(fixed.name_off != name_offset);
-            assert!(unsafe { fixed.__bindgen_anon_1.size } == 32);
-            assert!(sec_info.len() == 1);
-            assert!(sec_info[0].type_ == var_type_id);
+        if let BtfType::DataSec(fixed) = btf.type_by_id(datasec_type_id).unwrap() {
+            assert!(fixed.name_offset != name_offset);
+            assert!(fixed.size == 32);
+            assert!(fixed.entries.len() == 1);
+            assert!(fixed.entries[0].btf_type == var_type_id);
             assert!(
-                sec_info[0].offset == 64,
+                fixed.entries[0].offset == 64,
                 "expected 64, got {}",
-                sec_info[0].offset
+                fixed.entries[0].offset
             );
-            assert!(btf.string_at(fixed.name_off).unwrap() == ".data.foo")
+            assert!(btf.string_at(fixed.name_offset).unwrap() == ".data.foo")
         } else {
             panic!("not a datasec")
         }
@@ -1146,25 +1160,31 @@ mod tests {
     fn test_sanitize_func_and_proto() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let params = vec![
-            btf_param {
-                name_off: btf.add_string("a".to_string()),
-                type_: int_type_id,
+            BtfParam {
+                name_offset: btf.add_string("a".to_string()),
+                btf_type: int_type_id,
             },
-            btf_param {
-                name_off: btf.add_string("b".to_string()),
-                type_: int_type_id,
+            BtfParam {
+                name_offset: btf.add_string("b".to_string()),
+                btf_type: int_type_id,
             },
         ];
-        let func_proto_type_id = btf.add_type(BtfType::new_func_proto(params, int_type_id));
+        let func_proto_type_id =
+            btf.add_type(BtfType::FuncProto(FuncProto::new(params, int_type_id)));
         let inc = btf.add_string("inc".to_string());
-        let func_type_id = btf.add_type(BtfType::new_func(
+        let func_type_id = btf.add_type(BtfType::Func(Func::new(
             inc,
             func_proto_type_id,
-            btf_func_linkage::BTF_FUNC_STATIC,
-        ));
+            FuncLinkage::Static,
+        )));
 
         let features = Features {
             btf_func: false,
@@ -1173,21 +1193,20 @@ mod tests {
 
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
-
-        if let BtfType::Enum(fixed, vars) = btf.type_by_id(func_proto_type_id).unwrap() {
-            assert!(fixed.name_off == 0);
-            assert!(vars.len() == 2);
-            assert!(btf.string_at(vars[0].name_off).unwrap() == "a");
-            assert!(vars[0].val == int_type_id as i32);
-            assert!(btf.string_at(vars[1].name_off).unwrap() == "b");
-            assert!(vars[1].val == int_type_id as i32);
+        if let BtfType::Enum(fixed) = btf.type_by_id(func_proto_type_id).unwrap() {
+            assert!(fixed.name_offset == 0);
+            assert!(fixed.variants.len() == 2);
+            assert!(btf.string_at(fixed.variants[0].name_offset).unwrap() == "a");
+            assert!(fixed.variants[0].value == int_type_id as i32);
+            assert!(btf.string_at(fixed.variants[1].name_offset).unwrap() == "b");
+            assert!(fixed.variants[1].value == int_type_id as i32);
         } else {
             panic!("not an emum")
         }
 
         if let BtfType::Typedef(fixed) = btf.type_by_id(func_type_id).unwrap() {
-            assert!(fixed.name_off == inc);
-            assert!(unsafe { fixed.__bindgen_anon_1.type_ } == func_proto_type_id);
+            assert!(fixed.name_offset == inc);
+            assert!(fixed.btf_type == func_proto_type_id);
         } else {
             panic!("not a typedef")
         }
@@ -1200,20 +1219,20 @@ mod tests {
     fn test_fixup_func_proto() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+        let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
         let int_type_id = btf.add_type(int_type);
 
         let params = vec![
-            btf_param {
-                name_off: 0,
-                type_: int_type_id,
+            BtfParam {
+                name_offset: 0,
+                btf_type: int_type_id,
             },
-            btf_param {
-                name_off: 0,
-                type_: int_type_id,
+            BtfParam {
+                name_offset: 0,
+                btf_type: int_type_id,
             },
         ];
-        let func_proto = BtfType::new_func_proto(params, int_type_id);
+        let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
         let func_proto_type_id = btf.add_type(func_proto);
 
         let features = Features {
@@ -1224,9 +1243,9 @@ mod tests {
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
 
-        if let BtfType::FuncProto(_, vars) = btf.type_by_id(func_proto_type_id).unwrap() {
-            assert!(btf.string_at(vars[0].name_off).unwrap() == "param0");
-            assert!(btf.string_at(vars[1].name_off).unwrap() == "param1");
+        if let BtfType::FuncProto(fixed) = btf.type_by_id(func_proto_type_id).unwrap() {
+            assert!(btf.string_at(fixed.params[0].name_offset).unwrap() == "param0");
+            assert!(btf.string_at(fixed.params[1].name_offset).unwrap() == "param1");
         } else {
             panic!("not a func_proto")
         }
@@ -1239,25 +1258,31 @@ mod tests {
     fn test_sanitize_func_global() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let params = vec![
-            btf_param {
-                name_off: btf.add_string("a".to_string()),
-                type_: int_type_id,
+            BtfParam {
+                name_offset: btf.add_string("a".to_string()),
+                btf_type: int_type_id,
             },
-            btf_param {
-                name_off: btf.add_string("b".to_string()),
-                type_: int_type_id,
+            BtfParam {
+                name_offset: btf.add_string("b".to_string()),
+                btf_type: int_type_id,
             },
         ];
-        let func_proto_type_id = btf.add_type(BtfType::new_func_proto(params, int_type_id));
+        let func_proto_type_id =
+            btf.add_type(BtfType::FuncProto(FuncProto::new(params, int_type_id)));
         let inc = btf.add_string("inc".to_string());
-        let func_type_id = btf.add_type(BtfType::new_func(
+        let func_type_id = btf.add_type(BtfType::Func(Func::new(
             inc,
             func_proto_type_id,
-            btf_func_linkage::BTF_FUNC_GLOBAL,
-        ));
+            FuncLinkage::Global,
+        )));
 
         let features = Features {
             btf_func: true,
@@ -1269,7 +1294,7 @@ mod tests {
             .unwrap();
 
         if let BtfType::Func(fixed) = btf.type_by_id(func_type_id).unwrap() {
-            assert!(type_vlen(fixed) == btf_func_linkage::BTF_FUNC_STATIC as usize);
+            assert!(fixed.linkage() == FuncLinkage::Static);
         } else {
             panic!("not a func")
         }
@@ -1282,7 +1307,7 @@ mod tests {
     fn test_sanitize_float() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("float".to_string());
-        let float_type_id = btf.add_type(BtfType::new_float(name_offset, 16));
+        let float_type_id = btf.add_type(BtfType::Float(Float::new(name_offset, 16)));
 
         let features = Features {
             btf_float: false,
@@ -1291,9 +1316,9 @@ mod tests {
 
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
-        if let BtfType::Struct(fixed, _) = btf.type_by_id(float_type_id).unwrap() {
-            assert!(fixed.name_off == 0);
-            assert!(unsafe { fixed.__bindgen_anon_1.size } == 16);
+        if let BtfType::Struct(fixed) = btf.type_by_id(float_type_id).unwrap() {
+            assert!(fixed.name_offset == 0);
+            assert!(fixed.size == 16);
         } else {
             panic!("not a struct")
         }
@@ -1306,13 +1331,23 @@ mod tests {
     fn test_sanitize_decl_tag() {
         let mut btf = Btf::new();
         let name_offset = btf.add_string("int".to_string());
-        let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
 
         let name_offset = btf.add_string("foo".to_string());
-        let var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC));
+        let var_type_id = btf.add_type(BtfType::Var(Var::new(
+            name_offset,
+            int_type_id,
+            VarLinkage::Static,
+        )));
 
         let name_offset = btf.add_string("decl_tag".to_string());
-        let decl_tag_type_id = btf.add_type(BtfType::new_decl_tag(name_offset, var_type_id, -1));
+        let decl_tag_type_id =
+            btf.add_type(BtfType::DeclTag(DeclTag::new(name_offset, var_type_id, -1)));
 
         let features = Features {
             btf_decl_tag: false,
@@ -1321,9 +1356,9 @@ mod tests {
 
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
-        if let BtfType::Int(fixed, _) = btf.type_by_id(decl_tag_type_id).unwrap() {
-            assert!(fixed.name_off == name_offset);
-            assert!(unsafe { fixed.__bindgen_anon_1.size } == 1);
+        if let BtfType::Int(fixed) = btf.type_by_id(decl_tag_type_id).unwrap() {
+            assert!(fixed.name_offset == name_offset);
+            assert!(fixed.size == 1);
         } else {
             panic!("not an int")
         }
@@ -1336,11 +1371,11 @@ mod tests {
     fn test_sanitize_type_tag() {
         let mut btf = Btf::new();
 
-        let int_type_id = btf.add_type(BtfType::new_int(0, 4, BTF_INT_SIGNED, 0));
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(0, 4, IntEncoding::Signed, 0)));
 
         let name_offset = btf.add_string("int".to_string());
-        let type_tag_type = btf.add_type(BtfType::new_type_tag(name_offset, int_type_id));
-        btf.add_type(BtfType::new_ptr(0, type_tag_type));
+        let type_tag_type = btf.add_type(BtfType::TypeTag(TypeTag::new(name_offset, int_type_id)));
+        btf.add_type(BtfType::Ptr(Ptr::new(0, type_tag_type)));
 
         let features = Features {
             btf_type_tag: false,
@@ -1350,7 +1385,7 @@ mod tests {
         btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
             .unwrap();
         if let BtfType::Const(fixed) = btf.type_by_id(type_tag_type).unwrap() {
-            assert!(unsafe { fixed.__bindgen_anon_1.type_ } == int_type_id);
+            assert!(fixed.btf_type == int_type_id);
         } else {
             panic!("not a const")
         }
@@ -1358,4 +1393,29 @@ mod tests {
         let raw = btf.to_bytes();
         Btf::parse(&raw, Endianness::default()).unwrap();
     }
+
+    #[test]
+    #[cfg_attr(miri, ignore)]
+    fn test_read_btf_from_sys_fs() {
+        let btf = Btf::parse_file("/sys/kernel/btf/vmlinux", Endianness::default()).unwrap();
+        let task_struct_id = btf
+            .id_by_type_name_kind("task_struct", BtfKind::Struct)
+            .unwrap();
+        // we can't assert on exact ID since this may change across kernel versions
+        assert!(task_struct_id != 0);
+
+        let netif_id = btf
+            .id_by_type_name_kind("netif_receive_skb", BtfKind::Func)
+            .unwrap();
+        assert!(netif_id != 0);
+
+        let u32_def = btf.id_by_type_name_kind("__u32", BtfKind::Typedef).unwrap();
+        assert!(u32_def != 0);
+
+        let u32_base = btf.resolve_type(u32_def).unwrap();
+        assert!(u32_base != 0);
+
+        let u32_ty = btf.type_by_id(u32_base).unwrap();
+        assert_eq!(u32_ty.kind(), BtfKind::Int);
+    }
 }

+ 58 - 57
aya/src/obj/btf/relocation.rs

@@ -9,8 +9,8 @@ use crate::{
     },
     obj::{
         btf::{
-            fields_are_compatible, member_bit_field_size, member_bit_offset, types_are_compatible,
-            BtfType, MAX_SPEC_LEN,
+            fields_are_compatible, types_are_compatible, Array, BtfMember, BtfType, IntEncoding,
+            Struct, Union, MAX_SPEC_LEN,
         },
         Btf, BtfError, Object, Program, ProgramSection,
     },
@@ -207,7 +207,7 @@ fn relocate_btf_program<'target>(
         }
 
         let local_ty = local_btf.type_by_id(rel.type_id)?;
-        let local_name = &*local_btf.type_name(local_ty)?.unwrap();
+        let local_name = &*local_btf.type_name(local_ty)?;
         let access_str = &*local_btf.string_at(rel.access_str_offset)?;
         let local_spec = AccessSpec::new(local_btf, rel.type_id, access_str, *rel)?;
 
@@ -288,10 +288,10 @@ fn find_candidates<'target>(
     let mut candidates = Vec::new();
     let local_name = flavorless_name(local_name);
     for (type_id, ty) in target_btf.types().enumerate() {
-        if local_ty.kind()? != ty.kind()? {
+        if local_ty.kind() != ty.kind() {
             continue;
         }
-        let name = &*target_btf.type_name(ty)?.unwrap();
+        let name = &*target_btf.type_name(ty)?;
         if local_name != flavorless_name(name) {
             continue;
         }
@@ -342,9 +342,9 @@ fn match_candidate<'target>(
             // the first accessor is guaranteed to have a name by construction
             let local_variant_name = local_spec.accessors[0].name.as_ref().unwrap();
             match target_ty {
-                BtfType::Enum(_, members) => {
-                    for (index, member) in members.iter().enumerate() {
-                        let target_variant_name = candidate.btf.string_at(member.name_off)?;
+                BtfType::Enum(en) => {
+                    for (index, member) in en.variants.iter().enumerate() {
+                        let target_variant_name = candidate.btf.string_at(member.name_offset)?;
                         if flavorless_name(local_variant_name)
                             == flavorless_name(&target_variant_name)
                         {
@@ -389,24 +389,24 @@ fn match_candidate<'target>(
                     if i > 0 {
                         let target_ty = candidate.btf.type_by_id(target_id)?;
                         let array = match target_ty {
-                            BtfType::Array(_, array) => array,
+                            BtfType::Array(Array { array, .. }) => array,
                             _ => return Ok(None),
                         };
 
-                        let var_len = array.nelems == 0 && {
+                        let var_len = array.len == 0 && {
                             // an array is potentially variable length if it's the last field
                             // of the parent struct and has 0 elements
                             let parent = target_spec.accessors.last().unwrap();
                             let parent_ty = candidate.btf.type_by_id(parent.type_id)?;
                             match parent_ty {
-                                BtfType::Struct(_, members) => parent.index == members.len() - 1,
+                                BtfType::Struct(s) => parent.index == s.members.len() - 1,
                                 _ => false,
                             }
                         };
-                        if !var_len && accessor.index >= array.nelems as usize {
+                        if !var_len && accessor.index >= array.len as usize {
                             return Ok(None);
                         }
-                        target_id = candidate.btf.resolve_type(array.type_)?;
+                        target_id = candidate.btf.resolve_type(array.element_type)?;
                     }
 
                     if target_spec.parts.len() == MAX_SPEC_LEN {
@@ -442,21 +442,20 @@ fn match_member<'local, 'target>(
 ) -> Result<Option<u32>, ErrorWrapper> {
     let local_ty = local_btf.type_by_id(local_accessor.type_id)?;
     let local_member = match local_ty {
-        BtfType::Struct(_, members) | BtfType::Union(_, members) => {
-            // this won't panic, bounds are checked when local_spec is built in AccessSpec::new
-            members[local_accessor.index]
-        }
+        // this won't panic, bounds are checked when local_spec is built in AccessSpec::new
+        BtfType::Struct(s) => s.members.get(local_accessor.index).unwrap(),
+        BtfType::Union(u) => u.members.get(local_accessor.index).unwrap(),
         _ => panic!("bug! this should only be called for structs and unions"),
     };
 
-    let local_name = &*local_btf.string_at(local_member.name_off)?;
+    let local_name = &*local_btf.string_at(local_member.name_offset)?;
     let target_id = target_btf.resolve_type(target_id)?;
     let target_ty = target_btf.type_by_id(target_id)?;
 
-    let target_members = match target_ty {
-        BtfType::Struct(_, members) | BtfType::Union(_, members) => members,
+    let target_members: Vec<&BtfMember> = match target_ty.members() {
+        Some(members) => members.collect(),
         // not a fields type, no match
-        _ => return Ok(None),
+        None => return Ok(None),
     };
 
     for (index, target_member) in target_members.iter().enumerate() {
@@ -468,8 +467,9 @@ fn match_member<'local, 'target>(
             .into());
         }
 
-        let bit_offset = member_bit_offset(target_ty.info().unwrap(), target_member);
-        let target_name = &*target_btf.string_at(target_member.name_off)?;
+        // this will not panic as we've already established these are fields types
+        let bit_offset = target_ty.member_bit_offset(target_member).unwrap();
+        let target_name = &*target_btf.string_at(target_member.name_offset)?;
 
         if target_name.is_empty() {
             let ret = match_member(
@@ -477,7 +477,7 @@ fn match_member<'local, 'target>(
                 local_spec,
                 local_accessor,
                 target_btf,
-                target_member.type_,
+                target_member.btf_type,
                 target_spec,
             )?;
             if ret.is_some() {
@@ -488,9 +488,9 @@ fn match_member<'local, 'target>(
         } else if local_name == target_name {
             if fields_are_compatible(
                 local_spec.btf,
-                local_member.type_,
+                local_member.btf_type,
                 target_btf,
-                target_member.type_,
+                target_member.btf_type,
             )? {
                 target_spec.bit_offset += bit_offset;
                 target_spec.parts.push(index);
@@ -499,7 +499,7 @@ fn match_member<'local, 'target>(
                     index,
                     name: Some(target_name.to_owned()),
                 });
-                return Ok(Some(target_member.type_));
+                return Ok(Some(target_member.btf_type));
             } else {
                 return Ok(None);
             }
@@ -558,7 +558,7 @@ impl<'a> AccessSpec<'a> {
                 }
             }
             RelocationKind::EnumVariantExists | RelocationKind::EnumVariantValue => match ty {
-                BtfType::Enum(_, members) => {
+                BtfType::Enum(en) => {
                     if parts.len() != 1 {
                         return Err(RelocationError::InvalidAccessString {
                             access_str: spec.to_string(),
@@ -566,12 +566,12 @@ impl<'a> AccessSpec<'a> {
                         .into());
                     }
                     let index = parts[0];
-                    if index >= members.len() {
+                    if index >= en.variants.len() {
                         return Err(RelocationError::InvalidAccessIndex {
                             type_name: btf.err_type_name(ty),
                             spec: spec.to_string(),
                             index,
-                            max_index: members.len(),
+                            max_index: en.variants.len(),
                             error: "tried to access nonexistant enum variant".to_string(),
                         }
                         .into());
@@ -579,7 +579,10 @@ impl<'a> AccessSpec<'a> {
                     let accessors = vec![Accessor {
                         type_id,
                         index,
-                        name: Some(btf.string_at(members[index].name_off)?.to_string()),
+                        name: Some(
+                            btf.string_at(en.variants.get(index).unwrap().name_offset)?
+                                .to_string(),
+                        ),
                     }];
 
                     AccessSpec {
@@ -595,7 +598,7 @@ impl<'a> AccessSpec<'a> {
                     return Err(RelocationError::InvalidRelocationKindForType {
                         relocation_number: relocation.number,
                         relocation_kind: format!("{:?}", relocation.kind),
-                        type_kind: format!("{:?}", ty.kind()?.unwrap()),
+                        type_kind: format!("{:?}", ty.kind()),
                         error: "enum relocation on non-enum type".to_string(),
                     }
                     .into())
@@ -618,9 +621,9 @@ impl<'a> AccessSpec<'a> {
                     type_id = btf.resolve_type(type_id)?;
                     let ty = btf.type_by_id(type_id)?;
 
-                    use BtfType::*;
                     match ty {
-                        Struct(t, members) | Union(t, members) => {
+                        BtfType::Struct(Struct { members, .. })
+                        | BtfType::Union(Union { members, .. }) => {
                             if index >= members.len() {
                                 return Err(RelocationError::InvalidAccessIndex {
                                     type_name: btf.err_type_name(ty),
@@ -632,38 +635,38 @@ impl<'a> AccessSpec<'a> {
                                 .into());
                             }
 
-                            let member = members[index];
-                            bit_offset += member_bit_offset(t.info, &member);
+                            let member = &members[index];
+                            bit_offset += ty.member_bit_offset(member).unwrap();
 
-                            if member.name_off != 0 {
+                            if member.name_offset != 0 {
                                 accessors.push(Accessor {
                                     type_id,
                                     index,
-                                    name: Some(btf.string_at(member.name_off)?.to_string()),
+                                    name: Some(btf.string_at(member.name_offset)?.to_string()),
                                 });
                             }
 
-                            type_id = member.type_;
+                            type_id = member.btf_type;
                         }
 
-                        Array(_, array) => {
-                            type_id = btf.resolve_type(array.type_)?;
-                            let var_len = array.nelems == 0 && {
+                        BtfType::Array(Array { array, .. }) => {
+                            type_id = btf.resolve_type(array.element_type)?;
+                            let var_len = array.len == 0 && {
                                 // an array is potentially variable length if it's the last field
                                 // of the parent struct and has 0 elements
                                 let parent = accessors.last().unwrap();
                                 let parent_ty = btf.type_by_id(parent.type_id)?;
                                 match parent_ty {
-                                    Struct(_, members) => index == members.len() - 1,
+                                    BtfType::Struct(s) => index == s.members.len() - 1,
                                     _ => false,
                                 }
                             };
-                            if !var_len && index >= array.nelems as usize {
+                            if !var_len && index >= array.len as usize {
                                 return Err(RelocationError::InvalidAccessIndex {
                                     type_name: btf.err_type_name(ty),
                                     spec: spec.to_string(),
                                     index,
-                                    max_index: array.nelems as usize,
+                                    max_index: array.len as usize,
                                     error: "array index out of bounds".to_string(),
                                 }
                                 .into());
@@ -814,8 +817,8 @@ impl ComputedRelocation {
                     use BtfType::*;
                     match (local_ty, target_ty) {
                         (Ptr(_), Ptr(_)) => {}
-                        (Int(_, local_info), Int(_, target_info))
-                            if unsigned(*local_info) && unsigned(*target_info) => {}
+                        (Int(local), Int(target))
+                            if unsigned(local.data) && unsigned(target.data) => {}
                         _ => {
                             return Err(RelocationError::InvalidInstruction {
                                 relocation_number: rel.number,
@@ -885,7 +888,7 @@ impl ComputedRelocation {
                 let spec = spec.unwrap();
                 let accessor = &spec.accessors[0];
                 match spec.btf.type_by_id(accessor.type_id)? {
-                    BtfType::Enum(_, variants) => variants[accessor.index].val as u32,
+                    BtfType::Enum(en) => en.variants[accessor.index].value as u32,
                     _ => panic!("should not be reached"),
                 }
             }
@@ -946,9 +949,8 @@ impl ComputedRelocation {
 
         let ty = spec.btf.type_by_id(accessor.type_id)?;
         let (ll_ty, member) = match ty {
-            BtfType::Struct(ty, members) | BtfType::Union(ty, members) => {
-                (ty, members[accessor.index])
-            }
+            BtfType::Struct(t) => (ty, t.members.get(accessor.index).unwrap()),
+            BtfType::Union(t) => (ty, t.members.get(accessor.index).unwrap()),
             _ => {
                 return Err(RelocationError::InvalidRelocationKindForType {
                     relocation_number: rel.number,
@@ -961,17 +963,16 @@ impl ComputedRelocation {
         };
 
         let bit_off = spec.bit_offset as u32;
-        let member_type_id = spec.btf.resolve_type(member.type_)?;
+        let member_type_id = spec.btf.resolve_type(member.btf_type)?;
         let member_ty = spec.btf.type_by_id(member_type_id)?;
-        let ll_member_ty = member_ty.btf_type().unwrap();
 
         let mut byte_size;
         let mut byte_off;
-        let mut bit_size = member_bit_field_size(ll_ty, &member) as u32;
+        let mut bit_size = ll_ty.member_bit_field_size(member).unwrap() as u32;
         let is_bitfield = bit_size > 0;
         if is_bitfield {
             // find out the smallest int size to load the bitfield
-            byte_size = unsafe { ll_member_ty.__bindgen_anon_1.size };
+            byte_size = member_ty.size().unwrap();
             byte_off = bit_off / 8 / byte_size * byte_size;
             while bit_off + bit_size - byte_off * 8 > byte_size * 8 {
                 if byte_size >= 8 {
@@ -1006,8 +1007,8 @@ impl ComputedRelocation {
                 value.value = byte_size;
             }
             FieldSigned => match member_ty {
-                BtfType::Enum(_, _) => value.value = 1,
-                BtfType::Int(_, i) => value.value = ((i >> 24) & 0x0F) & BTF_INT_SIGNED,
+                BtfType::Enum(_) => value.value = 1,
+                BtfType::Int(i) => value.value = i.encoding() as u32 & IntEncoding::Signed as u32,
                 _ => (),
             },
             #[cfg(target_endian = "little")]

File diff suppressed because it is too large
+ 1061 - 367
aya/src/obj/btf/types.rs


+ 37 - 34
aya/src/obj/mod.rs

@@ -19,14 +19,14 @@ use relocation::*;
 
 use crate::{
     bpf_map_def,
-    generated::{bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, btf_var_secinfo, BPF_F_RDONLY_PROG},
+    generated::{bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
     obj::btf::{Btf, BtfError, BtfExt, BtfType},
     programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
     BpfError, BtfMapDef, PinningType,
 };
 use std::slice::from_raw_parts_mut;
 
-use self::btf::{BtfKind, FuncSecInfo, LineSecInfo};
+use self::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
 
 const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE;
 /// The first five __u32 of `bpf_map_def` must be defined.
@@ -830,14 +830,14 @@ impl Object {
         let btf = self.btf.as_ref().unwrap();
 
         for t in btf.types() {
-            if let BtfType::DataSec(_, sec_info) = &t {
+            if let BtfType::DataSec(datasec) = &t {
                 let type_name = match btf.type_name(t) {
-                    Ok(Some(name)) => name,
+                    Ok(name) => name,
                     _ => continue,
                 };
                 if type_name == section.name {
                     // each btf_var_secinfo contains a map
-                    for info in sec_info {
+                    for info in &datasec.entries {
                         let (map_name, def) = parse_btf_map_def(btf, info)?;
                         let symbol_index = symbols
                             .get(&map_name)
@@ -1144,20 +1144,20 @@ fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
         BtfType::Ptr(pty) => pty,
         other => {
             return Err(BtfError::UnexpectedBtfType {
-                type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32,
+                type_id: other.btf_type().unwrap_or(0) as u32,
             })
         }
     };
     // Safety: union
-    let arr = match &btf.type_by_id(unsafe { pty.__bindgen_anon_1.type_ })? {
-        BtfType::Array(_, arr) => arr,
+    let arr = match &btf.type_by_id(pty.btf_type)? {
+        BtfType::Array(Array { array, .. }) => array,
         other => {
             return Err(BtfError::UnexpectedBtfType {
-                type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32,
+                type_id: other.btf_type().unwrap_or(0) as u32,
             })
         }
     };
-    Ok(arr.nelems)
+    Ok(arr.len)
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -1226,68 +1226,71 @@ fn parse_map_def(name: &str, data: &[u8]) -> Result<bpf_map_def, ParseError> {
     }
 }
 
-fn parse_btf_map_def(btf: &Btf, info: &btf_var_secinfo) -> Result<(String, BtfMapDef), BtfError> {
-    let ty = match btf.type_by_id(info.type_)? {
-        BtfType::Var(ty, _) => ty,
+fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDef), BtfError> {
+    let ty = match btf.type_by_id(info.btf_type)? {
+        BtfType::Var(var) => var,
         other => {
             return Err(BtfError::UnexpectedBtfType {
-                type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32,
+                type_id: other.btf_type().unwrap_or(0) as u32,
             })
         }
     };
-    let map_name = btf.string_at(ty.name_off)?;
+    let map_name = btf.string_at(ty.name_offset)?;
     let mut map_def = BtfMapDef::default();
 
     // Safety: union
-    let root_type = btf.resolve_type(unsafe { ty.__bindgen_anon_1.type_ })?;
-    let members = match btf.type_by_id(root_type)? {
-        BtfType::Struct(_, members) => members,
+    let root_type = btf.resolve_type(ty.btf_type)?;
+    let s = match btf.type_by_id(root_type)? {
+        BtfType::Struct(s) => s,
         other => {
             return Err(BtfError::UnexpectedBtfType {
-                type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32,
+                type_id: other.btf_type().unwrap_or(0) as u32,
             })
         }
     };
 
-    for m in members {
-        match btf.string_at(m.name_off)?.as_ref() {
+    for m in &s.members {
+        match btf.string_at(m.name_offset)?.as_ref() {
             "type" => {
-                map_def.map_type = get_map_field(btf, m.type_)?;
+                map_def.map_type = get_map_field(btf, m.btf_type)?;
             }
             "key" => {
-                if let BtfType::Ptr(pty) = btf.type_by_id(m.type_)? {
+                if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
                     // Safety: union
-                    let t = unsafe { pty.__bindgen_anon_1.type_ };
+                    let t = pty.btf_type;
                     map_def.key_size = btf.type_size(t)? as u32;
                     map_def.btf_key_type_id = t;
                 } else {
-                    return Err(BtfError::UnexpectedBtfType { type_id: m.type_ });
+                    return Err(BtfError::UnexpectedBtfType {
+                        type_id: m.btf_type,
+                    });
                 }
             }
             "key_size" => {
-                map_def.key_size = get_map_field(btf, m.type_)?;
+                map_def.key_size = get_map_field(btf, m.btf_type)?;
             }
             "value" => {
-                if let BtfType::Ptr(pty) = btf.type_by_id(m.type_)? {
-                    // Safety: union
-                    let t = unsafe { pty.__bindgen_anon_1.type_ };
+                if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
+                    let t = pty.btf_type;
                     map_def.value_size = btf.type_size(t)? as u32;
                     map_def.btf_value_type_id = t;
                 } else {
-                    return Err(BtfError::UnexpectedBtfType { type_id: m.type_ });
+                    return Err(BtfError::UnexpectedBtfType {
+                        type_id: m.btf_type,
+                    });
                 }
             }
             "value_size" => {
-                map_def.value_size = get_map_field(btf, m.type_)?;
+                map_def.value_size = get_map_field(btf, m.btf_type)?;
             }
             "max_entries" => {
-                map_def.max_entries = get_map_field(btf, m.type_)?;
+                map_def.max_entries = get_map_field(btf, m.btf_type)?;
             }
             "map_flags" => {
-                map_def.map_flags = get_map_field(btf, m.type_)?;
+                map_def.map_flags = get_map_field(btf, m.btf_type)?;
             }
             "pinning" => {
-                let pinning = get_map_field(btf, m.type_)?;
+                let pinning = get_map_field(btf, m.btf_type)?;
                 map_def.pinning = PinningType::try_from(pinning).unwrap_or_else(|_| {
                     debug!("{} is not a valid pin type. using PIN_NONE", pinning);
                     PinningType::None

+ 38 - 34
aya/src/sys/bpf.rs

@@ -1,8 +1,12 @@
 use crate::{
-    generated::{
-        btf_func_linkage, btf_param, btf_var_secinfo, BPF_F_REPLACE, BTF_INT_SIGNED, BTF_VAR_STATIC,
+    generated::BPF_F_REPLACE,
+    obj::{
+        btf::{
+            BtfParam, BtfType, DataSec, DataSecEntry, DeclTag, Float, Func, FuncLinkage, FuncProto,
+            Int, IntEncoding, Ptr, TypeTag, Var, VarLinkage,
+        },
+        copy_instructions,
     },
-    obj::{btf::BtfType, copy_instructions},
     Btf,
 };
 use libc::{c_char, c_long, close, ENOENT, ENOSPC};
@@ -546,7 +550,7 @@ pub(crate) fn is_prog_name_supported() -> bool {
 pub(crate) fn is_btf_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("int".to_string());
-    let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+    let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
     btf.add_type(int_type);
     let btf_bytes = btf.to_bytes();
 
@@ -568,26 +572,26 @@ pub(crate) fn is_btf_supported() -> bool {
 pub(crate) fn is_btf_func_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("int".to_string());
-    let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+    let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
     let int_type_id = btf.add_type(int_type);
 
     let a_name = btf.add_string("a".to_string());
     let b_name = btf.add_string("b".to_string());
     let params = vec![
-        btf_param {
-            name_off: a_name,
-            type_: int_type_id,
+        BtfParam {
+            name_offset: a_name,
+            btf_type: int_type_id,
         },
-        btf_param {
-            name_off: b_name,
-            type_: int_type_id,
+        BtfParam {
+            name_offset: b_name,
+            btf_type: int_type_id,
         },
     ];
-    let func_proto = BtfType::new_func_proto(params, int_type_id);
+    let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
     let func_proto_type_id = btf.add_type(func_proto);
 
     let add = btf.add_string("inc".to_string());
-    let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_STATIC);
+    let func = BtfType::Func(Func::new(add, func_proto_type_id, FuncLinkage::Static));
     btf.add_type(func);
 
     let btf_bytes = btf.to_bytes();
@@ -610,26 +614,26 @@ pub(crate) fn is_btf_func_supported() -> bool {
 pub(crate) fn is_btf_func_global_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("int".to_string());
-    let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+    let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
     let int_type_id = btf.add_type(int_type);
 
     let a_name = btf.add_string("a".to_string());
     let b_name = btf.add_string("b".to_string());
     let params = vec![
-        btf_param {
-            name_off: a_name,
-            type_: int_type_id,
+        BtfParam {
+            name_offset: a_name,
+            btf_type: int_type_id,
         },
-        btf_param {
-            name_off: b_name,
-            type_: int_type_id,
+        BtfParam {
+            name_offset: b_name,
+            btf_type: int_type_id,
         },
     ];
-    let func_proto = BtfType::new_func_proto(params, int_type_id);
+    let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
     let func_proto_type_id = btf.add_type(func_proto);
 
     let add = btf.add_string("inc".to_string());
-    let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_GLOBAL);
+    let func = BtfType::Func(Func::new(add, func_proto_type_id, FuncLinkage::Global));
     btf.add_type(func);
 
     let btf_bytes = btf.to_bytes();
@@ -652,20 +656,20 @@ pub(crate) fn is_btf_func_global_supported() -> bool {
 pub(crate) fn is_btf_datasec_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("int".to_string());
-    let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+    let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
     let int_type_id = btf.add_type(int_type);
 
     let name_offset = btf.add_string("foo".to_string());
-    let var_type = BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC);
+    let var_type = BtfType::Var(Var::new(name_offset, int_type_id, VarLinkage::Static));
     let var_type_id = btf.add_type(var_type);
 
     let name_offset = btf.add_string(".data".to_string());
-    let variables = vec![btf_var_secinfo {
-        type_: var_type_id,
+    let variables = vec![DataSecEntry {
+        btf_type: var_type_id,
         offset: 0,
         size: 4,
     }];
-    let datasec_type = BtfType::new_datasec(name_offset, variables, 4);
+    let datasec_type = BtfType::DataSec(DataSec::new(name_offset, variables, 4));
     btf.add_type(datasec_type);
 
     let btf_bytes = btf.to_bytes();
@@ -688,7 +692,7 @@ pub(crate) fn is_btf_datasec_supported() -> bool {
 pub(crate) fn is_btf_float_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("float".to_string());
-    let float_type = BtfType::new_float(name_offset, 16);
+    let float_type = BtfType::Float(Float::new(name_offset, 16));
     btf.add_type(float_type);
 
     let btf_bytes = btf.to_bytes();
@@ -711,15 +715,15 @@ pub(crate) fn is_btf_float_supported() -> bool {
 pub(crate) fn is_btf_decl_tag_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("int".to_string());
-    let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
+    let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
     let int_type_id = btf.add_type(int_type);
 
     let name_offset = btf.add_string("foo".to_string());
-    let var_type = BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC);
+    let var_type = BtfType::Var(Var::new(name_offset, int_type_id, VarLinkage::Static));
     let var_type_id = btf.add_type(var_type);
 
     let name_offset = btf.add_string("decl_tag".to_string());
-    let decl_tag = BtfType::new_decl_tag(name_offset, var_type_id, -1);
+    let decl_tag = BtfType::DeclTag(DeclTag::new(name_offset, var_type_id, -1));
     btf.add_type(decl_tag);
 
     let btf_bytes = btf.to_bytes();
@@ -742,14 +746,14 @@ pub(crate) fn is_btf_decl_tag_supported() -> bool {
 pub(crate) fn is_btf_type_tag_supported() -> bool {
     let mut btf = Btf::new();
 
-    let int_type = BtfType::new_int(0, 4, BTF_INT_SIGNED, 0);
+    let int_type = BtfType::Int(Int::new(0, 4, IntEncoding::Signed, 0));
     let int_type_id = btf.add_type(int_type);
 
     let name_offset = btf.add_string("int".to_string());
-    let type_tag = BtfType::new_type_tag(name_offset, int_type_id);
+    let type_tag = BtfType::TypeTag(TypeTag::new(name_offset, int_type_id));
     let type_tag_type = btf.add_type(type_tag);
 
-    btf.add_type(BtfType::new_ptr(0, type_tag_type));
+    btf.add_type(BtfType::Ptr(Ptr::new(0, type_tag_type)));
 
     let btf_bytes = btf.to_bytes();
 

Some files were not shown because too many files changed in this diff