Megosztás:


Application Verifier – Az Application Verifier leállásainak hibakeresése

Hibakereső telepítése és beállítása

Egyes Application Verifier-műveletek kivételt eredményezhetnek. A hibakeresőt úgy kell beállítani, hogy ezeket a kivételeket a második lehetőségen észlelje, mivel maga az Application Verifier fogja kezelni az első esélybeli kivételeket.

A bevezetett kivételek három típusból állnak:

  • A rendszer hozzáférési szabálysértési kivételt (0xC0000005) hoz létre, ha a halombeállítás a halompuffer túlfutását észleli. Bizonyos esetekben a Rendszerútvonal használatának ellenőrzése beállítás hozzáférés-megsértést is okozhat.

  • Érvénytelen leírókivétel (0xC0000008) jön létre, ha az Érvénytelen leíróhasználat észlelése beállítás érvénytelen leíróműveletet észlel.

  • A rendszer egy verem túlcsordulási kivételt (0xC00000FD) hoz létre, amikor a Megfelelő verem ellenőrzése beállítás azt észleli, hogy a kezdeti verem túl rövid volt.

Az események előkészítésének egyik módja, ha elindítja a hibakeresőt egy parancssorban az alábbiak szerint:

windbg -xd av -xd ch -xd sov ApplicationCommandLine

vagy

cdb -xd av -xd ch -xd sov ApplicationCommandLine

Ha már elindította a hibakeresőt, az sxd (Kivételek beállítása) paranccsal észlelheti az összes hozzáférés-szabálysértést, érvénytelen leírót és verem-túlcsordulást második esélyű kivételként:

0:000> sxd av 

0:000> sxd ch 

0:000> sxd sov 1

Elméletileg egy kernel-hibakeresőn keresztül vezérelhető az Application Verifier. Ez azonban nem ajánlott – a .process és a .pagein parancsok gyakori használatát igényli, de nem ad több energiát, mint egy felhasználói módú hibakereső használata.

A hibakeresési eszközök telepítése

Az eszközök legújabb verziójának letöltéséhez tekintse meg a Windows hibakeresési eszközeinek letöltésével kapcsolatos témakört.

Hardver konfigurálása User-Mode hibakereséshez

A felhasználói módú hibakeresés általában egyetlen gépen történik: a hibakereső ugyanazon a számítógépen fut, mint a sikertelen alkalmazás.

Ebben az esetben nincs szükség konkrét hardverbeállításra. Ebben a témakörben a gazdaszámítógép és a célszámítógép kifejezés ebben az esetben felcserélhető.

Szoftver konfigurálása User-Mode hibakereséshez

Alapszintű User-Mode konfiguráció – A felhasználói módú hibakeresés megkezdése előtt le kell töltenie a szükséges szimbólumfájlokat, és be kell állítania bizonyos környezeti változókat.

Szimbólumfájlok

Le kell töltenie a hibakeresés alatt álló felhasználói módú folyamat szimbólumfájljait. Ha ez egy ön által írt alkalmazás, akkor teljes szimbólumfájlokkal kell rendelkeznie. Ha kereskedelmi alkalmazásról van szó, a szimbólumfájlok elérhetőek lehetnek egy webkiszolgálón, vagy letölthetők, forduljon a gyártóhoz.

ha távoli hibakeresést végez, a szimbólumfájl helye a használt módszertől függ:

  • Ha távoli hibakeresést végez a hibakeresőn keresztül, a szimbólumfájloknak a hibakereső kiszolgálóval rendelkező számítógépen kell lenniük.

  • Ha távoli hibakeresést végez remote.exekeresztül, a szimbólumfájloknak a hibakeresővel együtt kell lenniük a számítógépen.

  • Ha távoli hibakeresést végez egy folyamatkiszolgálón vagy egy KD kapcsolatkiszolgálón keresztül, a szimbólumfájloknak az intelligens ügyféllel együtt kell lenniük a számítógépen.

  • Ha a felhasználói módú hibakeresőt a kernel-hibakeresőből vezérli, a szimbólumfájloknak mindkét számítógépen meg kell lenniük.

Környezeti változók konfigurálása

A hibakereső számos környezeti változót használ számos fontos beállítás jelzésére.

További információ a hibakeresőkről: Első lépések a Windows hibakeresésével kapcsolatban

Az Application Verifier konfigurálása a hibakeresővel a parancssor használatával

Az Application Verifier konfigurálásához használhatja a CDB vagy az NTSD parancssort.

Használja a következő parancssort:

cdb OtherOptions -vf:Flags Target

Ahol a Cél a célalkalmazás neve, a Jelzők pedig a célalkalmazásra alkalmazni kívánt Alkalmazás-ellenőrző beállításokat adja meg.

A jelölőknek a kívánt beállításokat képviselő bitek összegének kell lenniük. Az egyes bitértékek a következők:

Zászló érték Értelmezés
00000001 HEAP-ELLENŐRZÉSEK
00000004 ELLENŐRZÉSEK KEZELÉSE
00000008 ALACSONY ERŐFORRÁSÚ SIM-KÁRTYA ELLENŐRZÉSEK
00000020 TLS-ELLENŐRZÉSEK
00000040 SZENNYEZETT VEREMEK
00000200 VESZÉLYES API-K
00001000 Kivétel ellenőrzések
00002000 MEMÓRIAELLENŐRZÉSEK
00020000 EGYÉB ELLENŐRZÉSEK
00040000 ZÁROLÁSI ELLENŐRZÉSEK

