Generate debug info for BPF extern declarations - #161390
Conversation
|
Some changes occurred in compiler/rustc_attr_parsing |
|
|
|
Thanks for the pull request, and welcome! The Rust Project has assigned @jdonszelmann (or someone else) to review your changes, you should hear from them (or someone else) within the next two weeks. Please see the contribution instructions for more information. |
|
@vadorovsky @tohojo @Gbell26 ^^ FYI |
This comment has been minimized.
This comment has been minimized.
| Allow(Target::ForeignStatic), | ||
| Allow(Target::ForeignFn), |
There was a problem hiding this comment.
This should probably be gated to ebpf.
There was a problem hiding this comment.
Thanks! I've added a target gate in LinkSectionParser::convert() that rejects #[link_section] on ForeignStatic and ForeignFn when the target arch is not BPF following the same pattern as the import_name_type x86 gate a few lines above, let me know if you'd like me to follow a different approach!
08d2375 to
17704ab
Compare
Investigate feasibility of using open-coded iterators from Aya to walk BPF program bytecode at load time (issue #19). Pin all Aya crates to git main (commit 70e1983) which includes kfunc relocation support from aya-rs/aya#1372. Add BpfInsn struct and instruction constants to bpf-rbacd-common. Declare the bpf_iter_num_{new,next,destroy} kfuncs as extern functions and implement walk_bpf_instructions() in the bpf_prog_load LSM hook. The code compiles and produces correct ELF relocations and BTF sections. End-to-end kfunc loading is blocked on rustc not emitting DWARF for extern declarations on BPF targets. Without that, bpf-linker cannot generate the .ksyms BTF DATASEC that Aya needs to resolve kfuncs. A compiler fix is in review at rust-lang/rust#161390. See docs/OPEN_CODED_ITERATORS.md for the full feasibility report and workarounds (bounded loops, bpf_loop). Signed-off-by: Daniel Mellado <dmellado@fedoraproject.org>
This comment has been minimized.
This comment has been minimized.
17704ab to
cc0f67c
Compare
Enable ksyms/kfunc support for BPF programs by emitting debug info metadata for extern statics and functions on BPF targets. - Allow #[link_section] on ForeignStatic and ForeignFn targets - Add LLVMRustDIBuilderCreateGlobalVariableExpression C++ wrapper to expose the isDefinition parameter (the LLVM-C API hard-codes it to true) - Emit DIGlobalVariable with isDefinition: false for extern statics and DISubprogram without SPFlagDefinition for extern functions, gated to Arch::Bpf - Refactor build_global_var_di_node into a shared inner function to avoid duplicating the static variable debug info logic The BTF entries generated from this metadata are required by the kernel verifier to resolve ksyms and kfuncs at BPF program load time. Co-authored-by: Altug Bozkurt <altugbozkurt09@gmail.com>
cc0f67c to
19fd8d5
Compare
| let function_type_metadata = create_subroutine_type(self, &signature); | ||
|
|
||
| let mut name = String::with_capacity(64); | ||
| type_names::push_item_name(tcx, def_id, false, &mut name); |
There was a problem hiding this comment.
Quoted LLM-generated analysis (Codex):
For
#[link_name = "bpf_task_acquire"] fn acquire(...), the new metadata names the functionacquire, while the LLVM symbol isbpf_task_acquire.LLVM's BTF generator uses
SP->getName()and ignoreslinkageName. Libbpf matches the BTF name against the ELF symbol, so it cannot resolve this extern.
| if self.tcx.is_foreign_item(def_id) { | ||
| base::set_link_section(g, fn_attrs); | ||
| if self.tcx.sess.target.arch == Arch::Bpf { | ||
| debuginfo::build_extern_static_di_node(self, def_id, g); |
There was a problem hiding this comment.
Quoted LLM-generated analysis (Codex):
With
#[linkage = "extern_weak"],check_and_apply_linkagereturns Rust's synthetic internal pointer global, not the external symbol. This block therefore attaches.ksymsand debug metadata to the wrapper, leaving the actual weak symbol without matching BTF.LLVM skips the external global without metadata and classifies the initialized internal wrapper as
VAR_STATIC, regardless ofDIGlobalVariable.isDefinition. Nullable weak function imports have the same problem: their native declaration is an LLVM function, but only the pointer wrapper receives global-variable metadata.
| cx.assume_dso_local(llfn, true); | ||
|
|
||
| if tcx.is_foreign_item(instance_def_id) { | ||
| base::set_link_section(llfn, tcx.codegen_fn_attrs(instance_def_id)); |
There was a problem hiding this comment.
Quoted LLM-generated analysis (Codex):
If two compatible extern declarations name the same function, and the unannotated declaration is referenced before the declaration carrying
#[link_section = ".ksyms"],get_declared_value(sym)reuses the first LLVM symbol and skips this block for the second declaration.The section attribute consequently depends on reference order. LLVM only adds the external function's DATASEC entry when the function has a section, so the annotated declaration can still produce a function without its required
.ksymsentry.
| @@ -0,0 +1,35 @@ | |||
| // Checks that BPF extern declarations are emitted as debug info declarations. | |||
| // | |||
| //@ only-bpf | |||
There was a problem hiding this comment.
Quoted LLM-generated analysis (Codex):
only-bpfis evaluated against compiletest's suite target, not this test's--targetflag. Normal x86_64/aarch64 CI therefore skips this test andlink-section-foreign.rs.Removing the filter alone is insufficient: these fixtures require BPF
core, which the host-target suite does not build. The existingbpf-alu32.rsusesadd-minicore/no_corewith a target override instead.
|
|
||
| extern "C" { | ||
| // CHECK: @EXTERN_STATIC = external {{.*}}global i32 | ||
| // CHECK-NOT: !DIGlobalVariable(name: "EXTERN_STATIC" |
There was a problem hiding this comment.
Quoted LLM-generated analysis (Codex):
This
CHECK-NOTonly searches between the static declaration and the next positive check, theextern_fndeclaration. LLVM prints theDIGlobalVariablemetadata after the functions, outside that interval.Consequently, removing the BPF gate around extern-static debug-info emission would still pass this check; it does not cover the regression it intends to catch.
Reworked version of #152899, rebased on current main with review feedback addressed.
Emit debug info metadata for extern statics and functions on BPF targets so that LLVM can generate BTF entries for ksym/kfunc resolution at load time.
#[link_section]onForeignStaticandForeignFnLLVMRustDIBuilderCreateGlobalVariableExpressionwrapper exposingisDefinitionDIGlobalVariable(isDefinition: false) andDISubprogram(no SPFlagDefinition) for BPF externsCo-authored-by: Altug Bozkurt altugbozkurt09@gmail.com
r? @jdonszelmann