Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
To laboratorium zawiera praktyczne ćwiczenia, które pokazują, jak debugować sterownik urządzenia audio Sysvad działający w trybie jądra.
Microsoft Windows Debugger (WinDbg) to zaawansowane narzędzie do debugowania opartego na systemie Windows, którego można użyć do przeprowadzania debugowania w trybie użytkownika i w trybie jądra. WinDbg zapewnia debugowanie na poziomie źródłowym dla jądra systemu Windows, sterowników trybu jądra i usług systemowych, a także aplikacji i sterowników trybu użytkownika.
WinDbg może przechodzić przez kod źródłowy, ustawiać punkty przerwania, wyświetlać zmienne (w tym obiekty języka C++), ślady stosu i pamięć. Okno Polecenia debugera umożliwia użytkownikowi wydawanie różnych poleceń.
Konfiguracja laboratorium
Aby ukończyć laboratorium, potrzebny będzie następujący sprzęt:
- Komputer przenośny lub komputer stacjonarny (host) z systemem Windows 10
- Komputer przenośny lub komputer stacjonarny (docelowy) z systemem Windows 10
- Koncentrator sieciowy/router i kable sieciowe do łączenia dwóch komputerów
- Dostęp do Internetu w celu pobrania plików symboli
Aby ukończyć laboratorium, potrzebne będzie następujące oprogramowanie.
- Microsoft Visual Studio 2017
- Windows Software Development Kit (SDK) dla systemu Windows 10
- Windows Driver Kit (WDK) dla systemu Windows 10
- Przykładowy sterownik dźwięku Sysvad dla systemu Windows 10
Aby uzyskać informacje na temat pobierania i instalowania zestawu WDK, zobacz Download the Windows Driver Kit (WDK).
Przewodnik po debugowaniu usługi Sysvad
To laboratorium przeprowadzi Cię przez proces debugowania sterownika trybu jądra. W ćwiczeniach użyto przykładowego sterownika audio wirtualnego Syvad. Ponieważ sterownik audio Syvad nie współdziała z rzeczywistym sprzętem audio, może być używany na większości urządzeń. Laboratorium obejmuje następujące zadania:
- Sekcja 1. Nawiązywanie połączenia z sesją WinDbg w trybie jądra
- Sekcja 2. Polecenia i techniki debugowania w trybie jądra
- Sekcja 3. Pobieranie i kompilowanie sterownika audio Sysvad
- Sekcja 4. Instalowanie sterownika audio Sysvad w systemie docelowym
- Sekcja 5. Wyświetlanie informacji o sterowniku za pomocą narzędzia WinDbg
- Sekcja 6. Wyświetlanie informacji o drzewie urządzeń Plug and Play
- Sekcja 7. Praca z punktami przerwania i kodem źródłowym
- Sekcja 8. Przyjrzyj się zmiennym
- Sekcja 9. Wyświetlanie stosów wywołań
- Sekcja 10. Wyświetlanie procesów i wątków
- Sekcja 11: IRQL, rejestry i deasemblacja
- Sekcja 12. Praca z pamięcią
- Sekcja 13. Zakończenie sesji WinDbg
- Sekcja 14. Zasoby debugowania systemu Windows
Laboratorium sterowników Echo
Sterownik Echo jest prostszym sterownikiem niż sterownik audio Sysvad. Jeśli dopiero zaczynasz korzystać z WinDbg, możesz najpierw rozważyć ukończenie laboratorium "Debugowanie uniwersalnych sterowników - Krok po kroku (tryb jądra Echo)". To laboratorium ponownie korzysta z instrukcji z tamtego laboratorium, więc jeśli ukończyłeś tamto laboratorium, możesz pominąć sekcje 1 i 2 tutaj.
Sekcja 1. Nawiązywanie połączenia z sesją WinDbg w trybie jądra
W sekcji 1 skonfigurujesz 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. WinDbg działa w systemie hosta , a sterownik Sysvad działa w systemie docelowym .
Użyj koncentratora sieciowego lub routera sieciowego oraz kabli sieciowych, aby połączyć dwa komputery.
Aby pracować z aplikacjami w trybie jądra i używać systemu WinDbg, zalecamy użycie sieci KDNET przez transport Ethernet. Aby uzyskać informacje o sposobie korzystania z protokołu transportowego Ethernet, zobacz Wprowadzenie do windbg (Kernel-Mode). 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, wykonaj następujące kroki.
<— w systemie hosta
- Otwórz wiersz polecenia w systemie hosta i wpisz ipconfig /all , aby określić jego adres IP.
C:\>ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : TARGETPC
...
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b3
Autoconfiguration IPv4 Address. . : 169.182.1.1
Subnet Mask . . . . . . . . . . . : 255.255.0.0
Default Gateway . . . . . . . . . :
Zarejestruj adres IP systemu hosta: ______________________________________
Zarejestruj nazwę hosta systemu hosta: ______________________________________
-> W systemie docelowym
- Otwórz wiersz polecenia w systemie docelowym i użyj polecenia ping , aby potwierdzić łączność sieciową między dwoma systemami. Użyj rzeczywistego adresu IP zarejestrowanego systemu hostów zamiast 169.182.1.1, który jest wyświetlany w przykładowych danych wyjściowych.
C:\> ping 169.182.1.1
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
Aby użyć narzędzia KDNET do włączenia debugowania w trybie jądra w systemie docelowym, wykonaj następujące kroki.
W systemie hosta znajdź katalog KDNET zestawu WDK. Domyślnie znajduje się on tutaj.
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
W tym laboratorium przyjęto, ż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 uruchomienie tej samej wersji bitowej narzędzi na hoście, na którym działa element docelowy. Na przykład, jeśli docelowy system działa na 32-bitowym Windows, uruchom 32-bitową wersję debugera na hoście. Aby uzyskać więcej informacji, zobacz Wybieranie 32-bitowych lub 64-bitowych narzędzi debugowania.
Znajdź te dwa pliki i skopiuj je na udział sieciowy lub pendrive, aby były dostępne na docelowym komputerze.
kdnet.exe
VerifiedNICList.xml
Na komputerze docelowym otwórz okno wiersza polecenia jako administrator. Wprowadź to polecenie, aby sprawdzić, czy karta sieciowa na komputerze docelowym jest obsługiwana.
C:\KDNET>kdnet
Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
- Wpisz to polecenie, aby ustawić adres IP systemu hosta. Użyj rzeczywistego adresu IP zarejestrowanego systemu hostów zamiast 169.182.1.1, który jest wyświetlany w przykładowych danych wyjściowych. Wybierz unikatowy adres portu dla każdej pary docelowej/hosta, z którą pracujesz, na przykład 50010.
C:\>kdnet 169.182.1.1 50010
Enabling network debugging on Intel(R) 82577LM Gigabit Network Connection.
Key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Ważne
Przed użyciem bcDEdit do zmiany informacji rozruchowych może być konieczne tymczasowe zawieszenie funkcji zabezpieczeń systemu Windows, takich jak BitLocker i Bezpieczny rozruch na komputerze testowym. Włącz ponownie te funkcje zabezpieczeń podczas testowania i 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.
- Wpisz to polecenie, aby potwierdzić, że ustawienia dbgsettings są ustawione poprawnie.
C:\> bcdedit /dbgsettings
busparams 0.25.0
key 2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype NET
hostip 169.182.1.1
port 50010
dhcp Yes
The operation completed successfully.
Skopiuj automatycznie wygenerowany unikatowy klucz do pliku tekstowego, aby uniknąć konieczności wpisywania go na komputerze hosta. Skopiuj plik tekstowy z kluczem do systemu hosta.
UwagaZapory i debugery
Jeśli zostanie wyświetlone wyskakujące okienko z zapory i chcesz użyć debugera, zaznacz wszystkie trzy pola.
<— w systemie hosta
- Na komputerze hosta otwórz okno wiersza polecenia jako administrator. Przejdź do katalogu WinDbg.exe. Użyjemy wersji x64 WinDbg.exe z zestawu Windows Driver Kit (WDK), która została zainstalowana jako część instalacji pakietu Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- Uruchom narzędzie WinDbg z debugowaniem użytkownika zdalnego przy użyciu następującego polecenia. Wartość klucza i portu jest zgodna z tym, co zostało ustawione wcześniej przy użyciu BCDEdit na docelowym urządzeniu.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
->W systemie docelowym
Uruchom ponownie system docelowy.
<-W systemie hosta
W ciągu minuty lub dwóch dane wyjściowe debugowania powinny być wyświetlane w systemie hosta.
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. Polecenia można wpisać w mniejszym okienku (okienku wprowadzania poleceń) w dolnej części okna i wyświetlić 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 w dół, aby przewijać historię poleceń. Po wyświetleniu polecenia możesz go edytować lub nacisnąć ENTER , aby uruchomić polecenie.
Sekcja 2. Polecenia i techniki debugowania w trybie jądra
W sekcji 2 użyjesz poleceń debugowania, aby wyświetlić informacje o systemie docelowym.
<— w systemie hosta
Włączanie języka znaczników debugera (DML) przy użyciu .prefer_dml
Niektóre polecenia debugowania wyświetlają tekst przy użyciu języka znaczników debugera, który można wybrać, aby szybko zebrać więcej informacji.
- Użyj Ctrl+Break (Blokada przewijania) w WinDBg, aby przerwać działanie kodu, który działa na systemie docelowym. Reagowanie systemu docelowego może zająć trochę czasu.
- Wpisz następujące polecenie, aby włączyć język DML w oknie Polecenia debugera.
0: kd> .prefer_dml 1
DML versions of commands on by default
Skorzystaj z pliku hh, aby uzyskać pomoc
Dostęp do pomocy poleceń referencyjnych można uzyskać przy użyciu polecenia hh .
- Wpisz następujące polecenie, aby wyświetlić pomoc dotyczącą poleceń dla .prefer_dml.
0: kd> .hh .prefer_dml
Plik pomocy debugera wyświetli pomoc dotyczącą polecenia .prefer_dml .
Wyświetlanie wersji systemu Windows w systemie docelowym
- Wyświetl szczegółowe informacje o wersji systemu docelowego, wpisując polecenie vertarget (Pokaż wersję komputera docelowego) w oknie WinDbg.
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
Wyświetlanie listy załadowanych modułów
- Możesz sprawdzić, czy pracujesz z odpowiednim procesem trybu jądra, wyświetlając załadowane moduły, wpisując polecenie lm (lista załadowanych modułów) w oknie WinDbg.
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
...
Uwaga Dane wyjściowe, które zostały pominięte, są oznaczone "… " w tym laboratorium.
Ponieważ nie ustawiono jeszcze ścieżki symboli i załadowanych symboli, w debugerze są dostępne ograniczone informacje.
Sekcja 3. Pobieranie i kompilowanie sterownika audio Sysvad
W sekcji 3 pobierzesz i skompilujesz sterownik audio Sysvad.
Zazwyczaj będziesz pracować z własnym kodem sterownika podczas korzystania z usługi WinDbg. Aby zapoznać się z debugowaniem sterowników audio, używany jest sterownik przykładowego dźwięku wirtualnego Sysvad. Ten przykład służy do zilustrowania sposobu, w jaki można wykonać pojedynczy krok za pomocą natywnego kodu trybu jądra. Ta technika może być bardzo cenna w przypadku debugowania złożonych problemów z kodem trybu jądra.
Aby pobrać i skompilować przykładowy sterownik audio sysvad, wykonaj następujące kroki.
Pobierz i wyodrębnij przykład audio Sysvad z usługi GitHub
Możesz użyć przeglądarki, aby wyświetlić przykład Sysvad i plik Readme.md tutaj:
https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad
W tym laboratorium pokazano, jak pobrać uniwersalne przykłady sterowników w jednym pliku zip.
a. Pobierz plik master.zip na lokalny dysk twardy.
https://github.com/Microsoft/Windows-driver-samples/archive/master.zip
b. Zaznacz i przytrzymaj (lub kliknij prawym przyciskiem myszy) Windows-driver-samples-master.zip, a następnie wybierz Wyodrębnij wszystko. Określ nowy folder lub przejdź do istniejącego folderu, który będzie przechowywać wyodrębnione pliki. Można na przykład określić C:\WDK_Samples\ jako nowy folder, do którego wyodrębniono pliki.
c. Po wyodrębnieniu plików przejdź do następującego podfolderu.
C:\WDK_Samples\Sysvad
Otwieranie rozwiązania sterownika w programie Visual Studio
W programie Visual Studio wybierz pozycję Plik>Otwórz>projekt/rozwiązanie... i przejdź do folderu zawierającego wyodrębnione pliki (na przykład C:\WDK_Samples\Sysvad). Kliknij dwukrotnie plik rozwiązania Syvad .
W programie Visual Studio znajdź Eksploratora rozwiązań. (Jeśli ta opcja nie jest jeszcze otwarta, wybierz pozycję Eksplorator rozwiązań z menu Widok ). W Eksploratorze rozwiązań można zobaczyć jedno rozwiązanie z wieloma projektami.
Ustaw konfigurację i platformę próbki
W Eksploratorze rozwiązań wybierz i przytrzymaj (lub kliknij prawym przyciskiem myszy) Rozwiązanie "sysvad" (7 z 7 projektów) i wybierz pozycję Configuration Manager. Upewnij się, że ustawienia konfiguracji i platformy są takie same dla czterech projektów. Domyślnie konfiguracja jest ustawiona na "Win10 Debug", a platforma jest ustawiona na "Win64" dla wszystkich projektów. Jeśli wprowadzisz jakiekolwiek zmiany konfiguracji i/lub platformy dla jednego projektu, musisz wprowadzić te same zmiany dla pozostałych trzech projektów.
Nuta W tym laboratorium założono, że jest używany 64-bitowy system Windows. Jeśli używasz 32-bitowego systemu Windows, skompiluj sterownik na 32 bity.
Sprawdź podpisywanie sterownika
Znajdź plik TabletAudioSample. Otwórz stronę właściwości sterownika Sysvad i upewnij się, że Podpisywanie sterownika>Tryb podpisu jest ustawiony na Podpis testowy.
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.
Tworzenie przykładu przy użyciu programu Visual Studio
W programie Visual Studio wybierz pozycję Build>Build Solution.
Okna kompilacji powinny wyświetlać komunikat wskazujący, że kompilacja dla wszystkich sześciu projektów zakończyła się pomyślnie.
Wskazówka
Jeśli wystąpi komunikat o błędzie kompilacji, użyj numeru błędu kompilacji, aby określić poprawkę. Na przykład błąd MSBuild MSB8040 opisuje sposób pracy z bibliotekami z zabezpieczeniami Spectre.
Lokalizowanie skompilowanych plików sterowników
W Eksploratorze plików przejdź do folderu zawierającego wyodrębnione pliki dla przykładu. Na przykład przejdź do folderu C:\WDK_Samples\Sysvad, 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 na przykład pozostawisz ustawienia domyślne bez zmian, skompilowane pliki sterowników zostaną zapisane w folderze o nazwie \x64\Debug dla 64-bitowej kompilacji debugowania.
Przejdź do folderu zawierającego pliki skompilowane dla sterownika TabletAudioSample:
C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. Folder będzie zawierać sterownik TabletAudioSample .SYS, plik symbolu .pdp oraz plik .inf. Należy również zlokalizować biblioteki dll DelayAPO, KWSApo i KeywordDetectorContosoAdapter oraz pliki symboli.
Aby zainstalować sterownik, potrzebne będą następujące pliki.
Nazwa pliku Opis TabletAudioSample.sys Plik sterownika. TabletAudioSample.pdb Plik symbolu sterownika. tabletaudiosample.inf Plik informacyjny (INF), który zawiera informacje potrzebne do zainstalowania sterownika. KeywordDetectorContosoAdapter.dll Przykładowy detektor słów kluczowych. KeywordDetectorContosoAdapter.pdb Przykładowy plik symbolu narzędzia do wykrywania słów kluczowych. DelayAPO.dll Przykładowe opóźnienie APO. DelayAPO.pdb Plik symboli opóźnienia APO. KWSApo.dll Przykładowy detektor słowa kluczowego APO. KWSApo.pdb Plik symbolu wykrywacza słów kluczowych. TabletAudioSample.cer Plik certyfikatu TabletAudioSample. Znajdź pamięć USB lub skonfiguruj udział sieciowy, aby skopiować pliki sterowników z hosta do systemu docelowego.
W następnej sekcji skopiujesz kod do systemu docelowego i zainstalujesz i przetestujesz sterownik.
Sekcja 4. Instalowanie przykładu sterownika audio Sysvad w systemie docelowym
W sekcji 4 zainstalujesz sterownik audio Sysvad za pomocą narzędzia devcon.
-> W systemie docelowym
Komputer, na którym jest instalowany sterownik, określa się jako komputer docelowy lub komputer testowy . Zazwyczaj jest to oddzielny komputer 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 sterownika należy przygotować komputer docelowy, włączając podpisywanie testowe. Po tym będziesz gotowy do uruchomienia zbudowanego przykładu sterownika na systemie docelowym.
Aby zainstalować sterownik w systemie docelowym, wykonaj następujące kroki.
Włącz testowo podpisane sterowniki
Aby włączyć możliwość uruchamiania podpisanych sterowników testowych:
Otwórz pozycję Ustawienia systemu Windows.
W Update and Securitywybierz Recovery.
W obszarze Zaawansowane uruchamianiekliknij Uruchom ponownie teraz.
Po ponownym uruchomieniu komputera wybierz pozycję Rozwiązywanie problemów.
Następnie wybierz pozycję Opcje zaawansowane, Ustawienia uruchamiania , a następnie wybierz pozycję Uruchom ponownie.
Wybierz Wyłącz wymuszanie podpisu sterownika, naciskając F7.
Komputer uruchomi się z zastosowaniem nowych wartości.
-> W systemie docelowym
Instalowanie sterownika
Poniższe instrukcje pokazują, jak zainstalować i przetestować przykładowy sterownik.
Plik INF wymagany do zainstalowania tego sterownika to TabletAudioSample.inf. Na komputerze docelowym otwórz okno wiersza polecenia jako administrator. Przejdź do folderu pakietu sterowników, kliknij prawym przyciskiem myszy plik TabletAudioSample.inf, a następnie wybierz polecenie Zainstaluj.
Zostanie wyświetlone okno dialogowe wskazujące, że sterownik testowy jest sterownikiem bez podpisu cyfrowego. Wybierz opcję Zainstaluj ten sterownik mimo to, aby kontynuować.
Wskazówka
Jeśli masz jakiekolwiek problemy z instalacją, sprawdź poniższy plik, aby uzyskać więcej informacji.
%windir%\inf\setupapi.dev.logAby uzyskać bardziej szczegółowe instrukcje, zobacz Konfigurowanie komputera na potrzeby wdrażania sterowników, testowania i debugowania.
Plik INF zawiera identyfikator sprzętu potrzebny do zainstalowania tabletaudiosample.sys. W przykładzie Syvad identyfikator sprzętu to:
root\sysvad_TabletAudioSampleBadanie sterownika w Menedżerze urządzeń
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ądzenia znajdź pozycję Wirtualne urządzenie audio (WDM) — przykład tabletu w węźle Urządzenie audio. Zazwyczaj znajduje się to w węźle Dźwięk, wideo i kontrolery gier . Upewnij się, że jest ona zainstalowana i aktywna.
Wyróżnij sterownik rzeczywistego sprzętu na komputerze w Menedżerze urządzeń. Następnie wybierz i przytrzymaj (lub kliknij prawym przyciskiem myszy) sterownik i wybierz pozycję Wyłącz, aby wyłączyć sterownik.
Potwierdź w Menedżerze urządzeń, że sterownik sprzętu audio wyświetla strzałkę w dół wskazującą, że jest wyłączona.
Po pomyślnym zainstalowaniu przykładowego sterownika możesz go przetestować.
Testowanie sterownika dźwięku Sysvad
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ądzenia znajdź pozycję Wirtualne urządzenie audio (WDM) — przykład tabletu.
Otwórz Panel sterowania i przejdź do pozycji Sprzęt i Dźwięk>Zarządzaj urządzeniami audio. W oknie dialogowym Dźwięk wybierz ikonę głośnika z etykietą Virtual Audio Device (WDM) — Przykład tabletu, a następnie wybierz opcję Ustaw wartość domyślną, ale nie wybieraj OK. Spowoduje to otwarcie okna dialogowego Dźwięk.
Znajdź plik MP3 lub inny plik audio na komputerze docelowym i kliknij go dwukrotnie, aby go odtworzyć. Następnie w oknie dialogowym Dźwięk sprawdź, czy we wskaźniku poziomu głośności widoczna jest aktywność, powiązanego ze sterownikiem Wirtualne urządzenie audio (WDM) — Tablet Sample.
Sekcja 5. Wyświetlanie informacji o sterowniku za pomocą narzędzia WinDbg
W sekcji 5 ustawisz ścieżkę symbolu i użyjesz poleceń debugera jądra, aby wyświetlić informacje o przykładowym sterowniku Sysvad.
Symbole umożliwiają, aby WinDbg wyświetlał dodatkowe informacje, takie jak nazwy zmiennych, które mogą być nieoceniona podczas debugowania. WinDbg używa formatów symboli debugowania programu Microsoft Visual Studio na potrzeby debugowania na poziomie źródła. Może uzyskać dostęp do dowolnego symbolu lub zmiennej z modułu, który zawiera pliki symboli PDB.
Aby załadować debuger, wykonaj następujące kroki.
<-W systemie hosta
Jeśli debuger został zamknięty, otwórz go ponownie, używając następującego polecenia w oknie wiersza polecenia administratora. Zastąp klucz i port wcześniej skonfigurowanym elementem .
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874pUżyj Ctrl+Break (Blokada przewijania), aby przerwać wykonywanie kodu w docelowym systemie.
Ustawianie ścieżki symboli
Aby ustawić ścieżkę symboli na serwer symboli firmy Microsoft w środowisku WinDbg, użyj polecenia .symfix .
0: kd> .symfixAby dodać lokalną lokalizację symboli, aby używać symboli lokalnych, dodaj ścieżkę przy użyciu komendy .sympath+, a następnie .reload /f.
0: kd> .sympath+ C:\WDK_Samples\Sysvad 0: kd> .reload /fUwaga Polecenie .reload z opcją wymuszania /f usuwa wszystkie informacje symboli dla określonego modułu i przeładowuje symbole. W niektórych przypadkach to polecenie również ponownie ładuje lub zwalnia sam moduł.
Nuta Aby korzystać z zaawansowanych funkcji zapewnianych przez usługę WinDbg, należy załadować odpowiednie symbole. Jeśli nie masz poprawnie skonfigurowanych symboli, otrzymasz komunikaty wskazujące, że symbole nie są dostępne podczas próby użycia funkcji, która jest zależna od symboli.
0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.
Zwróć uwagęna serwery symboli
Istnieje wiele podejść, których można użyć do pracy z symbolami. W wielu sytuacjach można skonfigurować komputer do uzyskiwania dostępu do symboli z serwera symboli udostępnianego przez firmę Microsoft w razie potrzeby. W tym przewodniku przyjęto założenie, że to podejście zostanie użyte. Jeśli symbole w środowisku znajdują się w innej lokalizacji, zmodyfikuj kroki, aby użyć tej lokalizacji. Aby uzyskać dodatkowe informacje, zobacz Ścieżka symboli dla debugera systemu Windows.
UwagaInformacje o wymaganiach dotyczących symboli kodu źródłowego
Aby przeprowadzić debugowanie źródłowe, należy utworzyć sprawdzoną (debugowanie) wersję plików binarnych. Kompilator utworzy pliki symboli (pliki pdb). Te pliki symboli pokażą debugerowi sposób, w jaki 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 jest, 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
Wpisz następujące polecenie w obszarze polecenia debugera, aby wyświetlić informacje o sterowniku Sysvad.
0: kd> lm m tabletaudiosample v Browse full module list start end module name fffff801`14b40000 fffff801`14b86000 tabletaudiosample (private pdb symbols) C:\Debuggers\sym\TabletAudioSample.pdb\E992C4803EBE48C7B23DC1596495CE181\TabletAudioSample.pdb Loaded symbol image file: tabletaudiosample.sys Image path: \SystemRoot\system32\drivers\tabletaudiosample.sys Image name: tabletaudiosample.sys Browse all global symbols functions data Timestamp: Thu Dec 10 12:20:26 2015 (5669DE8A) CheckSum: 0004891E ...Aby uzyskać więcej informacji, zobacz lm.
Wybierz link Przeglądaj wszystkie symbole globalne w wynikach debugowania, aby wyświetlić informacje o symbolach elementów rozpoczynających się literą a.
Ponieważ język DML jest włączony, niektóre elementy danych wyjściowych to gorące linki, które można wybrać. Wybierz link danych w danych wyjściowych debugowania, aby wyświetlić informacje o symbolach elementów rozpoczynających się literą a.
0: kd> x /D /f tabletaudiosample!a* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)Aby uzyskać informacje, zobacz x (Sprawdź symbole).
Rozszerzenie !lmi wyświetla szczegółowe informacje o module. Wpisz !lmi tabletaudiosample. Dane wyjściowe powinny być podobne do tekstu pokazanego poniżej.
0: kd> !lmi tabletaudiosample Loaded Module Info: [tabletaudiosample] Module: tabletaudiosample Base Address: fffff8069ad90000 Image Name: tabletaudiosample.sys Machine Type: 34404 (X64) Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017 Size: 48000 CheckSum: 42df7 Characteristics: 22 Debug Data Dirs: Type Size VA Pointer CODEVIEW a7, e5f4, d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F} Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb ?? 250, e69c, d29c [Data not mapped] Image Type: MEMORY - Image read successfully from loaded memory. Symbol Type: PDB - Symbols loaded successfully from image header. C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210] Load Report: private symbols & lines, not source indexed C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdbUżyj rozszerzenia !dh , aby wyświetlić informacje nagłówka, jak pokazano poniżej.
0: kd> !dh tabletaudiosample File Type: EXECUTABLE IMAGE FILE HEADER VALUES 8664 machine (X64) 9 number of sections 5669DE8A time date stamp Thu Dec 10 12:20:26 2015 0 file pointer to symbol table 0 number of symbols F0 size of optional header 22 characteristics Executable App can handle >2gb addresses ...
Sekcja 6. Wyświetlanie informacji o drzewie urządzeń Plug and Play
W sekcji 6 zostaną wyświetlone informacje o przykładowym sterowniku urządzenia Sysvad 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 . Uruchomienie tego polecenia może potrwać minutę lub dwie. W tym czasie wartość „*Zajęty” będzie wyświetlana w obszarze stanu WinDbg.
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 Ctrl+F, aby wyszukać nazwę sterownika urządzenia sysvad w wygenerowanych danych wyjściowych.
Wpis węzła urządzenia o nazwie
sysvad_TabletAudioSamplebędzie obecny w wynikach !devnode dla Syvad.DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0 InstancePath is "ROOT\sysvad_TabletAudioSample\0000" ServiceName is "sysvad_tabletaudiosample" State = DeviceNodeStarted (0x308) ...Należy pamiętać, że wyświetlany jest adres PDO i adres DevNode.
Użyj polecenia
!devnode 0 1 sysvad_TabletAudioSample, aby wyświetlić informacje o Plug and Play skojarzone z naszym sterownikiem urządzenia Sysvad.0: kd> !devnode 0 1 sysvad_TabletAudioSample Dumping IopRootDeviceNode (= 0xffffe00082df8d30) DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0 InstancePath is "ROOT\sysvad_TabletAudioSample\0000" ServiceName is "sysvad_tabletaudiosample" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307)Dane wyjściowe wyświetlane w poprzednim poleceniu zawierają PDO skojarzone z uruchomionym wystąpieniem naszego sterownika. W tym przykładzie jest to 0xffffe00089c575a0. Wprowadź polecenie !devobj<adres PDO>, aby wyświetlić informacje o Plug and Play skojarzone ze sterownikiem urządzenia Sysvad. Użyj adresu PDO wyświetlanego na Twoim komputerze przez program !devnode, a nie tego pokazywanego tutaj.
0: kd> !devobj 0xffffe00089c575a0 Device object (ffffe00089c575a0) is for: 0000004e \Driver\PnpManager DriverObject ffffe00082d47e60 Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040 SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 ExtensionFlags (0000000000) Characteristics (0x00000180) FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample Device queue is not busy.Dane wyjściowe wyświetlane w poleceniu !devobj zawierają nazwę dołączonego urządzenia: \Driver\sysvad_tabletaudiosample. Użyj polecenia !drvobj z maską bitową 2, aby wyświetlić informacje skojarzone z dołączonym urządzeniem.
0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2 Driver object (ffffe0008834f670) is for: \Driver\sysvad_tabletaudiosample DriverEntry: fffff80114b45310 tabletaudiosample!FxDriverEntry DriverStartIo: 00000000 DriverUnload: fffff80114b5fea0 tabletaudiosample!DriverUnload AddDevice: fffff80114b5f000 tabletaudiosample!AddDevice Dispatch routines: [00] IRP_MJ_CREATE fffff80117b49a20 portcls!DispatchCreate [01] IRP_MJ_CREATE_NAMED_PIPE fffff8015a949a00 nt!IopInvalidDeviceRequest [02] IRP_MJ_CLOSE fffff80115e26f90 ks!DispatchCleanup [03] IRP_MJ_READ fffff80115e32710 ks!DispatchRead [04] IRP_MJ_WRITE fffff80115e327e0 ks!DispatchWrite [05] IRP_MJ_QUERY_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [06] IRP_MJ_SET_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [07] IRP_MJ_QUERY_EA fffff8015a949a00 nt!IopInvalidDeviceRequest [08] IRP_MJ_SET_EA fffff8015a949a00 nt!IopInvalidDeviceRequest [09] IRP_MJ_FLUSH_BUFFERS fffff80115e32640 ks!DispatchFlush [0a] IRP_MJ_QUERY_VOLUME_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [0b] IRP_MJ_SET_VOLUME_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [0c] IRP_MJ_DIRECTORY_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [0d] IRP_MJ_FILE_SYSTEM_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [0e] IRP_MJ_DEVICE_CONTROL fffff80115e27480 ks!DispatchDeviceIoControl [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [10] IRP_MJ_SHUTDOWN fffff8015a949a00 nt!IopInvalidDeviceRequest [11] IRP_MJ_LOCK_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [12] IRP_MJ_CLEANUP fffff8015a949a00 nt!IopInvalidDeviceRequest [13] IRP_MJ_CREATE_MAILSLOT fffff8015a949a00 nt!IopInvalidDeviceRequest [14] IRP_MJ_QUERY_SECURITY fffff80115e326a0 ks!DispatchQuerySecurity [15] IRP_MJ_SET_SECURITY fffff80115e32770 ks!DispatchSetSecurity [16] IRP_MJ_POWER fffff80117b3dce0 portcls!DispatchPower [17] IRP_MJ_SYSTEM_CONTROL fffff80117b13d30 portcls!PcWmiSystemControl [18] IRP_MJ_DEVICE_CHANGE fffff8015a949a00 nt!IopInvalidDeviceRequest [19] IRP_MJ_QUERY_QUOTA fffff8015a949a00 nt!IopInvalidDeviceRequest [1a] IRP_MJ_SET_QUOTA fffff8015a949a00 nt!IopInvalidDeviceRequest [1b] IRP_MJ_PNP fffff80114b5f7d0 tabletaudiosample!PnpHandlerWprowadź polecenie !devstack<PDO address>, aby wyświetlić informacje Plug and Play skojarzone ze sterownikiem urządzenia. Dane wyjściowe wyświetlane w poleceniu !devnode 0 1 zawierają adres PDO skojarzony z uruchomionym wystąpieniem naszego sterownika. W tym przykładzie jest to 0xffffe00089c575a0. Użyj adresu PDO wyświetlanego przez program !devnode na komputerze, a nie tego pokazanego poniżej.
0: kd> !devstack 0xffffe00089c575a0 !DevObj !DrvObj !DevExt ObjectName ffffe00088d212e0 \Driver\ksthunk ffffe00088d21430 0000007b ffffe00088386a50 \Driver\sysvad_tabletaudiosampleffffe00088386ba0 0000007a > ffffe00089c575a0 \Driver\PnpManager 00000000 0000004e !DevNode ffffe00086e68190 : DeviceInst is "ROOT\sysvad_TabletAudioSample\0000" ServiceName is "sysvad_tabletaudiosample"
Dane wyjściowe pokazują, że mamy dość prosty stos sterowników urządzeń. Sterownik sysvad_TabletAudioSample jest elementem podrzędnym węzła PnPManager. PnPManager jest węzłem głównym.
Ten diagram przedstawia bardziej złożone drzewo węzłów urządzeń.
Nuta 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ń.
Sekcja 7. Praca z punktami przerwania
W sekcji 7 będziesz pracować z punktami przerwania, aby zatrzymać wykonywanie kodu w określonych punktach.
Ustawianie punktów przerwania przy użyciu poleceń
Punkty przerwania służą do zatrzymywania wykonywania kodu w określonym wierszu kodu. Następnie możesz przejść dalej w kodzie od tego momentu, aby debugować daną sekcję kodu.
Aby ustawić punkt przerwania przy użyciu polecenia debugowania, użyj jednego z następujących poleceń b .
Bp |
Ustawia punkt przerwania, który będzie aktywny do momentu, aż moduł zostanie usunięty z pamięci. |
Bu |
Ustawia nierozwiązany punkt przerwania, gdy moduł jest wyładowany i ponownie się włącza przy ponownym załadowaniu modułu. |
Bm |
Ustawia punkt przerwania dla symbolu. To polecenie będzie odpowiednio używać bu lub bp i umożliwia użycie symboli wieloznacznych * do ustawiania punktów przerwania dla każdego symbolu, który pasuje (jak na przykład wszystkie metody w klasie). |
Użyj interfejsu użytkownika WinDbg, aby potwierdzić, że tryb Debugowania>Źródła jest włączony w bieżącej sesji WinDbg.
Dodaj lokalizację kodu lokalnego do ścieżki źródłowej, wpisując następujące polecenie.
.sympath+ C:\WDK_Samples\SysvadDodaj lokalną lokalizację symboli do ścieżki symboli, wpisując następujące polecenie.
.sympath+ C:\WDK_Samples\SysvadUstaw maskę debugowania
Podczas pracy ze sterownikiem może być przydatne, aby zobaczyć wszystkie komunikaty, które mogą być wyświetlane. Wpisz następujące polecenie, aby zmienić domyślną maskę bitów debugowania, aby wszystkie komunikaty debugowania z systemu docelowego były wyświetlane w debugerze.
0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFFUstaw punkt przerwania za pomocą polecenia bm przy użyciu nazwy sterownika, a następnie nazwy funkcji (AddDevice), gdzie chcesz ustawić punkt przerwania, oddzielony wykrzyknikiem.
0: kd> bm tabletaudiosample!AddDevice breakpoint 1 redefined 1: fffff801`14b5f000 @!"tabletaudiosample!AddDevice"Możesz użyć innej składni w połączeniu z ustawianiem zmiennych, takich jak <moduł>!<symbol>, <klasa>::<metoda>,‘<file.cpp>:<numer linii>’, lub pominąć pewną liczbę razy <warunek><#>. Aby uzyskać więcej informacji, zobacz „Korzystanie z punktów przerwań”.
Wyświetl listę bieżących punktów przerwania, aby potwierdzić, że punkt przerwania został ustawiony, wpisując polecenie bl .
0: kd> bl 1 e fffff801`14b5f000 0001 (0001) tabletaudiosample!AddDeviceUruchom ponownie wykonywanie kodu w systemie docelowym, wpisując polecenie go g.
->W systemie docelowym
W systemie Windows otwórz Menedżera urządzeń przy użyciu ikony lub wprowadzając mmc devmgmt.msc. W Menedżerze urządzeń rozwiń węzeł Dźwięk, wideo i kontrolery gier . Wybierz wpis wirtualnego sterownika audio i przytrzymaj go (lub kliknij go prawym przyciskiem myszy), a następnie wybierz polecenie Wyłącz z menu.
Wybierz ponownie i przytrzymaj (lub kliknij prawym przyciskiem myszy) wpis wirtualnego sterownika audio, a następnie wybierz polecenie Włącz z menu.
<— w systemie hosta
Powinno to spowodować ponowne załadowanie sterownika przez system Windows, co wywołuje metodę AddDevice. Spowoduje to wyzwolenie punktu przerwania debugowania AddDevice, a wykonanie kodu sterownika w systemie docelowym powinno zostać zatrzymane.
Breakpoint 1 hit tabletaudiosample!AddDevice: fffff801`14baf000 4889542410 mov qword ptr [rsp+10h],rdxJeśli ścieżka źródłowa jest ustawiona prawidłowo, powinieneś zatrzymać się na procedurze AddDevice w pliku adapter.cpp
{ PAGED_CODE(); NTSTATUS ntStatus; ULONG maxObjects; DPF(D_TERSE, ("[AddDevice]")); maxObjects = g_MaxMiniports; #ifdef SYSVAD_BTH_BYPASS // // Allow three (3) Bluetooth hands-free profile devices. // maxObjects += g_MaxBthHfpMiniports * 3; #endif // SYSVAD_BTH_BYPASS // Tell the class driver to add the device. // ntStatus = PcAddAdapterDevice ( DriverObject, PhysicalDeviceObject, PCPFNSTARTDEVICE(StartDevice), maxObjects, 0 ); return ntStatus; } // AddDeviceWykonaj krok po wierszu przez kod, wpisując polecenie p lub naciskając F10. Możesz przejść do przodu z kodu sysvad AddDevice do PpvUtilCall, PnpCallAddDevice, a następnie do kodu PipCallDriverAddDevice systemu Windows. Możesz podać liczbę do polecenia p , aby przejść do przodu wielu wierszy, na przykład p 5.
Gdy skończysz przechodzić przez kod, użyj polecenia go g , aby ponownie uruchomić wykonywanie w systemie docelowym.
Ustawianie punktów przerwania dostępu do pamięci
Można również ustawić punkty przerwania uruchamiane, gdy uzyskiwany jest dostęp do lokalizacji pamięci. Użyj polecenia ba (break on access) z następującą składnią.
ba <access> <size> <address> {options}
| Opcja | Opis |
|---|---|
e |
wykonaj (gdy procesor CPU pobiera instrukcję z adresu) |
r |
odczyt/zapis (gdy procesor CPU odczytuje lub zapisuje pod adresem) |
w |
zapis (gdy CPU zapisuje do adresu) |
Należy pamiętać, że w danym momencie można ustawić tylko cztery punkty przerwania danych i trzeba upewnić się, że dane są poprawnie wyrównane, w przeciwnym razie punkt przerwania nie zostanie wyzwolony (słowa muszą mieć adresy podzielne przez 2, dwordy muszą być podzielne przez 4, a czwórki słów przez 8).
Aby na przykład ustawić punkt przerwania odczytu/zapisu na określonym adresie pamięci, użyj polecenia w następujący sposób.
ba r 4 fffff800`7bc9eff0
Modyfikowanie stanu punktu przerwania
Istniejące punkty przerwania można modyfikować przy użyciu następujących poleceń.
Bl |
Wyświetla listę punktów przerwania. |
p.n.e |
Usuwa 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. |
być |
Umożliwia punkt przerwania. Użyj be * do włączenia wszystkich punktów przerwania. |
Alternatywnie można również zmodyfikować punkty przerwania, wybierając pozycję Edytuj>punkty przerwania. Należy pamiętać, że okno dialogowe punktu przerwania działa tylko z istniejącymi punktami przerwania. Nowe punkty przerwania muszą być ustawione z wiersza polecenia.
Ustawianie punktu przerwania na mikserzeVolume
Różne części kodu sterownika audio są wywoływane w celu reagowania na różne zdarzenia po załadowaniu sterownika urządzenia. W następnej sekcji ustawimy punkt przerwania, który zostanie wyzwolony, gdy użytkownik dostosuje regulację głośności dla wirtualnego sterownika audio.
Aby ustawić punkt przerwania w aplikacji MixerVolume, wykonaj następujące kroki.
<— w systemie hosta
Aby zlokalizować metodę, która zmienia wolumin, użyj polecenia x, aby wyświetlić listę symboli w CAdapterCommon, które zawierają wolumin ciągu.
kd> x tabletaudiosample!CAdapterCommon::* ... fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long) …Użyj CTRL+F, aby wyszukać dane wyjściowe w górę dla woluminu i zlokalizować metodę MixerVolumeWrite.
Wyczyść poprzednie punkty przerwania przy użyciu bc *.
Ustaw punkt przerwania symbolu w procedurze CAdapterCommon::MixerVolumeWrite przy użyciu następującego polecenia.
kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite 1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"Wyświetl listę punktów przerwania, aby potwierdzić, że punkt przerwania został prawidłowo ustawiony.
kd> bl 1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668] 0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWriteUruchom ponownie wykonywanie kodu w systemie docelowym, wpisując polecenie go g.
W Panelu sterowania wybierz pozycję Sprzęt i Dźwięk.> Wybierz i przytrzymaj (lub kliknij prawym przyciskiem myszy) Przykład opisu ujścia i wybierz pozycję Właściwości. Wybierz kartę Poziomy . Dopasuj głośność suwaka.
Powinno to spowodować wywołanie punktu przerwania debugowania SetMixerVolume, a wykonanie kodu sterownika w systemie docelowym powinno zostać zatrzymane.
kd> g Breakpoint 1 hit tabletaudiosample!CAdapterCommon::MixerVolumeWrite: fffff801`177b26a0 44894c2420 mov dword ptr [rsp+20h],r9dPowinieneś zatrzymać się na tej linii w common.cpp
{ if (m_pHW) { m_pHW->SetMixerVolume(Index, Channel, Value); } } // MixerVolumeWriteUżyj polecenia dv, aby wyświetlić bieżące zmienne i ich wartości. Więcej informacji na temat zmiennych znajduje się w następnej sekcji tego laboratorium.
2: kd> dv this = 0x00000000`00000010 ulNode = 0x344 ulChannel = 0x210a45f8 lVolume = 0n24Naciśnij F10 , aby wykonać pojedynczy krok przez kod.
Naciśnij F5 , aby zakończyć wykonywanie kodu MixerVolumeWrite.
Podsumowanie — przechodzenie przez kod z okna polecenia debugera
Poniżej przedstawiono polecenia, których można użyć do przechodzenia przez kod (ze skojarzonymi krótkimi cięciami klawiatury pokazanymi w nawiasach).
Przerwij (Ctrl+Break) — to polecenie spowoduje przerwanie systemu, o ile system jest uruchomiony i jest w stanie komunikować się z WinDbg (sekwencja w debugerze jądra to Ctrl+C).
Przejdź do następnego kroku (F10) — to polecenie powoduje wykonywanie kodu o jeden krok lub jedną operację naraz. 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ć przy użyciu debugowania>Tryb źródłowy).
Wejście (F11) — to polecenie jest podobne do przeskoku, z tym wyjątkiem, że wykonywanie wywołania wchodzi do wywoływanej procedury.
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.
Uruchom 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; wykonanie kodu zostanie uruchomione do tego momentu. Należy pamiętać, że jeśli przepływ wykonywania kodu nie osiągnie punktu wskazanego przez kursor (np. instrukcja IF nie zostanie wykonana), usługa WinDbg nie zostanie przerwana, ponieważ wykonanie kodu nie dotarło do wskazanego punktu.
Uruchom (F5) — uruchom do momentu napotkania punktu przerwania lub wystąpienia zdarzenia, takiego jak błąd krytyczny.
Opcje zaawansowane
Ustaw punkt rozpoczęcia wykonywania od bieżącego wiersza (Ctrl+Shift+I) — w oknie źródłowym możesz umieścić kursor na wierszu, użyć tego skrótu klawiaturowego, a wykonywanie kodu rozpocznie się od tego punktu, gdy tylko pozwolisz na jego kontynuację (na przykład za pomocą F5 lub F10). Jest to przydatne, jeśli chcesz ponowić próbę sekwencji, ale wymaga to pewnej staranności. Na przykład rejestry i zmienne nie są ustawione na to, co byłoby, gdyby wykonywanie kodu osiągnęło ten wiersz naturalnie.
Bezpośrednie ustawienie rejestru eip — można umieścić wartość w rejestrze eip i natychmiast po naciśnięciu F5 (lub F10, F11 itp.), wykonanie rozpoczyna się od tego adresu. Jest to podobne do ustawiania instrukcji dla bieżącego wiersza wyznaczonego kursorem, z tą różnicą, że określono adres instrukcji zestawu.
Łatwiej jest przejść przez interfejs użytkownika niż z wiersza polecenia, dlatego ta metoda jest zalecana. W razie potrzeby następujące polecenia mogą służyć do przechodzenia przez plik źródłowy w wierszu polecenia:
.lines — włącz informacje o liniach źródłowych.
bp main — ustaw początkowy punkt przerwania na początku modułu.
l+t — krokowanie będzie wykonywane przez wiersz źródłowy.
Wybierz Debug>Tryb źródła, aby przejść do trybu źródłowego; samo
L+tpolecenie nie jest wystarczające.l+s — wiersze źródłowe będą wyświetlane po pojawieniu się monitu.
g — uruchom program do momentu wejścia do "main".
p — wykonaj jedną linię źródłową.
Aby uzyskać więcej informacji, zobacz debugowanie kodu źródłowego w WinDbg (wersja klasyczna) w dokumentacji referencyjnej debugowania.
Ustawianie punktów przerwania w kodzie
Punkt przerwania można ustawić w kodzie, dodając instrukcję DebugBreak() i ponownie kompilując projekt i ponownie instalując sterownik. Punkt przerwania zostanie wyzwolony za każdym razem, gdy sterownik jest włączony, dlatego będzie to technika stosowana we wczesnych etapach rozwoju, ale nie w kodzie produkcyjnym. Ta technika nie jest tak elastyczna, jak dynamiczne ustawianie punktów przerwania przy użyciu poleceń punktu przerwania.
Porada: Możesz zachować kopię sterownika Sysvad bez dodanego punktu przerwania do dalszej pracy laboratoryjnej.
Ustaw przerwę, która ma wystąpić za każdym razem, gdy metoda AddDevice jest uruchamiana, dodając instrukcję
DebugBreak()do przykładowego kodu.... // Insert the DebugBreak() statment before the PcAddAdapterDevice is called. // DebugBreak() // Tell the class driver to add the device. // ntStatus = PcAddAdapterDevice ( DriverObject, PhysicalDeviceObject, PCPFNSTARTDEVICE(StartDevice), maxObjects, 0 ); return ntStatus; } // AddDeviceWykonaj wszystkie kroki opisane wcześniej, aby ponownie skompilować sterownik w programie Microsoft Visual Studio i ponownie zainstalować go na maszynie docelowej. Pamiętaj, aby odinstalować istniejący sterownik przed zainstalowaniem zaktualizowanego sterownika.
Wyczyść wszystkie poprzednie punkty przerwania i upewnij się, że debuger jest dołączony do komputera docelowego.
Po uruchomieniu kodu i osiągnięciu instrukcji
DebugBreakwykonanie zostanie zatrzymane, a zostanie wyświetlony komunikat.KERNELBASE!DebugBreak: 77b3b770 defe __debugbreak
Sekcja 8. Wyświetlanie zmiennych
W sekcji 8 użyjesz poleceń debugera do wyświetlania zmiennych.
Przydatne może być sprawdzenie zmiennych podczas wykonywania kodu w celu potwierdzenia, że kod działa zgodnie z oczekiwaniami. W tych laboratoriach sprawdza się zmienne, gdy sterownik dźwięku generuje dźwięk.
Użyj polecenia dv, aby zbadać zmienne regionalne skojarzone z tabletaudiosample!CMiniportWaveRT::New*.
kd> dv tabletaudiosample!CMiniportWaveRT::New*Wyczyść poprzednie punkty przerwania
bc *Ustaw punkt przerwania dla symboli dla procedur CMiniportWaveCyclicStreamMSVAD za pomocą następującego polecenia.
0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream 1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"Uruchom ponownie wykonywanie kodu w systemie docelowym, wpisując polecenie go g.
-> W systemie docelowym
Znajdź mały plik multimedialny (na przykład plik dźwiękowy powiadomień systemu Windows z rozszerzeniem .wav pliku) i wybierz plik, aby go odtworzyć. Na przykład można użyć pliku Ring05.wav znajdującego się w katalogu Windows\Media.
<— w systemie hosta
Gdy plik multimedialny jest odtwarzany, punkt przerwania powinien zostać uaktywniony, a wykonanie kodu sterownika w systemie docelowym powinno zostać zatrzymane.
Breakpoint 1 hit tabletaudiosample!CMiniportWaveRT::NewStream: fffff801`177dffc0 44894c2420 mov dword ptr [rsp+20h],r9dOkno kodu źródłowego powinno wyróżniać klamrę przy wejściu do funkcji NewStream.
/*++ Routine Description: The NewStream function creates a new instance of a logical stream associated with a specified physical channel. Callers of NewStream should run at IRQL PASSIVE_LEVEL. Arguments: OutStream - OuterUnknown - Pin - Capture - DataFormat - Return Value: NT status code. --*/ { ...Zmienne lokalne
Nazwy i wartości wszystkich zmiennych lokalnych dla danej ramki można wyświetlić, wpisując polecenie dv.
0: kd> dv this = 0xffffe000`4436f8e0 OutStream = 0xffffe000`49d2f130 OuterUnknown = 0xffffe000`4436fa30 Pin = 0 Capture = 0x01 ' DataFormat = 0xffffe000`44227790 signalProcessingMode = {487E9220-E000-FFFF-30F1-D24900E0FFFF} ntStatus = 0n1055 stream = 0x00000000`00000200Wyświetlanie zmiennych przy użyciu języka DML
Aby użyć języka DML do eksplorowania zmiennych, wybierz podkreślone elementy. Akcja select tworzy polecenie dx (Display NatVis Expression), które umożliwia przechodzenie do szczegółów zagnieżdżonych struktur danych.
0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) : [Type: CMiniportWaveRT] [+0x020] m_lRefCount : 0 [+0x028] m_pUnknownOuter : 0xffffe001d1477e50 : [Type: IUnknown *] [+0x030] m_ulLoopbackAllocated : 0x2050 [+0x034] m_ulSystemAllocated : 0x180 [+0x038] m_ulOffloadAllocated : 0x0 [+0x03c] m_dwCaptureAllocatedModes : 0x0 0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID] [<Raw View>] 0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : [Type: _GUID] [+0x000] Data1 : 0x487e9220 [+0x004] Data2 : 0xe000 [+0x006] Data3 : 0xffff [+0x008] Data4 : [Type: unsigned char [8]] 0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) : [Type: unsigned char [8]] [0] : 0x30 [1] : 0xf1 [2] : 0xd2 [3] : 0x49 [4] : 0x0 [5] : 0xe0 [6] : 0xff [7] : 0xffzmienne globalne
Lokalizację pamięci zmiennej globalnej można znaleźć, wpisując ? <nazwa> zmiennej.
0: kd> ? signalProcessingMode Evaluate expression: -52768896396472 = ffffd001`c8acd348Spowoduje to zwrócenie lokalizacji pamięci zmiennej, w tym przypadku ffffd001'c8acd348. Zawartość lokalizacji pamięci można wyświetlić, zapisując wartość tej lokalizacji, wpisując polecenie dd z lokalizacją pamięci zwróconą przez poprzednie polecenie.
0: kd> dd ffffd001`c8acd348 ffffd001`c8acd348 487e9220 ffffe000 49d2f130 ffffe000 ffffd001`c8acd358 4837c468 ffffe000 18221570 ffffc000 ffffd001`c8acd368 4436f8e0 ffffe000 487e9220 ffffe000 ffffd001`c8acd378 18ab145b fffff801 4837c420 ffffe000 ffffd001`c8acd388 4436f8e0 ffffe000 49d2f130 ffffe000 ffffd001`c8acd398 4436fa30 ffffe000 00000000 00000000 ffffd001`c8acd3a8 00000001 00000000 44227790 ffffe000 ffffd001`c8acd3b8 18adc7f9 fffff801 495972a0 ffffe000Nazwy zmiennych można również używać za pomocą polecenia dd .
0: kd> dd signalProcessingMode ffffd001`c8acd348 487e9220 ffffe000 49d2f130 ffffe000 ffffd001`c8acd358 4837c468 ffffe000 18221570 ffffc000 ffffd001`c8acd368 4436f8e0 ffffe000 487e9220 ffffe000 ffffd001`c8acd378 18ab145b fffff801 4837c420 ffffe000 ffffd001`c8acd388 4436f8e0 ffffe000 49d2f130 ffffe000 ffffd001`c8acd398 4436fa30 ffffe000 00000000 00000000 ffffd001`c8acd3a8 00000001 00000000 44227790 ffffe000 ffffd001`c8acd3b8 18adc7f9 fffff801 495972a0 ffffe000Wyświetlanie zmiennych
Użyj elementu menu Wyświetl>ustawienia lokalne , aby wyświetlić zmienne lokalne. Ten interfejs zapewnia również możliwość przechodzenia do szczegółów bardziej złożonych struktur danych.
Użyj klawisza p lub F10, aby przejść do przodu około 10 wierszy w kodzie, aż do wyróżnienia wiersza kodu ntStatus = IsFormatSupported(Pin, Capture, DataFormat);.
PAGED_CODE(); ASSERT(OutStream); ASSERT(DataFormat); DPF_ENTER(("[CMiniportWaveRT::NewStream]")); NTSTATUS ntStatus = STATUS_SUCCESS; PCMiniportWaveRTStream stream = NULL; GUID signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT; *OutStream = NULL; // // If the data format attributes were specified, extract them. // if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES ) { // The attributes are aligned (QWORD alignment) after the data format PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT)); ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode); } // Check if we have enough streams. // if (NT_SUCCESS(ntStatus)) { ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode); } // Determine if the format is valid. // if (NT_SUCCESS(ntStatus)) { ntStatus = IsFormatSupported(Pin, Capture, DataFormat); } ...Użyj polecenia dv , aby wyświetlić nazwy i wartości wszystkich zmiennych lokalnych dla danej ramki. Należy pamiętać, że zgodnie z oczekiwaniami wartości różnią się od czasu ostatniego uruchomienia tego polecenia, ponieważ został uruchomiony dodatkowy kod, który zmienia zmienne lokalne, a niektóre zmienne nie znajdują się teraz w bieżącej ramce lub ich wartości uległy zmianie.
2: kd> dv this = 0xffffe001`d1182000 OutStream = 0xffffe001`d4776d20 OuterUnknown = 0xffffe001`d4776bc8 Pin = 0 Capture = 0x00 ' DataFormat = 0xffffe001`cd7609b0 signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE} ntStatus = 0n0 stream = 0x00000000`00000000
Sekcja 9. Wyświetlanie stosów wywołań
W sekcji 9 wyświetlisz stosy wywołań w celu sprawdzenia kodu wywołującego/wywoływanego.
Stos wywołań to łańcuch wywołań funkcji, które doprowadziły do aktualnej 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*:
Baza wiedzy |
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ń, możesz wybrać pozycję Wyświetl>stos wywołań , aby go wyświetlić. Wybierz kolumny w górnej części okna, aby przełączyć wyświetlanie dodatkowych informacji.
Ten output pokazuje stos wywołań podczas debugowania przykładowego kodu źródłowego adaptera w stanie zatrzymania.
0: kd> kb
# RetAddr : Args to Child : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e
Aby dokładniej zapoznać się z kodem, możesz użyć języka DML. Po wybraniu pierwszego wpisu 00 polecenie .frame (Ustaw kontekst lokalny) służy do ustawiania kontekstu, a następnie polecenie dv (Wyświetl zmienne lokalne) wyświetla zmienne lokalne.
0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000
Sekcja 10. Wyświetlanie procesów i wątków
W sekcji 10 użyjesz poleceń debugera do wyświetlania procesów i wątków.
Proces
Aby zmienić bieżący kontekst procesu, użyj polecenia .process <process>. W poniższym przykładzie pokazano, jak zidentyfikować proces i przełączyć kontekst na ten proces.
Użyj polecenia ,
!processaby wyświetlić bieżący proces, który jest zaangażowany w odtwarzanie dźwięku.Aby uzyskać więcej informacji, zobacz !process
Dane wyjściowe pokazują, że proces jest skojarzony z audiodg.exe. Jeśli nadal znajdujesz się w punkcie przerwania opisanym w poprzedniej sekcji tego tematu, obecny proces powinien być powiązany z grafiką audiodg.exe.
<— w systemie hosta
0: kd> !process
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
DeviceMap ffffc00019113080
Token ffffc0001f1d4060
ElapsedTime <Invalid>
UserTime 00:00:00.000
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 81632
QuotaPoolUsage[NonPagedPool] 9704
Working Set Sizes (now,min,max) (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
PeakWorkingSetSize 2101
VirtualSize 2097192 Mb
PeakVirtualSize 2097192 Mb
PageFaultCount 2336
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 1573
THREAD ffffe001d173e840 Cid 10f0.1dac Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
ffffe001d16c4dd0 NotificationEvent
ffffe001d08b0840 ProcessObject
THREAD ffffe001ceb77080 Cid 10f0.16dc Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001cf2d1840 QueueObject
THREAD ffffe001d112c840 Cid 10f0.0a4c Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001cf2d1840 QueueObject
THREAD ffffe001d16c7840 Cid 10f0.13c4 Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001cf2d1840 QueueObject
THREAD ffffe001cec67840 Cid 10f0.0dbc Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d173e5c0 QueueObject
THREAD ffffe001d1117840 Cid 10f0.1d6c Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d173e5c0 QueueObject
THREAD ffffe001cdeae840 Cid 10f0.0298 Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2
Należy pamiętać, że jeden z wątków skojarzonych z tym procesem znajduje się w stanie URUCHOMIONYM. Ten wątek obsługiwał odtwarzanie klipu multimedialnego w momencie, gdy punkt przerwania został osiągnięty.
Użyj polecenia !process 0 0 , aby wyświetlić podsumowanie informacji dla wszystkich procesów. W danych wyjściowych polecenia użyj CTRL+F, aby zlokalizować identyfikator procesu dla procesu skojarzonego z obrazem audiodg.exe. W poniższym przykładzie identyfikator procesu to ffffe001d147c840.
Zarejestruj identyfikator procesu skojarzony z audiodg.exe na komputerze osobistym, aby użyć go w dalszej części tego ćwiczenia laboratoryjnego. ________________________
...
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
...
Wprowadź g w debugerze, aby uruchomić kod w przód, dopóki klip multimedialny nie zakończy odtwarzania. Następnie przerwij działanie debugera, naciskając Ctrl+ScrLk (Ctrl+Break). Użyj polecenia !process, aby potwierdzić, że teraz uruchamiasz inny proces.
!process
PROCESS ffffe001cd0ad040
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 001aa000 ObjectTable: ffffc00017214000 HandleCount: <Data Not Accessible>
Image: System
VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
DeviceMap ffffc0001721a070
Token ffffc00017216a60
ElapsedTime 05:04:54.716
UserTime 00:00:00.000
KernelTime 00:00:20.531
QuotaPoolUsage[PagedPool] 0
QuotaPoolUsage[NonPagedPool] 0
Working Set Sizes (now,min,max) (1720, 50, 450) (6880KB, 200KB, 1800KB)
PeakWorkingSetSize 15853
VirtualSize 58 Mb
PeakVirtualSize 74 Mb
PageFaultCount 46128
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 66
THREAD ffffe001cd0295c0 Cid 0004.000c Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
fffff803cd8e0120 SynchronizationEvent
THREAD ffffe001cd02a6c0 Cid 0004.0010 Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
fffff803cd8e0ba0 Semaphore Limit 0x7fffffff
...
Powyższe dane wyjściowe pokazują, że jest uruchomiony inny proces systemowy ffffe001cd0ad040 . Nazwa obrazu pokazuje System, a nie audiodg.exe.
Teraz użyj polecenia !process, aby przełączyć się do procesu skojarzonego z audiodg.exe. W tym przykładzie identyfikator procesu to ffffe001d147c840. Zastąp identyfikator procesu w przykładzie identyfikatorem procesu, który wcześniej zarejestrowałeś.
0: kd> !process ffffe001d147c840
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
DeviceMap ffffc00019113080
Token ffffc0001f1d4060
ElapsedTime 1 Day 01:53:14.490
UserTime 00:00:00.031
KernelTime 00:00:00.031
QuotaPoolUsage[PagedPool] 81552
QuotaPoolUsage[NonPagedPool] 8344
Working Set Sizes (now,min,max) (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
PeakWorkingSetSize 2116
VirtualSize 2097189 Mb
PeakVirtualSize 2097192 Mb
PageFaultCount 2464
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 1418
THREAD ffffe001d173e840 Cid 10f0.1dac Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
ffffe001d16c4dd0 NotificationEvent
ffffe001d08b0840 ProcessObject
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 338852 Ticks: 197682 (0:00:51:28.781)
Context Switch Count 36 IdealProcessor: 0
UserTime 00:00:00.015
KernelTime 00:00:00.000
Win32 Start Address 0x00007ff7fb928de0
Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
THREAD ffffe001d115c080 Cid 10f0.15b4 Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d0bf0640 QueueObject
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 338852 Ticks: 197682 (0:00:51:28.781)
Context Switch Count 1 IdealProcessor: 0
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c3143dd0 Current ffffd001c3143520
Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
THREAD ffffe001d3a27040 Cid 10f0.17f4 Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d173e5c0 QueueObject
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 518918 Ticks: 17616 (0:00:04:35.250)
Context Switch Count 9 IdealProcessor: 1
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
Ponieważ ten kod nie jest aktywny, wszystkie wątki są w stanie oczekiwania, jak można było się spodziewać.
Wątki
Polecenia do wyświetlania i ustawiania wątków są bardzo podobne do tych procesów. Użyj polecenia !thread , aby wyświetlić wątki. Użyj .thread, aby ustawić bieżące wątki.
Aby eksplorować wątki skojarzone z odtwarzaczem multimediów, ponownie odtwórz klip multimedialny. Jeśli punkt przerwania opisany w poprzedniej sekcji nadal się utrzymuje, zatrzymasz się w kontekście audiodg.exe.
Użyj !thread -1 0, aby wyświetlić krótkie informacje dla bieżącego wątku. Pokazuje to adres wątku, identyfikatory wątku i procesu, adres bloku środowiska wątku (TEB), adres funkcji Win32 (jeśli istnieje), dla której utworzono wątek, oraz stan planowania wątku.
0: kd> !thread -1 0
THREAD ffffe001d3a27040 Cid 10f0.17f4 Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
Aby wyświetlić więcej informacji o uruchomionym wątku, wpisz !wątek. Powinny zostać wyświetlone informacje podobne do poniższych.
0: kd> !thread
THREAD ffffe001d3a27040 Cid 10f0.17f4 Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
ffffe001d429e580: (0006,02c8) Flags: 000008b4 Mdl: 00000000
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 537630 Ticks: 0
Context Switch Count 63 IdealProcessor: 1
UserTime 00:00:00.000
KernelTime 00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP RetAddr : Args to Child : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e
Użyj polecenia k, aby wyświetlić stos wywołań skojarzony z wątkiem.
0: kd> k
# Child-SP RetAddr Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e
Wprowadź g w debugerze, aby uruchomić kod w przód, dopóki klip multimedialny nie zakończy odtwarzania. Następnie włamaj się do debugera, naciskając Ctrl - ScrLk (Ctrl-Break) Użyj polecenia !thread, aby potwierdzić, że używasz teraz innego wątku.
0: kd> !thread
THREAD ffffe001ce80b840 Cid 17e4.01ec Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap ffffc0001974e2c0
Owning Process ffffe001d1760840 Image: rundll32.exe
Attached Process N/A Image: N/A
Wait Start TickCount 538040 Ticks: 0
Context Switch Count 3181840 IdealProcessor: 0
UserTime 00:00:08.250
KernelTime 00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP RetAddr : Args to Child : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff
Nazwa obrazu to rundll32.exe, która rzeczywiście nie jest nazwą obrazu skojarzona z odtwarzaniem klipu multimedialnego.
Uwaga Aby ustawić bieżący wątek, wpisz .thread <numer wątku>.
Aby uzyskać więcej informacji na temat wątków i procesów, zobacz następujące odwołania:
Sekcja 11: IRQL, rejestry i dezasemblacja
Wyświetl zapisany IRQL
W sekcji 11 wyświetlisz środowisko IRQL i zawartość rejestrów.
<— w systemie hosta
Poziom żądania przerwania (IRQL) służy do zarządzania priorytetem obsługi przerwań. Każdy procesor ma poziom IRQL, który wątki mogą podnieść lub obniżyć. Przerwy występujące w ustawieniu IRQL procesora lub poniżej niego 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ą. Rozszerzenie !irql wyświetla poziom żądania przerwania (IRQL) na bieżącym procesorze komputera docelowego przed awarią debugera. Kiedy komputer docelowy przechodzi w tryb debugowania, poziom IRQL zmienia się, ale poziom IRQL, który obowiązywał tuż przed przerwaniem debugowania, jest zapisywany i wyświetlany przez polecenie !irql.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
< Wyświetlanie rejestrów i dezasemblacji
Wyświetlanie rejestrów
Wyświetl zawartość rejestrów dla bieżącego wątku na bieżącym procesorze za pomocą r (Registers) polecenia.
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.
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, zobacz r (Rejestry).
Aby uzyskać informacje na temat zawartości rejestru, zobacz Architektura x86 i architektura x64.
Demontaż
Możesz rozebrać kod, który jest obecnie wykonywany, aby wyświetlić kod w języku asemblera, wybierając Widok>dezasemblacji.
Aby uzyskać więcej informacji na temat dezasemblacji języka asemblera, zobacz Annotated x86 Disassembly oraz Annotated x64 Disassembly.
Sekcja 12. Praca z pamięcią
W sekcji 12 użyjesz poleceń debugera, aby wyświetlić zawartość pamięci.
Wyświetlanie pamięci
Może być konieczne sprawdzenie pamięci w celu zidentyfikowania problemu lub sprawdzenia zmiennych, wskaźników itd. Pamięć można wyświetlić, wpisując jedno z następujących poleceń d* <adresu>.
baza danych |
Wyświetla dane w wartościach bajtów i znakach ASCII. |
Dd |
Wyświetla dane jako wyrazy o podwójnej szerokości (4 bajty). |
Du |
Wyświetla dane jako znaki Unicode. |
DW |
Wyświetla dane jako wartości wyrazów (2 bajty) i znaki ASCII. |
Nuta Jeśli próbujesz wyświetlić nieprawidłowy adres, jego zawartość jest wyświetlana jako znaki zapytania (?).
Alternatywnie możesz wyświetlić pamięć, wybierając pozycję Wyświetl>pamięć. Użyj listy rozwijanej formatu wyświetlania, aby zmienić sposób wyświetlania pamięci.
Aby wyświetlić dane skojarzone z regulatorem głośności, ustaw punkt przerwania, aby uruchomić rutynę PropertyHandlerAudioEngineVolumeLevel przy użyciu polecenia bm. Przed ustawieniem nowego punktu przerwania wyczyścimy wszystkie poprzednie punkty przerwania przy użyciu bc *.
kd> bc *Ustaw punkt przerwania, aby uruchomić funkcję PropertyHandlerAudioEngineVolumeLevel, używając polecenia bm.
kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume 1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"Wyświetl listę punktów przerwania, aby potwierdzić, że punkt przerwania został prawidłowo ustawiony.
kd> bl 1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"Użyj polecenia g , aby ponownie uruchomić wykonywanie kodu.
W systemie docelowym dostosuj głośność na pasku zadań systemu. Spowoduje to aktywację punktu przerwania.
Breakpoint 1 hit tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume: fffff80f`02c3a4b0 44894c2420 mov dword ptr [rsp+20h],r9dUżyj elementu menu Wyświetl>lokalnie , aby wyświetlić zmienne lokalne. Zanotuj bieżącą wartość zmiennej IVolume.
Typ danych i bieżąca wartość zmiennej IVolume można wyświetlić w przykładowym kodzie, wpisując polecenie dt i nazwę zmiennej.
kd> dt lVolume Local var @ 0xa011ea50 Type long 0n-6291456Punkt przerwania został uaktywniony przy wejściu do SetDeviceChannelVolume.
STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::SetDeviceChannelVolume(_In_ ULONG _ulNodeId, _In_ UINT32 _uiChannel, _In_ LONG _Volume) { NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; PAGED_CODE (); DPF_ENTER(("[CMiniportWaveRT::SetEndpointChannelVolume]")); IF_TRUE_ACTION_JUMP(_ulNodeId != KSNODE_WAVE_AUDIO_ENGINE, ntStatus = STATUS_INVALID_DEVICE_REQUEST, Exit); // Snap the volume level to our range of steppings. LONG lVolume = VOLUME_NORMALIZE_IN_RANGE(_Volume); ntStatus = SetChannelVolume(_uiChannel, lVolume); Exit: return ntStatus; }Aby wyświetlić wartość pod adresem pamięci IVolume, użyj polecenia dt (Typ wyświetlania).
kd> dt dt lVolume Local var @ 0xffffb780b7eee664 Type long 0n0Ponieważ zmienna nie została jeszcze zdefiniowana, nie zawiera informacji.
Naciśnij F10, aby przejść do ostatniego wiersza kodu w funkcji SetDeviceChannelVolume.
return ntStatus;Wyświetl wartość w lokalizacji pamięci IVolume za pomocą polecenia dt (Typ wyświetlania).
kd> dt lVolume Local var @ 0xffffb780b7eee664 Type long 0n-6291456Teraz, gdy zmienna jest aktywna, w tym przykładzie zostanie wyświetlona wartość 6291456.
Możesz również wyświetlić lokalizację pamięci IVolume za pomocą polecenia ? (Oceń wyrażenie).
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664Pokazany adres ffffb780'b7eee664 jest adresem zmiennej lVolume. Użyj polecenia dd, aby wyświetlić zawartość pamięci w tej lokalizacji.
kd> dd ffffb780`b7eee664 ffffb780`b7eee664 ffa00000 00000018 00000000 c52d7008 ffffb780`b7eee674 ffffc98e e0495756 fffff80e c52d7008 ffffb780`b7eee684 ffffc98e 00000000 fffff80e 00000000 ffffb780`b7eee694 ffffc98e ffa00000 ffffb780 b7eee710 ffffb780`b7eee6a4 ffffb780 00000000 00000000 c7477260 ffffb780`b7eee6b4 ffffc98e b7eee7a0 ffffb780 b7eee6f0 ffffb780`b7eee6c4 ffffb780 e04959ca fffff80e 00000000 ffffb780`b7eee6d4 00000000 00000028 00000000 00000002Pierwsze cztery bajty adresu można wyświetlić, określając parametr zakresu L4.
kd> dd ffffb780`b7eee664 l4 ffffb780`b7eee664 ffa00000 00000018 00000000 c52d7008Aby wyświetlić wyświetlane różne typy danych wyjściowych pamięci, wpisz polecenia du, da i db .
kd> du ffffb780`b7eee664 ffffb780`b7eee664 "" kd> a ffffb780`b7eee664 ffffb780`b7eee664 "" kd> db 0xffffae015ff97664 ffffae01`5ff97664 00 80 bc ff 18 00 00 00-00 00 00 00 08 50 e0 51 .............P.Q ffffae01`5ff97674 00 c0 ff ff 56 57 da 56-0e f8 ff ff 08 50 e0 51 ....VW.V.....P.Q ffffae01`5ff97684 00 c0 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00 ................ ffffae01`5ff97694 00 c0 ff ff aa 80 bc ff-01 ae ff ff 10 77 f9 5f .............w._ ffffae01`5ff976a4 01 ae ff ff 40 00 00 00-00 e6 ff ff 10 dc 30 55 ....@.........0U ffffae01`5ff976b4 00 c0 ff ff a0 77 f9 5f-01 ae ff ff f0 76 f9 5f .....w._.....v._ ffffae01`5ff976c4 01 ae ff ff ca 59 da 56-0e f8 ff ff 00 00 00 00 .....Y.V........ ffffae01`5ff976d4 00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00 ....(...........Użyj opcji zmiennoprzecinkowej df, aby wyświetlić dane jako liczby zmiennoprzecinkowe o pojedynczej precyzji (4 bajty).
df ffffb780`b7eee664 ffffb780`b7eee664 -1.#QNAN 3.3631163e-044 0 -2775.002 ffffb780`b7eee674 -1.#QNAN -5.8032637e+019 -1.#QNAN -2775.002 ffffb780`b7eee684 -1.#QNAN 0 -1.#QNAN 0 ffffb780`b7eee694 -1.#QNAN -1.#QNAN -1.#QNAN -2.8479408e-005
Zapisywanie w pamięci
Podobnie jak w przypadku poleceń używanych do odczytywania pamięci, można użyć poleceń e* w celu zmiany zawartości pamięci.
| Komenda | Opis |
|---|---|
szt. |
Ciąg ASCII (bez zakończenia NULL) |
UE |
Ciąg Unicode (niezakończony znakiem NULL) |
Ew |
Wartości wyrazów (2 bajty) |
eza |
Ciąg ASCII zakończony wartością NULL |
ezu |
Ciąg Unicode zakończony przy użyciu wartości NULL |
Eb |
Wartości bajtów |
Ed |
Wartości podwójnych wyrazów (4 bajty) |
W poniższym przykładzie pokazano, jak zastąpić pamięć.
Najpierw znajdź adres lVolume, który jest używany w przykładowym kodzie.
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664Zastąp ten adres pamięci nowymi znakami za pomocą polecenia eb .
kd> eb 0xffffb780`b7eee664 11 11 11 11 11Wyświetl lokalizację pamięci, aby potwierdzić, że znaki zostały zastąpione, wpisując polecenie db .
kd> db 0xffffb780`b7eee664 ffffb780`b7eee664 11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5 .............p-. ffffb780`b7eee674 8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5 ....VWI......p-. ffffb780`b7eee684 8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00 ................ ffffb780`b7eee694 8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7 ................ ffffb780`b7eee6a4 80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7 ............`rG. ffffb780`b7eee6b4 8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7 ................ ffffb780`b7eee6c4 80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00 .....YI......... ffffb780`b7eee6d4 00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00 ....(...........
Alternatywnie możesz zmodyfikować zawartość pamięci w oknie zegarka lub ustawień lokalnych. W oknie obserwacyjnym mogą być widoczne zmienne, które są poza kontekstem aktualnej ramki. Modyfikowanie ich nie jest istotne, jeśli nie są w kontekście.
Sekcja 13. Zakończenie sesji WinDbg
<-W systemie hosta
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 (wersja klasyczna) w dokumentacji referencyjnej debugowania.
Sekcja 14. Zasoby debugowania systemu Windows
Dodatkowe informacje są dostępne w debugowaniu systemu Windows. Należy pamiętać, że niektóre z tych książek będą używać starszych wersji systemu Windows, takich jak Windows Vista w ich przykładach, ale omówione koncepcje mają zastosowanie do większości wersji systemu Windows.
Książki
zaawansowane debugowanie systemu Windows przez Mario Hewardt i Daniel Pravat
Debugowanie wewnątrz systemu Windows: Praktyczny przewodnik po strategiach debugowania i śledzenia w systemie Windows® autorstwa Tarika Soulami
Windows Internals przez Pavel Yosifovich, Alex Ionescu, Mark Russinovich i David Solomon
Wideo
Defrag Tools Show WinDbg Epizody 13-29: </shows/defrag-tools/>
Dostawcy szkoleń:
OSR — https://www.osr.com/