Hibakeresés a!avrf használatával

A !avrf bővítmény szabályozza az Application Verifier beállításait, és az Application Verifier által előállított különféle kimeneteket jeleníti meg. A !arvrf bővítményről további információt a hibakereső dokumentációjában található !avrf című témakörben talál.

Szemantika

!avrf

A paraméterek nélküli !avrf parancs megjeleníti az Application Verifier beállításait, valamint az aktuális és az előző Application Verifier-törésekkel kapcsolatos információkat, ha vannak ilyenek.

!avrf –vs { Length | -aAddress }

Megjeleníti a virtuális tér műveleti naplót. A Hossz a legutóbbitól kezdődően megjelenítendő rekordok számát adja meg. A cím a virtuális címet adja meg. Ekkor megjelennek az ezt a virtuális címet tartalmazó virtuális műveletek rekordjai.

!avrf -hp { Length | -a Address }

Megjeleníti a halomműveleti naplót. A cím a halomcímet adja meg. Megjelennek az ezt a halomcímet tartalmazó halomműveletek rekordjai.

!avrf -cs { Length | -a Address }

Megjeleníti a kritikus szakasz törlési naplót. A Hossz a legutóbbitól kezdődően megjelenítendő rekordok számát adja meg. A cím a kritikus szakasz címét adja meg. A cím megadásakor megjelennek az adott kritikus szakasz rekordjai.

!avrf -dlls [ Length ]

Megjeleníti a DLL betöltési/eltávolítási naplót. A Hossz a legutóbbitól kezdődően megjelenítendő rekordok számát adja meg.

!avrf -trm

Megjeleníti az összes megszakított és felfüggesztett szál naplóját.

!avrf -ex [ Length ]

Megjeleníti a kivételnaplót. Az Application Verifier nyomon követi az alkalmazásban történt összes kivételt.

!avrf -threads [ ThreadID ]

A célfolyamat szálairól jelenít meg információkat. A gyermekszálak esetében a verem mérete és a szülő által megadott CreateThread jelzők is megjelennek. A szálazonosító megadása csak az adott szálra vonatkozó információkat jeleníti meg.

!avrf -tp [ ThreadID ]

Megjeleníti a szálkészlet naplót. Ez a napló különböző műveletekhez tartalmazhat veremnyomokat, például a szál affinitási maszkjának módosítását, a szál prioritásának módosítását, a szálüzenetek közzétételét, a COM inicializálását és a COM leállítását a szálkészleti visszahívás során. A szálazonosító megadása csak az adott szálra vonatkozó információkat jeleníti meg.

!avrf -srw [ Address | Address Length ] [ -stats ]

Megjeleníti a Slim Reader/Writer (SRW) naplót. A Cím megadása az adott SRW-zárolási címmel kapcsolatos rekordokat jeleníti meg. Ha a címmel együtt meg van adva a hossz, a címtartományon belüli összes SRW-zárolás megjelenik. A -stats beállítás kiírja az SRW zárolási statisztikáit.

!avrf -leak [ -m ModuleName ] [ -r ResourceType ] [ -a Address ] [ -t ]

Megjeleníti a kiemelkedő erőforrás-naplót. Előfordulhat, hogy ezek az erőforrások egy adott ponton szivárognak vagy sem. A ModuleName megadása (a bővítményt is beleértve) a megadott modulban lévő összes rendelkezésre álló erőforrást megjeleníti. A ResourceType megadása megjeleníti az adott erőforrástípushoz tartozó kinnlévő erőforrásokat. A Cím megadása az adott címmel rendelkező, függőben lévő erőforrások rekordjait adja meg. A ResourceType az alábbiak egyike lehet:

  • Halom: A halomfoglalások megjelenítése Win32 Halom API-k használatával
  • Helyi: Helyi/globális foglalások megjelenítése
  • CRT: A foglalások megjelenítése CRT API-k igénybevételével
  • Virtuális: Virtuális foglalások megjelenítése
  • BSTR: A BSTR-foglalások megjelenítése
  • Beállításjegyzék: Megnyílik a beállításkulcs megjelenítése
  • Power: Energiaértesítési objektumok megjelenítése
  • Leíró: Szál-, fájl- és eseményleíró-foglalások megjelenítése

!avrf –trace TraceIndex

Megjeleníti a megadott nyomkövetési index veremkövetését. Egyes struktúrák ezt a 16 bites indexszámot használják a veremkövetés azonosításához. Ez az index a veremnyom adatbázisban található egyik helyre mutat. Ha ilyen struktúrát elemez, hasznosnak fogja találni ezt a szintaxist.

!avrf -cnt

A globális számlálók listáját jeleníti meg.

!avrf -brk [ BreakEventType ]

Megadja, hogy ez egy eseménytörési parancs. Ha !avrf -brk további paraméterek nélkül használják, a törésesemény-beállítások megjelennek. A BreakEventType a törésesemény típusszámát adja meg. A lehetséges típusok listájához használja !avrf -brka következőt: .

