Fixed bug:

- When typedefs are nested
 - Offset issue when dealing with arrays

Signed-off-by: Quentin JEROME <qjerome@users.noreply.github.com>
pull/530/head
Quentin JEROME 2 years ago
parent 1db17d5ad3
commit b648e46fe6

@ -39,6 +39,19 @@ impl StructHelper {
} }
} }
fn resolve_indirect_type(btf: &Btf, t: &BtfType) -> Result<BtfType, BtfError> {
match t {
BtfType::Typedef(td) => {
let t = btf.type_by_id(td.btf_type)?;
if matches!(t, BtfType::Typedef(_)) {
return Self::resolve_indirect_type(btf, t);
}
Ok(t.clone())
}
_ => Ok(t.clone()),
}
}
// resolve structure members recursively // resolve structure members recursively
fn resolve_members_rec( fn resolve_members_rec(
&mut self, &mut self,
@ -51,8 +64,10 @@ impl StructHelper {
let mut member_offset = base_offset; let mut member_offset = base_offset;
for m in members { for m in members {
let member_name = btf.string_at(m.name_offset)?; let member_name = btf.string_at(m.name_offset)?;
// we get the member type // we get the member type
let member_type = btf.type_by_id(m.btf_type)?; let member_type = &Self::resolve_indirect_type(btf, btf.type_by_id(m.btf_type)?)?;
let mut member_size = member_type.size().unwrap_or_default(); let mut member_size = member_type.size().unwrap_or_default();
let mut p = member_path.clone(); let mut p = member_path.clone();
@ -80,21 +95,17 @@ impl StructHelper {
} }
BtfType::Array(array) => { BtfType::Array(array) => {
self.members.push(MemberHelper::new( let element_type = Self::resolve_indirect_type(
p, btf,
member_offset, btf.type_by_id(array.array.element_type)?,
member_type.clone(), )?;
Some(btf.type_by_id(array.array.element_type)?.clone()), member_size = array.array.len * element_type.size().unwrap_or_default();
));
}
BtfType::Typedef(td) => {
member_size = btf.type_by_id(td.btf_type)?.size().unwrap_or_default();
self.members.push(MemberHelper::new( self.members.push(MemberHelper::new(
p, p,
member_offset, member_offset,
member_type.clone(), member_type.clone(),
None, Some(element_type.clone()),
)); ));
} }
@ -110,6 +121,9 @@ impl StructHelper {
// members of unions all have the same offset // members of unions all have the same offset
if !matches!(t.kind(), BtfKind::Union) { if !matches!(t.kind(), BtfKind::Union) {
// a zero member_size is an issue as two members
// will have the same offsets
debug_assert_ne!(member_size, 0);
member_offset += member_size; member_offset += member_size;
} }
} }
@ -304,8 +318,11 @@ mod test {
assert_eq!(hlist_node.get_member("next").unwrap().offset, 0); assert_eq!(hlist_node.get_member("next").unwrap().offset, 0);
assert_eq!(hlist_node.get_member("pprev").unwrap().offset, ptr_size); assert_eq!(hlist_node.get_member("pprev").unwrap().offset, ptr_size);
// might be too tight to kernel version, consider removing if problematic
let dentry = StructHelper::from_btf(&btf, "dentry").unwrap(); let dentry = StructHelper::from_btf(&btf, "dentry").unwrap();
assert_eq!(dentry.get_member("d_name").unwrap().offset, 32); assert_eq!(dentry.get_member("d_name").unwrap().offset, 32);
assert_eq!(dentry.get_member("d_lockref").unwrap().offset, 88);
assert_eq!(dentry.get_member("d_alias").unwrap().offset, 176);
} }
#[test] #[test]

Loading…
Cancel
Save