Bagikan melalui


Pemverifikasi Aplikasi - Debugging Pemverifikasi Aplikasi Berhenti

Penginstalan dan penyiapan debugger

Beberapa tindakan Pemverifikasi Aplikasi dapat mengakibatkan pengecualian dimunculkan. Debugger harus diatur untuk menangkap pengecualian ini pada kesempatan kedua, karena Pemverifikasi Aplikasi itu sendiri akan menangani pengecualian kesempatan pertama.

Pengecualian yang dimunculkan adalah tiga jenis:

  • Pengecualian pelanggaran akses (0xC0000005) dihasilkan jika opsi heap mendeteksi kelebihan batas buffer tumpukan. Dalam beberapa kasus, opsi Periksa penggunaan jalur sistem juga dapat menyebabkan pelanggaran akses.

  • Pengecualian handel yang tidak valid (0xC0000008) dihasilkan ketika opsi Deteksi penggunaan handel yang tidak valid mendeteksi operasi handel yang tidak valid.

  • Pengecualian luapan tumpukan (0xC00000FD) dihasilkan ketika opsi Periksa kecukupan tumpukan mendeteksi bahwa tumpukan awal terlalu kecil.

Salah satu cara untuk mempersiapkan peristiwa ini adalah dengan memulai debugger pada baris perintah sebagai berikut:

windbg -xd av -xd ch -xd sov ApplicationCommandLine

atau

cdb -xd av -xd ch -xd sov ApplicationCommandLine

Jika Anda telah memulai debugger, Anda dapat menggunakan perintah sxd (Atur Pengecualian) untuk menangani semua pelanggaran akses, handle yang tidak valid, dan kelebihan tumpukan sebagai pengecualian peluang kedua.

0:000> sxd av 

0:000> sxd ch 

0:000> sxd sov 1

Secara teoritis dimungkinkan untuk mengontrol Application Verifier melalui debugger kernel. Namun, ini tidak disarankan — ini membutuhkan penggunaan perintah .process dan .pagein secara sering, tetapi tidak memberikan Anda kemampuan lebih dibandingkan dengan menggunakan debugger dalam mode pengguna.

Menginstal alat debug

Untuk mengunduh versi terbaru alat-alat, lihat Unduh Alat Penelusuran Kesalahan untuk Windows.

Mengonfigurasi Perangkat Keras untuk Debugging User-Mode

Pemecahan masalah pada mode pengguna umumnya dilakukan pada satu komputer: debugger dijalankan pada komputer yang sama dengan aplikasi yang mengalami kegagalan.

Dalam hal ini, tidak diperlukan penyiapan perangkat keras tertentu. Sepanjang topik ini, istilah komputer host dan komputer target saling dipertukarkan.

Mengonfigurasi Perangkat Lunak untuk Debugging User-Mode

Konfigurasi User-Mode Dasar - Sebelum dapat memulai debugging mode pengguna, Anda harus mengunduh file simbol yang diperlukan dan menetapkan variabel lingkungan tertentu.

File Simbol

Anda harus mengunduh file simbol untuk proses mode pengguna yang sedang di-debug. Jika ini adalah aplikasi yang telah Anda tulis, aplikasi harus dibangun dengan file simbol lengkap. Jika ini adalah aplikasi komersial, file simbol mungkin tersedia di server web atau untuk diunduh, hubungi produsen.

jika Anda melakukan debugging jarak jauh, lokasi file simbol bergantung pada metode yang digunakan.

  • Jika Anda melakukan penelusuran kesalahan jarak jauh melalui debugger, berkas simbol harus ada di komputer dengan server penelusuran kesalahan.

  • Jika Anda melakukan penelusuran kesalahan jarak jauh melalui remote.exe, file simbol harus berada di komputer dengan debugger.

  • Jika Anda melakukan debugging jarak jauh melalui server proses atau server koneksi Kernel Debugger (KD), file simbol harus berada di komputer dengan klien cerdas.

  • Jika Anda mengontrol debugger mode pengguna dari debugger kernel, file simbol harus ada di kedua komputer.