!avrf -flt [ EventTypeProbability ]

Meghatározza, hogy ez egy hibainjektálási parancs. Ha !avrf -flt további paraméterek nélkül használják, az aktuális hibainjektálási beállítások jelennek meg. Az EventType az esemény típusszámát adja meg. A valószínűség azt a gyakoriságot határozza meg, amellyel az esemény meghiúsul. Ez lehet 0 és 1 000 000 000 közötti egész szám (0xF4240).

!avrf -flt break EventType

Az Application Verifier a hiba minden egyes beadásakor feltöri a hibakeresőt.

!avrf -flt stacks Length

Megjeleníti a legutóbbi hibainjektált műveletek veremnyomainak hosszát.

!avrf -trg [ StartEnd | dll Module | all ]

Meghatározza, hogy ez egy céltartomány-parancs. Ha a -trg-t további paraméterek nélkül használják, az aktuális céltartományok jelennek meg. A Start a céltartomány vagy a kizárási tartomány kezdőcímét adja meg. A Végpont a céltartomány vagy a kizárási tartomány zárócímét adja meg. A modul a megcélzandó vagy kizárandó modul nevét adja meg. A modulnak tartalmaznia kell a modul teljes nevét, beleértve a .exe vagy .dll bővítményt. Az elérésiút-információkat nem szabad megadni. Ha az összeset megadja, az összes céltartomány vagy kizárási tartomány alaphelyzetbe állítódik.

!avrf -skp [ StartEnd | dll Module | all | Time ]

Azt adja meg, hogy ez egy kizárási tartomány parancsa. A Start a céltartomány vagy a kizárási tartomány kezdőcímét adja meg. A Végpont a céltartomány vagy a kizárási tartomány zárócímét adja meg. A modul a megcélzandó vagy kizárandó modul nevét adja meg. A modulnak tartalmaznia kell a modul teljes nevét, beleértve a .exe vagy .dll bővítményt. Az elérésiút-információkat nem szabad megadni. Ha az összes meg van adva, az összes céltartomány vagy kizárási tartomány alaphelyzetbe áll. Az idő megadása miatt a végrehajtás folytatása után az idő ezredmásodpercben minden hiba el lesz tiltva.

A hibakeresőben a !avrf parancs által megadott kimenet a következő.

0:000> !avrf
Application verifier settings (816431A7):

   - full page heap
   - COM
   - RPC
   - Handles
   - Locks
   - Memory
   - TLS
   - Exceptions
   - Threadpool
   - Leak
   - SRWLock

No verifier stop active.

Note: Sometimes bugs found by verifier manifest themselves as raised
exceptions (access violations, stack overflows, invalid handles), 
and it is not always necessary to have a verifier stop.

!avrf bővítmény megjegyzései

Ha a !avrf bővítményt paraméterek nélkül használja, az aktuális Application Verifier-beállításokat jeleníti meg.

A !avrf bővítmény a hibakereső Exts.dll használja.

Ha egy Application Verifier stop történt, a paraméterek nélküli !avrf bővítmény megmutatja a leállítás jellegét és az azt okozó tényezőket.

Ha hiányoznak ntdll.dll és verifier.dll szimbólumai, az !avrf bővítmény hibaüzenetet fog generálni.

Folytonos és Nem-Folytonos Leállások

Folyamatos leállítás hibakeresése

Íme egy példa egy érvénytelen handle kivételre, amelyet az Érvénytelen handle használatának észlelése beállítás váltott ki.

Először a következő üzenet jelenik meg:

Invalid handle - code c0000008 (first chance)

===================================================

VERIFIER STOP 00000300: pid 0x558: invalid handle exception for current stack trace

        C0000008 : Exception code.

        0012FBF8 : Exception record. Use .exr to display it.

        0012FC0C : Context record. Use .cxr to display it.

        00000000 :

===================================================

This verifier stop is continuable.

After debugging it use 'go' to continue.

===================================================

Break instruction exception - code 80000003 (first chance)

eax=00000000 ebx=6a27c280 ecx=6a226447 edx=0012fa4c esi=00942528 edi=6a27c260

eip=6a22629c esp=0012facc ebp=0012faf0 iopl=0         nv up ei pl zr na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

6a22629c cc               int     3

Figyelje meg, hogy az üzenet azt jelzi, hogy ez az alkalmazás-ellenőrző leállítása folytatható. Miután megismerte a történteket, folytathatja a célalkalmazás futtatását.

Először a !avrf bővítményt kell használnia. Ez az aktuális hibáról ad információt:

0:000> !avrf

Global flags: 00000100

Application verifier global flag is set.

Application verifier settings (00000004):

   - no heap checking enabled!

   - handle checks

Page heap is not active for this process.

Current stop 00000300 : c0000008 0012fbf8 0012fc0c 00000000 .

    Using an invalid handle (either closed or simply bad).

A kijelző utolsó sora összefoglalja a problémát.

Érdemes lehet áttekinteni néhány naplót ezen a ponton. Ha végzett, a g (Go) paranccsal indítsa újra az alkalmazást:

0:000> g

## Debugging a Non-Continuable Stop

Here is an example of an access violation that has been raised by the page heap option.

