Finally making use of bpftrace
I am old enough to remember when BPF meant the traditional Berkeley Packet Filter, and was confined to filtering network packets. It’s grown into much, much, more as eBPF and getting familiar with it so that I can add it to the suite of tips and tricks I can call upon has been on my to-do list for a while. To this end I was lucky enough to attend a live walk through of bpftrace last year. bpftrace is a high level tool that allows the easy creation and execution of eBPF tracers under Linux.
Recently I’ve been working on updating the RetroArch packages in Debian and as I was doing so I realised there was a need to update the quite outdated retroarch-assets package, which contains various icons and images used for the user interface. I wanted to try and re-generate as many of the artefacts as I could, to ensure the proper source was available. However it wasn’t always clear which files were actually needed and which were either ‘source’ or legacy. So I wanted to trace file opens by retroarch and see when it was failing to find files. Traditionally this is something I’d have used strace
for, but it seemed like a great opportunity to try out bpftrace
.
It turns out bpftrace ships with an example, opensnoop.bt which provided details of hooking the open syscall entry + exit and providing details of all files opened on the system. I only wanted to track opens by the retroarch
binary that failed, so I made a couple of modifications:
retro-failed-open-snoop.bt
#!/usr/bin/env bpftrace
/*
* retro-failed-open-snoop - snoop failed opens by RetroArch
*
* Based on:
* opensnoop Trace open() syscalls.
* For Linux, uses bpftrace and eBPF.
*
* Copyright 2018 Netflix, Inc.
* Licensed under the Apache License, Version 2.0 (the "License")
*
* 08-Sep-2018 Brendan Gregg Created this.
*/
BEGIN
{
printf("Tracing open syscalls... Hit Ctrl-C to end.\n");
printf("%-6s %-16s %3s %s\n", "PID", "COMM", "ERR", "PATH");
}
tracepoint:syscalls:sys_enter_open,
tracepoint:syscalls:sys_enter_openat
{
@filename[tid] = args->filename;
}
tracepoint:syscalls:sys_exit_open,
tracepoint:syscalls:sys_exit_openat
/@filename[tid]/
{
$ret = args->ret;
$errno = $ret > 0 ? 0 : - $ret;
if (($ret <= 0) && (strncmp("retroarch", comm, 9) == 0) ) {
printf("%-6d %-16s %3d %s\n", pid, comm, $errno,
str(@filename[tid]));
}
delete(@filename[tid]);
}
END
{
clear(@filename);
}
I had to install bpftrace (apt install bpftrace
) and then I ran bpftrace -o retro.log retro-failed-open-snoop.bt
as root and fired up retroarch
as a normal user.
bpftrace failed open log for retroarch
Attaching 6 probes...
Tracing open syscalls... Hit Ctrl-C to end.
PID COMM ERR PATH
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/glibc-hwcaps/x86-64-v2/lib
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/tls/x86_64/x86_64/libpulse
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/tls/x86_64/libpulsecommon-
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/tls/x86_64/libpulsecommon-
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/tls/libpulsecommon-16.1.so
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/x86_64/x86_64/libpulsecomm
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/x86_64/libpulsecommon-16.1
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/pulseaudio/x86_64/libpulsecommon-16.1
3394 retroarch 2 /etc/gcrypt/hwf.deny
3394 retroarch 2 /lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/tls/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/tls/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libgamemode.so
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/tls/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/tls/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/libgamemode.so.0
3394 retroarch 2 /lib/glibc-hwcaps/x86-64-v2/libgamemode.so.0
3394 retroarch 2 /lib/tls/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/tls/libgamemode.so.0
3394 retroarch 2 /lib/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/x86_64/libgamemode.so.0
3394 retroarch 2 /lib/libgamemode.so.0
3394 retroarch 2 /usr/lib/glibc-hwcaps/x86-64-v2/libgamemode.so.0
3394 retroarch 2 /usr/lib/tls/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/tls/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/tls/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/x86_64/libgamemode.so.0
3394 retroarch 2 /usr/lib/libgamemode.so.0
3394 retroarch 2 /lib/x86_64-linux-gnu/libgamemode.so
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/libgamemode.so
3394 retroarch 2 /lib/libgamemode.so
3394 retroarch 2 /usr/lib/libgamemode.so
3394 retroarch 2 /lib/x86_64-linux-gnu/libdecor-0.so
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/libdecor-0.so
3394 retroarch 2 /lib/libdecor-0.so
3394 retroarch 2 /usr/lib/libdecor-0.so
3394 retroarch 2 /etc/drirc
3394 retroarch 2 /home/noodles/.drirc
3394 retroarch 2 /etc/drirc
3394 retroarch 2 /home/noodles/.drirc
3394 retroarch 2 /usr/lib/x86_64-linux-gnu/dri/tls/iris_dri.so
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/glibc-hwcaps/x86-64-v2/libedit.so.
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/tls/x86_64/x86_64/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/tls/x86_64/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/tls/x86_64/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/tls/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/x86_64/x86_64/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/x86_64/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/x86_64/libedit.so.2
3394 retroarch 2 /lib/x86_64-linux-gnu/../lib/libedit.so.2
3394 retroarch 2 /etc/drirc
3394 retroarch 2 /home/noodles/.drirc
3394 retroarch 2 /etc/drirc
3394 retroarch 2 /home/noodles/.drirc
3394 retroarch 2 /etc/drirc
3394 retroarch 2 /home/noodles/.drirc
3394 retroarch 2 /home/noodles/.Xdefaults-udon
3394 retroarch 2 /home/noodles/.icons/default/cursors/00000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/default/index.theme
3394 retroarch 2 /usr/share/icons/default/cursors/000000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/default/cursors/0000000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/Adwaita/cursors/00000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/Adwaita/index.theme
3394 retroarch 2 /usr/share/icons/Adwaita/cursors/000000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/Adwaita/cursors/0000000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/hicolor/cursors/00000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/hicolor/index.theme
3394 retroarch 2 /usr/share/icons/hicolor/cursors/000000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/hicolor/cursors/0000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/hicolor/index.theme
3394 retroarch 2 /home/noodles/.XCompose
3394 retroarch 2 /home/noodles/.icons/default/cursors/00000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/default/index.theme
3394 retroarch 2 /usr/share/icons/default/cursors/000000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/default/cursors/0000000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/Adwaita/cursors/00000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/Adwaita/index.theme
3394 retroarch 2 /usr/share/icons/Adwaita/cursors/000000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/Adwaita/cursors/0000000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/hicolor/cursors/00000000000000000000000000
3394 retroarch 2 /home/noodles/.icons/hicolor/index.theme
3394 retroarch 2 /usr/share/icons/hicolor/cursors/000000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/hicolor/cursors/0000000000000000000000000000
3394 retroarch 2 /usr/share/pixmaps/hicolor/index.theme
3394 retroarch 2 /usr/share/libretro/assets/xmb/monochrome/png/disc.png
3394 retroarch 2 /usr/share/libretro/assets/xmb/monochrome/sounds
3394 retroarch 2 /usr/share/libretro/assets/sounds
3394 retroarch 2 /sys/class/power_supply/ACAD
3394 retroarch 2 /sys/class/power_supply/ACAD
3394 retroarch 2 /usr/share/libretro/assets/xmb/monochrome/png/disc.png
3394 retroarch 2 /usr/share/libretro/assets/ozone/sounds
3394 retroarch 2 /usr/share/libretro/assets/sounds
This was incredibly useful - the only theme image I was missing is disc.png
from XMB Monochrome (which fails to have SVG source). I also discovered the runtime optional loading of GameMode. This is available in Debian so it was a simple matter to add libgamemode0
to the binary package Recommends
.
So, a very basic example of using bpftrace, but a remarkably useful intro to it from my point of view!