Search code examples
linux-kernelperfbpf

What is a BPF scriptlet, and how to I compile and run one?


The Linux kernel source contains some perf BPF examples such as https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/examples/bpf/augmented_syscalls.c?h=v5.7. That contains a comment saying:

* Test it with:

* perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null

What does it mean to pass a .c file as the -e flag to perf trace? perf trace -h says:

-e, --event <event>   event/syscall selector. use 'perf list' to list available events

tools/perf/examples/bpf/augmented_syscalls.c doesn't seem like a syscall or event, it's a path to a C file. perf list doesn't indicate anything about passing a C file.

When I try to run that command, I get:

fatal error: 'stdio.h' file not found
#include <stdio.h>
         ^~~~~~~~~
1 error generated.
ERROR:  unable to compile examples/bpf/augmented_syscalls.c
Hint:   Check error message shown above.
Hint:   You can also pre-compile it into .o using:
                clang -target bpf -O2 -c examples/bpf/augmented_syscalls.c
        with proper -I and -D options.
event syntax error: 'examples/bpf/augmented_syscalls.c'
                     \___ Failed to load examples/bpf/augmented_syscalls.c from source: Error when compiling BPF scriptlet

So I guess this is a "scriptlet"? But I can't find much information about what a scriptlet is, or how to compile one.

clang -target bpf -O2 -c examples/bpf/augmented_syscalls.c gives me:

example.c:28:18: error: function cannot return function type 'int (struct syscall_enter_openat_args *)'
int syscall_enter(openat)(struct syscall_enter_openat_args *args)
                 ^
example.c:33:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
license(GPL);
^
example.c:33:9: error: a parameter list without types is only allowed in a function definition
license(GPL);

Which seems to make sense, since it doesn't look like valid C.


Solution

  • Not a full answer, but...

    There's some (limited) doc on the man page for perf record. Perf can take a C file containing an eBPF program, compile and run it to get more info from the kernel. I'm not familiar with the scriplet terminology used by perf, but it sounds like a mix of “script” and “proglet” and apparently designates a short eBPF program that perf can work with.

    Not sure why your perf trace fails. Could it be a mismatch between the perf version and the kernel? Note that the C program has been replaced with augmented_raw_syscalls.c on recent kernels. I can run perf with this newer program fine on my own setup (but then it doesn't help me debug yours).

    As for your clang line - it should be valid C, you're likely missing the relevant -I/-D options.