First, the following message appears:

Access violation - code c0000005 (first chance)

===================================================

VERIFIER STOP 00000008: pid 0x504: exception raised while verifying block header

        00EC1000 : Heap handle

        00F10FF8 : Heap block

        00000000 : Block size

        00000000 :

===================================================

This verifier stop is not continuable. Process will be terminated when you use the 'go' debugger command.

===================================================

Break instruction exception - code 80000003 (first chance)

eax=00000000 ebx=00000000 ecx=6a226447 edx=0012fab7 esi=00f10ff8 edi=00000008

eip=6a22629c esp=0012fb5c ebp=0012fb80 iopl=0         nv up ei pl zr na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

6a22629c cc               int     3

Ebben az esetben az üzenet azt jelzi, hogy ez az alkalmazás-ellenőrző leállítása nem folytatható. A hiba túl súlyos ahhoz, hogy a folyamat tovább fusson, és az Application Verifier nem képes a folyamat mentésére.

A !avrf bővítmény az aktuális hibával kapcsolatos információk megadására használható:

0:000> !avrf

Global flags: 02000100

Application verifier global flag is set.

Page heap global flag is set.

Application verifier settings (00000001):

   - full page heap

Page heaps active in the process (format: pageheap, lightheap, flags):

    00941000 , 00a40000 , 3 (pageheap traces )

    00b41000 , 00c40000 , 3 (pageheap traces )

    00cb1000 , 00db0000 , 3 (pageheap traces )

    00ec1000 , 00fc0000 , 3 (pageheap traces )

Current stop 00000008 : 00ec1000 00f10ff8 00000000 00000000 .

    Corrupted heap block.

A kijelző utolsó sora összefoglalja a problémát.

Érdemes lehet néhány naplót is megnézni ezen a ponton. Ezen a ponton érdemes lehet az .restart (Restart Target Application) parancsot használni. Vagy lehet, hogy inkább befejezi az Application Verifier-munkamenetet, és elkezdi kijavítani a kód hibáit.

Kritikus szakaszhibák hibakeresése

!cs hibakereső bővítmény

A !cs a felhasználói módban hibakeresőben és a kernel-hibakeresőben is használható az aktuális folyamat kritikus szakaszaival kapcsolatos információk megjelenítéséhez. A !cs kiterjesztéssel kapcsolatos további információkért tekintse meg a !cs fájlt a hibakereső dokumentációjában.

A típusadatokkal való egyező szimbólumok megadása kötelező, különösen ntdll.dllesetében.

A bővítmény szintaxisa a következő:

!cs [-s] – írja ki az aktuális folyamat összes aktív kritikus szakaszát.

!cs [-s] cím – megjeleníti a kritikus szakaszt ezen a címen.

!cs [-s] -d cím – a DebugInfo-nak megfelelő kritikus szakasz kiíratása ezen a címen.

A -s a kritikus szakasz inicializálási verem nyomkövetését fogja kihozni, ha elérhető.

Példák:

A kritikus szakasz adatainak kiírása a cím alapján

0:001> ! cs 0x7803B0F8

Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
DebugInfo          = 0x6A262080
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

Kritikus szakasz információinak memóriaképe a cím felhasználásával, beleértve az inicializálási verem-nyomkövetést is.

0:001> !cs -s 0x7803B0F8

Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
DebugInfo          = 0x6A262080
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

Stack trace for DebugInfo = 0x6A262080:
0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

A kritikus szakasz adatainak kiírása a hibakeresési információ címének használatával

0:001> !cs -d 0x6A262080

DebugInfo          = 0x6A262080
Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

A kritikus szakasz adatainak kiíratása a hibakeresési információ címének használatával, beleértve az inicializálási veremnyomot is.

0:001> !cs -s -d 0x6A262080

DebugInfo          = 0x6A262080
Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
Stack trace for DebugInfo = 0x6A262080:
0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE

Az aktuális folyamat összes aktív kritikus szakaszára vonatkozó információ kiírása

0:001> !cs

-----------------------------------------

DebugInfo          = 0x6A261D60
Critical section   = 0x6A262820 (ntdll!RtlCriticalSectionLock+0x0)
LOCKED
LockCount          = 0x0
OwningThread       = 0x460
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x0
-----------------------------------------

DebugInfo          = 0x6A261D80
Critical section   = 0x6A262580 (ntdll!DeferedCriticalSection+0x0)
NOT LOCKED
LockSemaphore      = 0x7FC
SpinCount          = 0x0
-----------------------------------------

DebugInfo          = 0x6A262600
Critical section   = 0x6A26074C (ntdll!LoaderLock+0x0)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
.....

Az aktuális folyamat összes aktív kritikus szakaszának információinak kiírása, a verem inicializálási nyomkövetésével együtt.


0:001> !cs -s

...

-----------------------------------------

DebugInfo          = 0x6A261EA0
Critical section   = 0xA8001C (+0xA8001C)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
No stack trace saved

-----------------------------------------

DebugInfo          = 0x6A261EC0
Critical section   = 0x6A263560 (ntdll!RtlpDphTargetDllsLock+0x0)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
No stack trace saved

-----------------------------------------