Mengonfigurasi Variabel Lingkungan

Debugger menggunakan berbagai variabel lingkungan untuk menunjukkan sejumlah pengaturan penting.

Untuk informasi selengkapnya tentang debugger, lihat Memulai Debugging Windows

Mengonfigurasi Pemverifikasi Aplikasi dengan Debugger menggunakan baris Perintah

Untuk mengonfigurasi Pemverifikasi Aplikasi, Anda dapat menggunakan baris perintah CDB atau NTSD.

Gunakan baris perintah berikut:

cdb OtherOptions -vf:Flags Target

Di mana Target adalah nama aplikasi target, dan Bendera menentukan opsi Pemverifikasi Aplikasi yang diinginkan yang akan diterapkan ke target ini.

Bendera harus berupa jumlah bit yang mewakili opsi yang diinginkan. Nilai bit individual adalah sebagai berikut:

Nilai penanda Makna
00000001 PEMERIKSAAN TUMPUKAN
00000004 MENANGANI PEMERIKSAAN
00000008 PEMERIKSAAN KARTU SIM DENGAN SUMBER DAYA RENDAH
00000020 PEMERIKSAAN TLS
00000040 TUMPUKAN KOTOR
00000200 API BERBAHAYA
00001000 PEMERIKSAAN PENGECUALIAN
00002000 PEMERIKSAAN MEMORI
00020000 PEMERIKSAAN LAIN-LAIN
00040000 PEMERIKSAAN PENGUNCIAN

Pemecahan masalah dengan !avrf

Ekstensi !avrf mengontrol pengaturan Pemverifikasi Aplikasi dan menampilkan berbagai output yang dihasilkan oleh Pemverifikasi Aplikasi. Untuk informasi tambahan tentang ekstensi !arvrf, lihat !avrf di dokumen debugger.

Sintaksis

!avrf

Perintah !avrf tanpa parameter apa pun menunjukkan pengaturan dan informasi Pemverifikasi Aplikasi serta gangguan Pemverifikasi Aplikasi saat ini dan sebelumnya jika ada.

!avrf –vs { Length | -aAddress }

Menampilkan log operasi ruang virtual. Panjang menentukan jumlah rekaman yang akan ditampilkan mulai dari yang terbaru. Alamat menentukan alamat virtual. Rekaman operasi virtual yang berisi alamat virtual ini akan ditampilkan.

!avrf -hp { Length | -a Address }

Menampilkan log operasi timbunan. Alamat menentukan alamat timbunan. Catatan operasi heap yang mencakup alamat heap ini akan ditampilkan.

!avrf -cs { Length | -a Address }

Menampilkan log penghapusan bagian penting. Panjang menentukan jumlah rekaman yang akan ditampilkan mulai dari yang terbaru. Alamat menentukan lokasi bagian kritis. Catatan untuk bagian kritis tertentu ditampilkan ketika Alamat ditentukan.

!avrf -dlls [ Length ]

Menampilkan log muat/lepas DLL. Panjang menentukan jumlah rekaman yang akan ditampilkan mulai dari yang terbaru.

!avrf -trm

Menampilkan log dari semua utas yang dihentikan dan ditangguhkan.

!avrf -ex [ Length ]

Menampilkan log pengecualian. Pemverifikasi Aplikasi melacak semua pengecualian yang terjadi dalam aplikasi.

!avrf -threads [ ThreadID ]

Menampilkan informasi tentang utas dalam proses target. Untuk thread anak, ukuran stack dan flag CreateThread yang ditentukan oleh induk juga ditampilkan. Jika memberikan ID utas, informasi hanya akan ditampilkan untuk utas tertentu tersebut.

!avrf -tp [ ThreadID ]

