Bagikan melalui


Penelusuran Kesalahan Perjalanan Waktu - Contoh Panduan Aplikasi

Logo penelusuran kesalahan perjalanan waktu yang menampilkan jam.

Lab ini memperkenalkan Time Travel Debugging (TTD), menggunakan program sampel kecil dengan kelemahan kode. TTD digunakan untuk men-debug, mengidentifikasi, dan akar penyebab masalah. Meskipun masalah dalam program kecil ini mudah ditemukan, prosedur umum dapat digunakan pada kode yang lebih kompleks. Prosedur umum ini dapat diringkas sebagai berikut.

  1. Ambil jejak perjalanan waktu dari program yang gagal.
  2. Gunakan perintah dx (Ekspresi Model Objek Debugger Tampilan) untuk menemukan peristiwa pengecualian yang disimpan dalam rekaman.
  3. Gunakan perintah !tt (perjalanan waktu) untuk melakukan perjalanan ke posisi peristiwa pengecualian dalam jejak.
  4. Dari titik itu dalam satu langkah pelacakan mundur sampai kode yang salah yang dimaksud masuk ke dalam cakupan.
  5. Dengan kode yang rusak dalam cakupan, lihat nilai lokal dan kembangkan hipotesis variabel yang mungkin berisi nilai yang salah.
  6. Tentukan alamat memori variabel dengan nilai yang salah.
  7. Atur titik henti akses memori (ba) pada alamat variabel tersangka menggunakan perintah ba (Break on Access ).
  8. Gunakan g- untuk menjalankan kembali ke titik akhir akses memori variabel tersangka.
  9. Lihat apakah lokasi tersebut, atau beberapa instruksi sebelumnya, adalah titik kelemahan kode. Jika demikian, Anda sudah selesai. Jika nilai yang salah berasal dari beberapa variabel lain, atur jeda lain pada titik henti akses pada variabel kedua.
  10. Gunakan g- untuk menjalankan kembali ke titik terakhir akses memori pada variabel tersangka kedua. Lihat apakah lokasi tersebut atau beberapa instruksi sebelum berisi kelemahan kode. Jika demikian, Anda sudah selesai.
  11. Ulangi proses ini berjalan kembali hingga kode yang mengatur nilai yang salah yang menyebabkan kesalahan berada.

Meskipun teknik umum yang dijelaskan dalam prosedur ini berlaku untuk serangkaian masalah kode yang luas, ada masalah kode unik yang akan memerlukan pendekatan unik. Teknik yang diilustrasikan dalam panduan harus berfungsi untuk memperluas set alat penelusuran kesalahan Anda dan akan menggambarkan beberapa hal yang mungkin dilakukan dengan jejak TTD.

Tujuan lab

Setelah menyelesaikan lab ini, Anda akan dapat menggunakan prosedur umum dengan jejak perjalanan waktu untuk menemukan masalah dalam kode.

Penyiapan lab

Anda akan memerlukan perangkat keras berikut untuk dapat menyelesaikan lab.

  • Laptop atau komputer desktop (host) yang menjalankan Windows 10 atau Windows 11

Anda akan memerlukan perangkat lunak berikut untuk dapat menyelesaikan lab.

  • The WinDbg. Untuk informasi tentang menginstal WinDbg, lihat WinDbg - Penginstalan
  • Visual Studio untuk membuat sampel kode C++.

Lab ini memiliki tiga bagian berikut.

Bagian 1: Buat kode sampel

Di Bagian 1, Anda akan membuat kode sampel menggunakan Visual Studio.