DebugInfo          = 0x6A261EE0
Critical section   = 0xA90608 (+0xA90608)
NOT LOCKED
LockSemaphore      = 0x7EC
SpinCount          = 0x0
Stack trace for DebugInfo = 0x6A261EE0:

0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A20B0DC: ntdll!CsrpConnectToServer+0x1BE
0x6A20B2AA: ntdll!CsrClientConnectToServer+0x148
0x77DBE83F: KERNEL32!BaseDllInitialize+0x11F
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

-----------------------------------------

DebugInfo          = 0x6A261F00
Critical section   = 0x77E1AEB8 (KERNEL32!BaseDllRegistryCache+0x18)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
Stack trace for DebugInfo = 0x6A261F00:
0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

Kivételhibák hibakeresése

A kivételnapló rögzíti a célfolyamatban történt összes kivételt.

A !avrf -ex Length bővítmény parancsával megjelenítheti az utolsó néhány kivételt; A hossz a kivételek számát adja meg. Ha a hossz nincs megadva, minden kivétel megjelenik.

Íme egy példa:

0:000> !avrf -ex 4

=================================

Thread ID: 0000052c
Exception code: c0000008
Exception address: 6a226663
Exception record: 0012fb50
Context record: 0012fb64

Displayed 1 exception log entries.

Hibakeresés során hibák kezelése

A !htrace a felhasználói módú hibakeresőben és a kernel-hibakeresőben is használható a folyamat egy vagy az összes leírójának veremkövetési információinak megjelenítéséhez. Ez az információ akkor érhető el, ha a folyamathoz engedélyezve van a handle követés – automatikusan engedélyezve van, ha a handle ellenőrzés engedélyezve van az alkalmazás verifikátorban. A verem nyomkövetései mentésre kerülnek minden alkalommal, amikor a folyamat megnyit vagy bezár egy leírót, vagy érvénytelen leíróra hivatkozik. A !htrace kiterjesztéssel kapcsolatos további információkért lásd: !htrace a hibakereső dokumentumokban.

A bővítmény kernel-hibakereső szintaxisa a következő:

!htrace [ handle [process] ]

Ha a fogantyú nincs megadva, vagy 0, akkor a folyamat összes fogópontjára vonatkozó információ megjelenik. Ha a folyamat nincs megadva, a rendszer az aktuális folyamatot használja.

A felhasználói módú hibakereső szintaxisa a következő:

!htrace [handle]

A felhasználói módú hibakereső bővítmény mindig megjeleníti az aktuális hibakeresési folyamat adatait.

Példák:

A 815328b0 folyamat 7CC-ének kezelésére vonatkozó memóriaképadatok

kd> !htrace 7CC 815328b0

Loaded \\...\kdexts extension DLL
Process 0x815328B0
ObjectTable 0xE15ECBB8

--------------------------------------

Handle 0x7CC - CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x77DBFCD6: KERNEL32!GetLocaleFileInfo+0x3D
0x77DBF942: KERNEL32!NlsProcessInitialize+0x11D
0x77E0C6DF: KERNEL32!NlsDllInitialize+0x35
0x6A20785C: ntdll!LdrpCallInitRoutine+0x14
0x6A205393: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DD80: ntdll!LdrpInitializeProcess+0xAF6

--------------------------------------

Handle 0x7CC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3180: ntoskrnl!ObpCreateHandle+0x304
0x801E1563: ntoskrnl!ObOpenObjectByName+0x1E9
0x77DBFCD6: KERNEL32!GetLocaleFileInfo+0x3D
0x77DBF942: KERNEL32!NlsProcessInitialize+0x11D
0x77E0C6DF: KERNEL32!NlsDllInitialize+0x35
0x6A20785C: ntdll!LdrpCallInitRoutine+0x14
0x6A205393: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DD80: ntdll!LdrpInitializeProcess+0xAF6

--------------------------------------

Parsed 0x1CA stack traces.
Dumped 0x2 stack traces.

A 815328b0 folyamat összes fogantyújának információinak kiírása

kd> !htrace 0 81400300

Process 0x81400300
ObjectTable 0xE10CCF60

--------------------------------------

Handle 0x7CC - CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7CC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE23B2: KERNEL32!CreateSemaphoreA+0x66
0x010011C5: badhandle!main+0x45
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - BAD REFERENCE:

0x8018F709: ntoskrnl!ExMapHandleToPointerEx+0xEA
0x801E10F2: ntoskrnl!ObReferenceObjectByHandle+0x12C
0x801902BE: ntoskrnl!NtSetEvent+0x6C
0x80154965: ntoskrnl!_KiSystemService+0xC4
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - CLOSE:

0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE265C: KERNEL32!CreateEventA+0x66
0x010011A0: badhandle!main+0x20
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Parsed 0x6 stack traces.

Dumped 0x5 stack traces.

Az aktuális folyamat 7DC számú hivatkozásának információinak kilistázása


kd> !htrace  7DC

Process 0x81400300

ObjectTable 0xE10CCF60

--------------------------------------

Handle 0x7DC - BAD REFERENCE:

0x8018F709: ntoskrnl!ExMapHandleToPointerEx+0xEA
0x801E10F2: ntoskrnl!ObReferenceObjectByHandle+0x12C
0x801902BE: ntoskrnl!NtSetEvent+0x6C
0x80154965: ntoskrnl!_KiSystemService+0xC4
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - CLOSE:

