On 5/25/22 2:53 AM, Matteo Nardi wrote:
This program will compile and run fine on my 64 bit system, but it will fail with a relocation error on 32 bit systems: SEC("tp/raw_syscalls/sys_enter") int sys_enter(struct trace_event_raw_sys_enter *ctx) { long int n = ctx->id; bpf_printk("hello world %d", n); return 0; } ``` libbpf: prog 'sys_enter': relo #0: insn #0 (LDX/ST/STX) accesses field incorrectly. Make sure you are accessing pointers, unsigned integers, or fields of matching type and size. libbpf: prog 'sys_enter': BPF program load failed: Invalid argument libbpf: prog 'sys_enter': -- BEGIN PROG LOAD LOG -- R1 type=ctx expected=fp ; long int n = ctx->id; 0: (85) call unknown#195896080 invalid func unknown#195896080 processed 1 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0 -- END PROG LOAD LOG -- libbpf: failed to load program 'sys_enter' libbpf: failed to load object 'bootstrap_bpf' libbpf: failed to load BPF skeleton 'bootstrap_bpf': -22 Failed to load and verify BPF skeleton ``` I'm cross-compiling using a Yocto build. I've reproduced this both with arm and x86. From my understanding, the issue comes from the `long int` in `trace_event_raw_sys_enter`, which is 64 bit in the compiled eBPF program, but 32 bit in the target kernel. struct trace_event_raw_sys_enter { struct trace_entry ent; long int id; long unsigned int args[6]; char __data[0]; } __attribute__((preserve_access_index)); Indeed, manually changing the `id` definition in `vmlinux.h` will fix the relocation error: struct trace_event_raw_sys_enter { u32 id; } __attribute__((preserve_access_index));
Right, for such cases, the bpf view of trace_event_raw_sys_enter will have a different view from the kernel due to different interpretation of 'long' type size. In the above case, you don't need to change vmlinux.h, you can define something like /* you can change "___correct" to anything "___<your name>" */ struct trace_event_raw_sys_enter___correct { u32 id; } __attribute__((preserve_access_index)); And use trace_event_raw_sys_enter___correct in your program and it should be okay.
"Q: clang flag for target bpf?"[0] hints that using a native target could help, but I guess that would completely break CORE relocations since `preserve_access_index` is a `-target bpf`-specific attribute, right?
The "-target bpf" approach is to compile bpf program .c file with "-target bpf" flag. The non-native mode is to first compile with from ".c"=>".ll" (from .c file to intermediate file with native target like x86) and then compile with -target bpf from .ll file to .o file. Typically use non-native mode, you directly use kernel headers and don't use vmlinux.h and CO-RE, which is discouraged for portability reasons. So in your case, use trace_event_raw_sys_enter___correct is the best approach.
Am I missing something? If I had to fix the issue right now I would replace all long definitions in `vmlinux.h` to u32 when targeting 32 bit systems. Could `bpftool btf dump` handle this? We're using eBPF on embedded systems, where 32 bit is still fairly common. Thanks. Best regards, Matteo Nardi [0] https://www.kernel.org/doc/html/latest/bpf/bpf_devel_QA.html#q-clang-flag-for-target-bpf