Skip to content

Commit

Permalink
Fix handling of function prototype type declaration inference in BTF
Browse files Browse the repository at this point in the history
We currently do not handle type declaration querying for function
prototypes correctly in our BTF logic. That can lead to errors during
skeleton generation.
With this change we treat them similar to how we treat functions
themselves (which can only occur in the form of pointers).

Signed-off-by: Daniel Müller <[email protected]>
  • Loading branch information
d-e-s-o committed Jul 28, 2023
1 parent 01bf4f2 commit 41dd7fd
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 6 deletions.
2 changes: 2 additions & 0 deletions libbpf-cargo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased
----------
- Added `Default` impl for generated `struct` types containing pointers
- Fixed handling of function prototypes type declaration inference in BTF and
skeleton generation
- Improved error reporting in build script usage
- Bumped minimum Rust version to `1.64`

Expand Down
12 changes: 6 additions & 6 deletions libbpf-cargo/src/gen/btf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ impl<'s> GenBtf<'s> {
}
BtfKind::Struct | BtfKind::Union | BtfKind::Enum | BtfKind::Enum64 =>
self.get_type_name_handling_anon_types(&ty).into_owned(),
// // The only way a variable references a function is through a function pointer.
// // Return c_void here so the final def will look like `*mut c_void`.
// //
// // It's not like rust code can call a function inside a bpf prog either so we don't
// // really need a full definition. `void *` is totally sufficient for sharing a pointer.
BtfKind::Func => "std::ffi::c_void".to_string(),
// The only way a variable references a function is through a function pointer.
// Return c_void here so the final def will look like `*mut c_void`.
//
// It's not like rust code can call a function inside a bpf prog either so we don't
// really need a full definition. `void *` is totally sufficient for sharing a pointer.
BtfKind::Func | BtfKind::FuncProto => "std::ffi::c_void".to_string(),
BtfKind::Var(t) => self.type_declaration(t.referenced_type())?,
_ => bail!("Invalid type: {ty:?}"),
});
Expand Down
40 changes: 40 additions & 0 deletions libbpf-cargo/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,46 @@ pub struct Bar {
assert_definition(&btf, &struct_foo, expected_output);
}

#[test]
fn test_btf_dump_struct_definition_func_proto() {
let prog_text = r#"
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
struct with_func_proto {
struct with_func_proto *next;
void (*func)(struct with_func_proto *);
};
struct with_func_proto w;
"#;

let expected_output = r#"
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct with_func_proto {
pub next: *mut with_func_proto,
pub func: *mut std::ffi::c_void,
}
impl Default for with_func_proto {
fn default() -> Self {
with_func_proto {
next: std::ptr::null_mut(),
func: std::ptr::null_mut(),
}
}
}
"#;

let mmap = build_btf_mmap(prog_text);
let btf = btf_from_mmap(&mmap);

// Find our struct
let struct_foo = find_type_in_btf!(btf, types::Struct<'_>, "with_func_proto");

assert_definition(&btf, &struct_foo, expected_output);
}

#[test]
fn test_btf_dump_struct_definition_long_array() {
let prog_text = r#"
Expand Down

0 comments on commit 41dd7fd

Please sign in to comment.