0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE265C: KERNEL32!CreateEventA+0x66
0x010011A0: badhandle!main+0x20
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Parsed 0x6 stack traces.

Dumped 0x3 stack traces.

Halomhibák hibakeresése

Heap verifier debugger bővítmény

A halom ellenőrző hibakereső kiterjesztés a !halom kiterjesztés része (NT halom hibakereső kiterjesztés). Egyszerű segítséget a "!heap -?" paranccsal kaphat. vagy részletesebb a !heap -p -? . Az aktuális bővítmény önmagában nem észleli, ha a lap halom engedélyezve van egy folyamathoz, és ennek megfelelően jár el. A bővítmény felhasználójának egyelőre tudnia kell, hogy a lap heap engedélyezve van, és a !heap -p által előtagolt parancsokat kell használnia. A !htrace kiterjesztéssel kapcsolatos további információkért lásd: !heap a hibakereső dokumentációjában.

!heap -p

Kiírja az összes teljes oldallap halom címét, amelyeket a folyamat során hoztak létre.

!heap -p -h ADDRESS-OF-HEAP

Teljes memóriakép a teljes oldal halomról a ADDRESS-OF-HEAP címen.

!heap -p -a ADDRESS

Megpróbálja kideríteni, hogy van-e halomblokk a ADDRESS-ben. Ennek az értéknek nem kell a blokk elejének címe lenni. A parancs akkor hasznos, ha nincs semmilyen nyom a memóriaterület természetéről.

Halomműveleti napló

A halomművelet naplója nyomon követi az összes halom rutint. Ezek közé tartozik a HeapAlloc, a HeapReAlloc és a HeapFree.

A !avrf -hp Length bővítményparancs használatával megjelenítheti az utolsó több rekordot; A hossz a rekordok számát határozza meg.

Az !avrf -hp -a Address használatával megjelenítheti az összes halomhely műveletet, amely hatással volt a megadott címre. Foglalási művelet esetén elegendő, ha a cím szerepel a lefoglalt halomblokkban. Ingyenes művelet esetén meg kell adni a blokk elejének pontos címét.

A napló minden egyes bejegyzése esetében a következő információk jelennek meg:

  • A heap függvényt hívták meg.
  • Annak a szálnak a szálazonosítója, amely a rutint meghívta.
  • A hívásban érintett cím – ez az a cím, amelyet egy foglalási rutin adott vissza, vagy amelyet egy ingyenes rutinnak adott át.
  • A hívásban érintett régió mérete.
  • A hívás veremnyoma.

A legutóbbi bejegyzések jelennek meg először.

Ebben a példában a két legutóbbi bejegyzés jelenik meg:

0:001> !avrf -hp 2

alloc (tid: 0xFF4): 
address: 00ea2fd0 
size: 00001030
00403062: Prymes!_heap_alloc_dbg+0x1A2
00402e69: Prymes!_nh_malloc_dbg+0x19
00402e1e: Prymes!_malloc_dbg+0x1E
00404ff3: Prymes!_stbuf+0xC3
00401c23: Prymes!printf+0x43
00401109: Prymes!main+0xC9
00402039: Prymes!mainCRTStartup+0xE9
77e7a278: kernel32!BaseProcessStart+0x23

alloc (tid: 0xFF4): 
address: 00ea07d0 
size: 00000830
00403062: Prymes!_heap_alloc_dbg+0x1A2
00402e69: Prymes!_nh_malloc_dbg+0x19
00402e1e: Prymes!_malloc_dbg+0x1E
00403225: Prymes!_calloc_dbg+0x25
00401ad5: Prymes!__initstdio+0x45
00401f38: Prymes!_initterm+0x18
00401da1: Prymes!_cinit+0x21
00402014: Prymes!mainCRTStartup+0xC4

77e7a278: kernel32!BaseProcessStart+0x23

Tipikus hibakeresési forgatókönyvek

Több hibaforgatókönyv is előfordulhat. Néhányat közülük elég sok nyomozói munkára van szükség ahhoz, hogy teljes képet kapjunk.

Hozzáférés megsértése nem akadálymentes lapon

Ha a teljes oldalas halom engedélyezve van, ez akkor fordul elő, ha a tesztelt alkalmazás a pufferhatáron túl fér hozzá. Ez akkor is előfordulhat, ha egy felszabadított blokkot érint. A kivételt okozó cím természetének megértéséhez a következőt kell használnia:

!heap –p –a ADDRESS-OF-AV

Sérült blokküzenet

A foglalás élettartama alatt (foglalás, felhasználó szintű felszabadítás, valós szintű felszabadítás) a lap kupackezelő ellenőrzi, hogy a blokk minden kitöltési mintája érintetlen-e, és hogy a blokkfejléc konzisztens adatokat tartalmaz-e. Ha ez nem így van, akkor egy ellenőrzési leállás történik.

Ha a blokk egy teljes oldalas halomblokk (például ha biztos benne, hogy a teljes oldal halom minden foglaláshoz engedélyezve van), akkor a "!heap –p –a ADDRESS" használatával megtudhatja, hogy mik a blokk jellemzői.

