O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Embedded Debugging, czyli co kryje się w jądrze?

72 visualizações

Publicada em

Prezentacja barcampu firmy Semihalf z 27.11.2018 r.

Jak zaglądnąć tam gdzie pozornie jest to niewykonalne? Kernel panic? Crash dump? Za pomocą narzędzi software'owych i sprzętowych można rozwiązać i takie problemy.

Zagadnienia:
Wsparcie sprzętowe procesorów do debugowania (stepping, pmu, etc.)
Wsparcie systemu operacyjnego (trap, crash dump)
Narzędzia: LLDB, KDB
Case study: (Linux, FreeBSD, macOS, Windows)

Publicada em: Software
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Embedded Debugging, czyli co kryje się w jądrze?

  1. 1. Embedded Debugging, czyli co kryje się w jądrze? Michał Krawczyk Copyright © 2018 Semihalf. All rights reserved.
  2. 2. Copyright © 2018 Semihalf. All rights reserved. 2 Jakie znamy metody debugowania programu?
  3. 3. Copyright © 2018 Semihalf. All rights reserved. 3 Metoda gumowej kaczuszki “Droga Kaczuszko, wykonujemy pętelkę, dopóki x nie będzie równe 3, rozumiesz?” Źródło [1]
  4. 4. Copyright © 2018 Semihalf. All rights reserved. 4 Logi
  5. 5. Copyright © 2018 Semihalf. All rights reserved. 5 Asercje
  6. 6. Copyright © 2018 Semihalf. All rights reserved. 6 Użycie debuggera
  7. 7. Copyright © 2018 Semihalf. All rights reserved. 7 Profilowanie
  8. 8. Copyright © 2018 Semihalf. All rights reserved. 8 Techniki mieszane
  9. 9. Copyright © 2018 Semihalf. All rights reserved. 9 Nie taki kernel straszny... Metoda User space Kernel Kaczuszka ✔ ✔ Logowanie ✔ ✔ Asercje ✔ ✔ Crash dump ✔ ✔ Debugger ✔ ✔ Profilowanie ✔ ✔
  10. 10. Copyright © 2018 Semihalf. All rights reserved. 10 Jakie funkcje powinien posiadać debugger?
  11. 11. Copyright © 2018 Semihalf. All rights reserved. 11 Jakie funkcje powinien posiadać debugger? ● Sterowanie wykonywaniem instrukcji - step, break, continue itp. ● Stawianie breakpointów - zatrzymanie przepływu programu po dotarciu do danej instrukcji w pamięci. ● Stawianie watchpointów - zatrzymanie przy dostępie do pewnego adresu w pamięci (zmiennej). ● Modyfikacja i podgląd pamięci programu - do podglądania zawartości zmiennych i ich modyfikacji. ● Podgląd zawartości rejestrów procesora - w szczególności przy programowaniu niskopoziomowym.
  12. 12. Copyright © 2018 Semihalf. All rights reserved. 12 Gdzie w tym wszystkim procesor? Bazujemy na architekturze x86_64 Intel 64 i ARMv8-A AARCH64. Kernel Obsługa wyjątków Wyjątki CPU Debugger PMU
  13. 13. Copyright © 2018 Semihalf. All rights reserved. 13 Halo, system! Tu procesor. System operacyjny może zgłaszać komunikaty do systemu operacyjnego za pomocą: Intel ● przerwań ● wyjątków ○ Fault ○ Trap ○ Abort
  14. 14. Copyright © 2018 Semihalf. All rights reserved. 14 Halo, system! Tu procesor. System operacyjny może zgłaszać komunikaty do systemu operacyjnego za pomocą: Intel ● przerwań ● wyjątków ○ Fault - podczas zgłaszania, adres powrotu wskazuje na instrukcję, która spowodowała ten wyjątek. Po jego obsłudze można wznowić program. ○ Trap - podczas zgłaszania, adres powrotu wskazuje na instrukcję następną po tej powodującej wyjątek. Po jego obsłudze można wznowić program. ○ Abort- nie zawsze da się go ściśle powiązać z instrukcją, która go spowodowała. Zgłasza poważne błędy. Po jego obsłudze nie można zrestartować programu, który go spowodował. Źródła wyjątków ● Błędy programowe wykryte przez procesor ● Wygenerowanie przerwania programowo (instrukcje INT n, INT3, INT1, INTO) ● Układ sprawdzający poprawność stanu szyn danych i procesora
  15. 15. Copyright © 2018 Semihalf. All rights reserved. 15 Wyjątki (Intel 64 i IA-32)
  16. 16. Copyright © 2018 Semihalf. All rights reserved. 16 Wyjątki (Intel 64 i IA-32)
  17. 17. Copyright © 2018 Semihalf. All rights reserved. 17 Narzędzia do debugowania (Intel) Rejestry do debugowania: DR0 - DR3 - pozwalają ustawić liniowy adres, który ma powodować wyjątek 1 (#DB). DR4 - DR5 - jeśli flaga DE nie jest ustawiona w CR4, to aliasują na DR6 i DR7, w przeciwnym wypadku są zarezerwowane, a dostęp do nich powoduje wyjątek. DR6 (Debug Status Register) - zawiera informacje, dlaczego wyjątek #DB lub #BP się wywołał. DR7 - (Debug Control Register) - pozwala m.in. włączać/wyłączać breakpointy DR0 - DR3 oraz ustawiać, co ma powodować ich wywołanie: ● Uruchomienie instrukcji pod danym adresem ● Zapis do pamięci pod danym adresem ● Odczyt i zapis do pamięci (ale bez pobierania instrukcji) pod danym adresem - tylko jeśli flaga DE w CR4 jest aktywowana ● Zapis I/O pod danym adresem
  18. 18. Copyright © 2018 Semihalf. All rights reserved. 18 Narzędzia do debugowania (Intel) Stepping Flaga TF w EFLAGS - kiedy jest aktywowana, wykonanie każdej instrukcji powoduje wyjątek. Software breakpoint INT3 - instrukcja procesora, która powoduje programowe wywołanie wyjątku nr 3 (#BP). Stosowane przez debuggery.
  19. 19. Copyright © 2018 Semihalf. All rights reserved. 19 Halo, system! Tu procesor. System operacyjny może zgłaszać komunikaty do systemu operacyjnego za pomocą Intel ● przerwań ● wyjątków ○ Fault ○ Trap ○ Abort ARMv8-A ● Wyjątków ○ Asynchronicznych ■ Przerwania (IRQ) i szybkie przerwania (FIQ) ■ System Error (SError) ○ Synchronicznych ■ Abort ■ Wyjątki generowane programowo ○ Reset
  20. 20. Copyright © 2018 Semihalf. All rights reserved. 20 Tabela wyjątków AArch64 Dla każdego typu poziomu wyjątków osobna tabela: ● EL0 - User space ● EL1 - Kernel ● EL2 - Hypervisor ● EL3 - Secure firmware Każdy wpis może się składać z 32 instrukcji (w przeciwieństwie do Intela, gdzie posiadał on jedynie adres segmentu w GDT do procedury obsługującej).
  21. 21. Copyright © 2018 Semihalf. All rights reserved. 21 Przykłady wyjątków (ARMv8-A) Rozróżniane na podstawie typu (SError, Synchronous), a dalej na podstawie wpisu w rejestrach ESR_ELn. System Error ● Błąd parzystości ● Nienaprawialny błąd ECC Abort ● Dostęp do pamięci, do której nie mamy dostępu (błąd wygenerowany przez MMU) ● Wyjątki do debugowania ● Nieznana instrukcja Wyjątki wygenerowane programowo ● SVC (Supervisor Call) - pozwala aplikacji w przestrzeni użytkownika uzyskać dostęp do usług systemu operacyjnego (system call)
  22. 22. Copyright © 2018 Semihalf. All rights reserved. 22 Narzędzia do debugowania (AArch64) Obsługa zdarzeń debugowych może przyjąć dwie formy, zależnie od konfiguracji: ● Halting debug (external debug) - gdy podpinamy się zewnętrznym debuggerem. Procesor przechodzi wtedy w stan debug. ● Monitor debug (self-hosted debug) - gdy nasz system wspiera debugowanie. Procesor wtedy zgłasza wyjątki debugowe. Zdarzenia powodujące wyjątki debugowe: ● Breakpoint ● Watchpoint ● Software Step ● Software Breakpoint Instruction (BRK) Jeśli jesteśmy wpięci zewnętrznym debuggerem, instrukcja HLT powoduje przejście procesora do stanu debugowego.
  23. 23. Copyright © 2018 Semihalf. All rights reserved. 23 Profilowanie procesora Współczesne procesory udostępniają wiele danych, do których mamy dostęp z poziomu systemu operacyjnego, takich jak: ● Liczba cykli procesora ● Odwołania do cache i cache miss ● Statystyki branch predictora (ile nie trafiono, a ile trafiono) I wiele, wiele, wiele innych… zależnie od architektury i konkretnego układu.
  24. 24. Copyright © 2018 Semihalf. All rights reserved. 24 Halo, procesor! Tu system. Już to naprawiam. 1. Procesor zgłasza wyjątek 2. Uruchamia on odpowiednią procedurę obsługi wyjątku 3. Procedura sprawdza, co dokładnie go spowodowało i próbuje go naprawić. a. Jeśli wyjątek nastąpił w kernelu, to zazwyczaj zabijany jest proces, który go spowodował, chyba że był to Page Fault 4. Jeśli wyjątek nastąpił w przestrzeni użytkownika, to wysyłany jest sygnał do procesu 5. Proces obsługuje sygnał (chyba że wysłany został SIGKILL)
  25. 25. Copyright © 2018 Semihalf. All rights reserved. 25 Debugowanie aplikacji w Linuxie Debuggery, takie jak lldb i gdb, korzystają z system calla ptrace. Pozwala on na: ● Dołączenie się do istniejącego procesu (wątku) ● Dostęp do pamięci oraz rejestrów procesu (wątku) ● Przechwytywanie sygnałów wysyłanych do procesu (wątku) ● Wykonywanie instrukcji krok po kroku ● Wznawianie wykonywania procesu (wątku) ● Zamknięcie procesu Przechwytywanie sygnału: ● Śledzony proces zatrzymuje się za każdym razem, gdy otrzymuje sygnał (za wyjątkiem SIGKILL) ● Debugger, może określić jego stan i powód stopa, za pomocą syscalla waitpid (np. sygnał SIGTRAP, jeśli był to wyjątek debugowy) ● Debugger może wznowić działanie wątku, zignorować sygnał lub wysłać inny
  26. 26. Copyright © 2018 Semihalf. All rights reserved. 26 Co się stanie, gdy w kernelu zdarzy się niespodziewany błąd, którego nie da się naprawić?
  27. 27. Copyright © 2018 Semihalf. All rights reserved. 27 Haters gonna hate, kernel gonna panic
  28. 28. Copyright © 2018 Semihalf. All rights reserved. 28 Linux panic
  29. 29. Copyright © 2018 Semihalf. All rights reserved. 29 Linux panic
  30. 30. Copyright © 2018 Semihalf. All rights reserved. 30 Windows - Blue-screen (of death)
  31. 31. Copyright © 2018 Semihalf. All rights reserved. 31 FreeBSD panic
  32. 32. Copyright © 2018 Semihalf. All rights reserved. 32 macOS Panic
  33. 33. Copyright © 2018 Semihalf. All rights reserved. 33 macOS panic
  34. 34. Copyright © 2018 Semihalf. All rights reserved. 34 Linux - kdump i kexec W momencie paniki, Linux może stworzyć core dumpa (zapisać obecny obraz pamięci i stan procesora) - funkcjonalność ta nazywa się kdump. kexec pozwala na uruchomienie się drugiego kernela w specjalnym miejscu w pamięci w momencie crasha, który powoduje zrzut pamięci. Zapobiega to używaniu wypaczonego kernela (tego, który spanikował) do zrzucania pamięci, co mogłoby powodować dalsze błędy. Domyślnie brak narzędzi, należy je pobrać (zależnie od dystrybucji). Core dump można dalej analizować gdb.
  35. 35. Copyright © 2018 Semihalf. All rights reserved. 35 Linux - kdb i kgdb Debugger kernelowy składa się z: 1. debug core Generyczna obsługa wyjątków, zatrzymywanie procesorów podczas wchodzenia do debuggera, programowe breakpointy, bezpieczny dostęp do pamięci, API do komunikacji frontend <-> debug core <-> kgdb drivers. 2. kgdb arch-specific implementation Wsparcie sprzętowych struktur do debugowania i wyjątków. 3. gdbstub frontend (kgdb) Logika do zdalnego debugowania po serialu przez gdb. 4. kdb frontend Frontend do debugowania, przypominający shella. 5. kgdb I/O driver Sterowniki do urządzeń I/O, które mogą być używane bezpiecznie z kontekstu debuggera.
  36. 36. Copyright © 2018 Semihalf. All rights reserved. 36 Linux - kdb i kgdb kdb ● Prosty shell ● Można debugować maszynę bezpośrednio lub poprzez konsolę serialową ● Poziom assemblera + symbole funkcji (jeśli dostępne) ● Możliwość sprawdzenia pamięci, rejestrów, procesów, dmesga ● Ustawianie breakpointów i podstawowa kontrola flow kgdb ● Używa gdb na drugiej maszynie do debugowania ● Używa sterowników I/O kgdb do komunikacji ● Możliwość działania na kodzie źródłowym (potrzebny plik vmlinux) ● Ustawianie breakpointów i podstawowa kontrola flow
  37. 37. Copyright © 2018 Semihalf. All rights reserved. 37 Linux - kmemleak ● Służy do wykrywania wycieków pamięci w kernelu. ● Śledzi wywołania funkcji alokujących pamięć i zapisuje je w drzewie. ● Skanuje pamięć i rejestry co pewien okres czasu, sprawdzając, czy jest jakiekolwiek w niej odwołanie do początku zarezerwowanej pamięci lub dowolnego miejsca w bloku. ● Zgłoszone miejsca można odczytać w pliku: /sys/kernel/debug/kmemleak. ● Wymaga wsparcia w kernelu (CONFIG_DEBUG_KMEMLEAK).
  38. 38. Copyright © 2018 Semihalf. All rights reserved. 38 Windows - core dump ● Complete memory dump Zrzuca całą fizyczną pamięć + dane specyficzne dla driverów. ● Active Memory Dump Podobny do Complete Mem Dump, ale nie zawiera pamięci nieistotnej dla debugowania. ● Kernel memory dump Zrzuca wyłącznie pamięć należącą do kernela w momencie paniki. ● Automatic Memory Dump To samo co Kernel mem dump, ale daje możliwość posiadania pliku stronicowania mniejszego niż ilość pamięci. ● Small Memory Dump Rozmiar 64KB. Zawiera dane z blue screena oraz debugowe logi, kontekst procesora, informacje o procesie który spowodował crash, informacje o wątku który spowodował crash, backtrace (max 16KB) kernela, listę załadowanych modułów, niektóre strony w pamięci.
  39. 39. Copyright © 2018 Semihalf. All rights reserved. 39 Windows - debuggery Visual Studio zintegrowane z Windows debuggerem ● Debugowanie zdalne (Ethernet, USB 2.0/3.0, FireWire, serial) ● Możliwość debugowania podobnie do zwykłych aplikacji ● Ograniczone do sterowników WinDBG ● Debugowanie zdalne ● Poziom kodu źródłowego i assemblera ● Interfejs graficzny ● Debugownie kernela i userspace’a KD (lub NTKD) ● Debugowanie zdalne ● Odpowiedni CLI WinDBG ● Debugowanie kernela
  40. 40. Copyright © 2018 Semihalf. All rights reserved. 40 FreeBSD - core dump FreeBSD tez ma możliwość tworzenia core dumpa. Wykorzystuje swap device do tworzenia zrzutów pamięci. Po ponownym uruchomieniu systemu, swap jest zapisywany na dysku w folderze /var/crash. Istnieją trzy typy zrzutów: ● Full dumps - zrzut całej pamięci ● Minidumps - zrzut wyłącznie stron używanych przez kernel ● Textdumps - tekstowy zapis panic loga i debuggera
  41. 41. Copyright © 2018 Semihalf. All rights reserved. 41 FreeBSD - kgdb i ddb ddb ● Prosty shell ● Można debugować maszynę bezpośrednio lub poprzez konsolę serialową ● Poziom assemblera + symbole funkcji (jeśli dostępne) ● Możliwość sprawdzenia pamięci, rejestrów, procesów, dmesga ● Ustawianie breakpointów, kontrola flow, możliwość uruchamiania funkcji systemu operacyjnego, modyfikacji pamięci kgdb ● Używa gdb na drugiej maszynie do debugowania ● Używany do analizy core dumpa ● Debugowanie po serialu ● Możliwość działania na kodzie źródłowym (kernel z makeoptions DEBUG=-g) ● Debugowanie jak podczas używania gdb
  42. 42. Copyright © 2018 Semihalf. All rights reserved. 42 macOS - ddb i lldb ddb ● Wbudowany w kernel ● Debugowanie po serialu (adaptery nie działają) ● Debugowanie na poziomie asemblera ● Możliwość stawiania breakpointów, watchpointów ● Przydaje się, gdy debugujemy wbudowany interfejs sieciowy, przerwania sprzętowe, lub zanim stos sieciowy zostanie zainicjalizowany lldb ● Zdalne debugowanie przez sieć ● Debugowanie na poziomie kodu źródłowego ● Przypomina debugowanie zwykłej aplikacji za pomocą lldb
  43. 43. Copyright © 2018 Semihalf. All rights reserved. 43 DTrace ● Natywne wsparcie wyłącznie we FreeBSD i macOS. ● Nieoficjalny port na Linuxa. ● Dynamicznie dodaje i usuwa próbniki. ● Skrypty pisane w języku D. ● We FreeBSD możliwość definiowania własnych próbników.
  44. 44. Copyright © 2018 Semihalf. All rights reserved. 44 DTrace
  45. 45. Copyright © 2018 Semihalf. All rights reserved. 45 Dziękuję za uwagę.
  46. 46. Copyright © 2018 Semihalf. All rights reserved. 46 Źródła [1] https://en.wikipedia.org/wiki/Rubber_duck_debugging#/media/File:Rubber_duck_assisting_with_debugging.jpg [2] https://docs.microsoft.com/en-us/visualstudio/profiling/profiling-feature-tour?view=vs-2017 [3] https://www.kernel.org/doc/html/v4.18/dev-tools/kgdb.html [4] https://help.ubuntu.com/lts/serverguide/kernel-crash-dump.html.en [5] https://www.kernel.org/doc/html/v4.18/dev-tools/kmemleak.html [6] https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/index [7] https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/crash-dump-files [8] https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/blue-screen-data [9] https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/build/build.html [10] https://www.freebsd.org/doc/en/books/developers-handbook/kerneldebug.html [11] The Design and Implementation of the FreeBSD Operating System (2nd Edition); Marshall Kirk McKusick; George V. Neville-Neil; Robert N.M. Watson [12] Understanding the LINUX Kernel: From I/O Ports to Process Management; Daniel Pierre Bovet; Marco Cesati [13] Intel® 64 and IA-32 Architectures Software Developer’s Manual, November 2018 [14] Programmer’s Guide for ARMv8-A, v1.0 2015

×