Menampilkan log thread pool. Log ini mungkin berisi jejak tumpukan untuk berbagai operasi seperti mengubah masker afinitas utas, mengubah prioritas utas, memposting pesan utas, menginisialisasi COM, dan membatalkan menginisialisasi COM dari dalam panggilan balik kumpulan utas. Memberikan ID utas hanya akan menampilkan informasi untuk utas tertentu tersebut.

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

Menampilkan log Slim Reader/Writer (SRW). Menentukan Alamat akan menampilkan rekaman yang berkaitan dengan alamat kunci SRW tersebut. Ketika Panjang ditentukan bersama dengan Alamat , semua kunci SRW dalam rentang alamat tersebut ditampilkan. Opsi -stats mencadangkan statistik kunci SRW.

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

Menampilkan log sumber daya yang menonjol. Sumber daya ini mungkin atau mungkin tidak bocor pada titik tertentu. Menentukan ModuleName (termasuk ekstensi) menampilkan semua sumber daya yang luar biasa dalam modul yang ditentukan. Menentukan ResourceType menampilkan sumber daya yang luar biasa dari jenis sumber daya tertentu. Mengidentifikasi Alamat membuang catatan sumber daya yang belum terproses dengan alamat tersebut. ResourceType bisa menjadi salah satu hal berikut:

  • Heap: Menampilkan alokasi heap menggunakan API Heap Win32
  • Lokal: Menampilkan alokasi Lokal/Global
  • CRT: Menampilkan alokasi menggunakan API CRT
  • Virtual: Menampilkan Reservasi Virtual
  • BSTR: Menampilkan alokasi BSTR
  • Registri: Menampilkan kunci Registri terbuka
  • Daya: Menampilkan objek pemberitahuan daya
  • Handle: Menampilkan alokasi utas, file, dan penanganan acara

!avrf –trace TraceIndex

Menampilkan pelacakan tumpukan untuk indeks pelacakan yang ditentukan. Beberapa struktur menggunakan nomor indeks 16-bit ini untuk mengidentifikasi jejak tumpukan. Indeks ini menunjuk ke lokasi dalam database pelacakan tumpukan. Jika Anda menganalisis struktur seperti itu, Anda akan menemukan sintaks ini berguna.

!avrf -cnt

Menampilkan daftar penghitung global.

!avrf -brk [ BreakEventType ]

Menentukan bahwa ini adalah perintah break-event. Ketika !avrf -brk digunakan tanpa parameter tambahan, pengaturan peristiwa pemutusan ditampilkan. BreakEventType menentukan nomor jenis peristiwa pemisah. Untuk daftar jenis yang mungkin, gunakan !avrf -brk.

!avrf -flt [ EventTypeProbability ]

Menentukan bahwa ini adalah perintah injeksi kesalahan. Ketika !avrf -flt digunakan tanpa parameter tambahan, pengaturan injeksi kesalahan saat ini ditampilkan. EventType menentukan nomor jenis peristiwa. Probabilitas menentukan frekuensi kejadian akan gagal. Ini bisa berupa bilangan bulat antara 0 dan 1.000.000 (0xF4240).

!avrf -flt break EventType

Menyebabkan Pemverifikasi Aplikasi masuk ke proses debugging setiap kali kesalahan ini disuntikkan.

!avrf -flt stacks Length

Menampilkan Jumlah panjang jejak tumpukan untuk operasi yang disuntikkan kesalahan terbaru.

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

Menentukan bahwa ini adalah perintah jangkauan target. Saat -trg digunakan tanpa parameter tambahan, rentang target saat ini ditampilkan. Mulai menentukan alamat awal rentang target atau rentang pengecualian. Akhir menentukan alamat akhir rentang target atau rentang pengecualian. Modul menentukan nama modul yang akan ditargetkan atau dikecualikan. Modul harus menyertakan nama modul lengkap, termasuk ekstensi .exe atau .dll. Informasi jalur tidak boleh disertakan. Menetapkan semua akan menyebabkan semua rentang target atau rentang pengecualian diatur ulang.

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

Menentukan bahwa ini adalah perintah rentang pengecualian. Mulai menentukan alamat awal rentang target atau rentang pengecualian. Akhir menentukan alamat akhir rentang target atau rentang pengecualian. Modul menentukan nama modul yang akan ditargetkan atau dikecualikan. Modul harus menyertakan nama modul lengkap, termasuk ekstensi .exe atau .dll. Informasi jalur tidak boleh disertakan. Dengan menyertakan semua, semua rentang target atau rentang pengecualian akan diatur ulang. Menentukan waktu menyebabkan semua kesalahan disembunyikan selama beberapa milidetik setelah eksekusi dilanjutkan.

Berikut ini adalah output yang disediakan oleh perintah !avrf dalam debugger.

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 extension komentar

Ketika ekstensi !avrf digunakan tanpa parameter, ekstensi ini menampilkan opsi Pemverifikasi Aplikasi saat ini.

Ekstensi !avrf menggunakan Exts.dll di debugger.

Jika Pemberhentian Pemverifikasi Aplikasi telah terjadi, ekstensi !avrf tanpa parameter akan mengungkapkan sifat penghentian dan apa yang menyebabkannya.

Jika simbol untuk ntdll.dll dan verifier.dll hilang, ekstensi !avrf akan menghasilkan pesan kesalahan.

Perhentian yang Dapat Dilanjutkan dan Tidak Dapat Dilanjutkan

Men-debug Penghentian yang Dapat Dilanjutkan

Berikut adalah contoh pengecualian handle yang tidak valid yang telah dihasilkan oleh opsi Deteksi penggunaan handle yang tidak valid.

Pertama, pesan berikut muncul:

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

Perhatikan bahwa pesan memberi tahu Anda bahwa Penghentian Pemverifikasi Aplikasi ini dapat dilanjutkan. Setelah Anda memahami apa yang telah terjadi, Anda dapat terus menjalankan aplikasi target.

Pertama, Anda harus menggunakan ekstensi !avrf. Ini memberikan informasi tentang kegagalan saat ini:

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).

Baris akhir tampilan ini meringkas masalah.

Anda mungkin ingin melihat beberapa log pada saat ini. Setelah selesai, gunakan perintah g (Go) untuk memulai aplikasi lagi:

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

Dalam hal ini, pesan memberi tahu Anda bahwa Penghentian Pemverifikasi Aplikasi ini tidak dapat dilanjutkan. Kesalahan terlalu parah agar proses terus berjalan, dan tidak ada cara bagi Pemverifikasi Aplikasi untuk menyelamatkan proses.

Ekstensi !avrf dapat digunakan untuk memberikan informasi tentang kegagalan saat ini:

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.

Baris akhir tampilan ini meringkas masalah.

Anda mungkin juga ingin melihat beberapa log pada saat ini. Anda mungkin ingin menggunakan perintah .restart (Restart Target Application) pada saat ini. Atau mungkin Anda lebih suka mengakhiri sesi Pemverifikasi Aplikasi dan mulai memperbaiki bug dalam kode Anda.

Men-debug Kesalahan Bagian Kritis

Ekstensi debugger !cs

!cs dapat digunakan dalam debugger mode pengguna dan debugger kernel untuk menampilkan informasi tentang bagian penting dalam proses saat ini. Untuk informasi tambahan tentang ekstensi !cs, lihat !cs di dokumen debugger.

Kecocokan simbol dengan informasi tipe diperlukan, terutama untuk ntdll.dll.

Sintaks untuk ekstensi ini adalah:

!cs [-s] - buang semua bagian penting aktif dalam proses saat ini.

!cs [-s] address - lakukan dump bagian penting di alamat ini.

!cs [-s] -d address - menampilkan critical section yang sesuai dengan DebugInfo di alamat ini.

-s akan membuang jejak tumpukan inisialisasi bagian penting jika tersedia.

Contoh:

Mencadangkan informasi tentang bagian penting menggunakan alamatnya

0:001> ! cs 0x7803B0F8

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

Membuang informasi tentang bagian penting menggunakan alamatnya, termasuk pelacakan tumpukan inisialisasi

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

Mencadangkan informasi tentang bagian penting menggunakan alamat info debugnya

0:001> !cs -d 0x6A262080

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

Mengeluarkan informasi tentang bagian kritis menggunakan alamat informasi debug, termasuk jejak tumpukan inisialisasi.

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

Membuang informasi tentang semua bagian penting aktif dalam proses saat ini

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
.....

Menampilkan informasi tentang semua bagian kritis yang aktif dalam proses saat ini, termasuk jejak tumpukan inisialisasi


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

Kesalahan Pengecualian saat Debugging

Log pengecualian mencatat semua pengecualian yang telah terjadi dalam proses target.

Anda dapat menggunakan perintah ekstensi !avrf -ex Length untuk menampilkan beberapa pengecualian terakhir; Panjang menentukan jumlah pengecualian. Jika Panjang dihilangkan, semua pengecualian ditampilkan.

Berikut adalah contohnya:

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.

Debugging Mengatasi Kesalahan

!htrace dapat digunakan dalam debugger mode pengguna dan debugger kernel untuk menampilkan informasi jejak tumpukan untuk satu atau semua handle dalam proses. Informasi ini tersedia jika pelacakan penanganan diaktifkan untuk proses - diaktifkan secara otomatis jika pemeriksaan penanganan diaktifkan di pemverifikasi aplikasi. Jejak tumpukan disimpan setiap kali proses membuka atau menutup handle, atau ketika merujuk pada handle yang tidak valid. Untuk informasi tambahan tentang ekstensi !htrace, lihat !htrace di dokumen debugger.

Sintaks debugger kernel untuk ekstensi ini adalah:

!htrace [ handle [process] ]

Jika handle tidak ditentukan atau bernilai 0, informasi tentang semua handle dalam proses akan ditampilkan. Jika proses tidak ditentukan, proses saat ini akan digunakan.

Sintaks debugger mode pengguna adalah:

!htrace [handle]

Ekstensi debugger mode pengguna selalu menampilkan informasi tentang proses debugee saat ini.

Contoh:

Informasi cadangan tentang menangani 7CC dalam proses 815328b0

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.

Mengeluarkan informasi tentang semua handel dalam proses 815328b0

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.

Mengeluarkan informasi tentang handle 7DC dalam proses saat ini


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.

Kesalahan Timbunan Debugging

Ekstensi debugger pemverifikasi heap

Ekstensi debugger pemeriksa heap adalah bagian dari ekstensi !heap (ekstensi debugger heap NT). Bantuan sederhana dapat diperoleh dengan !heap -? atau lebih luas dengan !heap -p -? . Ekstensi saat ini tidak secara otomatis mendeteksi apakah tumpukan halaman diaktifkan untuk suatu proses dan bertindak sesuai dengan itu. Untuk saat ini pengguna ekstensi perlu mengetahui bahwa timbunan halaman diaktifkan dan menggunakan perintah yang diawali oleh !heap -p . Untuk informasi tambahan tentang ekstensi !htrace, lihat !heap di dokumen debugger.

!heap -p

Menampilkan alamat dari semua timbunan halaman penuh yang dibuat dalam proses.

!heap -p -h ADDRESS-OF-HEAP

Pembuangan lengkap dari kumpulan halaman penuh di ADDRESS-OF-HEAP.

!heap -p -a ADDRESS

Mencoba menentukan apakah ada heap block pada ADDRESS. Nilai ini tidak perlu menjadi alamat awal blok. Perintah ini berguna jika tidak ada petunjuk apa pun tentang sifat area memori.

