Probe = точка на наблюдение
DTrace работи с probes — точки в кода (kernel или userspace), в които може да се "закачи" и да изпълни произволен код при тяхното достигане.
Форматът е: provider:module:function:name
Пример: syscall::open:entry — всеки open() system call преди изпълнение.
Zero overhead когато не се използва
DTrace probe-ите са NOP инструкции в нормален режим — буквално нищо не правят. Само когато активираш конкретен probe, ядрото го patch-ва на живо. Това означава: можеш да оставиш probe-ите в production код без никакво penalty.
$ sudo dtruss -p $(pgrep Safari)
$ sudo dtruss /usr/bin/curl https://example.com 2>&1 | head -50
open("/etc/resolv.conf\0", 0x0, 0x1B6) = 3 0 read(0x3, "# Generated by Ne", 0x1000) = 75 0 connect(0x5, { AF_INET6, ::ffff:93.184.216.34, 443 }, 0x1C) = -1 Err#36 getsockopt(0x5, 0xFFFF, 0x1007, 0x16F, 0x4) = 0 0 connect(0x5, { AF_INET6, ::ffff:93.184.216.34, 443 }, 0x1C) = 0 0 write(0x5, "GET / HTTP/1.1\r\nH", 0x55) = 85 0
$ sudo dtruss -t open -p $(pgrep "Spotify") 2>&1
$ sudo dtruss -a -p $(pgrep myapp) 2>&1 | tee trace.log
Решение: sudo dtruss ... — задължително с sudo. Ако пак не работи, SIP блокира. Виж горния warning banner.
| Provider | Probe | Какво трейсва | Пример usage |
|---|---|---|---|
| syscall | entry / return | Всеки kernel system call | Файлове, мрежа, процеси |
| proc | exec / exit / fork | Създаване/унищожаване на процеси | Кой процес стартира кой |
| io | start / done | Disk I/O операции | Бавни disk writes |
| profile | profile-997hz | Timer-based sampling | CPU profiling без инструментация |
| pid$target | library:function | Userspace функции на конкретен процес | Trace конкретна C функция |
| objc$target | ClassName:method | Objective-C method calls | Trace macOS app методи |
| vminfo | pgfault / cow_fault | Virtual memory events | Memory pressure диагностика |
| sched | on-cpu / off-cpu | CPU scheduling | Защо процес е throttled |
$ sudo dtrace -l -n 'pid$target:::' -p $(pgrep Safari) | wc -l
Probe = кога се изпълнява. Predicate = условие (опционално). Action = какво да се направи.
#!/usr/sbin/dtrace -s syscall::open*:entry /pid == $target/ { printf("%s\n", copyinstr(arg0)); } syscall::open*:return /pid == $target && arg0 == -1/ { printf("FAILED: %s (errno %d)\n", copyinstr(arg0), errno); }
io:::start { start[arg0] = timestamp; } io:::done /start[arg0]/ { this->elapsed = (timestamp - start[arg0]) / 1000000; /* само операции над 10ms */ this->elapsed > 10 ? printf("%dms %s %s\n", this->elapsed, args[0]->b_flags & B_READ ? "READ" : "WRITE", args[2]->fi_pathname) : 1; start[arg0] = 0; }
syscall:::entry /pid == $target/ { @calls[probefunc] = count(); } END { trunc(@calls, 20); printf("\nTop 20 syscalls:\n"); printa("%-30s %@d\n", @calls); }
mach_msg_trap 48291 kevent_qos 12847 bsdthread_ctl 8234 read 6721 psynch_cvsignal 5102 write 4891 open 312
syscall::connect:entry { printf("%s[%d] connect → %s\n", execname, pid, copyinstr(arg0)); } syscall::sendto:entry { printf("%s[%d] SEND %d bytes\n", execname, pid, arg2); }
proc:::exec-success { printf("%Y parent=%-20s new=%-30s\n", walltimestamp, curpsinfo->pr_psargs, execname); }
App се срива — не знаеш защо
sudo dtruss -f -p $(pgrep myapp) 2>&1 | grep "FAILED\|= -1"
Виждаш точно кои файлове не може да отвори, кои system calls фейлват и с кой errno код.
Решаваш за минути вместо часове с логове.
Намери hidden telemetry на app
sudo dtruss -t connect -p $(pgrep "SuspiciousApp") 2>&1
Виждаш всяка мрежова конекция. Ако app-ът изпраща данни без да ти каже — ще го видиш тук.
IP адреси, портове, всичко.
Защо стартирането на app е бавно
sudo dtrace -s slowio.d & ; open /Applications/SlowApp.app
Виждаш кои файлове се четат бавно по време на startup. Обикновено са липсващи шрифтове, бавен iCloud sync или огромен cache файл.
Reverse engineer непозната binary
sudo dtruss ./unknown_binary 2>&1 | tee binary_trace.txt
Без source код, без IDA Pro — виждаш всеки файл, мрежова конекция, environment variable и argument на binary-то.
Основна forensics техника.
CPU spike — кой е виновен
sudo dtrace -n 'profile-997 /arg0/ { @[execname, ksym(arg0)] = count(); } END { trunc(@, 20); printa(@); }'
997Hz CPU profiler — сэмплира всеки 1ms кой код се изпълнява. След 5 секунди Ctrl+C и виждаш top 20 функции, ядящи CPU. Без инструментация, без rebuild.
$ sudo fs_usage -w -f filesys $(pgrep Chrome)
$ sudo fs_usage -e -w $(pgrep Slack) | grep ".json"
$ sudo sc_usage $(pgrep Safari)
$ sample $(pgrep myapp) 10 -file /tmp/profile.txt
$ cat /tmp/profile.txt | head -60