|
@@ -417,15 +417,13 @@ impl Btf {
|
|
|
let mut types = mem::take(&mut self.types);
|
|
|
for i in 0..types.types.len() {
|
|
|
let kind = types.types.get(i).unwrap().kind()?.unwrap_or_default();
|
|
|
- // datasec sizes aren't set by llvm
|
|
|
- // we need to fix them here before loading the btf to the kernel
|
|
|
match kind {
|
|
|
// 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
|
|
|
BtfKind::Ptr => {
|
|
|
- if let Some(BtfType::Ptr(mut ty)) = types.types.get_mut(i) {
|
|
|
+ if let Some(BtfType::Ptr(ty)) = types.types.get_mut(i) {
|
|
|
ty.name_off = 0;
|
|
|
}
|
|
|
}
|
|
@@ -448,11 +446,12 @@ impl Btf {
|
|
|
offset: member.offset * 8,
|
|
|
})
|
|
|
}
|
|
|
- let struct_type = BtfType::new_struct(ty.name_off, members, 0);
|
|
|
- types.types[i] = struct_type;
|
|
|
+ types.types[i] = BtfType::new_struct(ty.name_off, 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
|
|
|
BtfKind::DataSec if features.btf_datasec => {
|
|
|
if let Some(BtfType::DataSec(ty, data)) = types.types.get(i) {
|
|
|
// Start DataSec Fixups
|
|
@@ -524,16 +523,14 @@ impl Btf {
|
|
|
}
|
|
|
}
|
|
|
// Sanitize FUNC_PROTO
|
|
|
- BtfKind::FuncProto if features.btf_func => {
|
|
|
+ BtfKind::FuncProto if !features.btf_func => {
|
|
|
if let Some(BtfType::FuncProto(ty, vars)) = types.types.get(i) {
|
|
|
debug!("{}: not supported. replacing with ENUM", kind);
|
|
|
let members: Vec<btf_enum> = vars
|
|
|
.iter()
|
|
|
- .map(|p| -> btf_enum {
|
|
|
- btf_enum {
|
|
|
- name_off: p.name_off,
|
|
|
- val: p.type_ as i32,
|
|
|
- }
|
|
|
+ .map(|p| btf_enum {
|
|
|
+ name_off: p.name_off,
|
|
|
+ val: p.type_ as i32,
|
|
|
})
|
|
|
.collect();
|
|
|
let enum_type = BtfType::new_enum(ty.name_off, members);
|
|
@@ -890,7 +887,9 @@ pub(crate) struct SecInfo<'a> {
|
|
|
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
- use crate::generated::{btf_param, btf_var_secinfo, BTF_INT_SIGNED, BTF_VAR_STATIC};
|
|
|
+ use crate::generated::{
|
|
|
+ btf_param, btf_var_secinfo, BTF_INT_SIGNED, BTF_VAR_GLOBAL_EXTERN, BTF_VAR_STATIC,
|
|
|
+ };
|
|
|
|
|
|
use super::*;
|
|
|
|
|
@@ -1008,15 +1007,68 @@ mod tests {
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn test_sanitize_btf() {
|
|
|
+ fn test_fixup_ptr() {
|
|
|
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 int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_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 features = Features {
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
|
|
|
+ .unwrap();
|
|
|
+ if let BtfType::Ptr(fixed) = btf.type_by_id(ptr_type_id).unwrap() {
|
|
|
+ assert!(
|
|
|
+ fixed.name_off == 0,
|
|
|
+ "expected offset 0, got {}",
|
|
|
+ fixed.name_off
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ panic!("not a ptr")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 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 features = Features {
|
|
|
+ btf_datasec: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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)
|
|
|
+ } else {
|
|
|
+ panic!("not an int")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 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 var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC));
|
|
|
|
|
|
let name_offset = btf.add_string(".data".to_string());
|
|
|
let variables = vec![btf_var_secinfo {
|
|
@@ -1024,164 +1076,293 @@ mod tests {
|
|
|
offset: 0,
|
|
|
size: 4,
|
|
|
}];
|
|
|
- let datasec_type = BtfType::new_datasec(name_offset, variables, 4);
|
|
|
- btf.add_type(datasec_type);
|
|
|
+ let datasec_type_id = btf.add_type(BtfType::new_datasec(name_offset, variables, 0));
|
|
|
|
|
|
- let name_offset = btf.add_string("float".to_string());
|
|
|
- let float_type = BtfType::new_float(name_offset, 16);
|
|
|
- btf.add_type(float_type);
|
|
|
+ let features = Features {
|
|
|
+ btf_datasec: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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)
|
|
|
+ } else {
|
|
|
+ panic!("not a struct")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 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_GLOBAL_EXTERN,
|
|
|
+ ));
|
|
|
+
|
|
|
+ let name_offset = btf.add_string(".data".to_string());
|
|
|
+ let variables = vec![btf_var_secinfo {
|
|
|
+ type_: var_type_id,
|
|
|
+ offset: 0,
|
|
|
+ size: 4,
|
|
|
+ }];
|
|
|
+ let datasec_type_id = btf.add_type(BtfType::new_datasec(name_offset, variables, 0));
|
|
|
+
|
|
|
+ let features = Features {
|
|
|
+ btf_datasec: true,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ btf.fixup_and_sanitize(
|
|
|
+ &HashMap::from([(".data".to_string(), 32u64)]),
|
|
|
+ &HashMap::from([("foo".to_string(), 64u64)]),
|
|
|
+ &features,
|
|
|
+ )
|
|
|
+ .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);
|
|
|
+ assert!(
|
|
|
+ sec_info[0].offset == 64,
|
|
|
+ "expected 64, got {}",
|
|
|
+ sec_info[0].offset
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ panic!("not a datasec")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 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,
|
|
|
+ name_off: btf.add_string("a".to_string()),
|
|
|
type_: int_type_id,
|
|
|
},
|
|
|
btf_param {
|
|
|
- name_off: b_name,
|
|
|
+ name_off: btf.add_string("b".to_string()),
|
|
|
type_: int_type_id,
|
|
|
},
|
|
|
];
|
|
|
- let func_proto = BtfType::new_func_proto(params, int_type_id);
|
|
|
- let func_proto_type_id = btf.add_type(func_proto);
|
|
|
+ let func_proto_type_id = btf.add_type(BtfType::new_func_proto(params, int_type_id));
|
|
|
+ let inc = btf.add_string("inc".to_string());
|
|
|
+ let func_type_id = btf.add_type(BtfType::new_func(
|
|
|
+ inc,
|
|
|
+ func_proto_type_id,
|
|
|
+ btf_func_linkage::BTF_FUNC_STATIC,
|
|
|
+ ));
|
|
|
+
|
|
|
+ let features = Features {
|
|
|
+ btf_func: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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);
|
|
|
+ } 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);
|
|
|
+ } else {
|
|
|
+ panic!("not a typedef")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
|
|
|
- let add = btf.add_string("static".to_string());
|
|
|
- let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_STATIC);
|
|
|
- btf.add_type(func);
|
|
|
+ #[test]
|
|
|
+ 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_id = btf.add_type(int_type);
|
|
|
|
|
|
- let c_name = btf.add_string("c".to_string());
|
|
|
- let d_name = btf.add_string("d".to_string());
|
|
|
let params = vec![
|
|
|
btf_param {
|
|
|
- name_off: c_name,
|
|
|
+ name_off: 0,
|
|
|
type_: int_type_id,
|
|
|
},
|
|
|
btf_param {
|
|
|
- name_off: d_name,
|
|
|
+ name_off: 0,
|
|
|
type_: int_type_id,
|
|
|
},
|
|
|
];
|
|
|
let func_proto = BtfType::new_func_proto(params, int_type_id);
|
|
|
let func_proto_type_id = btf.add_type(func_proto);
|
|
|
|
|
|
- let add = btf.add_string("global".to_string());
|
|
|
- let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_GLOBAL);
|
|
|
- btf.add_type(func);
|
|
|
-
|
|
|
- let cases = HashMap::from([
|
|
|
- (
|
|
|
- "noop",
|
|
|
- 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: true,
|
|
|
- },
|
|
|
- ),
|
|
|
- (
|
|
|
- "no datasec",
|
|
|
- Features {
|
|
|
- bpf_name: true,
|
|
|
- btf: true,
|
|
|
- btf_func: true,
|
|
|
- btf_func_global: true,
|
|
|
- btf_datasec: false,
|
|
|
- btf_float: true,
|
|
|
- btf_decl_tag: true,
|
|
|
- btf_type_tag: true,
|
|
|
- },
|
|
|
- ),
|
|
|
- (
|
|
|
- "no float",
|
|
|
- Features {
|
|
|
- bpf_name: true,
|
|
|
- btf: true,
|
|
|
- btf_func: true,
|
|
|
- btf_func_global: true,
|
|
|
- btf_datasec: true,
|
|
|
- btf_float: false,
|
|
|
- btf_decl_tag: true,
|
|
|
- btf_type_tag: true,
|
|
|
- },
|
|
|
- ),
|
|
|
- (
|
|
|
- "no func",
|
|
|
- Features {
|
|
|
- bpf_name: true,
|
|
|
- btf: true,
|
|
|
- btf_func: false,
|
|
|
- btf_func_global: true,
|
|
|
- btf_datasec: true,
|
|
|
- btf_float: true,
|
|
|
- btf_decl_tag: true,
|
|
|
- btf_type_tag: true,
|
|
|
- },
|
|
|
- ),
|
|
|
- (
|
|
|
- "no global func",
|
|
|
- Features {
|
|
|
- bpf_name: true,
|
|
|
- btf: true,
|
|
|
- btf_func: true,
|
|
|
- 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,
|
|
|
- },
|
|
|
- ),
|
|
|
- (
|
|
|
- "all off",
|
|
|
- Features {
|
|
|
- bpf_name: true,
|
|
|
- btf: true,
|
|
|
- btf_func: false,
|
|
|
- btf_func_global: false,
|
|
|
- btf_datasec: false,
|
|
|
- btf_float: false,
|
|
|
- btf_decl_tag: false,
|
|
|
- btf_type_tag: false,
|
|
|
- },
|
|
|
- ),
|
|
|
- ]);
|
|
|
-
|
|
|
- for (name, features) in cases {
|
|
|
- println!("[CASE] Sanitize {}", name);
|
|
|
- btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
|
|
|
- .unwrap();
|
|
|
- let raw_new_btf = btf.to_bytes();
|
|
|
- Btf::parse(&raw_new_btf, Endianness::default()).unwrap();
|
|
|
+ let features = Features {
|
|
|
+ btf_func: true,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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");
|
|
|
+ } else {
|
|
|
+ panic!("not a func_proto")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 params = vec![
|
|
|
+ btf_param {
|
|
|
+ name_off: btf.add_string("a".to_string()),
|
|
|
+ type_: int_type_id,
|
|
|
+ },
|
|
|
+ btf_param {
|
|
|
+ name_off: btf.add_string("b".to_string()),
|
|
|
+ type_: int_type_id,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ let func_proto_type_id = btf.add_type(BtfType::new_func_proto(params, int_type_id));
|
|
|
+ let inc = btf.add_string("inc".to_string());
|
|
|
+ let func_type_id = btf.add_type(BtfType::new_func(
|
|
|
+ inc,
|
|
|
+ func_proto_type_id,
|
|
|
+ btf_func_linkage::BTF_FUNC_GLOBAL,
|
|
|
+ ));
|
|
|
+
|
|
|
+ let features = Features {
|
|
|
+ btf_func: true,
|
|
|
+ btf_func_global: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
|
|
|
+ .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);
|
|
|
+ } else {
|
|
|
+ panic!("not a func")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 features = Features {
|
|
|
+ btf_float: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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);
|
|
|
+ } else {
|
|
|
+ panic!("not a struct")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 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 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 features = Features {
|
|
|
+ btf_decl_tag: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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);
|
|
|
+ } else {
|
|
|
+ panic!("not an int")
|
|
|
+ }
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ 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 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 features = Features {
|
|
|
+ btf_type_tag: false,
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ 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);
|
|
|
+ } else {
|
|
|
+ panic!("not a const")
|
|
|
}
|
|
|
+ // Ensure we can convert to bytes and back again
|
|
|
+ let raw = btf.to_bytes();
|
|
|
+ Btf::parse(&raw, Endianness::default()).unwrap();
|
|
|
}
|
|
|
}
|