Skip to content

Commit 3a9e1d5

Browse files
committed
libbpf-cargo: Relative anonymous type naming for struct fields
Previously, anonymous types were named as __anon_{id} with id as a global counter. This approach caused cascading renaming of all subsequent anonymous definitions after any C anonymous struct order/amount change. This was a major design problem not for only development but even portability, since here may be the case when something was changed in vmlinux.h leading to compilation errors. This commit addresses the issue by localizing cascading effects to the local struct layer rather than the global layer. While the solution is not fully ideal - cascading still occurs within individual structs - it eliminates the need for wide Rust code modifications when the order of anonymous struct definitions changes. Note, that the commit does not fully eliminates __anon_{id}, but the most important part of it. The commit is breaking and should be included in major version update.
1 parent ee1e39f commit 3a9e1d5

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

libbpf-cargo/src/gen/btf.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::fmt::Write;
1010
use std::mem::size_of;
1111
use std::num::NonZeroUsize;
1212
use std::ops::Deref;
13+
use std::rc::Rc;
1314

1415
use anyhow::anyhow;
1516
use anyhow::bail;
@@ -367,6 +368,13 @@ fn escape_reserved_keyword(identifier: Cow<'_, str>) -> Cow<'_, str> {
367368
}
368369
}
369370

371+
#[derive(Debug, Clone)]
372+
pub struct BtfDependency {
373+
pub name: Option<String>,
374+
pub dep_id: i32,
375+
pub child_counter: Rc<RefCell<i32>>,
376+
}
377+
370378
#[derive(Debug, Default)]
371379
pub(crate) struct TypeMap {
372380
/// A mapping from type to number, allowing us to assign numbers to
@@ -377,15 +385,70 @@ pub(crate) struct TypeMap {
377385
/// Mapping from type name to the number of times we have seen this
378386
/// name already.
379387
names_count: RefCell<HashMap<String, u8>>,
388+
389+
dependencies: RefCell<HashMap<TypeId, BtfDependency>>,
380390
}
381391

382392
impl TypeMap {
393+
pub fn derive_parent<'s>(&self, ty: &BtfType<'s>, parent: &BtfType<'s>) {
394+
let mut deps = self.dependencies.borrow_mut();
395+
if deps.get(&ty.type_id()).is_some() {
396+
return;
397+
}
398+
399+
let parent_dep = deps.get(&parent.type_id());
400+
if let Some(pdep) = parent_dep {
401+
let mut dep = pdep.clone();
402+
403+
if let Some(n) = parent.name() {
404+
dep.name = Some(n.to_string_lossy().to_string());
405+
}
406+
if ty.name().is_some() {
407+
dep.child_counter = Rc::new(RefCell::new(0));
408+
}
409+
410+
let parent_counter = Rc::<RefCell<i32>>::clone(&pdep.child_counter);
411+
*parent_counter.borrow_mut() += 1;
412+
dep.dep_id = *parent_counter.borrow();
413+
414+
deps.insert(ty.type_id(), dep);
415+
} else {
416+
let mut dep = BtfDependency {
417+
name: None,
418+
dep_id: 0,
419+
child_counter: Rc::new(RefCell::new(1)),
420+
};
421+
deps.insert(parent.type_id(), dep.clone());
422+
423+
if let Some(n) = parent.name() {
424+
dep.name = Some(n.to_string_lossy().to_string());
425+
}
426+
if ty.name().is_some() {
427+
dep.child_counter = Rc::new(RefCell::new(0));
428+
}
429+
dep.dep_id = 1;
430+
deps.insert(ty.type_id(), dep);
431+
}
432+
}
433+
434+
pub fn lookup_parent<'s>(&self, ty: &BtfType<'s>) -> Option<BtfDependency> {
435+
self.dependencies.borrow().get(&ty.type_id()).cloned()
436+
}
437+
383438
pub fn type_name_or_anon<'s>(&self, ty: &BtfType<'s>) -> Cow<'s, str> {
384439
match ty.name() {
385440
None => {
386441
let mut anon_table = self.types.borrow_mut();
387442
let len = anon_table.len() + 1; // use 1 index anon ids for backwards compat
388443
let anon_id = anon_table.entry(ty.type_id()).or_insert(len);
444+
445+
if let Some(parent) = self.lookup_parent(ty) {
446+
if let Some(name) = parent.name {
447+
if !name.is_empty() {
448+
return format!("{ANON_PREFIX}{}_{}", name, parent.dep_id).into();
449+
}
450+
}
451+
}
389452
format!("{ANON_PREFIX}{anon_id}").into()
390453
}
391454
Some(n) => match self.names.borrow_mut().entry(ty.type_id()) {
@@ -726,6 +789,7 @@ impl<'s> GenBtf<'s> {
726789
}
727790

728791
if let Some(next_ty_id) = next_type(field_ty)? {
792+
self.type_map.derive_parent(&next_ty_id, &t);
729793
dependent_types.push(next_ty_id);
730794
}
731795
let field_name = if let Some(name) = member.name {

0 commit comments

Comments
 (0)