浏览代码

Merge pull request #168 from dave-tucker/decl_tag

btf: Add support for BTF_TYPE_KIND_{TAG,DECL_TAG}
Alessandro Decina 3 年之前
父节点
当前提交
b45a160bb0
共有 4 个文件被更改,包括 205 次插入10 次删除
  1. 10 2
      aya/src/bpf.rs
  2. 72 2
      aya/src/obj/btf/btf.rs
  3. 63 6
      aya/src/obj/btf/types.rs
  4. 60 0
      aya/src/sys/bpf.rs

+ 10 - 2
aya/src/bpf.rs

@@ -28,8 +28,8 @@ use crate::{
     },
     sys::{
         bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_btf_datasec_supported,
-        is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported,
-        is_btf_supported, is_prog_name_supported,
+        is_btf_decl_tag_supported, is_btf_float_supported, is_btf_func_global_supported,
+        is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_prog_name_supported,
     },
     util::{bytes_of, possible_cpus, VerifierLog, POSSIBLE_CPUS},
 };
@@ -91,6 +91,8 @@ pub(crate) struct Features {
     pub btf_func_global: bool,
     pub btf_datasec: bool,
     pub btf_float: bool,
+    pub btf_decl_tag: bool,
+    pub btf_type_tag: bool,
 }
 
 impl Features {
@@ -119,6 +121,12 @@ impl Features {
 
             self.btf_float = is_btf_float_supported();
             debug!("[FEAT PROBE] BTF float support: {}", self.btf_float);
+
+            self.btf_decl_tag = is_btf_decl_tag_supported();
+            debug!("[FEAT PROBE] BTF decl_tag support: {}", self.btf_decl_tag);
+
+            self.btf_type_tag = is_btf_type_tag_supported();
+            debug!("[FEAT PROBE] BTF type_tag support: {}", self.btf_type_tag);
         }
     }
 }

+ 72 - 2
aya/src/obj/btf/btf.rs

