pull/1382/merge
Michal R 2 days ago committed by GitHub
commit c5591c236c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -77,6 +77,7 @@ dialoguer = { version = "0.12", default-features = false }
diff = { version = "0.1.13", default-features = false }
env_logger = { version = "0.11", default-features = false }
epoll = { version = "4.3.3", default-features = false }
foldhash = { version = "0.2", default-features = false }
futures = { version = "0.3.28", default-features = false }
glob = { version = "0.3.0", default-features = false }
hashbrown = { version = "0.16.0", default-features = false }

@ -18,6 +18,10 @@ workspace = true
[dependencies]
bytes = { workspace = true }
# hashbrown uses foldhash for its `DefaultHasher` implementation. However,
# hashbrown doesn't expose any API allowing to create hashers with fixed seed,
# so we need to use `foldhash::FixedState` directly.
foldhash = { workspace = true }
hashbrown = { workspace = true, features = ["default-hasher", "equivalent"] }
log = { workspace = true }
object = { workspace = true, features = ["elf", "read_core"] }

@ -8,10 +8,13 @@ use alloc::{
use core::{
cell::OnceCell,
ffi::{CStr, FromBytesUntilNulError},
fmt::Write as _,
hash::{BuildHasher as _, Hasher as _},
mem, ptr,
};
use bytes::BufMut as _;
use foldhash::fast::FixedState;
use log::debug;
use object::{Endianness, SectionIndex};
@ -275,6 +278,42 @@ fn add_type(header: &mut btf_header, types: &mut BtfTypes, btf_type: BtfType) ->
type_id as u32
}
/// [The maximum length of a symbol accepted by the Linux kernel][name-limit]
/// according to the [`KSYM_NAME_LEN` constant][ksym-name-len]. That limit got
/// increased in [kernel 6.1][ksym-name-len-bump], but we keep the old value
/// for backwards compatibility.
///
/// [name-limit]: https://github.com/torvalds/linux/blob/v4.20/kernel/bpf/btf.c#L442-L449
/// [ksym-name-len]: https://github.com/torvalds/linux/blob/v4.20/include/linux/kallsyms.h#L17
/// [ksym-name-len-bump]: https://github.com/torvalds/linux/commit/b8a94bfb33952bb17fbc65f8903d242a721c533d
const MAX_NAME_LEN: usize = 128;
// Sanitize Rust type names to be valid C type names. Kernel does not accept
// other characters like `<`, `>` that Rust emits.
fn sanitize_type_name(name: &str) -> String {
let mut sanitized = String::with_capacity(name.len());
for byte in name.bytes() {
// Characters which are valid in C type names (alphanumeric and `_`).
if matches!(byte, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'_') {
sanitized.push(byte as char);
} else {
write!(&mut sanitized, "_{:X}_", byte).unwrap();
}
}
if sanitized.len() > MAX_NAME_LEN {
let mut hasher = FixedState::default().build_hasher();
hasher.write(sanitized.as_bytes());
let hash = hasher.finish();
// leave space for underscore
let trim = MAX_NAME_LEN - 2 * size_of_val(&hash) - 1;
sanitized.truncate(trim);
write!(&mut sanitized, "_{:x}", hash).unwrap();
}
sanitized
}
impl Btf {
/// Creates a new empty instance with its header initialized
pub fn new() -> Self {
@ -695,8 +734,16 @@ impl Btf {
}
// Sanitize FUNC.
BtfType::Func(ty) => {
// Sanitize the name.
let name = self.string_at(ty.name_offset)?;
// Sanitize FUNC.
let fixed_name = sanitize_type_name(&name);
let name = if fixed_name != name {
ty.name_offset = self.add_string(&fixed_name);
fixed_name.into()
} else {
name
};
// Adjust type and linkage according to features.
if !features.btf_func {
debug!("{kind}: not supported. replacing with TYPEDEF");
*t = BtfType::Typedef(Typedef::new(ty.name_offset, ty.btf_type));
@ -805,6 +852,15 @@ impl Btf {
*t = BtfType::Union(Union::new(name_offset, size, members, Some(fallback)));
}
}
// Sanitize STRUCT.
BtfType::Struct(ty) => {
// Sanitize the name.
let name = self.string_at(ty.name_offset)?;
let fixed_name = sanitize_type_name(&name);
if fixed_name != name {
ty.name_offset = self.add_string(&fixed_name);
}
}
// The type does not need fixing up or sanitization.
_ => {}
}
@ -1417,6 +1473,57 @@ mod tests {
assert_eq!(btf.string_at(5).unwrap(), "widget");
}
#[test]
fn test_sanitize_type_name() {
let name = "MyStruct<u64>";
assert_eq!(sanitize_type_name(name), "MyStruct_3C_u64_3E_");
let name = "MyStruct<u64, u64>";
assert_eq!(sanitize_type_name(name), "MyStruct_3C_u64_2C__20_u64_3E_");
let name = "my_function<aya_bpf::BpfContext>";
assert_eq!(
sanitize_type_name(name),
"my_function_3C_aya_bpf_3A__3A_BpfContext_3E_"
);
let name = "my_function<aya_bpf::BpfContext, aya_log_ebpf::WriteToBuf>";
assert_eq!(
sanitize_type_name(name),
"my_function_3C_aya_bpf_3A__3A_BpfContext_2C__20_aya_log_ebpf_3A__3A_WriteToBuf_3E_"
);
let name = "PerfEventArray<[u8; 32]>";
assert_eq!(
sanitize_type_name(name),
"PerfEventArray_3C__5B_u8_3B__20_32_5D__3E_"
);
let name = "my_function<aya_bpf::this::is::a::very::long::namespace::BpfContext, aya_log_ebpf::this::is::a::very::long::namespace::WriteToBuf>";
let san = sanitize_type_name(name);
#[cfg(any(
target_arch = "aarch64",
target_arch = "loongarch64",
target_arch = "powerpc64",
target_arch = "riscv64",
target_arch = "x86_64"
))]
let expected_hash = "f6a9dc7f4a53c91d";
#[cfg(target_arch = "arm")]
let expected_hash = "e203c1e6145df4dd";
#[cfg(target_arch = "s390x")]
let expected_hash = "6609fba3a8753dce";
assert_eq!(san.len(), 128);
assert_eq!(
san,
format!(
"my_function_3C_aya_bpf_3A__3A_this_3A__3A_is_3A__3A_a_3A__3A_very_3A__3A_long_3A__3A_namespace_3A__3A_BpfContex_{expected_hash}"
)
);
}
#[test]
fn test_fixup_ptr() {
let mut btf = Btf::new();

@ -1,22 +1,9 @@
use core::marker::PhantomData;
pub mod array;
pub mod sk_storage;
pub use array::Array;
pub use sk_storage::SkStorage;
/// A marker used to remove names of annotated types in LLVM debug info and
/// therefore also in BTF.
#[repr(transparent)]
pub(crate) struct AyaBtfMapMarker(PhantomData<()>);
impl AyaBtfMapMarker {
pub(crate) const fn new() -> Self {
Self(PhantomData)
}
}
#[macro_export]
macro_rules! btf_map_def {
($name:ident, $t:ident) => {
@ -30,9 +17,6 @@ macro_rules! btf_map_def {
value: *const V,
max_entries: *const [i32; M],
map_flags: *const [i32; F],
// Anonymize the struct.
_anon: $crate::btf_maps::AyaBtfMapMarker,
}
#[expect(
@ -47,7 +31,6 @@ macro_rules! btf_map_def {
value: ::core::ptr::null(),
max_entries: ::core::ptr::null(),
map_flags: ::core::ptr::null(),
_anon: $crate::btf_maps::AyaBtfMapMarker::new(),
}
}
}

Loading…
Cancel
Save