Log operasi timbunan

Log operasi timbunan melacak semua rutinitas timbunan. Ini termasuk HeapAlloc, HeapReAlloc, dan HeapFree.

Anda dapat menggunakan !avrf -hp Length perintah ekstensi untuk menampilkan beberapa rekaman terakhir; Panjang menentukan jumlah rekaman.

Anda dapat menggunakan !avrf -hp -a Address untuk menampilkan semua operasi heap yang berdampak pada Alamat yang ditentukan. Untuk operasi alokasi, cukuplah Alamat terkandung dalam blok timbunan yang dialokasikan. Untuk operasi yang bebas biaya, alamat awal yang tepat dari blok harus diberikan.

Untuk setiap entri dalam log, informasi berikut ditampilkan:

  • Fungsi heap dipanggil.
  • ID utas utas yang disebut rutinitas.
  • Alamat yang terlibat dalam panggilan — ini adalah alamat yang dikembalikan oleh rutinitas alokasi atau yang diteruskan ke rutinitas gratis.
  • Ukuran wilayah yang terlibat dalam panggilan.
  • Pelacakan jejak panggilan

Entri terbaru ditampilkan terlebih dahulu.

Dalam contoh ini, dua entri terbaru ditampilkan:

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

Skenario debug umum

Ada beberapa skenario kegagalan yang mungkin ditemui. Beberapa dari mereka membutuhkan sedikit pekerjaan detektif untuk mendapatkan seluruh gambaran.

Pelanggaran akses di halaman yang tidak dapat diakses

Ini terjadi ketika fitur full page heap diaktifkan jika aplikasi yang diuji mengakses area di luar batas akhir buffer. Ini juga dapat terjadi jika menyentuh blok yang dibebaskan. Untuk memahami apa sifat alamat tempat pengecualian terjadi, Anda perlu menggunakan:

!heap –p –a ADDRESS-OF-AV

Pesan blokir rusak

Pada beberapa saat selama masa pengalokasian (user bebas, real bebas), pengelola heap halaman memeriksa apakah blok memiliki semua pola pengisian utuh dan header blok memiliki data yang konsisten. Jika ini tidak terjadi, Anda akan mendapatkan penghentian verifikasi.

** Jika blok tersebut adalah blok heap halaman penuh (misalnya, jika Anda tahu pasti bahwa heap halaman penuh diaktifkan untuk semua alokasi) maka Anda bisa menggunakan "!heap –p –a ADDRESS" untuk mengetahui karakteristik dari blok tersebut.

Jika blok adalah blok timbunan halaman ringan maka Anda perlu mencari tahu alamat awal untuk header blok. Anda dapat menemukan alamat awal dengan membuang 30-40 byte di bawah alamat yang dilaporkan dan mencari pola awal/akhir ajaib untuk header blok (ABCDAAAAA, ABCDBBBB, ABCDAAA9, ABCDBBBA).

Header akan memberikan semua informasi yang Anda butuhkan untuk memahami kegagalan. Terutama, pola ajaib akan memberi tahu apakah blok dialokasikan atau kosong dan apakah itu adalah blok tumpukan halaman ringan atau tumpukan halaman penuh. Informasi di sini harus dicocokkan dengan hati-hati dengan panggilan yang menyinggung.

Misalnya jika panggilan ke HeapFree dilakukan dengan alamat blok ditambah empat byte, maka Anda akan mendapatkan pesan yang rusak. Header blok akan terlihat baik-baik saja tetapi Anda harus melihat bahwa byte pertama setelah akhir header (byte pertama setelah nilai ajaib 0xDCBAXXXX) memiliki alamat yang berbeda daripada yang ada dalam panggilan.

Penunjuk pengisian khusus (fill pointers)