@@ -323,7 +323,7 @@ impl Btf {
 
             use BtfType::*;
             match ty {
-                Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) => {
+                Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) | TypeTag(ty) => {
                     // Safety: union
                     type_id = unsafe { ty.__bindgen_anon_1.type_ };
                     continue;
@@ -391,7 +391,13 @@ impl Btf {
                     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, _) => {
+                Typedef(ty)
+                | Volatile(ty)
+                | Const(ty)
+                | Restrict(ty)
+                | Var(ty, _)
+                | DeclTag(ty, _)
+                | TypeTag(ty) => {
                     // Safety: union
                     type_id = unsafe { ty.__bindgen_anon_1.type_ };
                     continue;
@@ -606,6 +612,24 @@ impl Btf {
                         btf.add_type(BtfType::Float(*ty));
                     }
                 }
+                BtfType::DeclTag(ty, btf_decl_tag) => {
+                    if !features.btf_decl_tag {
+                        debug!("{}: not supported. replacing with INT", kind);
+                        let int_type = BtfType::new_int(ty.name_off, 1, 0, 0);
+                        btf.add_type(int_type);
+                    } else {
+                        btf.add_type(BtfType::DeclTag(*ty, *btf_decl_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_ });
+                        btf.add_type(const_type);
+                    } else {
+                        btf.add_type(BtfType::TypeTag(*ty));
+                    }
+                }
                 // The type does not need sanitizing
                 ty => {
                     btf.add_type(ty.clone());
@@ -1028,6 +1052,14 @@ mod tests {
         let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_GLOBAL);
         btf.add_type(func);
 
+        let name_offset = btf.add_string("int".to_string());
+        let type_tag = BtfType::new_type_tag(name_offset, int_type_id);
+        btf.add_type(type_tag);
+
+        let name_offset = btf.add_string("decl_tag".to_string());
+        let decl_tag = BtfType::new_decl_tag(name_offset, var_type_id, -1);
+        btf.add_type(decl_tag);
+
         let cases = HashMap::from([
             (
                 "noop",
@@ -1038,6 +1070,8 @@ mod tests {
                     btf_func_global: true,
                     btf_datasec: true,
                     btf_float: true,
+                    btf_decl_tag: true,
+                    btf_type_tag: true,
                 },
             ),
             (
@@ -1049,6 +1083,8 @@ mod tests {
                     btf_func_global: true,
                     btf_datasec: false,
                     btf_float: true,
+                    btf_decl_tag: true,
+                    btf_type_tag: true,
                 },
             ),
             (
@@ -1060,6 +1096,8 @@ mod tests {
                     btf_func_global: true,
                     btf_datasec: true,
                     btf_float: false,
+                    btf_decl_tag: true,
+                    btf_type_tag: true,
                 },
             ),
             (
@@ -1071,6 +1109,8 @@ mod tests {
                     btf_func_global: true,
                     btf_datasec: true,
                     btf_float: true,
+                    btf_decl_tag: true,
+                    btf_type_tag: true,
                 },
             ),
             (
@@ -1082,6 +1122,34 @@ mod tests {
                     btf_func_global: false,
                     btf_datasec: true,
                     btf_float: true,
+                    btf_decl_tag: true,
+                    btf_type_tag: true,
+                },
+            ),
+            (
+                "no decl tag",
+                Features {
+                    bpf_name: true,
+                    btf: true,
+                    btf_func: true,
+                    btf_func_global: true,
+                    btf_datasec: true,
+                    btf_float: true,
+                    btf_decl_tag: false,
+                    btf_type_tag: true,
+                },
+            ),
+            (
+                "no type tag",
+                Features {
+                    bpf_name: true,
+                    btf: true,
+                    btf_func: true,
+                    btf_func_global: true,
+                    btf_datasec: true,
+                    btf_float: true,
+                    btf_decl_tag: true,
+                    btf_type_tag: false,
                 },
             ),
             (
@@ -1093,6 +1161,8 @@ mod tests {
                     btf_func_global: false,
                     btf_datasec: false,
                     btf_float: false,
+                    btf_decl_tag: false,
+                    btf_type_tag: false,
                 },
             ),
         ]);

+ 63 - 6
aya/src/obj/btf/types.rs

@@ -8,11 +8,12 @@ use object::Endianness;
 
 use crate::{
     generated::{
-        btf_array, btf_enum, btf_func_linkage, btf_member, btf_param, btf_type,
+        btf_array, btf_decl_tag, btf_enum, btf_func_linkage, btf_member, btf_param, btf_type,
         btf_type__bindgen_ty_1, btf_var, btf_var_secinfo, BTF_KIND_ARRAY, BTF_KIND_CONST,
-        BTF_KIND_DATASEC, BTF_KIND_ENUM, BTF_KIND_FLOAT, BTF_KIND_FUNC, BTF_KIND_FUNC_PROTO,
-        BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR, BTF_KIND_RESTRICT, BTF_KIND_STRUCT,
-        BTF_KIND_TYPEDEF, BTF_KIND_UNION, BTF_KIND_UNKN, BTF_KIND_VAR, BTF_KIND_VOLATILE,
+        BTF_KIND_DATASEC, BTF_KIND_DECL_TAG, BTF_KIND_ENUM, BTF_KIND_FLOAT, BTF_KIND_FUNC,
+        BTF_KIND_FUNC_PROTO, BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR, BTF_KIND_RESTRICT,
+        BTF_KIND_STRUCT, BTF_KIND_TYPEDEF, BTF_KIND_TYPE_TAG, BTF_KIND_UNION, BTF_KIND_UNKN,
+        BTF_KIND_VAR, BTF_KIND_VOLATILE,
     },
     obj::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH},
 };
@@ -36,6 +37,8 @@ pub(crate) enum BtfType {
     FuncProto(btf_type, Vec<btf_param>),
     Var(btf_type, btf_var),
     DataSec(btf_type, Vec<btf_var_secinfo>),
+    DeclTag(btf_type, btf_decl_tag),
+    TypeTag(btf_type),
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -58,6 +61,8 @@ pub(crate) enum BtfKind {
     FuncProto = BTF_KIND_FUNC_PROTO,
     Var = BTF_KIND_VAR,
     DataSec = BTF_KIND_DATASEC,
+    DeclTag = BTF_KIND_DECL_TAG,
+    TypeTag = BTF_KIND_TYPE_TAG,
 }
 
 impl TryFrom<u32> for BtfKind {
@@ -83,6 +88,8 @@ impl TryFrom<u32> for BtfKind {
             BTF_KIND_FUNC_PROTO => FuncProto,
             BTF_KIND_VAR => Var,
             BTF_KIND_DATASEC => DataSec,
+            BTF_KIND_DECL_TAG => DeclTag,
+            BTF_KIND_TYPE_TAG => TypeTag,
             kind => return Err(BtfError::InvalidTypeKind { kind }),
         })
     }
@@ -108,6 +115,8 @@ impl Display for BtfKind {
             BtfKind::FuncProto => write!(f, "[FUNC_PROTO]"),
             BtfKind::Var => write!(f, "[VAR]"),
             BtfKind::DataSec => write!(f, "[DATASEC]"),
+            BtfKind::DeclTag => write!(f, "[DECL_TAG]"),
+            BtfKind::TypeTag => write!(f, "[TYPE_TAG]"),
         }
     }
 }
@@ -177,6 +186,8 @@ impl BtfType {
             BtfKind::FuncProto => FuncProto(ty, unsafe { read_array(data, vlen)? }),
             BtfKind::Var => Var(ty, unsafe { read(data)? }),
             BtfKind::DataSec => DataSec(ty, unsafe { read_array(data, vlen)? }),
+            BtfKind::DeclTag => DeclTag(ty, unsafe { read(data)? }),
+            BtfKind::TypeTag => TypeTag(ty),
         })
     }
 
