Debugowanie sterowników systemu Windows krok po kroku – laboratorium (tryb jądra echo)
To laboratorium wprowadza debuger jądra WinDbg. Użyj narzędzia WinDbg do debugowania przykładowego kodu sterownika echa w trybie jądra.
Cele laboratorium
To laboratorium obejmuje ćwiczenia, które przedstawiają narzędzia debugowania, uczą typowych poleceń debugowania, ilustrują użycie punktów przerwania i pokazują sposób użycia rozszerzeń debugowania.
W tym laboratorium użyjesz połączenia debugowania jądra na żywo, aby zapoznać się z następującymi akcjami:
- Używanie poleceń debugera systemu Windows
- Użyj standardowych poleceń (stosy wywołań, zmienne, wątki, IRQL)
- Używanie zaawansowanych poleceń debugowania sterowników (!commands)
- Używanie symboli
- Ustawianie punktów przerwania w debugowaniu na żywo
- Wyświetlanie stosów wywołań
- Wyświetlanie drzewa urządzeń Plug and Play
- Praca z kontekstem wątku i procesu
Debugowanie trybu użytkownika i jądra
Podczas pracy z debugerem systemu Windows można wykonać dwa typy debugowania:
tryb użytkownika — aplikacje i podsystemy działają na komputerze w trybie użytkownika. Procesy uruchamiane w trybie użytkownika robią to we własnych wirtualnych przestrzeniach adresowych. Są one ograniczone do uzyskiwania bezpośredniego dostępu do wielu części systemu, w tym sprzętu systemowego, pamięci, która nie jest przydzielona do ich użycia, oraz innych części systemu, które mogą naruszyć integralność systemu. Ponieważ procesy uruchamiane w trybie użytkownika są skutecznie odizolowane od procesów systemu i innych procesów trybu użytkownika, nie mogą zakłócać tych zasobów.
tryb jądra — system operacyjny i programy uprzywilejowane działają w trybie jądra. Kod trybu jądra ma uprawnienia dostępu do dowolnej części systemu. Nie jest ograniczany, tak jak kod trybu użytkownika. Może on uzyskać dostęp do dowolnej części dowolnego innego procesu uruchomionego w trybie użytkownika lub w trybie jądra. Większość podstawowych funkcji systemu operacyjnego i wiele sterowników urządzeń sprzętowych działa w trybie jądra.
W tym ćwiczeniu omówiono polecenia debugowania, które są często używane podczas debugowania zarówno w trybie użytkownika, jak i w trybie jądra. Ćwiczenie obejmuje również rozszerzenia debugowania, czasami nazywane poleceniami "bang" !, które są używane do debugowania w trybie jądra.
Konfiguracja laboratorium
Do ukończenia laboratorium potrzebne są następujące sprzęty:
- Komputer przenośny lub komputer stacjonarny (host) z systemem Windows 10
- Drugi komputer przenośny lub komputer stacjonarny (docelowy) z systemem Windows 10
- Koncentrator sieciowy lub router oraz kable sieciowe do łączenia dwóch komputerów
- Dostęp do Internetu w celu pobrania plików symboli
Do ukończenia laboratorium potrzebne jest następujące oprogramowanie:
- Visual Studio
- Windows Software Development Kit (SDK) dla systemu Windows 10
- Windows Driver Kit (WDK) dla systemu Windows 10
- Przykładowy sterownik echo dla systemu Windows 10
Laboratorium zawiera następujące sekcje:
- Połącz z sesją WinDbg w trybie jądra
- polecenia i techniki debugowania w trybie jądra
- Pobierz i zbuduj sterownik echo KMDF
- Zainstaluj przykładowy sterownik echa w systemie docelowym
- użyj windbg, aby wyświetlić informacje o sterowniku
- Wyświetl informacje o drzewie urządzeń Plug and Play
- praca z punktami przerwania i kodem źródłowym
- Wyświetlanie zmiennych i stosów wywołań
- Wyświetlanie Procesów i Wątków
- IRQL, Rejestry i zakończenie sesji WinDbg
- zasoby debugowania systemu Windows
Połącz się z sesją WinDbg w trybie jądra
W tej sekcji skonfiguruj debugowanie sieci na hoście i systemie docelowym.
Komputery w tym laboratorium muszą być skonfigurowane do korzystania z połączenia sieciowego Ethernet na potrzeby debugowania jądra.
W tym laboratorium są używane dwa komputery. Debuger systemu Windows działa na hoście systemu, a sterownik echo platformy KMDF (Kernel Mode Driver Framework) działa na systemie docelowym.
Podłącz oba komputery, używając koncentratora sieciowego lub routera oraz kabli sieciowych.
Aby pracować z aplikacjami w trybie jądra i używać systemu WinDbg, zalecamy użycie sieci KDNET przez transport Ethernet. Aby uzyskać informacje na temat korzystania z protokołu transportowego Ethernet, zobacz Wprowadzenie do systemu WinDbg (tryb jądra). Aby uzyskać więcej informacji na temat konfigurowania komputera docelowego, zobacz Przygotowywanie komputera do ręcznego wdrażania sterowników i Konfigurowanie debugowania jądra sieci KDNET automatycznie.
Konfigurowanie debugowania w trybie jądra przy użyciu sieci Ethernet
Aby włączyć debugowanie w trybie jądra w systemie docelowym:
W systemie hosta otwórz okno wiersza polecenia i wprowadź ipconfig, aby określić jego adres IPv4.
Windows IP Configuration Ethernet adapter Ethernet: Connection-specific DNS Suffix . : Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3 Autoconfiguration IPv4 Address. . : 169.182.1.1 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . :
Zarejestruj adres IP systemu hosta: ______________________________________
W systemie docelowym otwórz okno wiersza polecenia i użyj polecenia
ping
, aby potwierdzić łączność sieciową między dwoma systemami.ping 169.182.1.1
Użyj rzeczywistego adresu IP systemu hosta, który zanotowałeś, zamiast 169.182.1.1, który jest pokazany w przykładzie.
Pinging 169.182.1.1 with 32 bytes of data: Reply from 169.182.1.1: bytes=32 time=1ms TTL=255 Reply from 169.182.1.1: bytes=32 time<1ms TTL=255 Reply from 169.182.1.1: bytes=32 time<1ms TTL=255 Reply from 169.182.1.1: bytes=32 time<1ms TTL=255 Ping statistics for 169.182.1.1: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 1ms, Average = 0ms
Włącz debugowanie w trybie jądra w systemie docelowym, wykonując następujące kroki.
Ważny
Przed użyciem bcDEdit do zmiany informacji rozruchowych może być konieczne tymczasowe wstrzymanie funkcji zabezpieczeń systemu Windows, takich jak BitLocker i Bezpieczny rozruch na komputerze testowym. Ponownie włącz te funkcje zabezpieczeń po zakończeniu testowania. Odpowiednio zarządzaj komputerem testowym, gdy funkcje zabezpieczeń są wyłączone. Bezpieczny rozruch jest zwykle wyłączony w interfejsie UEFI. Aby uzyskać dostęp do ustawień UEFI, wybierz opcje System, Odzyskiwanie, a następnie Zaawansowane uruchamianie. Po ponownym uruchomieniu wybierz pozycję Rozwiązywanie problemów, Opcje zaawansowane, Ustawienia oprogramowania układowego UEFI. Należy zachować ostrożność, ponieważ niepoprawne ustawienie opcji UEFI lub wyłączenie funkcji BitLocker może spowodować, że system będzie niemożliwy do użycia.
Na komputerze docelowym otwórz okno wiersza polecenia jako administrator. Wprowadź to polecenie, aby włączyć debugowanie:
bcdedit /set {default} DEBUG YES
Wprowadź to polecenie, aby włączyć podpisywanie testowe:
bcdedit /set TESTSIGNING ON
Wprowadź to polecenie, aby ustawić adres IP systemu hosta. Użyj adresu IP systemu hosta, który zarejestrowałeś wcześniej, a nie tego, który jest pokazany.
bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Ostrzeżenie
Aby zwiększyć bezpieczeństwo połączenia i zmniejszyć ryzyko losowych żądań połączenia debugera klienta, użyj automatycznie wygenerowanego klucza losowego. Aby uzyskać więcej informacji, zobacz Konfigurowanie debugowania jądra sieci KDNET automatycznie.
Wprowadź to polecenie, aby potwierdzić, że wartości
dbgsettings
są ustawione prawidłowo:bcdedit /dbgsettings
key 2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p debugtype NET hostip 169.168.1.1 port 50000 dhcp Yes The operation completed successfully.
Notatka
Jeśli otrzymasz komunikat z zapory i chcesz użyć debugera, zaznacz wszystkie trzy pola.
Na komputerze hosta otwórz okno wiersza polecenia jako administrator. W tym laboratorium jest używana wersja x64 WinDbg.exe z zestawu Windows Driver Kit (WDK), który został zainstalowany w ramach instalacji zestawu Windows. Przejdź do domyślnego katalogu WinDbg. Poniżej jest wyświetlana domyślna lokalizacja.
cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64
W tych laboratoriach założono, że oba komputery mają 64-bitową wersję systemu Windows zarówno na komputerze docelowym, jak i na hoście. Jeśli tak nie jest, najlepszym rozwiązaniem jest uruchamianie narzędzi o tej samej bitowości na hoście, na którym są uruchamiane przez system docelowy. Jeśli na przykład element docelowy uruchamia 32-bitowy system Windows, uruchom 32-bitową wersję debugera na hoście. Aby uzyskać więcej informacji, zobacz Wybieranie narzędzi debugowania 32-bitowego lub 64-bitowego.
Otwórz narzędzie WinDbg z debugowaniem użytkownika zdalnego przy użyciu następującego polecenia. Wartości klucza i portu są zgodne z wartościami ustawionymi wcześniej przy użyciu bcDEdit na komputerze docelowym.
WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Uruchom ponownie system docelowy.
W ciągu minuty lub dwóch dane wyjściowe debugowania powinny być wyświetlane w systemie hosta.
Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64 Copyright (c) Microsoft Corporation. All rights reserved. Using NET for debugging Opened WinSock 2.0 Waiting to reconnect... Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2 You can get the target MAC address by running .kdtargetmac command. Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE Kernel Debugger connection established. (Initial Breakpoint requested) Symbol search path is: srv* Executable search path is: Windows 10 Kernel Version 16299 MP (4 procs) Free x64 Product: WinNt, suite: TerminalServer SingleUserTS Built by: 16299.15.amd64fre.rs3_release.170928-1534 Machine Name: Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110 Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00) System Uptime: 0 days 0:00:20.534
Okno Polecenie debugera jest podstawowym oknem informacji o debugowaniu w usłudze WinDbg. Możesz wprowadzić polecenia debugera i wyświetlić dane wyjściowe polecenia w tym oknie.
Okno poleceń debugera jest podzielone na dwie części. Wprowadź polecenia w mniejszym okienku, czyli okienko wprowadzania poleceń w dolnej części okna, a następnie wyświetl dane wyjściowe polecenia w większym okienku w górnej części okna.
W okienku wprowadzania poleceń użyj strzałki w górę i strzałki w dół, aby przewijać historię poleceń. Po wyświetleniu polecenia możesz go edytować lub nacisnąć Enter, aby uruchomić polecenie.
Polecenia i techniki debugowania trybu jądra
W tej sekcji użyj poleceń debugowania, aby wyświetlić informacje o systemie docelowym.
Niektóre polecenia debugowania wyświetlają tekst przy użyciu języka DML (Debugger Markup Language), który można wybrać, aby szybko zebrać więcej informacji.
W systemie hosta użyj Ctrl+Scroll Lock w winDBg, aby włamać się do kodu uruchomionego w systemie docelowym. Reagowanie systemu docelowego może zająć trochę czasu.
Wprowadź następujące polecenie, aby włączyć kod DML w oknie polecenia debugera:
0: kd> .prefer_dml 1 DML versions of commands on by default
Aby uzyskać dostęp do pomocy dotyczącej poleceń referencyjnych, możesz użyć polecenia
.hh
. Wprowadź następujące polecenie, aby wyświetlić pomoc dotyczącą poleceń dla.prefer_dml
:0: kd> .hh .prefer_dml
Plik pomocy debugera wyświetla pomoc dotyczącą polecenia
.prefer_dml
.Aby wyświetlić szczegółowe informacje o wersji na systemie docelowym, w oknie WinDbg wprowadź polecenie vertarget (Pokaż wersję komputera docelowego):
0: kd> vertarget Windows 10 Kernel Version 9926 MP (4 procs) Free x64 Product: WinNt, suite: TerminalServer SingleUserTS Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648 Machine Name: "" Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0 Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00) System Uptime: 0 days 01:31:58.931
Aby sprawdzić, czy pracujesz z prawidłowym procesem trybu jądra, wprowadź polecenie lm (lista załadowanych modułów) w oknie WinDbg, aby wyświetlić załadowane moduły:
0: Kd> lm start end module name fffff801`09200000 fffff801`0925f000 volmgrx (no symbols) fffff801`09261000 fffff801`092de000 mcupdate_GenuineIntel (no symbols) fffff801`092de000 fffff801`092ec000 werkernel (export symbols) werkernel.sys fffff801`092ec000 fffff801`0934d000 CLFS (export symbols) CLFS.SYS fffff801`0934d000 fffff801`0936f000 tm (export symbols) tm.sys fffff801`0936f000 fffff801`09384000 PSHED (export symbols) PSHED.dll fffff801`09384000 fffff801`0938e000 BOOTVID (export symbols) BOOTVID.dll fffff801`0938e000 fffff801`093f7000 spaceport (no symbols) fffff801`09400000 fffff801`094cf000 Wdf01000 (no symbols) fffff801`094d9000 fffff801`09561000 CI (export symbols) CI.dll ...
Dane wyjściowe, które zostały pominięte, są oznaczone jako "..." w tym laboratorium.
Aby zażądać szczegółowych informacji na temat określonego modułu, użyj opcji rozszerzonej
v
.0: Kd> lm v m tcpip Browse full module list start end module name fffff801`09eeb000 fffff801`0a157000 tcpip (no symbols) Loaded symbol image file: tcpip.sys Image path: \SystemRoot\System32\drivers\tcpip.sys Image name: tcpip.sys Browse all global symbols functions data Timestamp: Sun Nov 09 18:59:03 2014 (546029F7) CheckSum: 00263DB1 ImageSize: 0026C000 Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4 Unable to enumerate user-mode unloaded modules, Win32 error 0n30
Nie ma ustawionej ścieżki symboli i załadowanych symboli, dlatego w debugerze są dostępne ograniczone informacje.
Pobierz i skomplikuj sterownik echa KMDF
W tej sekcji pobierz i skompiluj sterownik echa KMDF.
Zazwyczaj będziesz pracować z własnym kodem sterownika podczas korzystania z usługi WinDbg. Aby zapoznać się z obsługą WinDbg, laboratorium używa przykładowego sterownika "Echo" szablonu KMDF. Kod źródłowy jest dostępny, aby ułatwić zrozumienie informacji wyświetlanych w usłudze WinDbg. Ten przykład służy również do zilustrowania sposobu, w jaki można wykonać pojedynczy krok za pomocą natywnego kodu trybu jądra. Ta technika może być cenna w przypadku debugowania złożonych problemów z kodem trybu jądra.
Wyświetl próbkę echo na GitHubie.
Przeczytaj o przykładzie.
Aby pobrać i skompilować przykładowy sterownik Echo:
Najpierw pobierz i wyodrębnij przykład KMDF Echo z GitHuba.
Przykład Echo KMDF znajduje się w ogólnym folderze .
Pobierz przykłady sterowników w jednym pliku zip: przykłady sterowników
Pobierz plik zip na lokalny dysk twardy.
Wybierz i przytrzymaj lub kliknij prawym przyciskiem myszy plik zip i wybierz Wyodrębnij wszystkie. Określ nowy folder lub przejdź do istniejącego, aby przechowywać wyodrębnione pliki. Można na przykład określić C:\DriverSamples\ jako nowy folder, do którego mają zostać wyodrębnione pliki.
Po wyodrębnieniu plików przejdź do następującego podfolderu: C:\DriverSamples\general\echo\kmdf
W programie Microsoft Visual Studio wybierz pozycję Plik>Otwórz projekt/rozwiązanie>... i przejdź do folderu zawierającego wyodrębnione pliki, na przykład C:\DriverSamples\general\echo\kmdf. Kliknij dwukrotnie plik rozwiązania kmdfecho, aby go otworzyć.
W programie Visual Studio znajdź Eksploratora rozwiązań. Jeśli to okno nie jest jeszcze otwarte, wybierz pozycję Eksplorator rozwiązań z menu Widok. W Eksploratorze rozwiązań można zobaczyć jedno rozwiązanie z trzema projektami.
Ustaw konfigurację i platformę przykładu. W Eksploratorze rozwiązań wybierz i przytrzymaj lub kliknij prawym przyciskiem myszy rozwiązanie "kmdfecho" (3 projekty), a następnie wybierz pozycję Configuration Manager. Upewnij się, że konfiguracja i ustawienia platformy są takie same dla trzech projektów. Domyślnie konfiguracja jest ustawiona na Win10 Debugowanie, a platforma jest konfigurowana na Win64 dla wszystkich projektów. Jeśli wprowadzisz jakiekolwiek zmiany konfiguracji lub platformy dla jednego projektu, wprowadź te same zmiany dla pozostałych trzech projektów.
Próbki sterowników należy zmodyfikować, aby używać wartości, które nie nakładają się na istniejące sterowniki. Zapoznaj się z sekcją odnośnie przykładowego kodu i sterownika produkcyjnego – co zmienić w tych przykładach według sekcji, aby stworzyć unikalny przykład sterownika, który będzie współistniał z już zainstalowanymi rzeczywistymi sterownikami w Windows.
Ustaw bibliotekę środowiska uruchomieniowego. Otwórz stronę właściwości sterownika echa i znajdź C/C++>Code Generation. Zmień bibliotekę środowiska uruchomieniowego na debugowanie wielowątkowe (/MTd). Aby uzyskać więcej informacji na temat opcji kompilacji, zobacz /MD, /MT, /LD (Używanie biblioteki Run-Time).
We właściwościach sterownika upewnij się, że tryb podpisu > jest ustawiony na testowy podpis .
W programie Visual Studio wybierz pozycję Build>Build Solution.
W oknach kompilacji powinien zostać wyświetlony komunikat wskazujący, że kompilacja dla wszystkich trzech projektów zakończyła się pomyślnie.
Napiwek
Jeśli wystąpi komunikat o błędzie kompilacji, użyj numeru błędu kompilacji, aby określić poprawkę. Na przykład MSB8040 błędu MSBuild opisuje sposób pracy z bibliotekami zminimalizowanymi przez specyfikację.
W Eksploratorze plików przejdź do folderu zawierającego wyodrębnione pliki dla przykładu. Na przykład przejdź do C:\DriverSamples\general\echo\kmdf, jeśli jest to określony wcześniej folder. W tym folderze lokalizacja skompilowanych plików sterowników różni się w zależności od konfiguracji i ustawień platformy wybranych w programie Configuration Manager. Jeśli pozostawiono ustawienia domyślne bez zmian, skompilowane pliki sterowników zostaną zapisane w folderze o nazwie \x64\Debug kompilacji debugowania 64-bitowego.
Przejdź do folderu zawierającego pliki skompilowane dla sterownika autosync: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.
Folder powinien zawierać następujące pliki:
Plik Opis Echo.sys Plik sterownika. Echo.inf Plik informacyjny (INF), który zawiera informacje potrzebne do zainstalowania sterownika. Ponadto skompilowano plik echoapp.exe i powinien on znajdować się tutaj: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug.
Plik Opis EchoApp.exe Plik wykonywalny testu wiersza polecenia, który komunikuje się ze sterownikiem echo.sys. Znajdź pendrive USB lub skonfiguruj udział sieciowy, aby skopiować utworzone pliki sterowników i test EchoApp z komputera-host do docelowego systemu.
W następnej sekcji skopiuj kod do systemu docelowego i zainstaluj i przetestuj sterownik.
Zainstaluj próbkę sterownika echa KMDF w systemie docelowym
W tej sekcji użyj narzędzia DevCon, aby zainstalować przykładowy sterownik echo.
Komputer, na którym jest instalowany sterownik, określa się jako komputer docelowy lub komputer testowy . Zazwyczaj ten komputer jest oddzielony od komputera, na którym programujesz i kompilujesz pakiet sterowników. Komputer, na którym programujesz i kompilujesz sterownik, jest nazywany komputerem hosta .
Proces przenoszenia pakietu sterowników na komputer docelowy i instalowania sterownika jest nazywany wdrażaniem sterownika.
Przed wdrożeniem podpisanego testowego sterownika, przygotuj komputer docelowy, włączając testowe podpisywanie. Należy również zlokalizować narzędzie DevCon w instalacji zestawu WDK i skopiować je do systemu docelowego.
Aby zainstalować sterownik w systemie docelowym, wykonaj następujące kroki.
W systemie docelowym włącz sterowniki podpisane testowo.
Otwórz ustawienia systemu Windows.
W Update and Securitywybierz Recovery.
W obszarze Zaawansowane uruchamianiekliknij Uruchom ponownie teraz.
Po ponownym uruchomieniu komputera wybierz pozycję Opcje uruchamiania. W systemie Windows 10 wybierz pozycję Rozwiązywanie problemów z opcjami zaawansowanymi>>Ustawienia uruchamiania, a następnie wybierz pozycję Uruchom ponownie.
Wybierz Wyłącz wymuszanie sygnatury sterownika, naciskając klawisz F7.
Uruchom ponownie komputer docelowy.
W systemie hosta przejdź do folderu Tools w instalacji zestawu WDK i znajdź narzędzie DevCon. Na przykład wyszukaj następujący folder: C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe.
Utwórz folder w lokalizacji docelowej dla wbudowanego pakietu sterowników, na przykład C:\EchoDriver. Skopiuj devcon.exe do systemu docelowego. Znajdź certyfikat .cer w systemie hosta. Znajduje się on w tym samym folderze na komputerze hosta w folderze zawierającym skompilowane pliki sterowników. Skopiuj wszystkie pliki z wbudowanego sterownika opisanego wcześniej na komputerze hosta i zapisz je w tym samym folderze, który został utworzony na komputerze docelowym.
Na komputerze docelowym wybierz i przytrzymaj lub kliknij prawym przyciskiem myszy plik certyfikatu, a następnie wybierz Zainstaluj, a następnie postępuj zgodnie z monitami, aby zainstalować certyfikat testowy.
Jeśli potrzebujesz bardziej szczegółowych instrukcji dotyczących konfigurowania komputera docelowego, zobacz Przygotowywanie komputera do ręcznego wdrażania sterowników.
Poniższe instrukcje pokazują, jak zainstalować i przetestować przykładowy sterownik. Poniżej przedstawiono ogólną składnię narzędzia devcon używanego do instalowania sterownika:
devcon install <INF file> <hardware ID>
Plik INF wymagany do zainstalowania tego sterownika jest echo.inf. Plik inf zawiera identyfikator sprzętu do instalowania echo.sys. W próbce echo identyfikator sprzętu to root\ECHO.
Na komputerze docelowym otwórz okno wiersza polecenia jako administrator. Przejdź do folderu pakietu sterowników i wprowadź następujące polecenie:
devcon install echo.inf root\ECHO
Jeśli otrzymasz komunikat o błędzie, że devcon nie jest rozpoznawany, spróbuj dodać ścieżkę do narzędzia devcon. Jeśli na przykład skopiowano go do folderu o nazwie C:\Tools, spróbuj użyć następującego polecenia:
c:\tools\devcon install echo.inf root\ECHO
Zostanie wyświetlone okno dialogowe wskazujące, że sterownik testowy jest niepodpisanym sterownikiem. Wybierz pozycję Zainstaluj ten sterownik mimo wszystko, aby kontynuować.
Napiwek
Jeśli masz jakiekolwiek problemy z instalacją, sprawdź poniższy plik, aby uzyskać więcej informacji. %windir%\inf\setupapi.dev.log
Po pomyślnym zainstalowaniu przykładowego sterownika możesz go przetestować.
Na komputerze docelowym w oknie wiersza polecenia wprowadź devmgmt, aby otworzyć Menedżera urządzeń. W Menedżerze urządzeń, w menu Widok, wybierz pozycję Urządzenia według typu. W drzewie urządzeń znajdź przykładowy sterownik Echo WDF w węźle Sample Device.
Wprowadź echoapp, aby uruchomić aplikację testową echo w celu potwierdzenia, że sterownik działa.
C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully
Wyświetlanie informacji o sterowniku za pomocą narzędzia WinDbg
W tej sekcji ustaw ścieżkę symboli i użyj poleceń debugera jądra, aby wyświetlić informacje o przykładowym sterowniku echo KMDF.
Aby wyświetlić informacje o sterowniku:
W systemie hosta, jeśli zamkniesz debuger, otwórz go ponownie, używając następującego polecenia w oknie wiersza polecenia administratora.
WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Użyj Ctrl+Break (Blokada przewijania), aby przerwać wykonywanie kodu w docelowym systemie.
Aby ustawić ścieżkę symboli na serwer symboli firmy Microsoft w środowisku WinDbg, użyj polecenia
.symfix
.0: kd> .symfix
Aby dodać lokalizację symboli lokalnych do używania symboli lokalnych, dodaj ścieżkę przy użyciu
.sympath+
, a następnie.reload /f
.0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf 0: kd> .reload /f
Polecenie
.reload
z opcją/f
force usuwa wszystkie informacje o symbolach dla określonego modułu i ponownie ładuje symbole. W niektórych przypadkach to polecenie również ponownie ładuje lub zwalnia sam moduł.
Aby korzystać z zaawansowanych funkcji zapewnianych przez usługę WinDbg, należy załadować odpowiednie symbole. Jeśli nie masz poprawnie skonfigurowanych symboli, podczas próby użycia funkcji zależnych od symboli otrzymasz komunikaty wskazujące, że symbole nie są dostępne.
0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.
Istnieje wiele metod, których można użyć do pracy z symbolami. W wielu sytuacjach można skonfigurować komputer tak, aby uzyskiwał dostęp do symboli z serwera symboli udostępnianego przez firmę Microsoft w razie potrzeby. To laboratorium korzysta z tego podejścia. Jeśli symbole w środowisku znajdują się w innej lokalizacji, zmodyfikuj kroki, aby użyć tej lokalizacji. Aby uzyskać więcej informacji, zobacz ścieżka symboli dla debugera systemu Windows.
Aby przeprowadzić debugowanie źródłowe, należy utworzyć sprawdzoną (debugowanie) wersję plików binarnych. Kompilator tworzy pliki symboli (pliki.pdb). Te pliki symboli pokazują debugerowi, w jaki sposób instrukcje binarne odpowiadają wierszom źródłowym. Rzeczywiste pliki źródłowe muszą być również dostępne dla debugera.
Pliki symboli nie zawierają tekstu kodu źródłowego. W przypadku debugowania najlepiej, jeśli linker nie optymalizuje kodu. Debugowanie źródła i dostęp do zmiennych lokalnych są trudniejsze, a czasami prawie niemożliwe, jeśli kod został zoptymalizowany. Jeśli masz problemy z wyświetlaniem zmiennych lokalnych lub wierszy źródłowych, ustaw następujące opcje kompilacji:
set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
Wprowadź następujące polecenie w obszarze polecenia debugera, aby wyświetlić informacje o sterowniku echo:
0: kd> lm m echo* v Browse full module list start end module name fffff801`4ae80000 fffff801`4ae89000 ECHO (private pdb symbols) C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb Loaded symbol image file: ECHO.sys Image path: \SystemRoot\system32\DRIVERS\ECHO.sys Image name: ECHO.sys ...
Aby uzyskać więcej informacji, zobacz lm.
Ponieważ ten zestaw laboratoryjny
prefer_dml
został ustawiony wcześniej, niektóre elementy wynikowe są klikalnymi linkami, które można kliknąć. Aby wyświetlić informacje o symbolach, które zaczynają się literą "a", wybierz link Przeglądaj wszystkie symbole globalne w danych wyjściowych debugowania.0: kd> x /D Echo!a*
Przykład echo nie zawiera żadnych symboli rozpoczynających się literą "a", dlatego wpisz
x ECHO!Echo*
, aby wyświetlić informacje o wszystkich symbolach skojarzonych ze sterownikiem echo rozpoczynającym się od "Echo".0: kd> x ECHO!Echo* fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *) fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *) fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *) fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *) ...
Aby uzyskać więcej informacji, zobacz x (Sprawdzanie symboli).
Rozszerzenie
!lmi
wyświetla szczegółowe informacje o module. Wprowadź!lmi echo
. Dane wyjściowe powinny być podobne do tekstu pokazanego w tym przykładzie:0: kd> !lmi echo Loaded Module Info: [echo] Module: ECHO Base Address: fffff8010bf94000 Image Name: ECHO.sys …
Użyj rozszerzenia
!dh
, aby wyświetlić informacje nagłówka, jak pokazano w tym przykładzie:0: kd> !dh echo File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (i386) 6 number of sections 54AD8A42 time date stamp Wed Jan 07 11:34:26 2015 ...
Wprowadź następujące polecenie, aby zmienić domyślną maskę bitów debugowania, aby wszystkie komunikaty debugowania z systemu docelowego zostały wyświetlone w debugerze:
0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
Niektóre sterowniki wyświetlają dodatkowe informacje, gdy jest używana maska 0xFFFFFFFF. Ustaw maskę na 0x00000000, jeśli chcesz zmniejszyć ilość wyświetlanych informacji.
0: kd> ed nt!Kd_DEFAULT_MASK 0x00000000
Użyj polecenia
dd
, aby potwierdzić, że maska jest ustawiona, aby wyświetlić wszystkie komunikaty debugera.0: kd> dd nt!kd_DEFAULT_MASK fffff802`bb4057c0 ffffffff 00000000 00000000 00000000 fffff802`bb4057d0 00000000 00000000 00000000 00000000 fffff802`bb4057e0 00000001 00000000 00000000 00000000 fffff802`bb4057f0 00000000 00000000 00000000 00000000 fffff802`bb405800 00000000 00000000 00000000 00000000 fffff802`bb405810 00000000 00000000 00000000 00000000 fffff802`bb405820 00000000 00000000 00000000 00000000 fffff802`bb405830 00000000 00000000 00000000 00000000
Wyświetlanie informacji o drzewie urządzeń Plug and Play
W tej sekcji wyświetl informacje o przykładowym sterowniku urządzenia echo i miejscu jego życia w drzewie urządzeń Plug and Play.
Informacje o sterowniku urządzenia w drzewie urządzeń Plug and Play mogą być przydatne do rozwiązywania problemów. Jeśli na przykład sterownik urządzenia nie znajduje się w drzewie urządzeń, może wystąpić problem z instalacją sterownika urządzenia.
Aby uzyskać więcej informacji na temat rozszerzenia debugowania węzła urządzenia, zobacz !devnode.
W systemie hosta, aby wyświetlić wszystkie węzły urządzeń w drzewie urządzeń Plug and Play, wprowadź polecenie
!devnode 0 1
.0: kd> !devnode 0 1 Dumping IopRootDeviceNode (= 0xffffe0005a3a8d30) DevNode 0xffffe0005a3a8d30 for PDO 0xffffe0005a3a9e50 InstancePath is "HTREE\ROOT\0" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe0005a3a3d30 for PDO 0xffffe0005a3a4e50 InstancePath is "ROOT\volmgr\0000" ServiceName is "volmgr" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe0005a324560 for PDO 0xffffe0005bd95ca0… …
Użyj kombinacji Ctrl+F, aby przeszukać wygenerowany wynik w poszukiwaniu nazwy sterownika urządzenia, echo.
Sterownik urządzenia echo powinien zostać załadowany. Użyj polecenia
!devnode 0 1 echo
, aby wyświetlić informacje Plug and Play związane ze sterownikiem urządzenia Echo, jak pokazano w tym przykładzie:0: Kd> !devnode 0 1 echo Dumping IopRootDeviceNode (= 0xffffe0007b725d30) DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960 InstancePath is "ROOT\SAMPLE\0000" ServiceName is "ECHO" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) …
Dane wyjściowe wyświetlane w poprzednim poleceniu obejmują PDO skojarzone z uruchomionym wystąpieniem sterownika, w tym przykładzie 0xffffe0007b71a960. Wprowadź polecenie
!devobj <PDO address>
, aby wyświetlić informacje Plug and Play skojarzone ze sterownikiem urządzenia typu echo. Użyj adresu PDO, który jest wyświetlany przez!devnode
na komputerze, a nie ten pokazany tutaj.0: kd> !devobj 0xffffe0007b71a960 Device object (ffffe0007b71a960) is for: 0000000e \Driver\PnpManager DriverObject ffffe0007b727e60 Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040 Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT Characteristics (0x00000180) FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO Device queue is not busy.
Dane wyjściowe wyświetlane w poleceniu
!devnode 0 1
zawierają adres PDO skojarzony z uruchomionym wystąpieniem sterownika, w tym przykładzie jest to 0xffffe0007b71a960. Wprowadź polecenie!devstack <PDO address>
, aby wyświetlić informacje o Plug and Play skojarzone ze sterownikiem urządzenia. Użyj adresu PDO, który!devnode
wyświetla na twoim komputerze, a nie adresu pokazanego w tym przykładzie.0: kd> !devstack 0xffffe0007b71a960 !DevObj !DrvObj !DevExt ObjectName ffffe000801fee20 \Driver\ECHO ffffe0007f72eff0 > ffffe0007b71a960 \Driver\PnpManager 00000000 0000000e !DevNode ffffe0007b71a630 : DeviceInst is "ROOT\SAMPLE\0000" ServiceName is "ECHO"
Dane wyjściowe pokazują, że masz dość prosty stos sterowników urządzeń. Sterownik ech jest elementem podrzędnym węzła PnPManager. PnPManager jest węzłem głównym.
\Driver\ECHO
\Driver\PnpManager
Ten diagram przedstawia bardziej złożone drzewo węzłów urządzeń.
Aby uzyskać więcej informacji na temat bardziej złożonych stosów sterowników, zobacz stosy sterowników i Węzły urządzeń i stosy urządzeń.
Praca z punktami przerwania i kodem źródłowym
W tej sekcji ustaw punkty przerwania i wykonuj pojedyncze kroki w kodzie źródłowym trybu jądra.
Aby móc przechodzić przez kod i sprawdzać wartości zmiennych w czasie rzeczywistym, włącz punkty przerwania i ustaw ścieżkę do kodu źródłowego.
Punkty przerwania zatrzymują wykonywanie kodu w określonym wierszu kodu. Krok naprzód w kodzie od tego momentu w celu debugowania tej konkretnej sekcji kodu.
Aby ustawić punkt przerwania przy użyciu polecenia debugowania, użyj jednego z następujących b
poleceń.
Polecenie | Opis |
---|---|
bp |
Ustawia aktywny punkt przerwania do momentu, w którym moduł, w którym się znajduje, zostanie rozładowany. |
bu |
Ustawia punkt przerwania, który nie zostaje rozwiązany, gdy moduł jest odciążony, i ponownie włącza się po ponownym załadowaniu modułu. |
bm |
Ustawia punkt przerwania dla symbolu. To polecenie używa bu lub bp odpowiednio i umożliwia używanie symboli wieloznacznych (* ) do ustawiania punktów przerwania dla każdego symbolu, który pasuje, podobnie jak wszystkie metody w klasie. |
Aby uzyskać więcej informacji, zobacz debugowanie kodu źródłowego w usłudze WinDbg.
W systemie hosta użyj interfejsu użytkownika WinDbg, aby potwierdzić, że Debug>tryb źródłowy jest włączony w bieżącej sesji WinDbg.
Wprowadź następujące polecenie, aby dodać lokalną lokalizację kodu do ścieżki źródłowej:
.srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Wprowadź następujące polecenie, aby dodać lokalną lokalizację symboli do ścieżki symboli:
.sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Użyj polecenia
x
, aby zbadać symbole skojarzone ze sterownikiem echo, aby określić nazwę funkcji do użycia dla punktu przerwania. Aby zlokalizować nazwę funkcjiDeviceAdd
, możesz użyć symbolu wieloznakowego lub Ctrl+F.0: kd> x ECHO!EchoEvt* 8b4c7490 ECHO!EchoEvtIoQueueContextDestroy (void *) 8b4c7000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *) 8b4c7820 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *) 8b4cb0e0 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *) 8b4c75d0 ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int) 8b4cb170 ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct …
Dane wyjściowe pokazują, że metoda
DeviceAdd
dla sterownika echa toECHO!EchoEvtDeviceAdd
.Możesz też przejrzeć kod źródłowy, aby znaleźć nazwę funkcji punktu przerwania.
Ustaw punkt przerwania za pomocą polecenia
bm
przy użyciu nazwy sterownika, a następnie nazwy funkcji, na przykładAddDevice
, gdzie chcesz ustawić punkt przerwania, oddzielony wykrzyknikiem. Laboratorium używaAddDevice
do obserwowania procesu ładowania sterownika.0: kd> bm ECHO!EchoEvtDeviceAdd 1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
W połączeniu ze zmiennymi ustawieniami, takimi jak
<module>!<symbol>
,<class>::<method>
,'<file.cpp>:<line number>'
, lub pomiń kilka razy<condition> <#>
. Aby uzyskać więcej informacji, zobacz warunkowe punkty przerwania w systemie WinDbg i innych debugerach systemu Windows.Wyświetl listę bieżących punktów przerwania, aby potwierdzić, że punkt przerwania został ustawiony, wprowadzając polecenie
bl
:0: kd> bl 1 e fffff801`0bf9b1c0 0001 (0001) ECHO!EchoEvtDeviceAdd
Litera "e" w danych wyjściowych tutaj wskazuje, że punkt przerwania numer 1 jest aktywny.
Uruchom ponownie wykonywanie kodu w systemie docelowym, wprowadzając polecenie
g
(go).W systemie docelowym w systemie Windows otwórz Menedżer urządzeń używając ikony lub wprowadzając mmc devmgmt.msc. W Menedżerze urządzeń rozwiń węzeł Przykłady.
Wybierz i przytrzymaj lub kliknij prawym przyciskiem myszy wpis sterownika echa KMDF i wybierz Wyłącz z menu.
Wybierz i przytrzymaj lub kliknij prawym przyciskiem myszy ponownie wpis sterownika echa KMDF, a następnie wybierz Włącz z menu.
W systemie hosta po włączeniu sterownika powinien się uruchomić punkt przerwania debugowania AddDevice. Wykonanie kodu sterownika w systemie docelowym powinno zostać zatrzymane. Po osiągnięciu punktu przerwania wykonanie powinno zostać zatrzymane na początku procedury AddDevice. Dane wyjściowe z polecenia debugowania wyświetlają
Breakpoint 1 hit
.Wykonaj krok po wierszu kodu, wprowadzając polecenie
p
lub naciskając F10, aż osiągniesz następujący koniec procedury AddDevice. Znak nawiasu klamrowego (}
) został wyróżniony, jak pokazano poniżej.
W następnej sekcji sprawdź stan zmiennych po wykonaniu kodu DeviceAdd.
Istniejące punkty przerwania można modyfikować przy użyciu następujących poleceń:
Polecenie | Opis |
---|---|
bl |
Wyświetla listę punktów przerwania. |
bc |
Czyści punkt przerwania z listy. Użyj bc * , aby wyczyścić wszystkie punkty przerwania. |
bd |
Wyłącza punkt przerwania. Użyj bd * , aby wyłączyć wszystkie punkty przerwania. |
be |
Włącza punkt przerwania. Użyj be * , aby włączyć wszystkie punkty przerwania. |
Alternatywnie można również modyfikować punkty przerwania w interfejsie użytkownika usługi WinDbg.
Można również ustawić punkty przerwania uruchamiane, gdy uzyskiwany jest dostęp do lokalizacji pamięci. Użyj polecenia ba
(przerwanie dostępu) z następującą składnią:
ba <access> <size> <address> {options}
Opcja | Opis |
---|---|
e |
execute: gdy procesor pobiera instrukcję z adresu |
r |
odczyt/zapis: gdy procesor CPU odczytuje lub zapisuje na adres |
w |
write: gdy procesor CPU zapisuje do adresu |
W danym momencie można ustawić tylko cztery punkty przerwania danych. Do Ciebie należy upewnienie się, że prawidłowo wyrównujesz dane w celu zadziałania punktu przerwania. Wyrazy muszą kończyć się adresami podzielnymi przez 2, słowa dwords muszą być podzielne przez 4, a czworokątne wyrazy o 0 lub 8.
Aby na przykład ustawić punkt przerwania odczytu/zapisu na określonym adresie pamięci, możesz użyć polecenia takiego jak w tym przykładzie.
ba r 4 0x0003f7bf0
Możesz użyć następujących poleceń do przechodzenia przez kod ze skojarzonymi skrótami klawiszowymi wyświetlanymi w nawiasach.
- Przerwij (Ctrl+Break). To polecenie przerywa działanie systemu, o ile system jest uruchomiony i jest w komunikacji z windbg. Sekwencja w debugerze jądra to Ctrl+C.
- Uruchom polecenie na kursor (F7 lub Ctrl+F10). Umieść kursor w oknie źródłowym lub dezasemblacji, w którym ma zostać przerwane wykonanie, a następnie naciśnij F7. Wykonywanie kodu trwa do tego momentu. Jeśli przepływ wykonywania kodu nie osiągnie punktu wskazanego przez kursor, WinDbg nie zostanie przerwany. Taka sytuacja może wystąpić, jeśli instrukcja IF nie jest wykonywana.
- Uruchom (F5). Uruchamianie do momentu napotkania punktu przerwania lub wystąpienia zdarzenia, takiego jak sprawdzanie usterek.
- Krok do kroku (F10). To polecenie powoduje, że wykonanie kodu postępuje krok po kroku, wykonując jedną instrukcję za jednym razem. Jeśli zostanie napotkane wywołanie, wykonywanie kodu omija wywołanie bez wprowadzania wywoływanej procedury. Jeśli język programowania to C lub C++, a WinDbg jest w trybie źródłowym, tryb źródłowy można włączyć lub wyłączyć za pomocą Debug>Tryb źródłowy.
- Wejdź (F11). To polecenie jest podobne do kroku, z tą różnicą, że wykonanie wywołania przechodzi do wywoływanej procedury.
- Wyjdź (Shift+F11). To polecenie powoduje uruchomienie wykonywania do bieżącej procedury lub bieżącego miejsca w stosie wywołań i wyjście z niego. To polecenie jest przydatne, jeśli masz dość rutyny.
Aby uzyskać więcej informacji, zobacz debugowanie kodu źródłowego w usłudze WinDbg.
Wyświetlanie zmiennych i stosów wywołań
W tej sekcji są wyświetlane informacje o zmiennych i stosach wywołań.
W tym laboratorium założono, że zatrzymano cię w procedurze AddDevice przy użyciu opisanego wcześniej procesu. Aby wyświetlić pokazane tutaj dane wyjściowe, powtórz opisane wcześniej kroki, jeśli to konieczne.
Aby wyświetlić zmienne w systemie hosta, użyj widoku >lokalnego elementu menu, aby wyświetlić zmienne lokalne.
Aby znaleźć lokalizację adresu zmiennej globalnej, wprowadź ? <variable name>
.
- Wyjście (Shift+F11) — to polecenie powoduje, że wykonywanie przebiega do końca bieżącej procedury i opuszcza ją (bieżące miejsce w stosie wywołań). Jest to przydatne, jeśli widziałeś wystarczająco dużo rutyny.
Aby uzyskać więcej informacji, zobacz debugowanie kodu źródłowego w WinDbg (wersja klasyczna) w dokumentacji referencyjnej debugowania.
Sekcja 8. Wyświetlanie zmiennych i stosów wywołań
W sekcji 8 zostaną wyświetlone informacje o zmiennych i stosach wywołań.
W tym ćwiczeniu założono, że zatrzymałeś się na rutynie AddDevice przy użyciu opisanego wcześniej procesu. Aby wyświetlić dane wyjściowe w tym miejscu, powtórz opisane wcześniej kroki, jeśli to konieczne.
<— w systemie hosta
Wyświetlanie zmiennych
Użyj widoku >elementu menu lokalnego, aby wyświetlić zmienne lokalne.
zmienne globalne
Lokalizację adresu zmiennej globalnej można znaleźć, wpisując ? <nazwa zmiennej>.
Zmienne lokalne
Nazwy i wartości wszystkich zmiennych lokalnych dla danej ramki można wyświetlić, wpisując polecenie dv.
Aby wyświetlić nazwy i wartości wszystkich zmiennych lokalnych dla określonej ramki, wprowadź polecenie dv
:
0: kd> dv
Driver = 0x00001fff`7ff9c838
DeviceInit = 0xffffd001`51978190
status = 0n0
Stos wywołań to łańcuch wywołań funkcji, które doprowadziły do bieżącej lokalizacji licznika programu. Górna funkcja w stosie wywołań jest bieżącą funkcją, a następną funkcją jest funkcja, która wywołała bieżącą funkcję, i tak dalej.
Aby wyświetlić stos wywołań, użyj poleceń k*
.
Polecenie | Opis |
---|---|
kb |
Wyświetla stos i pierwsze trzy parametry. |
kp |
Wyświetla stosy i pełną listę parametrów. |
kn |
Umożliwia wyświetlenie stosu z informacjami o ramce umieszczonymi obok niego. |
Jeśli chcesz zachować dostępny stos wywołań w systemie hosta, wybierz widok >stos wywołań, aby go wyświetlić. Wybierz kolumny w górnej części okna, aby przełączyć wyświetlanie dodatkowych informacji.
Użyj polecenia
kn
, aby wyświetlić stos wywołań podczas debugowania przykładowego kodu adaptera w trybie przerwania.3: kd> kn # Child-SP RetAddr Call Site 00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138] 01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61] 02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72] 03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104] 04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397] 05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390] ...
Stos wywołań pokazuje, że jądro (nt) wywołało kod Plug and Play (PnP), który wywołał kod ramowej struktury sterowników (WDF), który później wywołał funkcję DeviceAdd
sterownika echa.
Wyświetlanie procesów i wątków
W tej sekcji są wyświetlane informacje o procesach i wątkach uruchomionych w trybie jądra.
Procesy
Informacje o procesie można wyświetlić lub ustawić przy użyciu rozszerzenia !process debugera. Ustaw punkt przerwania, aby zbadać proces używany podczas odtwarzania dźwięku.
W systemie hosta wprowadź polecenie
dv
, aby zbadać zmienne regionalne skojarzone z procedurąEchoEvtIo
:0: kd> dv ECHO!EchoEvtIo* ECHO!EchoEvtIoQueueContextDestroy ECHO!EchoEvtIoWrite ECHO!EchoEvtIoRead
Wyczyść poprzednie punkty przerwania przy użyciu
bc *
:0: kd> bc *
Ustaw punkt przerwania symbolu w procedurach
EchoEvtIo
przy użyciu następującego polecenia:0: kd> bm ECHO!EchoEvtIo* 2: aade5490 @!”ECHO!EchoEvtIoQueueContextDestroy” 3: aade55d0 @!”ECHO!EchoEvtIoWrite” 4: aade54c0 @!”ECHO!EchoEvtIoRead”
Wyświetl listę punktów przerwania, aby potwierdzić, że punkt przerwania został prawidłowo ustawiony:
0: kd> bl 1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197] 0001 (0001) ECHO!EchoEvtIoQueueContextDestroy ...
Wprowadź
g
, aby ponownie uruchomić wykonywanie kodu:0: kd> g
Na systemie docelowym uruchom program testowy sterownika
EchoApp.exe
.W systemie hosta po uruchomieniu aplikacji testowej wywoływana jest procedura we/wy w sterowniku. To wywołanie powoduje uruchomienie punktu przerwania i zatrzymanie wykonywania kodu sterownika w systemie docelowym.
Breakpoint 2 hit ECHO!EchoEvtIoWrite: fffff801`0bf95810 4c89442418 mov qword ptr [rsp+18h],r8
Użyj polecenia
!process
, aby wyświetlić bieżący proces, który jest zaangażowany w uruchamianie echoapp.exe:0: kd> !process PROCESS ffffe0007e6a7780 SessionId: 1 Cid: 03c4 Peb: 7ff7cfec4000 ParentCid: 0f34 DirBase: 1efd1b000 ObjectTable: ffffc001d77978c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf270050 ElapsedTime 00:00:00.052 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (682, 50, 345) (2728KB, 200KB, 1380KB) PeakWorkingSetSize 652 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 688 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe00080e32080 Cid 03c4.0ec0 Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
Dane wyjściowe pokazują, że proces jest skojarzony z wątkiem echoapp.exe, który był uruchomiony, gdy punkt kontrolny w zdarzeniu zapisu w sterowniku został przekroczony. Aby uzyskać więcej informacji, zobacz !process.
Użyj
!process 0 0
, aby wyświetlić podsumowanie informacji dla wszystkich procesów. W danych wyjściowych użyj Ctrl+F, aby zlokalizować ten sam adres procesu dla procesu skojarzonego z obrazem echoapp.exe. W tym przykładzie adres procesu toffffe0007e6a7780
.... PROCESS ffffe0007e6a7780 SessionId: 1 Cid: 0f68 Peb: 7ff7cfe7a000 ParentCid: 0f34 DirBase: 1f7fb9000 ObjectTable: ffffc001cec82780 HandleCount: 34. Image: echoapp.exe ...
Zarejestruj identyfikator procesu skojarzony z echoapp.exe, aby użyć go w dalszej części tego laboratorium. Możesz również użyć Ctrl+C, aby skopiować adres do buforu kopiowania do późniejszego użycia.
_____________________________________________________( adres procesuechoapp.exe)
Wprowadź
g
zgodnie z wymaganiami w debugerze, aby uruchomić kod do przodu, aż echoapp.exe zakończy działanie. Osiąga punkt przerwania w zdarzeniu odczytu i zapisu wiele razy. Po zakończeniu echoapp.exe przejdź do debugera, naciskając Ctrl+ScrLk (Ctrl+Break).Użyj polecenia
!process
, aby potwierdzić, że korzystasz z innego procesu. W przedstawionych tutaj danych wyjściowych proces, który ma wartość Obrazu System, różni się od wartości Obrazu Echo.1: kd> !process PROCESS ffffe0007b65d900 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 001ab000 ObjectTable: ffffc001c9a03000 HandleCount: 786. Image: System VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64. DeviceMap ffffc001c9a0c220 Token ffffc001c9a05530 ElapsedTime 21:31:02.516 ...
Dane wyjściowe pokazują, że proces systemowy ffffe0007b65d900 był uruchomiony po zatrzymaniu systemu operacyjnego.
Użyj polecenia
!process
, aby spróbować sprawdzić identyfikator procesu, który został skojarzony z wcześniej zarejestrowanymi ,echoapp.exe,. Podaj zarejestrowany wcześniej adres procesu echoapp.exe zamiast przykładowego adresu procesu pokazanego w tym przykładzie.0: kd> !process ffffe0007e6a7780 TYPE mismatch for process object at 82a9acc0
Obiekt procesu nie jest już dostępny, ponieważ proces echoapp.exe nie jest już uruchomiony.
Wątki
Polecenia do wyświetlania i ustawiania wątków są podobne do poleceń dla procesów. Użyj polecenia !thread, aby wyświetlić wątki. Użyj .thread, aby ustawić bieżące wątki.
W systemie hosta wprowadź
g
w debugerze, aby ponownie uruchomić wykonywanie kodu w systemie docelowym.W systemie docelowym uruchom program testowy EchoApp.exe.
W systemie hosta punkt przerwania został osiągnięty, a wykonywanie kodu zostało zatrzymane.
Breakpoint 4 hit ECHO!EchoEvtIoRead: aade54c0 55 push ebp
Aby wyświetlić uruchomione wątki, wprowadź !wątek. Powinny zostać wyświetlone informacje podobne do poniższego przykładu:
0: kd> !thread THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0008096c900 Image: echoapp.exe ...
Zanotuj nazwę obrazu echoapp.exe. Oznacza to, że patrzysz na wątek skojarzony z aplikacją testową.
Użyj polecenia
!process
, aby określić, czy ten wątek jest jedynym wątkiem uruchomionym w procesie skojarzonym z echoapp.exe. Numer wątku działającego w procesie to ten sam wątek, który wyświetliło polecenie!thread
.0: kd> !process PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf5dc050 ElapsedTime 00:00:00.048 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (681, 50, 345) (2724KB, 200KB, 1380KB) PeakWorkingSetSize 651 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 686 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
Użyj polecenia
!process 0 0
, aby zlokalizować adres procesu dwóch powiązanych procesów i zarejestrować ten adres procesu tutaj.Cmd.exe: ____________________________________________________________
EchoApp.exe: _______________________________________________________
0: kd> !process 0 0 … PROCESS ffffe0007bbde900 SessionId: 1 Cid: 0f34 Peb: 7ff72dfa7000 ParentCid: 0c64 DirBase: 19c5fa000 ObjectTable: ffffc001d8c2f300 HandleCount: 31. Image: cmd.exe … PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe …
Możesz też użyć
!process 0 17
, aby wyświetlić szczegółowe informacje o każdym procesie. Dane wyjściowe tego polecenia mogą być długie. Dane wyjściowe można przeszukiwać za pomocą Ctrl+F.Użyj polecenia
!process
, aby wyświetlić informacje dotyczące procesów działających na twoim komputerze. Podaj adres procesu z danych wyjściowych!process 0 0
, a nie adres przedstawiony w tym przykładzie.Te przykładowe dane wyjściowe są przeznaczone dla identyfikatora procesu cmd.exe, który został zarejestrowany wcześniej. Nazwa obrazu dla tego identyfikatora procesu to cmd.exe.
0: kd> !process ffffe0007bbde900 PROCESS ffffe0007bbde900 SessionId: 1 Cid: 0f34 Peb: 7ff72dfa7000 ParentCid: 0c64 DirBase: 19c5fa000 ObjectTable: ffffc001d8c2f300 HandleCount: 31. Image: cmd.exe VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001d8c48050 ElapsedTime 21:33:05.840 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 24656 QuotaPoolUsage[NonPagedPool] 3184 Working Set Sizes (now,min,max) (261, 50, 345) (1044KB, 200KB, 1380KB) PeakWorkingSetSize 616 VirtualSize 2097164 Mb PeakVirtualSize 2097165 Mb PageFaultCount 823 MemoryPriority FOREGROUND BasePriority 8 CommitCharge 381 THREAD ffffe0007cf34880 Cid 0f34.0f1c Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable ffffe0008096c900 ProcessObject Not impersonating ...
Te przykładowe dane wyjściowe są przeznaczone dla identyfikatora procesu echoapp.exe, który został zarejestrowany wcześniej.
0: kd> !process ffffe0008096c900 PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf5dc050 ElapsedTime 00:00:00.048 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (681, 50, 345) (2724KB, 200KB, 1380KB) PeakWorkingSetSize 651 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 686 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating ...
Zarejestruj w tym miejscu pierwszy adres wątku skojarzony z dwoma procesami.
Cmd.exe: ____________________________________________________
EchoApp.exe: _________________________________________________
Użyj polecenia
!Thread
, aby wyświetlić informacje o bieżącym wątku.0: kd> !Thread THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0008096c900 Image: echoapp.exe Attached Process N/A Image: N/A ...
Zgodnie z oczekiwaniami bieżący wątek jest wątkiem skojarzonym z echoapp.exe i jest w stanie działania.
Użyj polecenia
!Thread
, aby wyświetlić informacje o wątku skojarzonym z procesem cmd.exe. Podaj zarejestrowany wcześniej adres wątku.0: kd> !Thread ffffe0007cf34880 THREAD ffffe0007cf34880 Cid 0f34.0f1c Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable ffffe0008096c900 ProcessObject Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0007bbde900 Image: cmd.exe Attached Process N/A Image: N/A Wait Start TickCount 4134621 Ticks: 0 Context Switch Count 4056 IdealProcessor: 0 UserTime 00:00:00.000 KernelTime 00:00:01.421 Win32 Start Address 0x00007ff72e9d6e20 Stack Init ffffd0015551dc90 Current ffffd0015551d760 Base ffffd0015551e000 Limit ffffd00155518000 Call 0 Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5 Child-SP RetAddr : Args to Child : Call Site ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109] ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347] ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619] ...
Ten wątek jest skojarzony z cmd.exe i znajduje się w stanie oczekiwania.
Podaj adres oczekującego wątku CMD.exe, aby zmienić kontekst na ten oczekujący wątek.
0: kd> .Thread ffffe0007cf34880 Implicit thread is now ffffe000`7cf34880
Użyj polecenia
k
, aby wyświetlić stos wywołań skojarzony z wątkiem oczekiwania.0: kd> k *** Stack trace for last set context - .thread/.cxr resets it # Child-SP RetAddr Call Site 00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109] 01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347] 02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619] 03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683] ...
Elementy stosu wywołań, takie jak
KiCommitThreadWait
wskazują, że ten wątek nie jest uruchomiony zgodnie z oczekiwaniami.
Aby uzyskać więcej informacji na temat wątków i procesów, zobacz następujące odwołania:
IRQL, rejestruje i kończy sesję WinDbg
W tej sekcji wyświetl poziom żądania przerwania (IRQL) i zawartość rejestrów.
Wyświetl zapisany IRQL
Środowisko IRQL służy do zarządzania priorytetem obsługi przerwań. Każdy procesor ma ustawienie IRQL, które wątki mogą podnieść lub obniżyć. Przerwania występujące w ustawieniu IRQL procesora lub poniżej tego ustawienia są maskowane i nie zakłócają bieżącej operacji. Przerwania występujące powyżej ustawienia IRQL procesora mają pierwszeństwo przed bieżącą operacją.
W systemie hosta rozszerzenie !irql wyświetla IRQL na bieżącym procesorze komputera docelowego przed wystąpieniem przerwania debugera. Gdy komputer docelowy przechodzi do debugera, poziom IRQL zmienia się, ale poziom IRQL, który był aktywny tuż przed przerwą debugera, jest zapisywany i wyświetlany przez !irql
.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
Wyświetlanie rejestrów
Na systemie hosta wyświetl zawartość rejestrów dla bieżącego wątku na bieżącym procesorze, używając polecenia r (Rejestry).
0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
r8=000000000000003e r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0 nv up ei pl nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc int 3
Alternatywnie możesz wyświetlić zawartość rejestrów, wybierając opcję Wyświetl>Rejestry. Aby uzyskać więcej informacji, zobacz r (Rejestry).
Wyświetlanie zawartości rejestrów może być przydatne podczas przechodzenia krok po kroku przez wykonywanie kodu języka asemblera i w innych scenariuszach. Aby uzyskać więcej informacji na temat dezasemblacji języka asemblera, zobacz Adnotowana dezasemblacja x86 i Adnotowana dezasemblacja x64.
Aby uzyskać informacje na temat zawartości rejestru, zobacz architekturę x86 oraz architekturę x64.
Kończ sesję WinDbg
Jeśli chcesz pozostawić dołączony debuger, ale chcesz pracować na komputerze docelowym, wyczyść wszystkie punkty przerwania przy użyciu komendy bc *
, aby komputer docelowy nie próbował nawiązać połączenia z debugerem hosta. Następnie użyj polecenia g
, aby umożliwić ponowne uruchomienie komputera docelowego.
Aby zakończyć sesję debugowania, w systemie hosta wejdź do debugera i wprowadź polecenie qd
(Zamknij i odłącz) lub z menu wybierz Zatrzymaj debugowanie.
0: kd> qd
Aby uzyskać więcej informacji, zobacz Zakończenie sesji debugowania w usłudze WinDbg.
Zasoby debugowania systemu Windows
Więcej informacji znajduje się w temacie Debugowanie systemu Windows. Niektóre z tych książek używają wcześniejszych wersji systemu Windows, takich jak Windows Vista w ich przykładach, ale omówione pojęcia mają zastosowanie do większości wersji systemu Windows.
Książki
- Zaawansowane debugowanie systemu Windows przez Mario Hewardt i Daniel Pravat
- Debugowanie w systemie Windows: Praktyczny przewodnik strategii debugowania i diagnozowania w systemie Windows® autor: Tarik Soulami
- Windows Internals autorzy Pavel Yosifovich, Alex Ionescu, Mark Russinovich i David Solomon
Wideo
Dostawcy szkoleń