eBPF全局结构体声明加载失败咨询:是否违反eBPF规范?
Great question—this is a super common gotcha when working with older LLVM versions and eBPF, so let’s break this down clearly.
First: Why the Global Struct Causes a Load Failure
The kernel’s eBPF verifier enforces strict rules about what data can be loaded into the kernel. When you declare a struct like struct my_foo global_foo; in the global scope, LLVM 5.0 will place it into an ELF section (your Section 6, likely .data or a custom section).
Here’s the problem: the verifier blocks uninitialized or writable global data by default unless it fits specific criteria:
- It’s read-only (stored in
.rodata), or - It’s an eBPF map (the official way to share state between user/kernel space), or
- It’s a simple constant type (like a const integer).
When you move the struct inside main() (your eBPF program’s entry point), it gets allocated on the stack instead. The verifier allows stack-allocated data (as long as you don’t exceed stack size limits), so the load succeeds.
Is Global Declaration Always Against eBPF Rules?
Nope—but it’s heavily constrained, especially with older toolchains like LLVM 5.0. Newer LLVM versions (10+) and kernel releases have better support for global variables, but LLVM 5.0’s eBPF implementation is pretty limited.
Fixes for Your Scenario
You’ve already found one working fix (moving the struct to the function), but here are other options depending on your needs:
Mark the global struct as
const
If your struct is read-only (e.g., static configuration), addingconsttells LLVM to put it in.rodata, which the verifier usually accepts:const struct my_foo global_foo = { .field_a = 42, .field_b = "hello" };Use an eBPF Map for Writable State
If you need to modify the struct’s data or share it between eBPF programs/user space, maps are the standard eBPF way to do this. Define a map like:struct bpf_map_def SEC("maps") my_foo_map = { .type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(int), .value_size = sizeof(struct my_foo), .max_entries = 1, // Adjust based on your needs };Then access it in your code with helpers like
bpf_map_lookup_elem.Upgrade Your LLVM Version
LLVM 5.0 is quite old (released in 2017). Newer versions have improved eBPF support, including better handling of global variables that fit verifier rules. Upgrading to LLVM 10+ might resolve the issue without changing your code.Verify the ELF Section Type
You mentioned usingllvm-objdumpto inspect Section 6. Double-check its type withllvm-readelf -S your_program.o:- If it’s
.data(writable), the verifier will reject it. - If it’s
.rodata(read-only), it should pass (assuming the struct’s contents are verifier-safe).
- If it’s
内容的提问来源于stack exchange,提问作者Mark