Membuat aplikasi sampel di Visual Studio

  1. Di Microsoft Visual Studio, klik File>Proyek/Solusi Baru>... dan klik templat Visual C++.

    Pilih Aplikasi Konsol Win32.

    Berikan nama proyek DisplayGreeting dan klik OK.

  2. Hapus centang pemeriksaan Siklus Hidup Pengembangan Keamanan (SDL).

    Pengaturan Panduan Aplikasi Win32 di Visual Studio.

  3. Klik Selesai.

  4. Tempelkan teks berikut ke panel DisplayGreeting.cpp di Visual Studio.

    // DisplayGreeting.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <array>
    #include <stdio.h>
    #include <string.h>
    
    void GetCppConGreeting(wchar_t* buffer, size_t size)
    {
        wchar_t const* const message = L"HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YOUR TIME TRAVEL DEBUGGING!";
    
        wcscpy_s(buffer, size, message);
    }
    
    int main()
    {
         std::array <wchar_t, 50> greeting{};
         GetCppConGreeting(greeting.data(), sizeof(greeting));
    
         wprintf(L"%ls\n", greeting.data());
    
         return 0;
    }
    
  5. Di Visual Studio, klik Properti Proyek>DisplayGreeting. Kemudian klik C/C++ dan Pembuatan Kode.

    Atur properti berikut.

    Pengaturan Nilai
    Pemeriksaan Keamanan Nonaktifkan Pemeriksaan Keamanan (/GS-)
    Pemeriksaan Runtime Dasar Default

    Catatan

    Meskipun pengaturan ini tidak disarankan, dimungkinkan untuk membayangkan skenario di mana seseorang akan menyarankan penggunaan pengaturan ini untuk mempercepat pengkodian atau untuk memfasilitasi lingkungan pengujian tertentu.

  6. Di Visual Studio, klik Bangun>Solusi Build.

    Jika semua berjalan dengan baik, jendela build harus menampilkan pesan yang menunjukkan bahwa build berhasil.

  7. Menemukan file aplikasi sampel bawaan

    Di Penjelajah Solusi, klik kanan pada proyek DisplayGreeting dan pilih Buka Folder di File explorer.

    Navigasikan ke folder Debug yang berisi file exe dan simbol pdb yang sesuai untuk sampel. Misalnya, Anda akan menavigasi ke C:\Projects\DisplayGreeting\Debug, jika itu adalah folder tempat proyek Anda disimpan.

  8. Jalankan aplikasi sampel dengan kelemahan kode

    Klik dua kali pada file exe untuk menjalankan aplikasi sampel.

    Cuplikan layar konsol yang menjalankan file DisplayGreeting.exe.

    Jika kotak dialog ini muncul, pilih Tutup program

    Cuplikan layar kotak dialog yang menampilkan 'DisplayGreeting.exe telah berhenti berfungsi.'

    Di bagian berikutnya dari panduan, kita akan merekam eksekusi aplikasi sampel untuk melihat apakah kita dapat menentukan mengapa pengecualian ini terjadi.

Bagian 2: Rekam jejak sampel "DisplayGreeting"

Di Bagian 2, Anda akan merekam jejak sampel aplikasi "DisplayGreeting" yang tidak beres

Untuk meluncurkan aplikasi sampel dan merekam jejak TTD, ikuti langkah-langkah ini. Untuk informasi umum tentang merekam jejak TTD, lihat Penelusuran Kesalahan Perjalanan Waktu - Merekam jejak

  1. Jalankan WinDbg sebagai Administrator, sehingga dapat merekam jejak perjalanan waktu.

  2. Di WinDbg, pilih Mulai Penelusuran kesalahan>File>Luncurkan yang dapat dieksekusi (tingkat lanjut).

  3. Masukkan jalur ke mode pengguna yang dapat dieksekusi yang ingin Anda rekam atau pilih Telusuri untuk menavigasi ke yang dapat dieksekusi. Untuk informasi tentang bekerja dengan menu yang dapat dieksekusi peluncuran di WinDbg, lihat WinDbg - Memulai sesi mode pengguna.

    Cuplikan layar WinDbg dengan kotak centang 'Rekam dengan Penelusuran Kesalahan Perjalanan Waktu' di layar Luncurkan Yang Dapat Dieksekusi (Tingkat Lanjut).

  4. Centang kotak Rekam dengan Penelusuran Kesalahan Perjalanan Waktu untuk merekam jejak saat executable diluncurkan.

  5. Klik Konfigurasikan dan Rekam untuk mulai merekam.

  6. Saat kotak dialog "Konfigurasikan perekaman" muncul, Klik Rekaman untuk meluncurkan executable dan mulai merekam.

    Cuplikan layar WinDbg yang menampilkan dialog Konfigurasi Rekaman dengan jalur diatur ke sementara.

  7. Dialog perekaman muncul yang menunjukkan jejak sedang direkam. Tak lama setelah itu, aplikasi mengalami crash.

  8. Klik Tutup Program, untuk menutup kotak dialog "DisplayGreeting telah berhenti berfungsi".

    Kotak dialog memperlihatkan aplikasi DisplayGreeting telah berhenti berfungsi.

  9. Ketika program crash, file pelacakan akan ditutup dan ditulis ke disk.

    Cuplikan layar output WinDbg yang menampilkan keyframe 1/1 yang diindeks.

  10. Debugger akan secara otomatis membuka file pelacakan dan mengindeksnya. Pengindeksan adalah proses yang memungkinkan penelusuran kesalahan file pelacakan yang efisien. Proses pengindeksan ini akan memakan waktu lebih lama untuk file pelacakan yang lebih besar.

    (5120.2540): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: D:0 [Unindexed] Index
    !index
    Indexed 10/22 keyframes
    Indexed 20/22 keyframes
    Indexed 22/22 keyframes
    Successfully created the index in 755ms.
    

