Zostało wprowadzone eksperymentalne wydanie narzędzia do dynamicznego debugowania DTrace dla Linux 2.0.0-1.14, zrealizowane w postaci procesu działającego w przestrzeni użytkownika, wykorzystującego podsystem eBPF oraz wbudowane mechanizmy śledzenia udostępniane przez jądro Linux. Funkcjonalnie wdrożenie DTrace oparte na eBPF jest zbliżone do pierwszej wersji DTrace dla Linux, zrealizowanej w formie modułu jądra. Kod projektu jest udostępniany na licencji GPLv2.
Narzędzie może być używane z domyślnymi jądrami Linux obsługującymi BPF. Do działania wymagana jest biblioteka libctf z implementacją wsparcia dla formatu debugowania CTF (Compact Type Format), która wchodzi w skład pakietu binutils, począwszy od wydania 2.40, lub biblioteka libdtrace-ctf, przeniesiona z systemu Solaris. Dodatkowo oferowane są dwa patche do jądra 6.7, które umożliwiają wykorzystanie rozszerzonych możliwości do pozyskiwania dodatkowych danych o modułach i jądrze.
Technologia DTrace została opracowana w celu rozwiązania problemów związanych z dynamicznym śledzeniem jądra i końcowych aplikacji w systemie operacyjnym Solaris. DTrace daje użytkownikowi możliwość szczegółowego śledzenia zachowania systemu i diagnozowania problemów w czasie rzeczywistym. W trakcie debugowania DTrace nie wpływa na działanie badanych aplikacji i nie odbija się na ich wydajności, co pozwala na analizę działających systemów w locie. Wśród mocnych stron DTrace wymienia się wysokopoziomowy język D, podobny do AWK, na którym znacznie łatwiej jest tworzyć skrypty śledzące w porównaniu do dostępnych dla eBPF narzędzi do pisania handlerów w językach C, Python i Lua z zewnętrznymi bibliotekami.
Podstawowe funkcje:
- Dostępne dostawcy:
- cpc (CPU Performance Counter) — pozyskiwanie informacji o wydajności.
- dtrace — wtyczki BEGIN, END oraz ERROR, uruchamiane przed lub po innych kontrolach, a także przy wystąpieniu błędów.
- fbt (Function Boundary Tracing) — śledzenie wywołań funkcji jądra.
- lockstat — śledzenie stanu blokad.
- pid — śledzenie wywołań funkcji w procesach działających w przestrzeni użytkownika.
- proc — śledzenie aktywności związanej z procesami, taką jak uruchamianie i kończenie pracy (fork, exec, exit, fault).
- profile — zapis statystyk wydajności w określonych interwałach czasowych.
- sdt, rawtp — statyczne śledzenie jądra (SDT — Statically Defined Tracing).
- usdt: statyczne śledzenie aplikacji (USDT — Userspace Statically Defined Tracing)
- sched — śledzenie rozdziału zasobów CPU.
- sycall — śledzenie wejść i wyjść z wywołań systemowych.
- Agregacja zbieranych danych: możliwość zastosowania funkcji agregujących (avg, count, llquantize, lquantize, max, min, quantize, stddev i sum) oraz działań agregujących (clear, normalize, printa). Wsparcie dla zapisywania wyników zastosowania funkcji agregujących w tablicach zwykłych i asocjacyjnych.
- Wsparcie dla spekulacyjnego śledzenia, umożliwiającego efemeryczne śledzenie danych, decydując, które z nich powinny być zapisywane w buforze śledzenia, a które odrzucane. Dostępne funkcje: speculation, speculate, commit i discard.
- Wsparcie dla zmiennych globalnych i lokalnych, TLS (Thread-Local Storage), tablic asocjacyjnych i ciągów.
- Udostępnienie wbudowanych zmiennych: arg0 — arg9, args[], caller, curcpu, curthread, epid, errno, execname, gid, id, pid, ppid, probefunc, probemod, probename, probeprov, stackdepth, tid, timestamp, ucaller, uid, uregs[], ustackdepth, walltimestamp.
- Wsparcie dla działań: exit, freopen, ftruncate, mod, printa, printf, raise, setopt, stack, sym, system, trace, tracemem, uaddr, umod, ustack i usym.
- Obecność wbudowanych funkcji: alloca, basename, bcopy, copyin, copyinstr, copyinto, copyout, copyoutstr, dirname, getmajor, getminor, htonl, htonll, htons, index, inet_ntoa, lltostr, mutex_owned, mutex_owner, mutex_type_adaptive, mutex_type_spin, ntohl, ntohll, ntohs, progenyof, rand, rindex, rw_iswriter, rw_read_held, rw_write_held, strchr, strjoin, strlen, strrchr, strstr, strtok, substr.
- Obecność liczników danych, które nie trafiają do buforów śledzenia.
- Wsparcie dla kompilacji skryptów śledzenia w języku D do formy programów BPF.
- Przedkompilacja funkcji BPF dla wywołań bibliotecznych.
- Opcja bpflog dla uzyskania logu walidacji załadowanych programów BPF.
- Dynamiczne generowanie kodu i przedkompilacja kodu do ponownego wykorzystania w programach BPF.
Zmiany w nowej wersji:
- W dostawcy pid, stosowanym do śledzenia procesów w przestrzeni użytkownika, dodano wsparcie dla śledzenia wykonania instrukcji poprzez ich przesunięcie w kodzie.
- Dodano wsparcie dla użycia funkcji stack() i ustack() do agregacji zbieranych danych.
- Możliwość usuwania z tablic asocjacyjnych elementów dowolnych typów poprzez przypisanie literału 0.
- Dodano działanie print do wyświetlania strukturalnych danych z adnotacjami typu.
- Dodano nowe wbudowane funkcje cleanpath(), d_path() i link_ntop().
- Dodano parametry „-xcpu”, umożliwiający powiązanie testów z określonymi CPU.
- Dodano parametry „-xlockmem” do ograniczenia rozmiaru pamięci.
- Zapewniono możliwość przechowywania danych śledzenia procesów (USDT) pomiędzy ponownymi uruchomieniami dtprobed.
- Wsparcie dla mechanizmu BTF (BPF Type Format), dostarczającego informacji do weryfikacji typów w pseudokodzie BPF.
- Możliwość używania skryptu configure do kompilacji.
Źródło: opennet.ru