Ha a blokk egy egyszerű oldal halomblokk, akkor meg kell tudnia a blokk fejlécének kezdő címét. A kezdőcímet úgy találhatja meg, hogy a jelentett cím alatti 30–40 bájtot kiment, és megkeresi a blokkfejlécek jellegzetes kezdő/záró mintáit (ABCDAAAA, ABCDBBBB, ABCDAAA9, ABCDBBBA).

A fejléc minden olyan információt megad, amely a hiba megértéséhez szükséges. Különösen a mágikus mintázatok jelzik, hogy a blokk ki van-e osztva vagy szabad, illetve hogy egy kis lapkészlet vagy egy teljes lapkészlet blokkja. Az itt található információkat gondosan össze kell egyeztetni a jogsértő hívással.

Ha például a HeapFree hívása egy blokk címével és négy bájttal történik, akkor a sérült üzenet jelenik meg. A blokkfejléc jól fog kinézni, de látnia kell, hogy a fejléc vége utáni első bájt (a 0xDCBAXXXX mágikus érték után az első bájt) egy másik címmel rendelkezik, mint a hívásban.

Speciális kitöltési mutatók

Az oldalhalom-kezelő a felhasználói foglalást olyan értékekkel tölti ki, amelyek kernelmutatóknak tűnnek. Ez akkor fordul elő, amikor a blokk felszabadul (a kitöltési érték F0), és amikor a blokk le lesz foglalva, de nincs kérés a blokk nullázására (a könnyű oldalhalomnál a kitöltési érték E0, a teljes oldalhalomnál pedig C0). A nem nullázott foglalások tipikusan a malloc/new használókra jellemzőek. Ha hiba (hozzáférés-megsértés) történik, amikor olvasási/írási kísérleteket kísérel meg olyan címeken, mint a F0F0F0F0, E0E0E0E0, C0C0C0C0, akkor valószínűleg az egyik ilyen esetet éri el.

Az F0F0F0F0 címen történő olvasás/írás azt jelenti, hogy egy blokkot használtak, miután felszabadult. Sajnos szüksége lesz néhány nyomozói munkára, hogy megtudja, melyik blokk okozta ezt. Le kell kérnie a hiba verem-nyomkövetését, majd meg kell vizsgálnia a veremen lévő függvények kódját. Az egyikük tévesen feltételezheti, hogy egy allokáció még él.

A E0E0E0E0/C0C0C0C0 olvasási/írási művelet azt jelenti, hogy az alkalmazás nem inicializálta megfelelően a foglalást. Ehhez az aktuális veremkövetésben lévő függvények kódvizsgálatára is szükség van. Íme egy példa erre a hibára. A tesztelési folyamat során egy hozzáférési jogsértést észleltek a HeapFree művelet végrehajtása közben, a cím E0E0E0E0 esetén. Kiderült, hogy a teszt lefoglalt egy struktúrát, nem helyesen inicializálta, majd meghívta az objektum destruktorát. Mivel egy adott mező nem null értékű (E0E0E0E0 volt benne), törlést hívott meg rajta.

Laphalom Technikai Részletei

A halomsérülések (túlcsordulások vagy alulcsordulások) észleléséhez az AppVerifier úgy módosítja a memória lefoglalásának módját, hogy a kért memóriát teljes, nem írható lapokkal vagy speciális címkékkel osztja ki a lefoglalt memória előtt és után. Az AppVerifier úgy működik, hogy betölti a Verifier.dll-t az ellenőrzött folyamatba, és átirányítja az alkalmazás által hívott Win32 Halom API-kat a megfelelő Verifier.dll API-khoz.

Ha a kért memóriát teljes, nem írható lapokkal kitölti (a TELJES beállítás engedélyezve van a lap halomtulajdonságok szakaszában, és ez az alapértelmezett beállítás), az AppVerifier nagy mennyiségű virtuális memóriát fog használni, de előnye, hogy a halomsérülési események valós időben gyorsítótárazódnak a túlcsordulás vagy az alulcsordulás bekövetkezésekor. Ne feledje, hogy a memória ebben a módban a következőképpen fog kinézni [AppVerifier Read-Only Halomlap (4k)] [A teszt alatt lévő alkalmazás által kért memória mennyisége] vagy ehhez hasonló [Az alkalmazás által kért memória mennyisége a teszt alatt] [AppVerifier Read-Only Halomlap (4k)].

A halomellenőrzés a Backward tulajdonságtól függően egy védőlapot helyez el a foglalás elején vagy végén. Ha a hátramenet hamis (ami az alapértelmezett érték), akkor a kiosztás végén egy védőlapot helyez el, hogy elfogja a puffertúlcsordulásokat. Ha igaz értékre van állítva, a védelmi lap a lefoglalás elejére kerül, hogy elfogja a puffer alulcsordulásait.

A program által igényelt memória speciális címkékkel való kitöltésekor (a halom tulajdonságai között található 'Teljes' jelölőnégyzet kikapcsolásával engedélyezve), az AppVerifier ellenőrzi és figyelmeztet arra, amikor a memória felszabadul. A technika használata során az a fő probléma, hogy vannak olyan esetek, amikor a memória sérülése csak a memória felszabadításakor lesz észlelhető (a memóriablokk minimális mennyisége 8 bájt), így ha egy 3 bájtos változó vagy egy 5 bájtos túlcsordulás történik, akkor a rendszer nem észleli azonnal.