Catatan

Keyframe adalah lokasi dalam jejak yang digunakan untuk pengindeksan. Keyframe dihasilkan secara otomatis. Jejak yang lebih besar akan berisi lebih banyak keyframe.

  1. Pada titik ini Anda berada di awal file pelacakan dan siap untuk melakukan perjalanan maju dan mundur ke waktu.

    Sekarang setelah Anda merekam jejak TTD, Anda dapat memutar ulang jejak kembali atau bekerja dengan file pelacakan, misalnya membagikannya dengan rekan kerja. Untuk informasi selengkapnya tentang bekerja dengan file pelacakan, lihat Penelusuran Kesalahan Perjalanan Waktu - Bekerja dengan File Pelacakan

Di bagian berikutnya dari lab ini kita akan menganalisis file jejak untuk menemukan masalah dengan kode kita.

Bagian 3: Menganalisis rekaman file pelacakan untuk mengidentifikasi masalah kode

Di Bagian 3, Anda akan menganalisis rekaman file jejak untuk mengidentifikasi masalah kode.

Mengonfigurasi Lingkungan WinDbg

  1. Tambahkan lokasi simbol lokal Anda ke jalur simbol dan muat ulang simbol, dengan mengetik perintah berikut.

    .sympath+ C:\MyProjects\DisplayGreeting\Debug
    .reload
    
  2. Tambahkan lokasi kode lokal Anda ke jalur sumber dengan mengetik perintah berikut.

    .srcpath+ C:\MyProjects\DisplayGreeting\DisplayGreeting
    
  3. Agar dapat melihat status tumpukan dan variabel lokal, pada pita WinDbg, pilih Tampilan dan Lokal dan Tampilan dan Tumpukan. Atur jendela untuk memungkinkan Anda melihatnya, kode sumber, dan jendela perintah secara bersamaan.

  4. Pada pita WinDbg, pilih Sumber dan File Sumber Terbuka. Temukan file DisplayGreeting.cpp dan buka.

Memeriksa pengecualian

  1. Ketika file pelacakan dimuat, file tersebut akan menampilkan informasi bahwa terjadi pengecualian.

    2fa8.1fdc): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: 15:0
    eax=68ef8100 ebx=00000000 ecx=77a266ac edx=69614afc esi=6961137c edi=004da000
    eip=77a266ac esp=0023f9b4 ebp=0023fc04 iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
    ntdll!LdrpInitializeProcess+0x1d1c:
    77a266ac 83bdbcfeffff00  cmp     dword ptr [ebp-144h],0 ss:002b:0023fac0=00000000
    
  2. Gunakan perintah dx untuk mencantumkan semua peristiwa dalam rekaman. Peristiwa pengecualian tercantum dalam peristiwa.

    0:000> dx -r1 @$curprocess.TTD.Events
    ...
    [0x2c]           : Module Loaded at position: 9967:0
    [0x2d]           : Exception at 9BDC:0
    [0x2e]           : Thread terminated at 9C43:0
    ...
    
    

    Catatan

    Dalam panduan ini tiga periode digunakan untuk menunjukkan bahwa output asing dihapus.

  3. Klik peristiwa Pengecualian untuk menampilkan informasi tentang peristiwa TTD tersebut.

    0:000> dx -r1 @$curprocess.TTD.Events[17]
    @$curprocess.TTD.Events[17]                 : Exception at 68:0
        Type             : Exception
        Position         : 68:0 [Time Travel]
        Exception        : Exception of type Hardware at PC: 0X540020
    
  4. Klik bidang Pengecualian untuk menelusuri lebih lanjut data pengecualian.

    0:000> dx -r1 @$curprocess.TTD.Events[17].Exception
    @$curprocess.TTD.Events[17].Exception                 : Exception of type Hardware at PC: 0X540020
        Position         : 68:0 [Time Travel]
        Type             : Hardware
        ProgramCounter   : 0x540020
        Code             : 0xc0000005
        Flags            : 0x0
        RecordAddress    : 0x0
    

    Data pengecualian menunjukkan bahwa ini adalah kesalahan Perangkat Keras yang dilemparkan oleh CPU. Ini juga menyediakan kode pengecualian 0xc0000005 yang menunjukkan bahwa ini adalah pelanggaran akses. Ini biasanya menunjukkan bahwa kami mencoba menulis ke memori yang tidak dapat kita akses.

  5. Klik tautan [Perjalanan Waktu] di peristiwa pengecualian untuk berpindah ke posisi tersebut di pelacakan.

    0:000> dx @$curprocess.TTD.Events[17].Exception.Position.SeekTo()
    Setting position: 68:0
    
    @$curprocess.TTD.Events[17].Exception.Position.SeekTo()
    (16c8.1f28): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: 68:0
    eax=00000000 ebx=00cf8000 ecx=99da9203 edx=69cf1a6c esi=00191046 edi=00191046
    eip=00540020 esp=00effe4c ebp=00520055 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
    00540020 ??
    

    Catatan dalam output ini adalah bahwa tumpukan dan penunjuk dasar menunjuk ke dua alamat yang sangat berbeda.

    esp=00effe4c ebp=00520055
    

    Ini dapat menunjukkan bahwa kerusakan tumpukan - mungkin fungsi yang dikembalikan dan kemudian merusak tumpukan. Untuk memvalidasi ini, kita perlu melakukan perjalanan kembali sebelum status CPU rusak dan melihat apakah kita dapat menentukan kapan kerusakan tumpukan terjadi.

Memeriksa variabel lokal dan mengatur titik henti kode

Pada titik kegagalan dalam pelacakan, biasanya berakhir beberapa langkah setelah penyebab sebenarnya dalam kode penanganan kesalahan. Dengan perjalanan waktu kita dapat kembali instruksi pada satu waktu, untuk menemukan akar penyebab sebenarnya.

  1. Dari pita Beranda gunakan perintah Langkah Ke Belakang untuk mengembalikan tiga instruksi. Saat Anda melakukan ini, terus periksa tumpukan dan jendela memori.

    Jendela perintah akan menampilkan posisi perjalanan waktu dan daftar saat Anda mundur tiga instruksi.

    0:000> t-
    Time Travel Position: 67:40
    eax=00000000 ebx=00cf8000 ecx=99da9203 edx=69cf1a6c esi=00191046 edi=00191046
    eip=00540020 esp=00effe4c ebp=00520055 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
    00540020 ??              ???
    
    0:000> t-
    Time Travel Position: 67:3F
    eax=00000000 ebx=00cf8000 ecx=99da9203 edx=69cf1a6c esi=00191046 edi=00191046
    eip=0019193d esp=00effe48 ebp=00520055 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
    DisplayGreeting!main+0x4d:
    0019193d c3
    
    0:000> t-
    Time Travel Position: 67:39
    eax=0000004c ebx=00cf8000 ecx=99da9203 edx=69cf1a6c esi=00191046 edi=00191046
    eip=00191935 esp=00effd94 ebp=00effe44 iopl=0         nv up ei pl nz ac po nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000212
    DisplayGreeting!main+0x45:
    

    Catatan

    Dalam panduan ini, output perintah menunjukkan perintah yang dapat digunakan alih-alih opsi Menu UI untuk memungkinkan pengguna dengan preferensi penggunaan baris perintah untuk menggunakan perintah baris perintah.

  2. Pada titik ini dalam pelacakan tumpukan dan penunjuk dasar kita memiliki nilai yang lebih masuk akal, sehingga tampaknya kita telah semakin dekat dengan titik dalam kode tempat kerusakan terjadi.

    esp=00effd94 ebp=00effe44
    

    Yang juga menarik adalah bahwa jendela lokal berisi nilai dari aplikasi target kami dan jendela kode sumber menyoroti baris kode yang siap untuk dieksekusi pada titik ini dalam jejak.

    Cuplikan layar WinDbg menampilkan jendela Lokal dengan output ASCII memori dan jendela Kode Sumber.

  3. Untuk menyelidiki lebih lanjut, kita dapat membuka jendela memori untuk melihat konten di dekat alamat memori pointer dasar 0x00effe44.

  4. Untuk menampilkan karakter ASCII terkait, dari pita Memori, pilih Teks lalu ASCII.

    Cuplikan layar Pratinjau WinDbg yang menampilkan output ASCII memori dan jendela Kode Sumber.

  5. Alih-alih pointer dasar yang menunjuk ke instruksi, itu menunjuk ke teks pesan kami. Jadi ada sesuatu yang tidak benar di sini, ini mungkin dekat dengan titik waktu bahwa kita telah merusak tumpukan. Untuk menyelidiki lebih lanjut, kami akan menetapkan titik henti.

Catatan

Dalam sampel yang sangat kecil ini akan sangat mudah untuk hanya melihat dalam kode, tetapi jika ada ratusan baris kode dan puluhan subroutine teknik yang dijelaskan di sini dapat digunakan untuk mengurangi waktu yang diperlukan untuk menemukan masalah.

TTD dan titik henti

Menggunakan titik henti adalah pendekatan umum untuk menjeda eksekusi kode pada beberapa peristiwa yang menarik. TTD memungkinkan Anda untuk mengatur titik henti dan melakukan perjalanan kembali ke waktu hingga titik henti tersebut terpukul setelah jejak direkam. Kemampuan untuk memeriksa status proses setelah masalah terjadi, untuk menentukan lokasi terbaik untuk titik henti, memungkinkan alur kerja penelusuran kesalahan tambahan yang unik untuk TTD.

Titik henti akses memori

Anda dapat mengatur titik henti yang diaktifkan saat lokasi memori diakses. Gunakan perintah ba (putuskan akses), dengan sintaks berikut.

ba <access> <size> <address> {options}
Opsi Deskripsi

e

jalankan (ketika CPU mengambil instruksi dari alamat)

r

baca/tulis (saat CPU membaca atau menulis ke alamat)

w

tulis (ketika CPU menulis ke alamat)

Perhatikan bahwa Anda hanya dapat mengatur empat titik henti data pada waktu tertentu dan terserah Anda untuk memastikan bahwa Anda menyelaraskan data dengan benar atau Anda tidak akan memicu titik henti (kata harus berakhir di alamat yang dapat dibagi dengan 2, kata sandi harus dapat dibagi dengan 4, dan quadwords sebesar 0 atau 8).

Mengatur pemutusan pada titik henti akses memori untuk penunjuk dasar

  1. Pada titik ini dalam jejak kami ingin mengatur titik henti pada akses memori tulis ke penunjuk dasar - ebp yang dalam contoh kami adalah 00effe44. Untuk melakukan ini, gunakan perintah ba menggunakan alamat yang ingin kita pantau. Kami ingin memantau penulisan selama empat byte, jadi kami menentukan w4.

    0:000> ba w4 00effe44
    
  2. Pilih Tampilkan lalu Titik Henti untuk mengonfirmasi bahwa titik henti diatur sebagaimana dimaksud.

    Cuplikan layar jendela Titik Henti WinDbg menampilkan satu titik henti.

  3. Dari menu Beranda, pilih Kembali untuk melakukan perjalanan kembali tepat waktu hingga titik henti terbentur.

    0:000> g-
    Breakpoint 0 hit
    Time Travel Position: 5B:92
    eax=0000000f ebx=003db000 ecx=00000000 edx=00cc1a6c esi=00d41046 edi=0053fde8
    eip=00d4174a esp=0053fcf8 ebp=0053fde8 iopl=0         nv up ei pl nz ac pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
    DisplayGreeting!DisplayGreeting+0x3a:
    00d4174a c745e000000000  mov     dword ptr [ebp-20h],0 ss:002b:0053fdc8=cccccccc
    
  4. Pilih Tampilkan lalu Lokal. Di jendela lokal kita dapat melihat bahwa variabel tujuan hanya memiliki bagian dari pesan, sementara sumbernya berisi semua teks. Informasi ini mendukung gagasan bahwa tumpukan rusak.

    Cuplikan layar WinDbg yang menampilkan jendela Lokal.

  5. Pada titik ini kita dapat memeriksa tumpukan program untuk melihat kode apa yang aktif. Dari pita Tampilan pilih Tumpukan.

    Cuplikan layar WinDbg yang menampilkan jendela Tumpukan.

Karena sangat tidak mungkin bahwa fungsi Microsoft yang disediakan wscpy_s() akan memiliki bug kode seperti ini, kita melihat lebih jauh di tumpukan. Tumpukan menunjukkan bahwa Salam!panggilan utama Salam! GetCppCongreeting. Dalam sampel kode kami yang sangat kecil, kami hanya dapat membuka kode pada saat ini dan kemungkinan menemukan kesalahan dengan cukup mudah. Tetapi untuk menggambarkan teknik yang dapat digunakan dengan program yang lebih besar dan lebih kompleks, kami akan mengatur titik henti baru untuk menyelidiki lebih lanjut.

Mengatur pemutusan pada titik henti akses untuk fungsi GetCppConGreeting

  1. Gunakan jendela titik henti untuk menghapus titik henti yang ada dengan mengklik kanan titik henti yang ada dan memilih Hapus.

  2. Tentukan alamat DisplayGreeting! Fungsi GetCppConGreeting menggunakan perintah dx .

    0:000> dx &DisplayGreeting!GetCppConGreeting
    &DisplayGreeting!GetCppConGreeting                 : 0xb61720 [Type: void (__cdecl*)(wchar_t *,unsigned int)]
        [Type: void __cdecl(wchar_t *,unsigned int)]
    
  3. Gunakan perintah ba untuk mengatur titik henti pada akses memori. Karena fungsi hanya akan dibaca dari memori untuk eksekusi, kita perlu mengatur r - read breakpoint.

    0:000> ba r4 b61720
    
  4. Konfirmasikan bahwa titik henti Baca Perangkat Keras aktif di jendela titik henti.

    Cuplikan layar jendela Titik Henti WinDbg menampilkan satu titik henti baca perangkat keras.

  5. Saat kita bertanya-tanya tentang ukuran string salam, kita akan mengatur jendela pengawasan untuk menampilkan nilai sizeof (salam). Dari pita Tampilan, pilih Tonton dan sediakan ukurandari(salam).

    Cuplikan layar WinDbg yang menampilkan jendela Watch Locals.

  6. Pada menu Perjalanan Waktu, gunakan Perjalanan waktu untuk memulai atau menggunakan !tt 0perintah untuk berpindah ke awal jejak.

    0:000> !tt 0
    Setting position to the beginning of the trace
    Setting position: 15:0
    (1e5c.710): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: 15:0
    eax=68e28100 ebx=00000000 ecx=77a266ac edx=69e34afc esi=69e3137c edi=00fa2000
    eip=77a266ac esp=00ddf3b8 ebp=00ddf608 iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
    ntdll!LdrpInitializeProcess+0x1d1c:
    77a266ac 83bdbcfeffff00  cmp     dword ptr [ebp-144h],0 ss:002b:00ddf4c4=00000000
    
  7. Pada menu Beranda, pilih Buka atau gunakan g perintah , untuk maju dalam kode hingga titik henti tertembak.

    0:000> g
    Breakpoint 2 hit
    Time Travel Position: 4B:1AD
    eax=00ddf800 ebx=00fa2000 ecx=00ddf800 edx=00b61046 esi=00b61046 edi=00b61046
    eip=00b61721 esp=00ddf7a4 ebp=00ddf864 iopl=0         nv up ei pl nz na po nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
    DisplayGreeting!GetCppConGreeting+0x1:
    00b61721 8bec            mov     ebp,esp
    
  8. Pada menu Beranda, pilih Langkah Mundur atau gunakan g-u perintah untuk mundur satu langkah.

    0:000> g-u
    Time Travel Position: 4B:1AA
    eax=00ddf800 ebx=00fa2000 ecx=00ddf800 edx=00b61046 esi=00b61046 edi=00b61046
    eip=00b61917 esp=00ddf7ac ebp=00ddf864 iopl=0         nv up ei pl nz na po nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
    DisplayGreeting!main+0x27:
    00b61917 e8def7ffff      call    DisplayGreeting!ILT+245(?GetCppConGreetingYAXPA_WIZ) (00b610fa)
    
  9. Sepertinya kita telah menemukan akar penyebabnya. Panjang array salam yang kami deklarasikan adalah 50 karakter, sedangkan sizeof(greeting) yang kita berikan ke GetCppConGreeting 0x64, 100).

    Cuplikan layar WinDbg menampilkan kode DisplayGreeting dengan jendela Watch Locals memperlihatkan 0x64.

    Saat melihat masalah ukuran lebih lanjut, kami juga melihat bahwa panjang pesan adalah 75 karakter, 76 termasuk akhir karakter string.

    HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YOUR TIME TRAVEL DEBUGGING!
    
  10. Salah satu cara untuk memperbaiki kode adalah dengan memperluas ukuran array karakter menjadi 100.

    std::array <wchar_t, 100> greeting{};
    

    Dan kita juga perlu mengubah sizeof (salam) menjadi ukuran (salam) dalam baris kode ini.

     GetCppConGreeting(greeting.data(), size(greeting));
    
  11. Untuk memvalidasi perbaikan ini, kita dapat mengkompilasi ulang kode dan mengonfirmasi bahwa kode berjalan tanpa kesalahan.

