Re: Relocation error on 32 bit systems of longs from vmlinux.h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





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



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux