Bagikan melalui


WinDbg - Garis Waktu

Logo WinDbg dengan kaca pembesar memeriksa bit.

Time Travel Debugging (TTD) memungkinkan pengguna untuk merekam jejak, yang merupakan rekaman eksekusi program. Garis waktu adalah representasi visual peristiwa yang terjadi selama eksekusi. Peristiwa ini dapat menjadi lokasi: titik henti, baca/tulis memori, panggilan dan pengembalian fungsi, dan pengecualian.

Garis waktu dalam debugger menampilkan pengecualian, akses memori, titik henti, dan panggilan fungsi.

Gunakan jendela garis waktu untuk melihat peristiwa penting dengan cepat, memahami posisi relatif, dan dengan mudah melompat ke lokasinya di file pelacakan TTD Anda. Gunakan beberapa garis waktu untuk menjelajahi peristiwa secara visual dalam pelacakan perjalanan waktu dan menemukan korelasi peristiwa.

Jendela garis waktu ditampilkan saat membuka file pelacakan TTD dan menampilkan peristiwa utama tanpa Anda harus membuat kueri model data secara manual. Pada saat yang sama, semua objek perjalanan waktu tersedia untuk memungkinkan kueri data yang lebih kompleks.

Untuk informasi selengkapnya tentang membuat dan bekerja dengan file pelacakan Perjalanan Waktu, lihat Penelusuran Kesalahan Perjalanan Waktu - Gambaran Umum.

Jenis Garis Waktu

Jendela garis waktu dapat menampilkan peristiwa berikut:

  • Pengecualian (Anda dapat memfilter lebih lanjut pada kode pengecualian tertentu)
  • Titik henti
  • Panggilan Fungsi (pencarian dalam bentuk modul!function)
  • Akses Memori (baca / tulis / jalankan antara dua alamat memori)

Arahkan mouse ke atas setiap peristiwa untuk mendapatkan informasi lebih lanjut melalui tipsalat. Mengklik peristiwa akan menjalankan kueri untuk peristiwa tersebut dan menampilkan informasi selengkapnya. Mengklik dua kali peristiwa akan melompat ke lokasi tersebut di file pelacakan TTD.

Pengecualian

Saat Anda memuat file pelacakan dan garis waktu aktif, itu akan menampilkan pengecualian apa pun dalam perekaman secara otomatis.

Saat Anda mengarahkan mouse ke atas informasi titik henti seperti jenis pengecualian dan kode pengecualian ditampilkan.

Garis waktu dalam debugger menampilkan pengecualian dengan informasi tentang kode pengecualian tertentu.

Anda dapat memfilter lebih lanjut pada kode pengecualian tertentu menggunakan bidang kode pengecualian opsional.

Kotak dialog pengecualian debugger garis waktu dengan jenis garis waktu diatur ke pengecualian dan kode pengecualian diatur ke 0xC0000004.

Anda juga dapat menambahkan garis waktu baru untuk jenis pengecualian tertentu.

Titik henti

Setelah menambahkan titik henti, Anda dapat menampilkan posisi kapan titik henti tersebut ditemui pada garis waktu. Ini dapat dilakukan misalnya menggunakan perintah bp Set Breakpoint. Saat Anda mengarahkan mouse ke atas titik henti, alamat dan penunjuk instruksi yang terkait dengan titik henti ditampilkan.

Garis waktu dalam debugger menampilkan sekitar 30 indikator titik henti.

Saat titik henti dibersihkan, garis waktu titik henti terkait akan dihapus secara otomatis.

Panggilan Fungsi

Anda dapat menampilkan posisi panggilan fungsi pada garis waktu. Untuk melakukan ini, berikan pencarian dalam bentuk module!function, misalnya TimelineTestCode!multiplyTwo. Anda juga dapat menentukan wildcard, misalnya TimelineTestCode!m*.

Menambahkan garis waktu di debugger dengan nama panggilan fungsi dimasukkan.

Saat Anda mengarahkan mouse ke atas fungsi, panggil nama fungsi, parameter input, nilainya, dan nilai pengembalian ditampilkan. Contoh ini menunjukkan buffer dan ukuran karena itu adalah parameter untuk DisplayGreeting! GetCppCongreeting.

Garis waktu dalam debugger menampilkan panggilan fungsi dan jendela daftar.

Akses Memori

Gunakan garis waktu akses memori untuk menampilkan ketika rentang memori tertentu telah dibaca atau ditulis, atau di mana eksekusi kode telah terjadi. Alamat mulai dan berhenti digunakan untuk menentukan rentang antara dua alamat memori.

Menambahkan dialog akses memori garis waktu dengan tombol tulis dipilih.

Saat Anda mengarahkan mouse ke atas item akses memori, nilai dan penunjuk instruksi ditampilkan.

Garis waktu dalam debugger yang menampilkan peristiwa akses memori.

Bekerja dengan garis waktu

Garis abu-abu vertikal mengikuti kursor saat mengarahkan kursor ke garis waktu. Garis biru vertikal menunjukkan posisi saat ini dalam pelacakan.

Klik ikon kaca pembesar untuk memperbesar dan memperkecil garis waktu.

Di area kontrol garis waktu atas gunakan persegi panjang untuk menggeser tampilan garis waktu. Seret pemisah luar persegi panjang untuk mengubah ukuran tampilan garis waktu saat ini.

Garis waktu dalam debugger memperlihatkan area atas yang digunakan untuk memilih viewport aktif.

Gerakan Mouse

Perbesar dan perkecil menggunakan roda Ctrl + Scroll.

Geser dari sisi ke sisi menggunakan Shift + Roda Gulir.

Teknik penelusuran kesalahan garis waktu

Untuk menunjukkan teknik garis waktu penelusuran kesalahan, Panduan Penelusuran Kesalahan Perjalanan Waktu digunakan kembali di sini. Demonstrasi ini mengasumsikan bahwa Anda telah menyelesaikan dua langkah pertama untuk membangun kode sampel dan membuat rekaman TTD menggunakan dua langkah pertama yang dijelaskan di sana.

Bagian 1: Buat kode sampel

Bagian 2: Rekam jejak sampel "DisplayGreeting"

Dalam skenario ini, langkah pertama adalah menemukan pengecualian dalam jejak perjalanan waktu. Ini dapat dilakukan dengan mengklik dua kali pada satu-satunya pengecualian yang ada di garis waktu.

Melihat di jendela perintah kita melihat perintah berikut dikeluarkan ketika kita mengklik pengecualian.

(2dcc.6600): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: CC:0
@$curprocess.TTD.Events.Where(t => t.Type == "Exception")[0x0].Position.SeekTo()

Pilih Lihat>>Daftar untuk menampilkan register pada saat ini di garis waktu untuk memulai penyelidikan kami.

Garis waktu dalam debugger yang menampilkan pengecualian demolab dan jendela daftar.

Dalam catatan output perintah bahwa tumpukan (esp) dan penunjuk dasar (ebp) menunjuk ke dua alamat yang sangat berbeda. 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.

Seperti yang kita lakukan, kita akan memeriksa nilai variabel lokal dan tumpukan.

Pilih Tampilkan>>Lokal untuk menampilkan nilai lokal.

Pilih Tampilkan>>Tumpukan untuk menampilkan tumpukan eksekusi 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.

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

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

0:000> t-
Time Travel Position: CB:41
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00540020 esp=003cf7d0 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: CB:40
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00061767 esp=003cf7cc 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+0x57:
00061767 c3              ret
0:000> t-
Time Travel Position: CB:3A
eax=0000004c ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=0006175f esp=003cf718 ebp=003cf7c8 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
DisplayGreeting!main+0x4f:
0006175f 33c0            xor     eax,eax

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=003cf718 ebp=003cf7c8

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

Untuk menyelidiki lebih lanjut, kita dapat membuka jendela memori untuk melihat konten di dekat alamat memori penunjuk tumpukan (esp). Dalam contoh ini memiliki nilai 003cf7c8. Pilih Ascii Teks>>Memori>>untuk menampilkan teks ASCII yang disimpan di alamat tersebut.

Debugger menampilkan jendela register, stack, dan memory.

Garis waktu akses memori

Setelah lokasi memori yang menarik diidentifikasi, tambahkan garis waktu akses memori menggunakan nilai tersebut. Klik + Tambahkan garis waktu dan isi alamat awal. Kita akan melihat 4 byte, jadi menambahkannya ke alamat awal 003cf7c8, kita memiliki 003cf7cb. Defaultnya adalah melihat semua penulisan memori, tetapi Anda juga dapat melihat hanya menulis atau eksekusi kode di alamat tersebut.

Menambahkan dialog akses memori garis waktu dengan tombol tulis dipilih dan nilai awal 003cf7c8.

Kita sekarang dapat melintasi garis waktu secara terbalik untuk memeriksa pada titik mana dalam perjalanan kali ini melacak lokasi memori ini ditulis untuk melihat apa yang dapat kita temukan. Mengklik posisi ini di garis waktu, kita melihat bahwa lokal menghargai nilai yang berbeda untuk string yang sedang disalin. Nilai tujuan tampaknya tidak lengkap, seolah-olah panjang string kami tidak benar.

Garis waktu akses memori dan jendela lokal yang menampilkan nilai lokal dengan nilai sumber dan tujuan yang berbeda.

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

Untuk menjelajahi teknik penelusuran kesalahan garis waktu alternatif, klik pengecualian di garis waktu dan sekali lagi menempuh tiga langkah kembali, menggunakan perintah Langkah Ke Belakang pada pita Beranda .

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.

Seperti disebutkan sebelumnya, penunjuk dasar (esp) alih-alih menunjuk ke instruksi, menunjuk ke teks pesan kami.