Mengatur titik henti menggunakan jendela sumber

  1. Cara alternatif untuk melakukan penyelidikan ini adalah dengan mengatur titik henti dengan mengklik baris kode apa pun. Misalnya mengklik di sisi kanan baris definisi std:array di jendela sumber akan mengatur titik henti di sana.

    Cuplikan layar jendela Sumber di WinDbg dengan titik henti yang diatur pada std::array.

  2. Pada menu Perjalanan Waktu, gunakan perintah Perjalanan waktu untuk memulai untuk berpindah ke awal pelacakan.

    0:000> !tt 0
    Setting position to the beginning of the trace
    Setting position: 15:0
    (1e5c.710): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: 15:0
    eax=68e28100 ebx=00000000 ecx=77a266ac edx=69e34afc esi=69e3137c edi=00fa2000
    eip=77a266ac esp=00ddf3b8 ebp=00ddf608 iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
    ntdll!LdrpInitializeProcess+0x1d1c:
    77a266ac 83bdbcfeffff00  cmp     dword ptr [ebp-144h],0 ss:002b:00ddf4c4=00000000
    
  3. Pada Pita Beranda klik Masuk untuk melakukan perjalanan kembali hingga titik henti ditemui.

    Breakpoint 0 hit
    Time Travel Position: 5B:AF
    eax=0000000f ebx=00c20000 ecx=00000000 edx=00000000 esi=013a1046 edi=00effa60
    eip=013a17c1 esp=00eff970 ebp=00effa60 iopl=0         nv up ei pl nz na po nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
    DisplayGreeting!DisplayGreeting+0x41:
    013a17c1 8bf4            mov     esi,esp
    

Mengatur pemutusan pada titik henti akses untuk variabel salam

Cara alternatif lain untuk melakukan penyelidikan ini, adalah dengan mengatur titik henti pada variabel tersangka dan memeriksa kode apa yang mengubahnya. Misalnya, untuk mengatur titik henti pada variabel salam dalam metode GetCppConGreeting, gunakan prosedur ini.

Bagian panduan ini mengasumsikan bahwa Anda masih berada di titik henti dari bagian sebelumnya.

  1. Dari Tampilan lalu Lokal. Di jendela lokal, salam tersedia dalam konteks saat ini, sehingga kita akan dapat menentukan lokasi memorinya.

  2. Gunakan perintah dx untuk memeriksa array salam.

    0:000> dx &greeting
    &greeting                 : 0xddf800 [Type: std::array<wchar_t,50> *]
       [+0x000] _Elems           : "꽘棶檙瞝???" [Type: wchar_t [50]]
    

    Dalam jejak ini, salam terletak dalam memori di ddf800.

  3. Gunakan jendela titik henti untuk menghapus titik henti yang ada dengan mengklik kanan titik henti yang ada dan memilih Hapus.

  4. Atur titik henti dengan perintah ba menggunakan alamat memori yang ingin kita pantau untuk akses tulis.

    ba w4 ddf800
    
  5. Pada menu Perjalanan Waktu, gunakan perintah Perjalanan waktu untuk memulai untuk berpindah ke awal pelacakan.

    0:000> !tt 0
    Setting position to the beginning of the trace
    Setting position: 15:0
    (1e5c.710): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: 15:0
    eax=68e28100 ebx=00000000 ecx=77a266ac edx=69e34afc esi=69e3137c edi=00fa2000
    eip=77a266ac esp=00ddf3b8 ebp=00ddf608 iopl=0         nv up ei pl nz na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
    ntdll!LdrpInitializeProcess+0x1d1c:
    77a266ac 83bdbcfeffff00  cmp     dword ptr [ebp-144h],0 ss:002b:00ddf4c4=00000000
    
  6. Pada menu Beranda, pilih Buka untuk melanjutkan ke titik pertama akses memori array salam.

    0:000> g-
    Breakpoint 0 hit
    Time Travel Position: 5B:9C
    eax=cccccccc ebx=002b1000 ecx=00000000 edx=68d51a6c esi=013a1046 edi=001bf7d8
    eip=013a1735 esp=001bf6b8 ebp=001bf7d8 iopl=0         nv up ei pl nz na po nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
    DisplayGreeting!GetCppConGreeting+0x25:
    013a1735 c745ec04000000  mov     dword ptr [ebp-14h],4 ss:002b:001bf7c4=cccccccc
    

    Atau, kita bisa melakukan perjalanan ke akhir jejak dan bekerja secara terbalik melalui kode untuk menemukan titik terakhir dalam jejak tempat lokasi memori array ditulis.

Gunakan TTD. Objek memori untuk melihat akses memori