@@ -193,7 +204,8 @@ impl BtfType {
             | BtfType::Ptr(btf_type)
             | BtfType::Typedef(btf_type)
             | BtfType::Func(btf_type)
-            | BtfType::Float(btf_type) => bytes_of::<btf_type>(btf_type).to_vec(),
+            | BtfType::Float(btf_type)
+            | BtfType::TypeTag(btf_type) => bytes_of::<btf_type>(btf_type).to_vec(),
             BtfType::Int(btf_type, len) => {
                 let mut buf = bytes_of::<btf_type>(btf_type).to_vec();
                 buf.append(&mut len.to_ne_bytes().to_vec());
@@ -238,6 +250,11 @@ impl BtfType {
                 buf
             }
             BtfType::Unknown => vec![],
+            BtfType::DeclTag(btf_type, btf_decl_tag) => {
+                let mut buf = bytes_of::<btf_type>(btf_type).to_vec();
+                buf.append(&mut bytes_of::<btf_decl_tag>(btf_decl_tag).to_vec());
+                buf
+            }
         }
     }
 
@@ -248,7 +265,7 @@ impl BtfType {
         match self {
             Unknown => ty_size,
             Fwd(_) | Const(_) | Volatile(_) | Restrict(_) | Ptr(_) | Typedef(_) | Func(_)
-            | Float(_) => ty_size,
+            | Float(_) | TypeTag(_) => ty_size,
             Int(_, _) => ty_size + mem::size_of::<u32>(),
             Enum(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_enum>(),
             Array(_, _) => ty_size + mem::size_of::<btf_array>(),
@@ -257,6 +274,7 @@ impl BtfType {
             FuncProto(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_param>(),
             Var(_, _) => ty_size + mem::size_of::<btf_var>(),
             DataSec(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_var_secinfo>(),
+            DeclTag(_, _) => ty_size + mem::size_of::<btf_decl_tag>(),
         }
     }
 
@@ -280,6 +298,8 @@ impl BtfType {
             FuncProto(ty, _) => ty,
             Var(ty, _) => ty,
             DataSec(ty, _) => ty,
+            DeclTag(ty, _) => ty,
+            TypeTag(ty) => ty,
         })
     }
 
@@ -408,6 +428,43 @@ impl BtfType {
         };
         BtfType::Array(btf_type, btf_array)
     }
+
+    pub(crate) fn new_decl_tag(name_off: u32, type_: u32, component_idx: i32) -> BtfType {
+        let info = (BTF_KIND_DECL_TAG) << 24;
+        let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
+        btf_type.name_off = name_off;
+        btf_type.info = info;
+        btf_type.__bindgen_anon_1.type_ = type_;
+        let btf_decl_tag = btf_decl_tag { component_idx };
+        BtfType::DeclTag(btf_type, btf_decl_tag)
+    }
+
+    pub(crate) fn new_type_tag(name_off: u32, type_: u32) -> BtfType {
+        let info = (BTF_KIND_TYPE_TAG) << 24;
+        let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
+        btf_type.name_off = name_off;
+        btf_type.info = info;
+        btf_type.__bindgen_anon_1.type_ = type_;
+        BtfType::TypeTag(btf_type)
+    }
+
+    pub(crate) fn new_ptr(type_: u32) -> BtfType {
+        let info = (BTF_KIND_PTR) << 24;
+        let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
+        btf_type.name_off = 0;
+        btf_type.info = info;
+        btf_type.__bindgen_anon_1.type_ = type_;
+        BtfType::Ptr(btf_type)
+    }
+
+    pub(crate) fn new_const(type_: u32) -> BtfType {
+        let info = (BTF_KIND_CONST) << 24;
+        let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
+        btf_type.name_off = 0;
+        btf_type.info = info;
+        btf_type.__bindgen_anon_1.type_ = type_;
+        BtfType::Const(btf_type)
+    }
 }
 
 fn type_kind(ty: &btf_type) -> Result<BtfKind, BtfError> {

+ 60 - 0
aya/src/sys/bpf.rs

@@ -670,6 +670,66 @@ 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_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_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);
+    btf.add_type(decl_tag);
+
+    let btf_bytes = btf.to_bytes();
+
+    let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
+    let u = unsafe { &mut attr.__bindgen_anon_7 };
+    u.btf = btf_bytes.as_ptr() as u64;
+    u.btf_size = btf_bytes.len() as u32;
+
+    match sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) {
+        Ok(v) => {
+            let fd = v as RawFd;
+            unsafe { close(fd) };
+            true
+        }
+        Err(_) => false,
+    }
+}
+
+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_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_type = btf.add_type(type_tag);
+
+    btf.add_type(BtfType::new_ptr(type_tag_type));
+
+    let btf_bytes = btf.to_bytes();
+
+    let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
+    let u = unsafe { &mut attr.__bindgen_anon_7 };
+    u.btf = btf_bytes.as_ptr() as u64;
+    u.btf_size = btf_bytes.len() as u32;
+
+    match sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) {
+        Ok(v) => {
+            let fd = v as RawFd;
+            unsafe { close(fd) };
+            true
+        }
+        Err(_) => false,
+    }
+}
+
 pub fn sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult {
     syscall(Syscall::Bpf { cmd, attr })
 }