Skip to content

Commit

Permalink
examples/c: Add USDT example
Browse files Browse the repository at this point in the history
Add a new example to demonstrate the usage of libbpf USDT
functionality.

Closes: libbpf#80
Signed-off-by: Hengqi Chen <chenhengqi@outlook.com>
  • Loading branch information
chenhengqi authored and anakryiko committed Jun 29, 2022
1 parent 2b5b2bb commit 4f0d020
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 2 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,28 @@ $ sudo cat /sys/kernel/debug/tracing/trace_pipe
<...>-461101 [018] d... 505434.345367: bpf_trace_printk: UPROBE EXIT: return = 5
```

## USDT

`usdt` is an example of dealing with USDT probe. It attaches USDT BPF programs to
the [libc:setjmp](https://www.gnu.org/software/libc/manual/html_node/Non_002dlocal-Goto-Probes.html) probe, which is triggered by calling `setjmp` in user-space program once per second and logs USDT arguments using `bpf_printk()` macro:

```shell
$ sudo ./usdt
libbpf: loading object 'usdt_bpf' from buffer
...
Successfully started!
...........
```

You can see `usdt` demo output in `/sys/kernel/debug/tracing/trace_pipe`:
```shell
$ sudo cat /sys/kernel/debug/tracing/trace_pipe
usdt-1919077 [005] d..21 537310.886092: bpf_trace_printk: USDT auto attach to libc:setjmp: arg1 = 55d03d6a42a0, arg2 = 0, arg3 = 55d03d65e54e
usdt-1919077 [005] d..21 537310.886105: bpf_trace_printk: USDT manual attach to libc:setjmp: arg1 = 55d03d6a42a0, arg2 = 0, arg3 = 55d03d65e54e
usdt-1919077 [005] d..21 537311.886214: bpf_trace_printk: USDT auto attach to libc:setjmp: arg1 = 55d03d6a42a0, arg2 = 0, arg3 = 55d03d65e54e
usdt-1919077 [005] d..21 537311.886227: bpf_trace_printk: USDT manual attach to libc:setjmp: arg1 = 55d03d6a42a0, arg2 = 0, arg3 = 55d03d65e54e
```

# Fentry

`fentry` is an example that uses fentry and fexit BPF programs for tracing. It
Expand Down
2 changes: 2 additions & 0 deletions examples/c/.gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/.output
/bootstrap
/minimal
/minimal_legacy
/uprobe
/kprobe
/fentry
/profile
/usdt
3 changes: 1 addition & 2 deletions examples/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX))
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)

APPS = minimal minimal_legacy bootstrap uprobe kprobe fentry
APPS = minimal minimal_legacy bootstrap uprobe kprobe fentry usdt

CARGO ?= $(shell which cargo)
ifeq ($(strip $(CARGO)),)
Expand Down Expand Up @@ -131,4 +131,3 @@ $(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)

# keep intermediate (.skel.h, .bpf.o, etc) targets
.SECONDARY:

29 changes: 29 additions & 0 deletions examples/c/usdt.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2022 Hengqi Chen */
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/usdt.bpf.h>

pid_t my_pid;

SEC("usdt/libc.so.6:libc:setjmp")
int BPF_USDT(usdt_auto_attach, void *arg1, int arg2, void *arg3)
{
pid_t pid = bpf_get_current_pid_tgid() >> 32;

if (pid != my_pid)
return 0;

bpf_printk("USDT auto attach to libc:setjmp: arg1 = %lx, arg2 = %d, arg3 = %lx", arg1, arg2, arg3);
return 0;
}

SEC("usdt")
int BPF_USDT(usdt_manual_attach, void *arg1, int arg2, void *arg3)
{
bpf_printk("USDT manual attach to libc:setjmp: arg1 = %lx, arg2 = %d, arg3 = %lx", arg1, arg2, arg3);
return 0;
}

char LICENSE[] SEC("license") = "Dual BSD/GPL";
89 changes: 89 additions & 0 deletions examples/c/usdt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2022 Hengqi Chen */
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#include <linux/limits.h>
#include "usdt.skel.h"

static volatile sig_atomic_t exiting;
static jmp_buf env;

static void sig_int(int signo)
{
exiting = 1;
}

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}

static void usdt_trigger() {
setjmp(env);
}

int main(int argc, char **argv)
{
struct usdt_bpf *skel;
int err;

libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);

skel = usdt_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeleton\n");
return 1;
}

skel->bss->my_pid = getpid();

err = usdt_bpf__load(skel);
if (!skel) {
fprintf(stderr, "Failed to load BPF skeleton\n");
return 1;
}

/*
* Manually attach to libc.so we find.
* We specify pid here, so we don't have to do pid filtering in BPF program.
*/
skel->links.usdt_manual_attach = bpf_program__attach_usdt(skel->progs.usdt_manual_attach, getpid(),
"libc.so.6", "libc", "setjmp", NULL);
if (!skel->links.usdt_manual_attach) {
err = errno;
fprintf(stderr, "Failed to attach BPF program `usdt_manual_attach`\n");
goto cleanup;
}

/*
* Auto attach by libbpf, libbpf should be able to find libc.so in your system.
* By default, auto attach does NOT specify pid, so we do pid filtering in BPF program
*/
err = usdt_bpf__attach(skel);
if (err) {
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto cleanup;
}

if (signal(SIGINT, sig_int) == SIG_ERR) {
err = errno;
fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
goto cleanup;
}

printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
"to see output of the BPF programs.\n");

while (!exiting) {
/* trigger our BPF programs */
usdt_trigger();
fprintf(stderr, ".");
sleep(1);
}

cleanup:
usdt_bpf__destroy(skel);
return -err;
}

0 comments on commit 4f0d020

Please sign in to comment.