diff --git a/libbpf-cargo/src/gen/btf.rs b/libbpf-cargo/src/gen/btf.rs index a79c6903..fbecc969 100644 --- a/libbpf-cargo/src/gen/btf.rs +++ b/libbpf-cargo/src/gen/btf.rs @@ -10,6 +10,7 @@ use std::fmt::Write; use std::mem::size_of; use std::num::NonZeroUsize; use std::ops::Deref; +use std::rc::Rc; use anyhow::anyhow; use anyhow::bail; @@ -367,6 +368,20 @@ fn escape_reserved_keyword(identifier: Cow<'_, str>) -> Cow<'_, str> { } } +#[derive(Debug, Clone)] +struct BtfDependency { + /// Name of the dependency parent + parent_name: Option, + + /// Dependency id relative to the parent's `child_counter` + dep_id: i32, + + /// The `child_counter` for the dependency if it is intended to be + /// a parent itself. + /// For an anonymous unit this should be a pointer to the parent's `child_counter` + child_counter: Rc>, +} + #[derive(Debug, Default)] pub(crate) struct TypeMap { /// A mapping from type to number, allowing us to assign numbers to @@ -377,15 +392,75 @@ pub(crate) struct TypeMap { /// Mapping from type name to the number of times we have seen this /// name already. names_count: RefCell>, + + /// Mapping from type to it's parent. Used in anonymous members naming + dependency_tree: RefCell>, } impl TypeMap { + fn derive_parent<'s>(&self, ty: &BtfType<'s>, parent: &BtfType<'s>) { + let mut deps = self.dependency_tree.borrow_mut(); + if deps.get(&ty.type_id()).is_some() { + return; + } + + let pdep = deps.entry(parent.type_id()).or_insert(BtfDependency { + parent_name: None, + dep_id: 0, + child_counter: Rc::new(RefCell::new(0)), + }); + + let mut dep = pdep.clone(); + + // If parent is named, derive it. + // Otherwise derive parent's parent + if let Some(n) = parent.name() { + dep.parent_name = Some(n.to_string_lossy().to_string()); + } + + // If the current unit is named, self-assign the child_counter. + // Otherwise derive a parent's one + if ty.name().is_some() { + dep.child_counter = Rc::new(RefCell::new(0)); + } + + // Increment parent's `child_counter` and assign the new value to dep_id + let parent_counter = Rc::clone(&pdep.child_counter); + *parent_counter.borrow_mut() += 1; + dep.dep_id = *parent_counter.borrow(); + + deps.insert(ty.type_id(), dep); + } + + fn lookup_parent<'s>(&self, ty: &BtfType<'s>) -> Option { + self.dependency_tree.borrow().get(&ty.type_id()).cloned() + } + pub fn type_name_or_anon<'s>(&self, ty: &BtfType<'s>) -> Cow<'s, str> { match ty.name() { None => { let mut anon_table = self.types.borrow_mut(); let len = anon_table.len() + 1; // use 1 index anon ids for backwards compat - let anon_id = anon_table.entry(ty.type_id()).or_insert(len); + + let anon_id = match anon_table.entry(ty.type_id()) { + Entry::Occupied(anon_id) => { + let anon_id = anon_id.get(); + *anon_id + } + Entry::Vacant(anon_id) => { + if let Some(dep) = self.lookup_parent(ty) { + if let Some(name) = dep.parent_name { + if !name.is_empty() { + return format!("{ANON_PREFIX}{}_{}", name, dep.dep_id).into(); + } + } + } + + let anon_id = anon_id.insert(len); + *anon_id + } + }; + format!("{ANON_PREFIX}{anon_id}").into() } Some(n) => match self.names.borrow_mut().entry(ty.type_id()) { @@ -726,6 +801,7 @@ impl<'s> GenBtf<'s> { } if let Some(next_ty_id) = next_type(field_ty)? { + self.type_map.derive_parent(&next_ty_id, &t); dependent_types.push(next_ty_id); } let field_name = if let Some(name) = member.name { diff --git a/libbpf-cargo/src/test.rs b/libbpf-cargo/src/test.rs index cc249314..f678d4c2 100644 --- a/libbpf-cargo/src/test.rs +++ b/libbpf-cargo/src/test.rs @@ -2514,24 +2514,24 @@ struct Foo foo; #[repr(C)] pub struct Foo { pub x: i32, - pub bar: __anon_1, + pub bar: __anon_Foo_1, pub __pad_36: [u8; 4], - pub baz: __anon_2, + pub baz: __anon_Foo_2, pub w: i32, pub __pad_52: [u8; 4], } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_1 { +pub union __anon_Foo_1 { pub y: [u8; 10], pub z: [u16; 16], } -impl std::fmt::Debug for __anon_1 { +impl std::fmt::Debug for __anon_Foo_1 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_1 { +impl Default for __anon_Foo_1 { fn default() -> Self { Self { y: [u8::default(); 10], @@ -2540,16 +2540,16 @@ impl Default for __anon_1 { } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_2 { +pub union __anon_Foo_2 { pub w: u32, pub u: *mut u64, } -impl std::fmt::Debug for __anon_2 { +impl std::fmt::Debug for __anon_Foo_2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_2 { +impl Default for __anon_Foo_2 { fn default() -> Self { Self { w: u32::default(), @@ -2594,25 +2594,25 @@ struct Foo foo; #[repr(C)] pub struct Foo { pub x: i32, - pub bar: __anon_1, - pub baz: __anon_2, + pub bar: __anon_Foo_1, + pub baz: __anon_Foo_2, pub w: i32, pub __pad_68: [u8; 4], } #[derive(Debug, Default, Copy, Clone)] #[repr(C)] -pub struct __anon_1 { +pub struct __anon_Foo_1 { pub y: [u8; 10], pub z: [u16; 16], } #[derive(Debug, Copy, Clone)] #[repr(C)] -pub struct __anon_2 { +pub struct __anon_Foo_2 { pub w: u32, pub __pad_4: [u8; 4], pub u: *mut u64, } -impl Default for __anon_2 { +impl Default for __anon_Foo_2 { fn default() -> Self { Self { w: u32::default(), @@ -2667,31 +2667,31 @@ struct Foo foo; #[repr(C)] pub struct Foo { pub x: i32, - pub bar: __anon_1, - pub zerg: __anon_2, - pub baz: __anon_3, + pub bar: __anon_Foo_1, + pub zerg: __anon_Foo_2, + pub baz: __anon_Foo_3, pub w: i32, pub __pad_76: [u8; 4], - pub flarg: __anon_4, + pub flarg: __anon_Foo_4, } #[derive(Debug, Default, Copy, Clone)] #[repr(C)] -pub struct __anon_1 { +pub struct __anon_Foo_1 { pub y: [u8; 10], pub z: [u16; 16], } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_2 { +pub union __anon_Foo_2 { pub a: *mut i8, pub b: i32, } -impl std::fmt::Debug for __anon_2 { +impl std::fmt::Debug for __anon_Foo_2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_2 { +impl Default for __anon_Foo_2 { fn default() -> Self { Self { a: std::ptr::null_mut(), @@ -2700,12 +2700,12 @@ impl Default for __anon_2 { } #[derive(Debug, Copy, Clone)] #[repr(C)] -pub struct __anon_3 { +pub struct __anon_Foo_3 { pub w: u32, pub __pad_4: [u8; 4], pub u: *mut u64, } -impl Default for __anon_3 { +impl Default for __anon_Foo_3 { fn default() -> Self { Self { w: u32::default(), @@ -2716,16 +2716,16 @@ impl Default for __anon_3 { } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_4 { +pub union __anon_Foo_4 { pub c: u8, pub d: [u64; 5], } -impl std::fmt::Debug for __anon_4 { +impl std::fmt::Debug for __anon_Foo_4 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_4 { +impl Default for __anon_Foo_4 { fn default() -> Self { Self { c: u8::default(), @@ -2763,20 +2763,20 @@ struct Foo foo = {{0}}; #[derive(Debug, Default, Copy, Clone)] #[repr(C)] pub struct Foo { - pub __anon_1: __anon_1, + pub __anon_Foo_1: __anon_Foo_1, } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_1 { +pub union __anon_Foo_1 { pub name: *mut i8, pub tp: *mut std::ffi::c_void, } -impl std::fmt::Debug for __anon_1 { +impl std::fmt::Debug for __anon_Foo_1 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_1 { +impl Default for __anon_Foo_1 { fn default() -> Self { Self { name: std::ptr::null_mut(), @@ -2792,6 +2792,134 @@ impl Default for __anon_1 { assert_definition(&btf, &struct_foo, expected_output); } +#[test] +fn test_btf_dump_anon_member_tree() { + let prog_text = r#" +#include "vmlinux.h" +#include + +struct Foo { + union { + struct { + char *name; + void *tp; + }; + struct Bar { + union { + struct { + char *name; + void *trp; + }; + struct Baz { + char *name; + void *trp; + } baz; + }; + } bar; + }; +}; + +struct Foo foo = {0}; +"#; + + let expected_output = r#" +#[derive(Debug, Default, Copy, Clone)] +#[repr(C)] +pub struct Foo { + pub __anon_Foo_1: __anon_Foo_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union __anon_Foo_1 { + pub __anon_Foo_2: __anon_Foo_2, + pub bar: Bar, +} +impl std::fmt::Debug for __anon_Foo_1 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(???)") + } +} +impl Default for __anon_Foo_1 { + fn default() -> Self { + Self { + __anon_Foo_2: __anon_Foo_2::default(), + } + } +} +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct __anon_Foo_2 { + pub name: *mut i8, + pub tp: *mut std::ffi::c_void, +} +impl Default for __anon_Foo_2 { + fn default() -> Self { + Self { + name: std::ptr::null_mut(), + tp: std::ptr::null_mut(), + } + } +} +#[derive(Debug, Default, Copy, Clone)] +#[repr(C)] +pub struct Bar { + pub __anon_Bar_1: __anon_Bar_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union __anon_Bar_1 { + pub __anon_Bar_2: __anon_Bar_2, + pub baz: Baz, +} +impl std::fmt::Debug for __anon_Bar_1 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(???)") + } +} +impl Default for __anon_Bar_1 { + fn default() -> Self { + Self { + __anon_Bar_2: __anon_Bar_2::default(), + } + } +} +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct __anon_Bar_2 { + pub name: *mut i8, + pub trp: *mut std::ffi::c_void, +} +impl Default for __anon_Bar_2 { + fn default() -> Self { + Self { + name: std::ptr::null_mut(), + trp: std::ptr::null_mut(), + } + } +} +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct Baz { + pub name: *mut i8, + pub trp: *mut std::ffi::c_void, +} +impl Default for Baz { + fn default() -> Self { + Self { + name: std::ptr::null_mut(), + trp: std::ptr::null_mut(), + } + } +} +"#; + + let mmap = build_btf_mmap(prog_text); + let btf = btf_from_mmap(&mmap); + let struct_foo = find_type_in_btf!(btf, types::Struct<'_>, "Foo"); + + assert_definition(&btf, &struct_foo, expected_output); +} + #[test] fn test_btf_dump_definition_anon_enum() { let prog_text = r#" @@ -2811,17 +2939,17 @@ struct Foo foo; #[derive(Debug, Default, Copy, Clone)] #[repr(C)] pub struct Foo { - pub test: __anon_1, + pub test: __anon_Foo_1, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[repr(transparent)] -pub struct __anon_1(pub u32); +pub struct __anon_Foo_1(pub u32); #[allow(non_upper_case_globals)] -impl __anon_1 { - pub const FOO: __anon_1 = __anon_1(1); +impl __anon_Foo_1 { + pub const FOO: __anon_Foo_1 = __anon_Foo_1(1); } -impl Default for __anon_1 { - fn default() -> Self { __anon_1::FOO } +impl Default for __anon_Foo_1 { + fn default() -> Self { __anon_Foo_1::FOO } } "#; @@ -2918,40 +3046,40 @@ struct bpf_sock_tuple_5_15 tup; #[derive(Debug, Default, Copy, Clone)] #[repr(C)] pub struct bpf_sock_tuple_5_15 { - pub __anon_1: __anon_1, + pub __anon_bpf_sock_tuple_5_15_1: __anon_bpf_sock_tuple_5_15_1, pub __pad_36: [u8; 4], - pub __anon_2: __anon_2, + pub __anon_bpf_sock_tuple_5_15_2: __anon_bpf_sock_tuple_5_15_2, } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_1 { - pub ipv4: __anon_3, - pub ipv6: __anon_4, +pub union __anon_bpf_sock_tuple_5_15_1 { + pub ipv4: __anon_bpf_sock_tuple_5_15_3, + pub ipv6: __anon_bpf_sock_tuple_5_15_4, } -impl std::fmt::Debug for __anon_1 { +impl std::fmt::Debug for __anon_bpf_sock_tuple_5_15_1 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_1 { +impl Default for __anon_bpf_sock_tuple_5_15_1 { fn default() -> Self { Self { - ipv4: __anon_3::default(), + ipv4: __anon_bpf_sock_tuple_5_15_3::default(), } } } #[derive(Copy, Clone)] #[repr(C)] -pub union __anon_2 { +pub union __anon_bpf_sock_tuple_5_15_2 { pub a: i32, pub b: *mut i8, } -impl std::fmt::Debug for __anon_2 { +impl std::fmt::Debug for __anon_bpf_sock_tuple_5_15_2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(???)") } } -impl Default for __anon_2 { +impl Default for __anon_bpf_sock_tuple_5_15_2 { fn default() -> Self { Self { a: i32::default(), @@ -2960,7 +3088,7 @@ impl Default for __anon_2 { } #[derive(Debug, Default, Copy, Clone)] #[repr(C)] -pub struct __anon_3 { +pub struct __anon_bpf_sock_tuple_5_15_3 { pub saddr: u32, pub daddr: u32, pub sport: u16, @@ -2968,7 +3096,7 @@ pub struct __anon_3 { } #[derive(Debug, Default, Copy, Clone)] #[repr(C)] -pub struct __anon_4 { +pub struct __anon_bpf_sock_tuple_5_15_4 { pub saddr: [u32; 4], pub daddr: [u32; 4], pub sport: u16,