Alulcsordulási esemény esetén a rendszer megpróbál írni egy Read-Only lapra. Ez kivételt fog kiváltani. Vegye figyelembe, hogy ez a kivétel csak akkor fogható el, ha a célalkalmazást egy hibakereső alatt futtatják. Vegye figyelembe, hogy a teljes oldal halom mód is észleli ezeket a hibákat, mert padding+guard oldalakat használ. Azért használná a könnyű lapkészletet, ha a számítógép nem tudja elviselni a teljes lapkészlet magas memóriaigényét.

Memóriaigényes alkalmazások esetén, vagy ha az AppVerifier használata hosszú ideig szükséges (például stressztesztelés), jobb, ha a teljesítménycsökkenés miatt normál (könnyű) halomteszteket futtat a teljes mód helyett. Amikor azonban problémába ütközik, a további vizsgálathoz kapcsolja be a teljes lapokra vonatkozó heap funkciót.

Az egyéni memóriahalmokat használó alkalmazások (memóriahalom, amely megkerüli az operációs rendszer memóriahalom-megvalósítását) lehet, hogy nem használják ki teljes mértékben a page heap előnyeit, vagy működésképtelenné válhatnak, amikor az engedélyezve van.

Memóriahibák hibakeresése

A memória-ellenőrző hibakereső bővítménye

A virtuális tér műveleti naplója nyomon követi az összes olyan rutint, amely bármilyen módon módosítja egy folyamat virtuális területét. Ezek közé tartozik a VirtualAlloc, a VirtualFree, a MapViewOfFile és a UnmapViewOfFile.

A !avrf -vs Length bővítményparancs használatával megjelenítheti az utolsó több rekordot; A hossz a rekordok számát határozza meg.

A !avrf -vs -a Cím használatával megjelenítheti a megadott címet érintő összes virtuálistér-műveletet. Foglalás esetén elegendő, ha a cím szerepel a lefoglalt blokkban. Ingyenesen meg kell adni a régió elejének pontos címét.

A napló minden egyes bejegyzése esetében a következő információk jelennek meg:

  • A hívott függvény
  • A rutint meghívó szál szálazonosítója
  • A hívásban érintett cím – ez az a cím, amelyet egy foglalási rutin adott vissza, vagy amelyet egy ingyenes rutinnak adott át
  • A hívásban érintett régió mérete
  • A memóriaművelet típusa (a AllocationType paraméter)
  • A kért védelem típusa
  • A hívás veremnyoma

Példák

A legutóbbi bejegyzések jelennek meg először.

Az alábbi példában a két legutóbbi bejegyzés jelenik meg:

0:001> !avrf -vs 2

VirtualFree (tid: 0xB4): addr:04bb0000 sz:00400000 op:8000 prot:0
        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef6525: mshtml+0x116525
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

VirtualFree (tid: 0xB4): addr:04bb0000 sz:00001000 op:4000 prot:0

        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef65ae: mshtml+0x1165AE
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

A kimenetből látható, hogy a szál 0xB4 először kibontott egy lapot, majd kiadta a teljes virtuális régiót.

Itt látható a cím 0x4BB1000 befolyásoló összes művelet:

0:001> !avrf -vs -a 4bb1000

Searching in vspace log for address 04bb1000 ...

VirtualFree (tid: 0xB4): addr:04bb0000 sz:00400000 op:8000 prot:0
        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef6525: mshtml+0x116525
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

VirtualFree (tid: 0xB4): addr:04bb1000 sz:00001000 op:4000 prot:0

        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef65ae: mshtml+0x1165AE
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

VirtualAlloc (tid: 0xB4): addr:04bb0000 sz:00010000 op:1000 prot:4

        00aa1ac2: verifier!VsLogCall+0x42
        00aa1988: verifier!AVrfpNtAllocateVirtualMemory+0x37
        68925ca3: kernel32!VirtualAllocEx+0x61
        68926105: kernel32!VirtualAlloc+0x16
        75ef63f3: mshtml+0x1163F3

VirtualAlloc (tid: 0xB4): addr:04bb0000 sz:00400000 op:2000 prot:4

        00aa1ac2: verifier!VsLogCall+0x42
        00aa1988: verifier!AVrfpNtAllocateVirtualMemory+0x37
        68925ca3: kernel32!VirtualAllocEx+0x61
        68926105: kernel32!VirtualAlloc+0x16
        75ef63d9: mshtml+0x1163D9

A kimenet elolvasásához ne feledje, hogy a bejegyzések a legutóbbival kezdődnek. Így ez a napló azt mutatja, hogy a szál 0xB4 lefoglalt egy nagy régiót, amelyben lekötött egy lapot. Később megszüntette a lapot, majd kiadta a teljes virtuális régiót.

Lásd még:

Application Verifier – Áttekintés

Application Verifier – Alkalmazások tesztelése

Application Verifier – Az Application Verifier tesztelése

Application Verifier – Kódok és definíciók leállítása

Application Verifier – Gyakori kérdések