Skip to content

Commit e956876

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 e956876

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

libbpf-cargo/src/gen/btf.rs

Lines changed: 68 additions & 1 deletion
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,16 +385,74 @@ 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 let Some(_) = deps.get(&ty.type_id()) {
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 let Some(_) = ty.name() {
407+
dep.child_counter = Rc::new(RefCell::new(0));
408+
}
409+
410+
let parent_counter = pdep.child_counter.clone();
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 let Some(_) = ty.name() {
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
436+
.borrow()
437+
.get(&ty.type_id())
438+
.map(|x| x.clone())
439+
}
440+
383441
pub fn type_name_or_anon<'s>(&self, ty: &BtfType<'s>) -> Cow<'s, str> {
384442
match ty.name() {
385443
None => {
386444
let mut anon_table = self.types.borrow_mut();
387445
let len = anon_table.len() + 1; // use 1 index anon ids for backwards compat
388446
let anon_id = anon_table.entry(ty.type_id()).or_insert(len);
389-
format!("{ANON_PREFIX}{anon_id}").into()
447+
448+
if let Some(parent) = self.lookup_parent(ty) {
449+
if let Some(name) = parent.name {
450+
if name.len() != 0 {
451+
return format!("{ANON_PREFIX}{}_{}", name, parent.dep_id).into();
452+
}
453+
}
454+
}
455+
return format!("{ANON_PREFIX}{anon_id}").into();
390456
}
391457
Some(n) => match self.names.borrow_mut().entry(ty.type_id()) {
392458
Entry::Occupied(entry) => Cow::Owned(entry.get().clone()),
@@ -726,6 +792,7 @@ impl<'s> GenBtf<'s> {
726792
}
727793

728794
if let Some(next_ty_id) = next_type(field_ty)? {
795+
self.type_map.derive_parent(&next_ty_id, &t);
729796
dependent_types.push(next_ty_id);
730797
}
731798
let field_name = if let Some(name) = member.name {

0 commit comments

Comments
 (0)