ajor / bpftrace

High-level tracing language for Linux eBPF - development moved to https://github.com/iovisor/bpftrace
https://github.com/iovisor/bpftrace
Apache License 2.0
250 stars 15 forks source link

Add ability to get kernel version from header at runtime #46

Closed xbe closed 6 years ago

xbe commented 6 years ago

After a build using docker, I was getting this error:

# build-debug/src/bpftrace -e 'kprobe:sys_nanosleep { printf("%u: sleep by %d\n", nsecs, tid); }'
Attaching 1 probe...
Error loading program: kprobe:sys_nanosleep

strace to the rescue:

# strace build-debug/src/bpftrace -e 'kprobe:sys_nanosleep { printf("%u: sleep by %d\n", nsecs, tid); }'
*snip*
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=21, insns=0x7f48b7d51000, license="GPL", log_level=0, log_size=0, log_buf=0, kern_version=266001}, 72) = -1 E2BIG (Argument list too long)
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=21, insns=0x7f48b7d51000, license="GPL", log_level=0, log_size=0, log_buf=0, kern_version=266001}, 72) = -1 EINVAL (Invalid argument)
brk(0x22f9000)                          = 0x22f9000
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=21, insns=0x7f48b7d51000, license="GPL", log_level=1, log_size=65536, log_buf=0x22c8c50, kern_version=266001}, 72) = -1 EINVAL (Invalid argument)
write(2, "bpf: Failed to load program: Inv"..., 46) = 46
write(2, "\n", 1)                       = 1
brk(0x22e9000)                          = 0x22e9000
uname({sysname="Linux", nodename="factotum", ...}) = 0
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=21, insns=0x7f48b7d51000, license="GPL", log_level=0, log_size=0, log_buf=0, kern_version=265472}, 72) = -1 E2BIG (Argument list too long)
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=21, insns=0x7f48b7d51000, license="GPL", log_level=0, log_size=0, log_buf=0, kern_version=265472}, 72) = -1 EINVAL (Invalid argument)
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=21, insns=0x7f48b7d51000, license="GPL", log_level=1, log_size=65536, log_buf=0x22c8c50, kern_version=265472}, 72) = -1 EINVAL (Invalid argument)
write(2, "bpf: Failed to load program: Inv"..., 46) = 46

It's trying different kernel versions and getting a -EINVAL. Checking the source code for bpf_prog_load(), I see that one of the ways for that function to return -EINVAL is if the given kern_version doesn't match the definition of LINUX_VERSION_CODE in /usr/include/linux/version.h (or wherever this header is).

This happens because my docker image has a different kernel version than my machine, and bpftrace uses the LINUX_VERSION_CODE macro in its version getter (preprocessing is a compile-time operation). This patch adds the ability for bpftrace to get the value of LINUX_VERSION_CODE at runtime, which is what we need to do if we want to run bpftrace on a different kernel version than it was compiled on.

ajor commented 6 years ago

Good idea!