Skip to content

Commit

Permalink
btfparse: Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrogario committed Jan 14, 2024
1 parent c8f61d2 commit 5097f1f
Showing 1 changed file with 92 additions and 52 deletions.
144 changes: 92 additions & 52 deletions btfparse/src/btf/type_information.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ impl TypeInformation {
match type_var {
TypeVariant::Void => {
return Err(BTFError::new(
BTFErrorKind::UnsupportedType,
BTFErrorKind::InvalidTypePath,
"The void type can't be dereferenced with a path",
));
}
Expand Down Expand Up @@ -534,19 +534,18 @@ impl TypeInformation {
tid = element_tid;
}

TypeVariant::Ptr(ptr) => {
let pointee_tid = *ptr.tid();
let element_type_size = self.size_of(pointee_tid)?;
type_var => {
let error_message = match type_var {
TypeVariant::Ptr(_) => {
format!("Type {:?} is a ptr, and dereferencing it would require a read operation", type_var)
}

offset += index * element_type_size;
tid = pointee_tid;
}
_ => {
format!("Type {:?} is not indexable", type_var)
}
};

_ => {
return Err(BTFError::new(
BTFErrorKind::InvalidTypePath,
&format!("Type {:?} is not indexable", type_var),
));
return Err(BTFError::new(BTFErrorKind::InvalidTypePath, &error_message));
}
};
}
Expand Down Expand Up @@ -658,10 +657,11 @@ mod tests {
.id_to_name_map
.insert(1, String::from("unsigned int"));

// tid:2 BTF_KIND_PTR
// tid:2 BTF_KIND_PTR. Make this reference the named struct type we define
// later on
type_info.id_to_type_map.insert(
2,
TypeVariant::Ptr(Ptr::create(Header::create(Kind::Ptr, 0, 0, false, 0), 0)),
TypeVariant::Ptr(Ptr::create(Header::create(Kind::Ptr, 0, 0, false, 6), 6)),
);

// tid:3 BTF_KIND_ARRAY
Expand Down Expand Up @@ -821,26 +821,26 @@ mod tests {
type_info.id_to_type_map.insert(
12,
TypeVariant::Volatile(Volatile::create(
Header::create(Kind::Volatile, 0, 0, false, 1),
1,
Header::create(Kind::Volatile, 0, 0, false, 6),
6,
)),
);

// tid:13 BTF_KIND_CONST
type_info.id_to_type_map.insert(
13,
TypeVariant::Const(Const::create(
Header::create(Kind::Const, 0, 0, false, 1),
1,
Header::create(Kind::Const, 0, 0, false, 6),
6,
)),
);

// tid:14 BTF_KIND_RESTRICT
type_info.id_to_type_map.insert(
14,
TypeVariant::Restrict(Restrict::create(
Header::create(Kind::Restrict, 0, 0, false, 1),
1,
Header::create(Kind::Restrict, 0, 0, false, 6),
6,
)),
);

Expand Down Expand Up @@ -1004,17 +1004,17 @@ mod tests {
assert_eq!(type_info.name_of(10).unwrap(), "StructForwardDecl");
assert!(type_info.size_of(10).unwrap_err().kind() == BTFErrorKind::NotSized);

// The typedef points to the named struct, which is 28 bytes
// The typedef references the named struct, which is 28 bytes
assert_eq!(type_info.size_of(11).unwrap(), 28);

// The volatile points to the int, which is 4 bytes
assert_eq!(type_info.size_of(12).unwrap(), 4);
// The volatile references the named struct `Struct`, which is 28 bytes
assert_eq!(type_info.size_of(12).unwrap(), 28);

// The const points to the int, which is 4 bytes
assert_eq!(type_info.size_of(13).unwrap(), 4);
// The const references the named struct `Struct`, which is 28 bytes
assert_eq!(type_info.size_of(13).unwrap(), 28);

// The restrict points to the int, which is 4 bytes
assert_eq!(type_info.size_of(14).unwrap(), 4);
// The restrict references the named struct `Struct`, which is 28 bytes
assert_eq!(type_info.size_of(14).unwrap(), 28);

// The BTF_KIND_FUNC has no size because it is not a type
assert_eq!(type_info.name_of(15).unwrap(), "func");
Expand All @@ -1035,47 +1035,87 @@ mod tests {
// The BTF_KIND_DECL_TAG has no size
assert!(type_info.size_of(20).unwrap_err().kind() == BTFErrorKind::NotSized);

// The BTF_KIND_DECL_TAG has size of the type it is applied to (named struct)
// The BTF_KIND_TYPE_TAG has size of the type it is applied to (named struct)
assert_eq!(type_info.size_of(21).unwrap(), 28);
}

#[test]
fn test_offset_of() {
let type_info = get_test_type_info();
let int_value_offset = type_info
.offset_of(type_info.id_of("Struct").unwrap(), "int_value")
.unwrap();

assert_eq!(int_value_offset, 16 * 8);
// void, int, ptr, enum, enum64, fwd, float
let no_deref_tid_list1 = [0, 1, 2, 8, 9, 10, 19];

// func, func_proto, var, datasec, decl_tag, type tag
let no_deref_tid_list2 = [15, 16, 17, 18, 20, 21];

for tid in no_deref_tid_list1.iter().chain(no_deref_tid_list2.iter()) {
assert_eq!(
type_info.offset_of(*tid, "test").unwrap_err().kind(),
BTFErrorKind::InvalidTypePath
);

assert_eq!(
type_info.offset_of(*tid, "[0]").unwrap_err().kind(),
BTFErrorKind::InvalidTypePath
);
}

// Arrays can only be dereferenced with indexes
assert_eq!(
type_info.offset_of(3, "test").unwrap_err().kind(),
BTFErrorKind::InvalidTypePath
);

assert_eq!(type_info.offset_of(3, "[0]").unwrap(), 0);
assert_eq!(type_info.offset_of(3, "[1]").unwrap(), 4);
assert_eq!(type_info.offset_of(3, "[2]").unwrap(), 8);
assert_eq!(type_info.offset_of(3, "[3]").unwrap(), 12);
assert_eq!(type_info.offset_of(3, "[4]").unwrap(), 16);
assert_eq!(type_info.offset_of(3, "[5]").unwrap(), 20);
assert_eq!(type_info.offset_of(3, "[6]").unwrap(), 24);
assert_eq!(type_info.offset_of(3, "[7]").unwrap(), 28);
assert_eq!(type_info.offset_of(3, "[8]").unwrap(), 32);
assert_eq!(type_info.offset_of(3, "[9]").unwrap(), 36);

assert_eq!(
type_info.offset_of(3, "[10]").unwrap_err().kind(),
BTFErrorKind::InvalidTypePath
);

let ptr_value_offset = type_info
.offset_of(type_info.id_of("Struct").unwrap(), "ptr_value")
.unwrap();
// Named struct and the typedef/const/volatile/restrict that reference it
for struct_tid in [6, 11, 12, 13, 14] {
let int_value_offset = type_info.offset_of(struct_tid, "int_value").unwrap();

assert_eq!(ptr_value_offset, 20 * 8);
assert_eq!(int_value_offset, 16 * 8);

let anon_struct_value1_offset = type_info
.offset_of(type_info.id_of("Struct").unwrap(), "anon_struct_value1")
.unwrap();
let ptr_value_offset = type_info.offset_of(struct_tid, "ptr_value").unwrap();

assert_eq!(anon_struct_value1_offset, 0);
assert_eq!(ptr_value_offset, 20 * 8);

let anon_struct_value2_offset = type_info
.offset_of(type_info.id_of("Struct").unwrap(), "anon_struct_value2")
.unwrap();
let anon_struct_value1_offset = type_info
.offset_of(struct_tid, "anon_struct_value1")
.unwrap();

assert_eq!(anon_struct_value2_offset, 4 * 8);
assert_eq!(anon_struct_value1_offset, 0);

let anon_union_value1_offset = type_info
.offset_of(type_info.id_of("Struct").unwrap(), "anon_union_value1")
.unwrap();
let anon_struct_value2_offset = type_info
.offset_of(struct_tid, "anon_struct_value2")
.unwrap();

assert_eq!(anon_union_value1_offset, 8 * 8);
assert_eq!(anon_struct_value2_offset, 4 * 8);

let anon_union_value2_offset = type_info
.offset_of(type_info.id_of("Struct").unwrap(), "anon_union_value2")
.unwrap();
let anon_union_value1_offset = type_info
.offset_of(struct_tid, "anon_union_value1")
.unwrap();

assert_eq!(anon_union_value2_offset, 8 * 8);
assert_eq!(anon_union_value1_offset, 8 * 8);

let anon_union_value2_offset = type_info
.offset_of(struct_tid, "anon_union_value2")
.unwrap();

assert_eq!(anon_union_value2_offset, 8 * 8);
}
}
}

0 comments on commit 5097f1f

Please sign in to comment.