How is "%p"
implemented in bpf_trace_printk
? It seems very different with printf
.
#include <uapi/linux/ptrace.h>
int print_args(struct pt_regs *ctx) {
void *ptr = (void*)PT_REGS_PARM1(ctx);
bpf_trace_printk("args: %lx %p %ld\n", ptr, ptr, ptr);
return 0;
}
I use this eBPF program to trace argument to one function. The parameter's type is a pointer to some struct.
One output is:
args: 7ffde047d6c4 00000000ec7e9023 140728366257860
We can notice that the output of "%p"
is very strange.
If we use a standard C program to check the output:
#include <stdio.h>
int main() {
void *ptr = (void*)0x7ffde047d6c4;
printf("args: %lx %p %ld\n", ptr, ptr, ptr);
return 0;
}
We will get: args: 7ffde047d6c4 0x7ffde047d6c4 140728366257860
TL;DR. The value you're seeing is a hash of the actual address, computed by ptr_to_id()
. The address is hashed to avoid pointer leaks while still being able to use this value as a unique identifier.
Explanations. The implementation of the bpf_trace_printk
helper can be found in kernel/trace/bpf_trace.c
in the kernel sources. Most of the code is there to restrict what specifiers you can use, before calling __trace_printk()
. You can follow the trail of functions to vsnprintf()
which, for %p
, calls pointer()
whose default behavior is to hash the address to avoid pointer leaks.