strg+c
unterbrochen werdenal@ganymed:~/coding$ gdb ./a.out
GNU gdb (Debian 13.2-1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...
(gdb) run
Starting program: /home/local/al/coding/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
__strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:76
76 ../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory.
(gdb)
Unterstützt verschiedene Ziele (targets), wie z. B. i386, amd64, …
Erweiterbar um weitere Ziele mittels GDB-Stub
(Ziel muss nur das GDB-Protokoll implementieren)
Können wir den GNU Debugger einfach für einen Betriebssystemkern (hier: Linux) nutzen?
Nein!
Problem: GDB läuft selbst ein Anwendungsprozess und soll der Betriebssystemkern untersuchen. Wir müssen von von außen an den Kern. Aber wie?
Wie kann ich einen laufenden Betriebssystemkern oder einen laufenden Computer untersuchen?
Lässt sich „einfach” über einen GDB bedienen
Benötigt zwei Computer:
Device under Test (DUT) und Entwicklungsmaschine
Aus dem untersuchten System die Kontrolle an den GDB übergeben
echo g > /proc/sysrq-trigger
Kernparameter kgdbwait
Verweilt nicht zu lange im GDB, bevor Ihr c
drückt. Ansonsten beschwert sich der Linux-Kern
[ 116.011870][ C0] INFO: NMI handler (kgdb_nmi_handler) took too long to run: 50930.300 msecs
Pro
Contra
Und nu?
strg+c
) möglich(Geht bei uns auch mit dem Parameter -g XX/vmlinux
für das Skript boot.sh
)
Quellen
(GCC-Erweiterung mcount)
Frontend
Wichtige Erkenntnis: Abwägung zwischen spezifische Informationen sind direkt verfügbar vs. universell im Kern einsetzbar (Danke an Julia Evans für ihre schöne Einteilung und Brendan Gregg)
int3
(auf x86)int3
)
jmp
-Instruktion statt int3
Wir schauen uns SystemTap an. Warum? Weil ich „nur” SystemTap kann. 😎
Ursprüngliches Konzept von Frank Ch. Eigler et al. [4]
Nutzt verschiedene Backends:
kprobes, uprobes, ebpf, …
C-ähnliche Sprache zum Erstellen von Skripten
Kapselung von häufig-genutzten Funktionen in Tapsets
Zustand modifizieren oder echten C-Code einbauen mit dem Guru-Mode (-g
)
Schaut gerne in den Beginners Guide
root@debian:~# stap -vt -r /mnt/linux/ test.stp
Pass 1: parsed user script and 484 library scripts using 132404virt/107252res/11404shr/94996data kb, in 140usr/20sys/166real ms.
Pass 2: analyzed script: 1 probe, 4 functions, 0 embeds, 0 globals using 194428virt/170444res/12876shr/157020data kb, in 790usr/940sys/12830real ms.
Pass 3: translated to C into "/tmp/stap0a74pc/stap_9bf5fa33360a9fd150b4098db40097b6_1408_src.c" using 194428virt/170636res/13068shr/157020data kb, in 40usr/690sys/10335real ms.
Pass 4: compiled C into "stap_9bf5fa33360a9fd150b4098db40097b6_1408.ko" in 1660usr/430sys/4530real ms.
Pass 5: starting run.
sshd (440) wrote 36 bytes
sshd (440) wrote 76 bytes
----- probe hit report:
kernel.function("vfs_write@fs/read_write.c:564").return, (test.stp:1:1), hits: 6, cycles: 152min/2273avg/7049max, variance: 18695040, from: kernel.function("vfs_write@fs/read_write.c:564").return from: kernel.function("vfs_write").return, index: 0
----- refresh report:
Pass 5: run completed in 40usr/30sys/2789real ms.
-v
: Erhöhe das Log-Level-t
: Erhebe Timing-Informationen während der Ausführung und gebe sie aus-r
: Pfad zum Linux-Quellcode-Verzeichnis, hier /mnt/linux
syscall.open
kernel.function("foo@bar.c")
→ Funktion foo()
in Datei bar.c
kernel.function("*@bar.c")
→ jede Funktion in Datei bar.c
kernel.statement("*@fs/namei.c:3080")
→ Zeile 3080 in Datei fs/namei.c
Ausgabe: