From 88d205b5e36385ecea4746541abd0b75a0bd5d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= Date: Fri, 9 Aug 2024 14:17:01 +0200 Subject: [PATCH] debugging: slides: develop eBPF part in the training MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit eBPF is currently mentioned in the training, but it is far from enough to give enough knowledge to start writing some tooling in eBPF: we only mention the core concepts, introduce two tracing/profiling frameworks, and have no lab about it. Add core content to really teach how to manipulate eBPF. The new content brings the following organization: - general intro: how and why, the setup, the core components - writing ebpf programs - managing ebpf programs with bcc - manual operations with clang and bpftool - managing ebpf programs with libbpf The new content is integrated in the "System Wide Profiling and Tracing" part, and has been put as the last subpart (just after LTTng) Also, since the new corresponding lab is big enough, it is done separately from the current system wide tracing lab. Signed-off-by: Alexis Lothoré --- labs/debugging-ebpf/debugging-ebpf.tex | 8 +- .../bpf_lifecycle.dia | 1100 +++++++++++++++++ .../debugging-system-wide-profiling.tex | 1044 +++++++++++----- .../lttng_graph.png | Bin 42371 -> 0 bytes 4 files changed, 1858 insertions(+), 294 deletions(-) create mode 100644 slides/debugging-system-wide-profiling/bpf_lifecycle.dia delete mode 100644 slides/debugging-system-wide-profiling/lttng_graph.png diff --git a/labs/debugging-ebpf/debugging-ebpf.tex b/labs/debugging-ebpf/debugging-ebpf.tex index 7d53cbe006..550cab1d19 100644 --- a/labs/debugging-ebpf/debugging-ebpf.tex +++ b/labs/debugging-ebpf/debugging-ebpf.tex @@ -165,7 +165,13 @@ \section{Improving our program} As a final improvement, we will trace the parent PID as well to know who is starting any program. \begin{itemize} \item Edit your eBPF program to read the parent PID. This info can be captured by retrieving the current \code{struct task_struct}, and identifying the relevant fields. Check both Elixir for the layout of \code{struct task_struct}, and \manpage{bpf-helpers}{7} to learn how to get the current task. - \item We are using CO-RE definition for kernel data (through vmlinux.h), so we can not dereference directly a \code{struct task_struct} in our eBPF program, we must use helpers to retrieve struct fields. You can check \href{https://nakryiko.com/posts/bpf-core-reference-guide/#the-missing-manual}{this blog post from Andrii Nakryiko} to learn about such helpers. + \item We are using CO-RE definition for kernel data (through vmlinux.h), so + we can not dereference directly a \code{struct task_struct} in our eBPF + program, we must use helpers to retrieve struct fields. You can check + \href{https://nakryiko.com/posts/bpf-core-reference-guide/#the-missing-manual}{this + blog post from Andrii Nakryiko} to learn about such helpers. Also, you will + need to check \kstruct{task_struct} to know what field to extract to get the + parent PID. \item Update your userspace program to read and print the newly captured value \end{itemize} diff --git a/slides/debugging-system-wide-profiling/bpf_lifecycle.dia b/slides/debugging-system-wide-profiling/bpf_lifecycle.dia new file mode 100644 index 0000000000..61847f9d1f --- /dev/null +++ b/slides/debugging-system-wide-profiling/bpf_lifecycle.dia @@ -0,0 +1,1100 @@ + + + + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #myprog.bpf.c# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #myprog.bpf.o# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #verifier# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #kernel# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #userspace# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #clang# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #bpf()# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #attach# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #program runs +on event# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #userspace tool# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #map_1# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #myprog# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #map_2# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slides/debugging-system-wide-profiling/debugging-system-wide-profiling.tex b/slides/debugging-system-wide-profiling/debugging-system-wide-profiling.tex index 43f0d9b58b..00cf6fa4de 100644 --- a/slides/debugging-system-wide-profiling/debugging-system-wide-profiling.tex +++ b/slides/debugging-system-wide-profiling/debugging-system-wide-profiling.tex @@ -177,7 +177,7 @@ \subsection{perf} \begin{itemize} \item {\em perf} allows to create dynamic tracepoints on both kernel functions and user-space functions. - \item In order to be able to insert probes, \kconfig{CONFIG_KPROBE} must be + \item In order to be able to insert probes, \kconfig{CONFIG_KPROBES} must be enabled in the kernel. \begin{itemize} \item Note: {\em libelf} is required to compile {\em perf} with @@ -644,8 +644,6 @@ \subsection{ftrace and trace-cmd} ... \end{minted} \end{block} - - \end{frame} \begin{frame}[fragile] @@ -795,6 +793,192 @@ \subsection{ftrace and trace-cmd} \center\includegraphics[height=0.8\textheight]{slides/debugging-system-wide-profiling/kernelshark.png} \end{frame} +\setuplabframe +{System wide profiling} +{ + Profiling a system from userspace to kernel space + \begin{itemize} + \item Profiling with ftrace, uprobes and kernelshark + \item Profiling with perf + \end{itemize} +} + +\subsection{LTTng} + +\begin{frame} + \frametitle{{\em LTTng}} + \begin{columns} + \column{0.65\textwidth} + \begin{itemize} + \item LTTng is an open source tracing framework for Linux maintained by + the \href{https://www.efficios.com/}{EfficiOS} company. + \item LTTng allows understanding the interactions between the kernel and + applications (C, C++, Java, Python). + \begin{itemize} + \item Also expose a \code{/dev/lttng-logger} that can be used from any + application. + \end{itemize} + \item Tracepoints are associated with a payload (data). + \item LTTng is focused on low-overhead tracing. + \item Uses the Common Trace Format (so traces are readable with other + software like babeltrace or trace-compass) + \end{itemize} + \column{0.35\textwidth} + \includegraphics[height=0.3\textheight]{slides/debugging-system-wide-profiling/lttng-logo.jpg} + \end{columns} +\end{frame} + +\begin{frame} + \frametitle{Tracepoints with {\em LTTng} } + \begin{itemize} + \item LTTng works with a session daemon that receive all events from kernel + and userspace LTTng tracing components. + \item LTTng can use and trace the following instrumentation points: + \begin{itemize} + \item LTTng kernel tracepoints + \item kprobes and kretprobes + \item Linux kernel system calls + \item Linux user space probe + \item User space LTTng tracepoints + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Creating userspace tracepoints with {\em LTTng}} + \begin{itemize} + \item New userspace tracepoints can be defined using LTTng. + \item Tracepoints have multiple characteristics: + \begin{itemize} + \item A provider namespace + \item A name identifying the tracepoint + \item Parameters of various types (int, char *, etc) + \item Fields describing how to display the tracepoint parameters + (decimal, hexadecimal, etc) (see \href{https://lttng.org/man/3/lttng-ust/v2.13/}{LTTng-ust} manpage + for types) + \end{itemize} + \item Developpers must perform multiple operations to use UST tracepoint: + write a tracepoint provider (.h), write a tracepoint package (.c), build + the package, call the tracepoint in the traced application, and finally + build the application, linked with lttng-ust library and the package provider. + \item LTTng provides the \code{lttng-gen-tp} to ease all those steps, + allowing to only write a template (.tp) file. + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Defining a {\em LTTng} tracepoint (1/2)} + + \begin{itemize} + \item Tracepoint template (\code{hello_world-tp.tp}): + \begin{block}{} + \begin{minted}[fontsize=\tiny]{C} + LTTNG_UST_TRACEPOINT_EVENT( + // Tracepoint provider name + hello_world, + + // Tracepoint/event name + first_tp, + + // Tracepoint arguments (input) + LTTNG_UST_TP_ARGS( + char *, text + ), + + // Tracepoint/event fields (output) + LTTNG_UST_TP_FIELDS( + lttng_ust_field_string(message, text) + ) + ) + \end{minted} + \end{block} + \item \code{lttng-gen-tp} will take this template file and generate/build + all needed files (.h, .c and .o files) + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Defining a {\em LTTng} tracepoint (2/2)} + \begin{itemize} + \item Build tracepoint provider: + \end{itemize} + \begin{block}{} + \begin{minted}[fontsize=\tiny]{console} +$ lttng-gen-tp hello_world-tp.tp + \end{minted} + \end{block} + \begin{itemize} + \item Tracepoint usage (\code{hello_world.c}): + \end{itemize} + \begin{block}{} + \begin{minted}[fontsize=\tiny]{C} +#include +#include "hello-tp.h" + +int main(int argc, char *argv[]) +{ + lttng_ust_tracepoint(hello_world, my_first_tracepoint, 23, "hi there!"); + return 0; +} + \end{minted} + \end{block} + \begin{itemize} + \item Compilation: + \end{itemize} + \begin{block}{} + \begin{minted}[fontsize=\tiny]{console} +$ gcc hello_world.c hello_world-tp.o -llttng-ust -o hello_world + \end{minted} + \end{block} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Using {\em LTTng}} + \begin{block}{} + \begin{minted}[fontsize=\small]{console} +$ lttng create my-tracing-session --output=./my_traces +$ lttng list --kernel +$ lttng list --userspace +$ lttng enable-event --userspace hello_world:my_first_tracepoint +$ lttng enable-event --kernel --syscall open,close,write +$ lttng start +$ /* Run your application or do something */ +$ lttng destroy +$ babeltrace2 ./my_traces + \end{minted} + \end{block} + \begin{itemize} + \item You can also use + \href{https://eclipse.dev/tracecompass/trace-compass}{trace-compass} + to display the traces in a GUI + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Remote tracing with {\em LTTng}} + \begin{itemize} + \item LTTng allows to record traces over the network. + \item Useful for embedded systems with limited storage capabilities. + \item On the remote computer, run \code{lttng-relayd} command + \end{itemize} + \begin{block}{} + \begin{minted}[fontsize=\small]{console} +$ lttng-relayd --output=${PWD}/traces + \end{minted} + \end{block} + \begin{itemize} + \item Then on the target, at session creation, use the \code{--set-url} + \end{itemize} + \begin{block}{} + \begin{minted}[fontsize=\small]{console} +$ lttng create my-session --set-url=net://remote-system + \end{minted} + \end{block} + \begin{itemize} + \item Traces will then be recorded directly on the remote computer. + \end{itemize} +\end{frame} + \subsection{eBPF} \begin{frame}{The ancestor: Berkeley Packet filter} @@ -845,55 +1029,233 @@ \subsection{eBPF} \begin{frame} \frametitle{eBPF (1/2)} \begin{itemize} - \item \href{https://ebpf.io/}{eBPF} framework in the kernel allows running - user-written BPF programs within the kernel in a safe and efficient - way (Added in kernel 3.15) - \item Execution is event-driven and can be hooked using Kprobes, tracepoints - and other methods of tracing - \item Executes complex actions and reports data to userspace for - events that took place in the kernel. - \item Used to hook into various places of the kernel: VFS, Network stack, - syscalls, load balancing, security, etc - \end{itemize} - \center\includegraphics[height=0.2\textheight]{slides/debugging-linux-application-stack/logo_ebpf.png}\\ + \item \href{https://ebpf.io/}{eBPF} is a new framework allowing to run + small user programs directly in the kernel, in a safe and efficient way. It + has been added in kernel 3.18 but it is still evolving and receiving + updates frequently. + \item eBPF programs can capture and expose kernel data to userspace, and + also alter kernel behavior based on some user-defined rules. + \item eBPF is event-driven: an eBPF program is triggered and executed on a + specific kernel event + \item A major benefit from eBPF is the possibility to reprogram the kernel + behavior, without performing kernel development: + \begin{itemize} + \item no risk of crashing the kernel because of bugs + \item faster development cycles to get a new feature ready + \end{itemize} + \end{itemize} + \center\includegraphics[height=0.2\textheight]{slides/debugging-linux-application-stack/logo_ebpf.png}\\ \tiny Image credits: \url{https://ebpf.io/} \end{frame} \begin{frame} \frametitle{eBPF (2/2)} \begin{itemize} - \item Programs are loaded using the \code{bpf()} system call - (\manpage{bpf}{2}) and then verified by the kernel BPF verifier before - being executed. + \item The most notable eBPF features are: + \begin{itemize} + \item A new instruction set, interpreter and verifier + \item A wide variety of "attach" locations, allowing to hook programs + almost anywhere in the kernel + \item dedicated data structures called "maps", to exchange data between + multiple eBPF programs or between programs and userspace + \item A dedicated \code{bpf()} syscall to manipulate eBPF programs and data + \item plenty of (kernel) helper functions accessible from eBPF programs. + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{eBPF program lifecycle} + \begin{center} + \includegraphics[height=0.8\textheight]{slides/debugging-system-wide-profiling/bpf_lifecycle.pdf} + \end{center} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Kernel configuration for eBPF} + \begin{itemize} + \item \kconfig{CONFIG_NET} to enable eBPF subsystem + \item \kconfig{CONFIG_BPF_SYSCALL} to enable the \code{bpf()} syscall + \item \kconfig{CONFIG_BPF_JIT} to enable JIT on programs and so increase performance + \item \kconfig{CONFIG_BPF_JIT_ALWAYS_ON} to force JIT + \item \kconfigval{CONFIG_BPF_UNPRIV_DEFAULT_OFF}{n} in \textbf{development} to + allow eBPF usage without root + \item You may then want to enable more general features to "unlock" + specific hooking locations: \begin{itemize} - \item Check of privileges to execute BPF program - \item Verifies that the BPF program always runs to completion and does not - loop forever + \item \kconfig{CONFIG_KPROBES} to allow hooking programs on kprobes + \item \kconfig{CONFIG_TRACING} to allow hooking programs on kernel tracepoints + \item \kconfig{CONFIG_NET_CLS_BPF} to write packets classifiers + \item \kconfig{CONFIG_CGROUP_BPF} to attach programs on cgroups hooks \end{itemize} - \item Almost all architectures have a BPF JIT support which allows - translating the BPF format into native CPU instruction, thus being - (almost) as fast as natively compiled code - \item BPF programs can return values in maps of various types (hash tables, - arrays, etc) which allows sharing data between user-space, eBPF - programs and kernel space. - \item Only some functions (called helpers) can be called in eBPF programs. - \item eBPF programs are attached to events (invoked on trigger). + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{eBPF ISA} + \begin{itemize} + \item eBPF is a "virtual" ISA, defining its own set of instructions: load + and store instruction, arithmetic instructions, jump instructions,etc + \item It also defines a set of 10 64-bits wide registers as well as a + calling convention: + \begin{itemize} + \item \code{R0}: return value from functions and BPF program + \item \code{R1, R2, R3, R4, R5}: function arguments + \item \code{R6, R7, R8, R9}: callee-saved registers + \item \code{R10}: stack pointer + \end{itemize} + \end{itemize} + \begin{block}{} + \begin{minted}[fontsize=\scriptsize]{console} +; bpf_printk("Hello %s\n", "World"); + 0: r1 = 0x0 ll + 2: r2 = 0xa + 3: r3 = 0x0 ll + 5: call 0x6 +; return 0; + 6: r0 = 0x0 + 7: exit + \end{minted} + \end{block} +\end{frame} + +\begin{frame}[fragile] + \frametitle{The eBPF verifier} + \begin{itemize} + \item When loaded into the kernel, a program must first be validated by the + eBPF verifier. + \item The verifier is a complex piece of software which checks eBPF + programs against a set of rules to ensure that running those may not + compromise the whole kernel. For example: + \begin{itemize} + \item a program must always return and so not contain paths which could + make them "infinite" (e.g: no infinite loop) + \item a program must make sure that a pointer is valid before + dereferencing it + \item a program can not access arbitrary memory addresses, it must use + passed context and available helpers + \end{itemize} + \item If a program violates one of the verifier rules, it will be rejected. + \item Despite the presence of the verifier, you still need to be careful when + writing programs ! eBPF programs run with preemption enabled (but CPU + migration disabled), so they can still suffer from concurrency issues + \begin{itemize} + \item Hopefully there are some mechanisms and helpers to avoid those isses, + like per-cpu maps types. + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Program types and attach points} + \begin{itemize} + \item There are different "types" of places to which a program can be + hooked + \begin{itemize} + \item an arbitrary kprobe + \item a kernel-defined static tracepoint + \item a specific perf event + \item throughout the network stack + \item and a lot more, see \ksym{bpf_attach_type} + \end{itemize} + \item A specific attach-point type can only be hooked with a set of + specific program types, see \ksym{bpf_prog_type} and + \kdochtml{bpf/libbpf/program_types}. + \item The program type then defines the data passed to an eBPF program as + input when it is invoked. For example: + \begin{itemize} + \item A \code{BPF_PROG_TYPE_TRACEPOINT} program will receive a structure + containing all data returned to userspace by the targeted tracepoint. + \item A \code{BPF_PROG_TYPE_SCHED_CLS} program (used to implement packets + classifiers) will receive a \kstruct{__sk_buff}, the kernel + representation of a socket buffer. + \item You can learn about the context passed to any program type by + checking \kfile{include/linux/bpf_types.h} + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{eBPF maps} + \begin{itemize} + \item eBPF programs exchange data with userspace or other programs through + maps of different nature: + \begin{itemize} + \item \code{BPF_MAP_TYPE_ARRAY}: generic array storage. Can be + differentiated per cpu + \item \code{BPF_MAP_TYPE_HASH}: a storage composed of key-value pairs. + Keys can be of different types: \code{__u32}, a device type, an ip address... + \item \code{BPF_MAP_TYPE_QUEUE}: a FIFO-type queue + \item \code{BPF_MAP_TYPE_CGROUP_STORAGE}: a specific hash map keyed by a + cgroup id. There are other types of maps specific to other object types + (inodes, tasks, sockets, etc) + \item etc... + \end{itemize} + \item For basic data, it is easier and more efficient to directly use eBPF + global variables (no syscalls involved, contrary to maps) + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{The \code{bpf()} syscall} + \begin{itemize} + \item The kernel exposes a \code{bpf()} syscall to allow interacting with the + eBPF subsystem + \item The syscall takes a set of subcommands, and depending on the + subcommand, some specific data: + \begin{itemize} + \item \ksym{BPF_PROG_LOAD} to load a bpf program + \item \ksym{BPF_MAP_CREATE} to allocate maps to be used by a program + \item \ksym{BPF_MAP_LOOKUP_ELEM} to search for an entry in a map + \item \ksym{BPF_MAP_UPDATE_ELEM} to update an entry in a map + \item etc + \end{itemize} + \item The syscall works with file descriptors pointing to eBPF resources. + Those resources (program, maps, links, etc) remain valid while there is at least + one program holding a valid file descriptor to it. Those are automatically cleaned + once there are no user left. + \item For more details, see \manpage{bpf}{2} \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Writing eBPF programs} \begin{itemize} - \item eBPF programs can be written in (restricted) C and are compiled - using clang compiler - \item BCC (BPF Compiler Collection) provides a toolkit to write BPF - programs more easily using C language (also provides LUA and Python - front-ends) + \item eBPF programs can either be written directly in raw eBPF assembly or in + higher level languages (e.g: C or rust), and are compiled using the clang + compiler. + \item The kernel provides some helpers that can be called from an eBPF program: \begin{itemize} - \item Allows to write tracing and profiling program easily + \item \code{bpf_trace_printk} Emits a log to the trace buffer + \item \code{bpf_map_{lookup,update,delete}_elem} Manipulates maps + \item \code{bpf_probe_{read,write}[_user]} Safely read/write data from/to kernel or userspace + \item \code{bpf_get_current_pid_tgid} Returns current Process ID and Thread group ID + \item \code{bpf_get_current_uid_gid} Returns current User ID and Group ID + \item \code{bpf_get_current_comm} Returns the name of the executable running in the + current task + \item \code{bpf_get_current_task} Returns the current \kstruct{task_struct} + \item Many other helpers are available, see \manpage{bpf-helpers}{7} + \end{itemize} + \item Kernel also exposes kfuncs (see \kdochtml{bpf/kfuncs}), but contrary + to bpf-helpers, those do not belong to the kernel stable interface. + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Manipulating eBPF program} + \begin{itemize} + \item There are different ways to build, load and manipulate eBPF programs: + \begin{itemize} + \item One way is to write an eBPF program, build it with clang, and then load it, + attach it and read data from it with bare \code{bpf()} calls in a custom + userspace program + \item One can also use \code{bpftool} on the built ebpf program to + manipulate it (load, attach, read maps, etc), without writing any userspace tool + \item Or we can write our own eBPF tool thanks to some intermediate libraries which handle most of the + hard work, like libbpf + \item We can also use specialized frameworks like BCC or bpftrace to really + get all operations (bpf program build included) handled \end{itemize} - \item {\em bpftrace} is a high level language allowing to easily write tracing - functions \end{itemize} \end{frame} @@ -917,7 +1279,7 @@ \subsection{eBPF} \end{itemize} \column{0.25\textwidth} \vspace{0.5cm} - \includegraphics[height=0.2\textheight]{slides/debugging-linux-application-stack/logo_bcc.png}\\ + \includegraphics[height=0.2\textheight]{slides/debugging-linux-application-stack/logo_bcc.png}\\ \tiny Image credits: \url{https://github.com/iovisor/bcc} \end{columns} \end{frame} @@ -963,8 +1325,25 @@ \subsection{eBPF} \begin{frame}[fragile] \frametitle{Using BCC with python} \begin{itemize} - \item BCC python support allows to easily write and hook C program for BPF - tracing. + \item BCC exposes a \code{bcc} module, and especially a \code{BPF} class + \item eBPF programs are written in C and stored either in external files + or directly in a python string. + \item When an instance of the \code{BPF} class is created and fed with the + program (either as string or file), it automatically builds, loads, and + possibly attaches the program + \item There are multiple ways to attach a program: + \begin{itemize} + \item By using a proper program name prefix, depending on the targeted + attach point (and so the attach step is performed automatically) + \item By explicitely calling the relevant attach method on the \code{BPF} + instance created earlier + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Using BCC with python} + \begin{itemize} \item Hook with a {\em kprobe} on the \code{clone()} system call and display \verb+"Hello, World!"+ each time it is called \end{itemize} @@ -987,317 +1366,404 @@ \subsection{eBPF} \end{frame} \begin{frame}[fragile] - \frametitle{bpftrace} - \begin{columns} - \column{0.75\textwidth} - \begin{itemize} - \item bpftrace is a high level tracing language allowing to write tracing - expressions easily (\url{https://bpftrace.org/}) - \item Also provide tools to trace various parts of the kernel - \begin{itemize} - \item Internally uses LLVM to compile script and BCC to interact with the BPF programs - \end{itemize} - \item bpftrace is inspired by awk and C, and predecessor tracers such as DTrace and SystemTap - \item Rich syntax documented at \url{https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md} - \end{itemize} - \column{0.25\textwidth} - \vspace{0.5cm} - %% Source: https://commons.wikimedia.org/wiki/File:Elf-layout--en.svg - \includegraphics[height=0.2\textheight]{slides/debugging-system-wide-profiling/bpftrace.png}\\ - \tiny Image credits: \url{https://bpftrace.org/} - \end{columns} + \frametitle{libbpf} + \begin{itemize} + \item Instead of using a high level framework like BCC, one can use libbpf to + build custom tools with a finer control on every aspect of the program. + \item libbpf is a C-based library that aims to ease eBPF programming thanks + to the following features: + \begin{itemize} + \item userspace APIs to handle open/load/attach/teardown of bpf programs + \item userspace APIs to interact with attached programs + \item eBPF APIs to ease eBPF program writing + \end{itemize} + \item Packaged in many distributions and build systems (e.g.: Buildroot) + \item Learn more at \url{https://libbpf.readthedocs.io/en/latest/} + \end{itemize} \end{frame} \begin{frame}[fragile] - \frametitle{bpftrace tools} - - \begin{center} - \includegraphics[height=0.8\textheight]{slides/debugging-system-wide-profiling/bpftrace_tools_early2019.png}\\ - \tiny Image credits: \url{https://www.brendangregg.com/ebpf.html} - \end{center} + \frametitle{eBPF programming with libbpf (1/2)} + \begin{block}{\code{my_prog.bpf.c}} + \begin{minted}[fontsize=\tiny]{C} + #include + #include + #include + + #define TASK_COMM_LEN 16 + struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, __u32); + __type(value, __u64); + __uint(max_entries, 1); + } counter_map SEC(".maps"); + + struct sched_switch_args { + unsigned long long pad; + char prev_comm[TASK_COMM_LEN]; + int prev_pid; + int prev_prio; + long long prev_state; + char next_comm[TASK_COMM_LEN]; + int next_pid; + int next_prio; + }; + \end{minted} + \end{block} \end{frame} \begin{frame}[fragile] - \frametitle{Using bpftrace} - \begin{itemize} - \item Counting all syscalls per process: - \end{itemize} - \begin{block}{} - \begin{minted}[fontsize=\small]{console} -$ sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }' -Attaching 1 probe... -^C -@[packagekitd]: 1 -@[GUsbEventThread]: 1 -@[gvfs-afc-volume]: 1 -@[ibus-extension-]: 4 + \frametitle{eBPF programming with libbpf (2/2)} + \begin{block}{\code{my_prog.bpf.c}} + \begin{minted}[fontsize=\tiny]{C} + SEC("tracepoint/sched/sched_switch") + int sched_tracer(struct sched_switch_args *ctx) + { + __u32 key = 0; + __u64 *counter; + char *file; + + char fmt[] = "Old task was %s, new task is %s\n"; + bpf_trace_printk(fmt, sizeof(fmt), ctx->prev_comm, ctx->next_comm); + + counter = bpf_map_lookup_elem(&counter_map, &key); + if(counter) { + *counter += 1; + bpf_map_update_elem(&counter_map, &key, counter, 0); + } + + return 0; + } + + char LICENSE[] SEC("license") = "Dual BSD/GPL"; \end{minted} \end{block} \end{frame} -\begin{frame} - \frametitle{eBPF: resources} - \begin{itemize} - \item A Beginner’s Guide to eBPF Programming - Liz Rice, 2020 - \begin{itemize} - \item Slides: \url{https://speakerdeck.com/lizrice/beginners-guide-to-ebpf} - \item Video: \url{https://www.youtube.com/watch?v=lrSExTfS-iQ} - \item Resources: \url{https://github.com/lizrice/ebpf-beginners} - \end{itemize} - \end{itemize} - \begin{center} - \includegraphics[height=0.6\textheight]{slides/debugging-system-wide-profiling/ebpf_liz_rice_2020.png} - \end{center} -\end{frame} - -\subsection{LTTng} -\begin{frame} - \frametitle{{\em LTTng} (1/2)} - \begin{columns} - \column{0.65\textwidth} - \begin{itemize} - \item LTTng is an open source tracing framework for Linux maintained by - the \href{https://www.efficios.com/}{EfficiOS} company. - \item LTTng allows understanding the interactions between the kernel and - applications (C, C++, Java, Python). - \begin{itemize} - \item Also expose a \code{/dev/lttng-logger} that can be used from any - application. - \end{itemize} - \item Tracepoints are associated with a payload (data). - \item LTTng is focused on low-overhead tracing. - \item LTTng provides a unified logging of all events (kernel/user). - \end{itemize} - \column{0.35\textwidth} - \includegraphics[height=0.3\textheight]{slides/debugging-system-wide-profiling/lttng-logo.jpg} - \end{columns} -\end{frame} - -\begin{frame} - \frametitle{{\em LTTng} (2/2)} - \begin{itemize} - \item Uses the \href{https://diamon.org/ctf/}{CTF} trace format (Common - Trace Format). - \item LTTng is made of multiple components: +\begin{frame}[fragile] + \frametitle{Building eBPF programs} + \begin{itemize} + \item An eBPF program written in C can be built into a loadable object + thanks to clang: + \begin{block}{} + \begin{minted}{console} + $ clang -target bpf -O2 -g -c my_prog.bpf.c -o my_prog.bpf.o + \end{minted} + \end{block} \begin{itemize} - \item LTTng-tools: Libraries and command-line interface to control tracing. - \item LTTng-modules: Linux kernel modules to instrument and trace the kernel. - \item LTTng-UST: Libraries and Java/Python packages to instrument and trace user applications. + \item The \code{-g} option allows to add debug information as well as + BTF information \end{itemize} - \item Already packaged by various distribution (debian, fedora, etc) and - present in Buildroot and openembedded-core. - \item Uses a single tool \code{lttng} to control tracing. - \item No need to recompile the kernel but a few options are need + \item GCC can be used too with recent versions \begin{itemize} - \item \kconfig{CONFIG_MODULES}, \kconfig{CONFIG_KALLSYMS}, \kconfig{CONFIG_HIGH_RES_TIMERS}, - \kconfig{CONFIG_TRACEPOINTS}, \kconfig{CONFIG_KPROBES} + \item the toolchain can be installed with the \code{gcc-bpf} package in + Debian/Ubuntu + \item it exposes the \code{bpf-unknown-none} target \end{itemize} + \item To easily manipulate this program with a userspace program based on libbpf, + we need "skeleton" APIs, which can be generated with to \code{bpftool} \end{itemize} \end{frame} \begin{frame}[fragile] - \frametitle{LTTng architecture} - \begin{center} - \includegraphics[height=0.8\textheight]{slides/debugging-system-wide-profiling/lttng_graph.png}\\ - \tiny Image credits: \url{https://lttng.org/} - \end{center} -\end{frame} - -\begin{frame} - \frametitle{Tracepoints with {\em LTTng} } + \frametitle{bpftool} \begin{itemize} - \item LTTng can use and trace the following instrumentation points: + \item \code{bpftool} is a command line tool allowing to interact with bpf + object files and the kernel to manipulate bpf programs: \begin{itemize} - \item LTTng kernel tracepoints - \item kprobes and kretprobes - \item Linux kernel system calls - \item Linux user space probe - \item User space LTTng tracepoints + \item Load programs into the kernel + \item List loaded programs + \item Dump program instructions, either as BPF code or JIT code + \item List loaded maps + \item Dump map content + \item Attach programs to hooks (so they can run) + \item etc \end{itemize} - \item LTTng works with a session daemon that receive all events from kernel - and userspace LTTng tracing components. - \item Session daemon should be started as daemon and the user should be in - the {\em tracing} group. + \item You may need to mount the bpf filesystem to be able to pin program + (needed to keep a program loaded after bpftool has finished running): + \begin{block}{} + \begin{minted}{console} + $ mount -t bpf none /sys/fs/bpf + \end{minted} + \end{block} \end{itemize} \end{frame} -\begin{frame} - \frametitle{Creating userspace tracepoints with {\em LTTng}} +\begin{frame}[fragile] + \frametitle{bpftool} \begin{itemize} - \item New userspace tracepoints can be defined using LTTng. - \item Tracepoints have multiple characteristics: - \begin{itemize} - \item A provider namespace - \item A name identifying the tracepoint - \item Parameters of various types (int, char *, etc) - \item Fields describing how to display the tracepoint parameters - (decimal, hexadecimal, etc) - \end{itemize} - \item Tracepoints are defined using a tracepoint provider header file - template and a tracepoint provider package file. - \begin{itemize} - \item The tracepoint provider header file template contains the definition - of the tracepoints. - \item The tracepoint provider package is the instantiation of the - tracepoints. - \end{itemize} - \item See \href{https://lttng.org/man/3/lttng-ust/v2.13/}{LTTng-ust} manpage - for types + \item List loaded programs \end{itemize} -\end{frame} - -\begin{frame}[fragile] - \frametitle{Defining a {\em LTTng} tracepoint (1/2)} - + \begin{block}{} + \fontsize{10}{10}\selectfont + \begin{minted}{console} +$ bpftool prog +348: tracepoint name sched_tracer tag 3051de4551f07909 gpl +loaded_at 2024-08-06T15:43:11+0200 uid 0 +xlated 376B jited 215B memlock 4096B map_ids 146,148 +btf_id 545 + \end{minted} + \end{block} \begin{itemize} - \item Tracepoint provider header file (\code{hello_world-tp.h}): + \item Load and attach a program \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\tiny]{C} -#undef LTTNG_UST_TRACEPOINT_PROVIDER -#define LTTNG_UST_TRACEPOINT_PROVIDER hello_world - -#undef LTTNG_UST_TRACEPOINT_INCLUDE -#define LTTNG_UST_TRACEPOINT_INCLUDE "./hello-tp.h" - -#if !defined(_HELLO_TP_H) || defined(LTTNG_UST_TRACEPOINT_HEADER_MULTI_READ) -#define _HELLO_TP_H - -#include - -LTTNG_UST_TRACEPOINT_EVENT( - hello_world, - my_first_tracepoint, - LTTNG_UST_TP_ARGS( - int, my_integer_arg, - char *, my_string_arg - ), - LTTNG_UST_TP_FIELDS( - lttng_ust_field_integer(int, my_integer_field, my_integer_arg) - lttng_ust_field_string(my_string_field, my_string_arg) - ) -) -#endif /* _HELLO_TP_H */ - -#include - \end{minted} + \fontsize{10}{10}\selectfont + \begin{minted}{console} +$ mkdir /sys/fs/bpf/myprog +$ bpftool prog loadall trace_execve.bpf.o /sys/fs/bpf/myprog autoattach + \end{minted} \end{block} -\end{frame} - -\begin{frame}[fragile] - \frametitle{Defining a {\em LTTng} tracepoint (2/2)} \begin{itemize} - \item Tracepoint provider package (\code{hello_world-tp.c}): + \item Unload a program \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\tiny]{C} -#define LTTNG_UST_TRACEPOINT_CREATE_PROBES -#define LTTNG_UST_TRACEPOINT_DEFINE - -#include "hello-tp.h" - \end{minted} + \fontsize{10}{10}\selectfont + \begin{minted}{console} +$ rm -rf /sys/fs/bpf/myprog + \end{minted} \end{block} +\end{frame} +\begin{frame}[fragile] + \frametitle{bpftool} \begin{itemize} - \item Tracepoint usage (\code{hello_world.c}): + \item Dump a loaded program \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\tiny]{C} -#include -#include "hello-tp.h" - -int main(int argc, char *argv[]) -{ - lttng_ust_tracepoint(hello_world, my_first_tracepoint, 23, "hi there!"); - return 0; -} - \end{minted} + \fontsize{8}{8}\selectfont + \begin{minted}{console} +$ bpftool prog dump xlated id 348 +int sched_tracer(struct sched_switch_args * ctx): +; int sched_tracer(struct sched_switch_args *ctx) + 0: (bf) r4 = r1 + 1: (b7) r1 = 0 +; __u32 key = 0; + 2: (63) *(u32 *)(r10 -4) = r1 +; char fmt[] = "Old task was %s, new task is %s\n"; + 3: (73) *(u8 *)(r10 -8) = r1 + 4: (18) r1 = 0xa7325207369206b + 6: (7b) *(u64 *)(r10 -16) = r1 + 7: (18) r1 = 0x7361742077656e20 +[...] + \end{minted} \end{block} \begin{itemize} - \item Compilation: + \item Dump eBPF program logs \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\tiny]{console} -$ gcc hello_world.c hello_world-tp.c -llttng-ust -o hello_world - \end{minted} + \fontsize{6}{6}\selectfont + \begin{minted}{console} +$ bpftool prog tracelog +kworker/u80:0-11 [013] d..41 1796.003605: bpf_trace_printk: Old task was kworker/u80:0, new task is swapper/13 +-0 [013] d..41 1796.003609: bpf_trace_printk: Old task was swapper/13, new task is kworker/u80:0 +sudo-18640 [010] d..41 1796.003613: bpf_trace_printk: Old task was sudo, new task is swapper/10 +-0 [010] d..41 1796.003617: bpf_trace_printk: Old task was swapper/10, new task is sudo +[...] + \end{minted} \end{block} \end{frame} \begin{frame}[fragile] - \frametitle{Generating tracepoints using \code{lttng-gen-tp}} + \frametitle{bpftool} \begin{itemize} - \item Writing both the \code{.h} and \code{.c} boilerplate can be avoided - using \code{lttng-gen-tp}. - \item \code{lttng-gen-tp} takes a template file (\code{.tp}) as input and will - generate both the provider header and package files (\code{.h}, - \code{.c} and \code{.o} files): + \item List created maps \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\tiny]{C} - LTTNG_UST_TRACEPOINT_EVENT( - // Tracepoint provider name - hello_world, - - // Tracepoint/event name - first_tp, - - // Tracepoint arguments (input) - LTTNG_UST_TP_ARGS( - char *, text - ), - - // Tracepoint/event fields (output) - LTTNG_UST_TP_FIELDS( - lttng_ust_field_string(message, text) - ) -) - \end{minted} + \fontsize{9}{9}\selectfont + \begin{minted}{console} +$ bpftool map +80: array name counter_map flags 0x0 + key 4B value 8B max_entries 1 memlock 256B + btf_id 421 +82: array name .rodata.str1.1 flags 0x80 + key 4B value 33B max_entries 1 memlock 288B + frozen +96: array name libbpf_global flags 0x0 + key 4B value 32B max_entries 1 memlock 280B +[...] + \end{minted} \end{block} -\end{frame} - -\begin{frame}[fragile] - \frametitle{Using {\em LTTng}} + \begin{itemize} + \item Show a map content + \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\small]{console} -$ lttng create my-tracing-session --output=./my_traces -$ lttng list --kernel -$ lttng list --userspace -$ lttng enable-event --userspace hello_world:my_first_tracepoint -$ lttng enable-event --kernel --syscall open,close,write -$ lttng start -$ /* Run your application or do something */ -$ lttng destroy -$ babeltrace2 ./my_traces - \end{minted} + \fontsize{9}{9}\selectfont + \begin{minted}{console} +$ sudo bpftool map dump id 80 +[{ + "key": 0, + "value": 4877514 + } +] + \end{minted} \end{block} \end{frame} \begin{frame}[fragile] - \frametitle{Remote tracing with {\em LTTng}} + \frametitle{bpftool} \begin{itemize} - \item LTTng allows to record traces over the network. - \item Useful for embedded systems with limited storage capabilities. - \item On the remote computer, run \code{lttng-relayd} command + \item Generate libbpf APIs to manipulate a program \end{itemize} \begin{block}{} - \begin{minted}[fontsize=\small]{console} -$ lttng-relayd --output=${PWD}/traces - \end{minted} + \fontsize{9}{9}\selectfont + \begin{minted}{console} +$ bpftool gen skeleton trace_execve.bpf.o name trace_execve > trace_execve.skel.h + \end{minted} \end{block} \begin{itemize} - \item Then on the target, at session creation, use the \code{--set-url} + \item We can then write our userspace program and benefit from high level + APIs to manipulate our eBPF program: + \begin{itemize} + \item instantiation of a global context object which will have references + to all of our programs, maps, links, etc + \item loading/attaching/unloading of our programs + \item eBPF program directly embedded in the generated header as a byte + array + \end{itemize} \end{itemize} +\end{frame} + +\begin{frame}[fragile] + \frametitle{Userspace code with libbpf} \begin{block}{} - \begin{minted}[fontsize=\small]{console} -$ lttng create my-session --set-url=net://remote-system - \end{minted} + \begin{minted}[fontsize=\tiny]{C} + #include + #include + #include + #include "trace_sched_switch.skel.h" + + int main(int argc, char *argv[]) + { + struct trace_sched_switch *skel; + int key = 0; + long counter = 0; + + skel = trace_sched_switch__open_and_load(); + if(!skel) + exit(EXIT_FAILURE); + if (trace_sched_switch__attach(skel)) { + trace_sched_switch__destroy(skel); + exit(EXIT_FAILURE); + } + + while(true) { + bpf_map__lookup_elem(skel->maps.counter_map, &key, sizeof(key), &counter, sizeof(counter), 0); + fprintf(stderr, "Scheduling switch count: %d\n", counter); + sleep(1); + } + + return 0; + } + \end{minted} \end{block} +\end{frame} + +\begin{frame} + \frametitle{eBPF programs portability (1/2)} + \begin{itemize} + \item Kernel internals, contrary to userspace APIs, do not expose stable APIs. + This means that an eBPF program manipulating some kernel data may not work + with another kernel version + \item The CO-RE (Compile Once - Run Everywhere) approach aims to solve this issue + and make programs portable between \textbf{kernel versions}. It relies on + the following features: + \begin{itemize} + \item your kernel must be built with + \kconfigval{CONFIG_DEBUG_INFO_BTF}{y} to have BTF data embedded. BTF is a + format similar to dwarf which encodes data layout and functions + signatures in an efficient way. + \item your eBPF compiler must be able to emit BTF relocations (both clang + and GCC are capable of this on recent versions, with the \code{-g} argument) + \item you need a BPF loader capable of processing BPF programs based on BTF data and + adjust accordingly data accesses: \code{libbpf} is the de-facto standard bpf + loader + \item you then need eBPF APIs to read/write to CO-RE relocatable + variables. libbpf provides such helpers, like \code{bpf_core_read} + \end{itemize} + \item To learn more, take a look at + \href{https://nakryiko.com/posts/bpf-core-reference-guide/}{Andrii + Nakryiko's CO-RE guide} + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{eBPF programs portability (2/2)} \begin{itemize} - \item Traces will then be recorded directly on the remote computer. + \item Despite CO-RE, you may still face different constraints on different + kernel versions, because of major features introduction or change, since + the eBPF subsystem keeps receiving frequent updates: + \begin{itemize} + \item eBPF tail calls (which allow a program to call a function ) have + been added in version 4.2, and allow to call another program only since + version 5.10 + \item eBPF spin locks have been added in version 5.1 to prevent + concurrent accesses to maps shared between cpus. + \item Different attach types keep being added, but possibly on different + kernel versions when it depends on the architecture: fentry/fexit attach + points have been added in kernel 5.5 for x86 but in 6.0 for arm32. + \item Any kind of loop (even bounded) was forbidden until version 5.3 + \item \code{CAP_BPF} capability, allowing a process to perform eBPF tasks, has + been added in version 5.8 + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{eBPF for tracing/profiling} + \begin{itemize} + \item eBPF is a very powerful framework to spy on kernel internals: thanks + to the wide variety of attach point, you can expose almost any kernel code path and data. + \item In the mean time, eBPF programs remain isolated from kernel code, + which makes it safe (compared to kernel development) and easy to use. + \item Thanks to the in-kernel interpreter and optimizations like JIT compilation, eBPF is very well + suited for tracing or profiling with low overhead, even in production + environments, while being very flexible. + \item This is why eBPF adoption level keeps growing for debugging, tracing + and profiling in the Linux ecosystem. As a few examples, we find eBPF usage in: + \begin{itemize} + \item tracing frameworks like \href{https://github.com/iovisor/bcc}{BCC} + and \href{https://github.com/bpftrace/bpftrace}{bpftrace} + \item network infrastructure components, like + \href{https://github.com/cilium/cilium}{Cilium} or \href{https://github.com/projectcalico/calico}{Calico} + \item network packet tracers, like + \href{https://github.com/cilium/pwru}{pwru} or + \href{https://github.com/feiskyer/dropwatch}{dropwatch} + \item And many more, check \href{https://ebpf.io/applications/}{ebpf.io} + for more examples + \end{itemize} \end{itemize} \end{frame} +\begin{frame}[fragile] + \frametitle{eBPF: resources} + \begin{itemize} + \item BCC tutorial: + \url{https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md} + \item libbpf-bootsrap: \url{https://github.com/libbpf/libbpf-bootstrap} + \item A Beginner’s Guide to eBPF Programming - Liz Rice, 2020 + \begin{itemize} + \item Video: \url{https://www.youtube.com/watch?v=lrSExTfS-iQ} + \item Resources: \url{https://github.com/lizrice/ebpf-beginners} + \end{itemize} + \end{itemize} + \begin{center} + \includegraphics[height=0.4\textheight]{slides/debugging-system-wide-profiling/ebpf_liz_rice_2020.png} + \end{center} +\end{frame} + +\setuplabframe +{System wide profiling} +{ + Creating custom tracing tools with eBPF + \begin{itemize} + \item Tracing with BCC + \item Converting a BCC script to libbpf + \item Bringing advanced features to the tool + \end{itemize} +} + \subsection{Choosing the right tool} \begin{frame}[fragile] @@ -1315,16 +1781,8 @@ \subsection{Choosing the right tool} \item For "constant" load problems, snapshot tools works fine. \item For sporadic problems, record traces and analyze them. \end{itemize} + \item If you happen to have a complex setup that you often have to bring up, + it is likely a sign that you want to ease this setup with some custom tooling: + scripting, custom traces, eBPF, etc \end{itemize} \end{frame} - -\setuplabframe -{System wide profiling} -{ - Profiling a system from userspace to kernel space - \begin{itemize} - \item Profiling with ftrace, uprobes and kernelshark - \item Profiling with LTTng and trace-compass - \item Profiling with perf - \end{itemize} -} diff --git a/slides/debugging-system-wide-profiling/lttng_graph.png b/slides/debugging-system-wide-profiling/lttng_graph.png deleted file mode 100644 index d15947efa76b42fe0209ccb9eedd71e6a1e8888f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42371 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