Pengelola timbunan halaman mengisi alokasi pengguna dengan nilai yang akan terlihat sebagai penunjuk kernel. Ini terjadi ketika blok dibebaskan (nilai isi adalah F0) dan ketika blok dialokasikan tetapi tidak ada permintaan yang dibuat untuk membuat blok bernilai nol (nilai isi adalah E0 untuk heap halaman ringan dan C0 untuk heap halaman penuh). Alokasi yang tidak diinisialisasi dengan nol adalah umum untuk pengguna malloc/new. Jika ada kegagalan (pelanggaran akses) di mana baca/tulis dicoba di alamat seperti F0F0F0F0, E0E0E0E0, C0C0C0C0 maka kemungkinan besar Anda mencapai salah satu kasus ini.

Baca/tulis di F0F0F0F0 berarti blok telah digunakan setelah dibebaskan. Sayangnya Anda akan membutuhkan sedikit usaha detektif untuk mengetahui blok mana yang menyebabkan ini. Anda perlu mendapatkan jejak tumpukan kegagalan dan kemudian memeriksa kode untuk fungsi pada tumpukan. Salah satunya mungkin membuat asumsi yang salah tentang alokasi yang masih digunakan.

Baca/tulis di E0E0E0E0/C0C0C0C0 berarti aplikasi tidak memulai dengan tepat proses alokasinya. Ini juga memerlukan inspeksi kode fungsi dalam jejak tumpukan saat ini. Berikut ini adalah contoh untuk kegagalan semacam ini. Dalam proses pengujian, diperhatikan adanya pelanggaran akses saat melakukan HeapFree pada alamat E0E0E0E0. Ternyata pengujian mengalokasikan struktur, tidak menginisialisasinya dengan benar dan kemudian memanggil destruktor objek. Karena bidang tertentu tidak null (berisi E0E0E0E0 di dalamnya), pemanggilan operasi hapus dilakukan pada bidang tersebut.

Detail Teknis Timbunan Halaman

Untuk mendeteksi korupsi tumpukan (luapan atau kekurangan memori), AppVerifier akan memodifikasi cara memori dialokasikan dengan menyisipkan halaman penuh yang tidak dapat ditulis ulang atau tag khusus sebelum dan sesudah memori yang dialokasikan. AppVerifier melakukan ini dengan memuat Verifier.dll ke dalam proses yang sedang diverifikasi dan mengalihkan beberapa API Heap Win32 yang dipanggil oleh aplikasi ke API Verifier.dll yang sesuai.

Saat memori yang diminta ditambal dengan halaman tidak dapat ditulis penuh (pengaturan PENUH diaktifkan pada bagian properti heap halaman dan merupakan pengaturan default), AppVerifier akan mengonsumsi sejumlah besar memori virtual tetapi memiliki keuntungan bahwa kejadian kerusakan heap di-cache secara real time ketika terjadi luapan atau aliran bawah. Ingatlah bahwa memori dalam mode ini akan terlihat seperti ini [AppVerifier Read-Only Heap Page (4k)] [Jumlah memori yang diminta oleh Aplikasi di bawah pengujian] atau seperti ini [Jumlah memori yang diminta oleh Aplikasi di bawah pengujian] [AppVerifier Read-Only Heap Page (4k)].

Pemeriksaan timbunan akan menempatkan halaman penjaga di awal atau akhir alokasi tergantung pada properti Mundur. Jika Backward diatur ke False, yang merupakan default, itu akan menempatkan halaman penjaga di akhir alokasi untuk menangkap buffer overruns. Jika diatur ke Benar, halaman proteksi ditempatkan di awal alokasi untuk mendeteksi masalah pengerjaan buffer.

Saat memberi bantalan pada memori yang telah diminta dengan tag khusus (diaktifkan dengan tidak mencentang kotak centang "Penuh" di properti heap), AppVerifier akan memeriksa serta memberi tahu Anda saat memori ini dibebaskan. Masalah utama dalam menggunakan teknik ini adalah bahwa ada beberapa kasus ketika kerusakan memori hanya akan terdeteksi ketika memori dirilis (jumlah minimum blok memori adalah 8 byte), jadi ketika pada variabel 3-byte atau luapan 5-byte terjadi itu tidak akan segera terdeteksi.