Cara lain untuk menentukan titik apa dalam memori jejak yang telah diakses, adalah dengan menggunakan TTD. Objek memori dan perintah dx.

  1. Gunakan perintah dx untuk memeriksa array salam.

    0:000> dx &greeting
    &greeting                 : 0xddf800 [Type: std::array<wchar_t,50> *]
       [+0x000] _Elems           : "꽘棶檙瞝???" [Type: wchar_t [50]]
    

    Dalam jejak ini, salam terletak dalam memori di ddf800.

  2. Gunakan perintah dx untuk melihat empat byte dalam memori yang dimulai dari alamat tersebut dengan akses tulis baca.

    0:000> dx -r1 @$cursession.TTD.Memory(0xddf800,0xddf804, "rw")
    @$cursession.TTD.Memory(0x1bf7d0,0x1bf7d4, "rw")                
        [0x0]           
        [0x1]           
        [0x2]           
        [0x3]           
        [0x4]           
        [0x5]           
        [0x6]           
        [0x7]           
        [0x8]           
        [0x9]           
        [0xa]           
        ...         
    
  3. Klik salah satu kemunculan untuk menampilkan informasi lebih lanjut tentang kemunculan akses memori tersebut.

    0:000> dx -r1 @$cursession.TTD.Memory(0xddf800,0xddf804, "rw")[5]
    @$cursession.TTD.Memory(0xddf800,0xddf804, "rw")[5]                
        EventType        : MemoryAccess
        ThreadId         : 0x710
        UniqueThreadId   : 0x2
        TimeStart        : 27:3C1 [Time Travel]
        TimeEnd          : 27:3C1 [Time Travel]
        AccessType       : Write
        IP               : 0x6900432f
        Address          : 0xddf800
        Size             : 0x4
        Value            : 0xddf818
    
  4. Klik [Perjalanan Waktu] untuk memposisikan jejak pada titik waktu.

    0:000> dx @$cursession.TTD.Memory(0xddf800,0xddf804, "rw")[5].TimeStart.SeekTo()
    @$cursession.TTD.Memory(0xddf800,0xddf804, "rw")[5].TimeStart.SeekTo()
    (1e5c.710): Break instruction exception - code 80000003 (first/second chance not available)
    Time Travel Position: 27:3C1
    eax=00ddf81c ebx=00fa2000 ecx=00ddf818 edx=ffffffff esi=00000000 edi=00b61046
    eip=6900432f esp=00ddf804 ebp=00ddf810 iopl=0         nv up ei pl nz ac po nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000212
    ucrtbased!_register_onexit_function+0xf:
    6900432f 51              push    ecx
    
  5. Jika kita tertarik pada kemunculan terakhir akses memori baca/tulis dalam jejak, kita dapat mengklik item terakhir dalam daftar atau menambahkan . Fungsi last() ke akhir perintah dx.

    0:000> dx -r1 @$cursession.TTD.Memory(0xddf800,0xddf804, "rw").Last()
    @$cursession.TTD.Memory(0xddf800,0xddf804, "rw").Last()                
        EventType        : MemoryAccess
        ThreadId         : 0x710
        UniqueThreadId   : 0x2
        TimeStart        : 53:100E [Time Travel]
        TimeEnd          : 53:100E [Time Travel]
        AccessType       : Read
        IP               : 0x690338e4
        Address          : 0xddf802
        Size             : 0x2
        Value            : 0x45
    
  6. Kita kemudian dapat mengklik [Perjalanan Waktu] untuk pindah ke posisi tersebut dalam jejak dan melihat lebih jauh eksekusi kode pada saat itu, menggunakan teknik yang dijelaskan sebelumnya di lab ini.

Untuk informasi selengkapnya tentang TTD. Objek memori, lihat TTD. Objek Memori.

Ringkasan

Dalam sampel yang sangat kecil ini masalah dapat ditentukan dengan melihat beberapa baris kode, tetapi dalam program yang lebih besar teknik yang disajikan di sini dapat digunakan untuk mengurangi waktu yang diperlukan untuk menemukan masalah.

Setelah jejak direkam, langkah-langkah pelacakan dan repro dapat dibagikan, dan masalahnya akan dapat direproduksi sesuai permintaan pada PC apa pun.

Lihat Juga

Penelusuran Kesalahan Perjalanan Waktu - Gambaran Umum

Penelusuran Kesalahan Perjalanan Waktu - Perekaman

Penelusuran Kesalahan Perjalanan Waktu - Memutar ulang pelacakan

Penelusuran Kesalahan Perjalanan Waktu - Bekerja dengan file pelacakan