Gunakan perintah ba untuk mengatur titik henti pada akses memori. Kita akan mengatur titik henti w - tulis untuk melihat kapan area memori ini ditulis.

0:000> ba w4 003cf7c8

Meskipun kita akan menggunakan titik henti akses memori sederhana, titik henti dapat dibangun untuk menjadi pernyataan kondisional yang lebih kompleks. Untuk informasi selengkapnya, lihat bp, bu, bm (Set Breakpoint).

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

Pada titik ini kita dapat memeriksa tumpukan program untuk melihat kode apa yang aktif.

Garis waktu dalam debugger yang menampilkan garis waktu akses memori dan 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 mengilustrasikan teknik yang dapat digunakan dengan program yang lebih besar dan lebih kompleks, kita akan mengatur tambahkan garis waktu panggilan fungsi.

Garis waktu panggilan fungsi

Klik + Tambahkan garis waktu dan isi DisplayGreeting!GetCppConGreeting untuk string pencarian fungsi.

Kotak centang Lokasi mulai dan Akhir menunjukkan bahwa awal dan akhir panggilan fungsi dalam pelacakan.

Kita dapat menggunakan Perintah dx untuk menampilkan objek panggilan fungsi untuk melihat bidang TimeStart dan TimeEnd terkait yang sesuai dengan Lokasi Mulai dan Lokasi Akhir panggilan fungsi.

dx @$cursession.TTD.Calls("DisplayGreeting!GetCppConGreeting")[0x0]
    EventType        : 0x0
    ThreadId         : 0x6600
    UniqueThreadId   : 0x2
    TimeStart        : 6D:BD [Time Travel]
    SystemTimeStart  : Thursday, October 31, 2019 23:36:05
    TimeEnd          : 6D:742 [Time Travel]
    SystemTimeEnd    : Thursday, October 31, 2019 23:36:05
    Function         : DisplayGreeting!GetCppConGreeting
    FunctionAddress  : 0x615a0
    ReturnAddress    : 0x61746
    Parameters  

Baik kotak Mulai atau Akhir, atau lokasi Mulai dan Akhir, harus dicentang.

Tambahkan dialog Garis Waktu baru yang menampilkan penambahan garis waktu panggilan Fungsi dengan string pencarian fungsi DisplayGreeting! GetCppCongreeting.

Karena kode kami tidak rekursif atau retrant, sangat mudah untuk menemukan pada garis waktu ketika metode GetCppConGreeting dipanggil. Panggilan ke GetCppConGreeting juga terjadi pada saat yang sama dengan titik henti kami serta peristiwa akses memori yang kami tentukan. Jadi sepertinya kami telah mempersempit area kode untuk melihat dengan cermat untuk akar penyebab crash aplikasi kami.

Garis waktu dalam debugger menampilkan garis waktu akses memori dan jendela lokal dengan pesan dan buffer yang berisi nilai string yang berbeda.

Menjelajahi eksekusi kode dengan melihat beberapa garis waktu

Meskipun sampel kode kami kecil, teknik menggunakan beberapa garis waktu memungkinkan eksplorasi visual pelacakan perjalanan waktu. Anda dapat melihat di seluruh file jejak untuk mengajukan pertanyaan, seperti "kapan area memori diakses sebelum titik henti ditemui?".

Garis waktu dalam debugger yang menampilkan garis waktu akses memori dan jendela lokal.

Kemampuan untuk melihat korelasi tambahan dan menemukan hal-hal yang mungkin tidak Anda harapkan, membedakan alat garis waktu agar tidak berinteraksi dengan jejak perjalanan waktu menggunakan perintah baris perintah.

Marka Buku Garis Waktu

Bookmark posisi Perjalanan Waktu penting di WinDbg alih-alih menyalin secara manual menempelkan posisi ke notepad. Marka buku memudahkan untuk melihat sekilas posisi yang berbeda dalam jejak relatif terhadap peristiwa lain, dan untuk membuat anotasinya.

Anda dapat memberikan nama deskriptif untuk marka buku.

Dialog bookmark baru memperlihatkan contoh nama untuk panggilan API pertama di aplikasi Display Greeting.

Akses Bookmark melalui jendela Garis Waktu yang tersedia di Lihat > Garis Waktu. Saat Anda mengarahkan mouse ke atas bookmark, bookmark akan menampilkan nama bookmark.

Garis waktu menampilkan tiga marka buku dengan kursor mengarahkan kursor ke satu, mengungkapkan nama bookmark.

Anda dapat mengklik kanan marka buku untuk melakukan perjalanan ke posisi tersebut, mengganti nama, atau menghapus marka buku.

Menu popup klik kanan bookmark yang menampilkan opsi untuk melakukan perjalanan ke posisi, mengedit, dan menghapus.

Catatan

Dalam versi 1.2402.24001.0 dari debugger, fitur marka buku tidak tersedia.

Lihat Juga

Fitur WinDbg

Panduan Penelusuran Kesalahan Perjalanan Waktu