Pada kejadian underflow, kami akan mencoba menulis ke halaman Read-Only. Ini akan memicu pengecualian. Perhatikan bahwa pengecualian ini hanya dapat ditangkap jika aplikasi target sedang dijalankan di bawah debugger. Perhatikan bahwa mode tumpukan halaman penuh juga akan mendeteksi kesalahan ini karena menggunakan halaman padding+guard. Alasan Anda akan menggunakan timbunan halaman ringan adalah jika komputer Anda tidak dapat mentolerir batasan memori tinggi dari tumpukan halaman penuh.

Untuk aplikasi intensif memori, atau ketika diperlukan untuk menggunakan AppVerifier selama jangka waktu yang lama (misalnya, pengujian stres), lebih baik menjalankan pengujian tumpukan normal (ringan) alih-alih mode penuh karena penurunan performa. Namun, ketika Anda mengalami masalah, aktifkan tumpukan halaman penuh untuk menyelidiki lebih lanjut.

Aplikasi yang menggunakan heap kustom (heap yang melewati implementasi sistem operasi dari heap) mungkin tidak mendapatkan manfaat penuh dari penggunaan heap halaman atau bahkan mungkin tidak berfungsi dengan benar saat diaktifkan.

Pemecahan Kesalahan Memori

Ekstensi debugger pemverifikasi memori

Log operasi ruang virtual melacak semua rutinitas yang memodifikasi ruang virtual proses dengan cara apa pun. Ini termasuk VirtualAlloc, VirtualFree, MapViewOfFile, dan UnmapViewOfFile.

Anda dapat menggunakan !avrf -vs Length perintah ekstensi untuk menampilkan beberapa rekaman terakhir; Panjang menentukan jumlah rekaman.

Anda dapat menggunakan !avrf -vs -a Alamat untuk menampilkan semua operasi ruang virtual yang memengaruhi Alamat yang ditentukan. Untuk alokasi, cukup bahwa alamat terkandung dalam blok yang dialokasikan. Secara gratis, alamat yang tepat dari awal wilayah harus diberikan.

Untuk setiap entri dalam log, informasi berikut ditampilkan:

  • Fungsi yang disebut
  • ID utas yang memanggil rutinitas
  • Alamat yang terlibat dalam panggilan — ini adalah alamat yang dikembalikan oleh rutinitas alokasi atau yang diteruskan ke rutinitas gratis
  • Ukuran wilayah yang terlibat dalam panggilan
  • Jenis operasi memori (parameter AllocationType)
  • Jenis perlindungan yang diminta
  • Jejak tumpukan panggilan

Contoh

Entri terbaru ditampilkan terlebih dahulu.

Dalam contoh berikut, dua entri terbaru ditampilkan:

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

Ini dapat dilihat dari output bahwa utas 0xB4 pertama kali menonaktifkan halaman dan kemudian merilis seluruh wilayah virtual.

Berikut adalah tampilan semua operasi yang memengaruhi alamat 0x4BB1000:

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

Untuk membaca output ini, ingatlah bahwa entri dibuang dimulai dengan yang terbaru. Dengan demikian, log ini menunjukkan bahwa utas 0xB4 mengalokasikan wilayah besar di mana ia menerapkan halaman. Kemudian, halaman didisaktifkan, lalu melepaskan seluruh wilayah virtual.

Lihat Juga

Pemverifikasi Aplikasi - Gambaran Umum

Pemverifikasi Aplikasi - Aplikasi Pengujian

Pemverifikasi Aplikasi - Pengujian dalam Pemverifikasi Aplikasi

Pemverifikasi Aplikasi - Hentikan Kode dan Definisi

Pemverifikasi Aplikasi - Tanya Jawab Umum