Pelacakan Referensi Objek dengan Tag

Objek kernel adalah objek data primitif yang diterapkan kernel Windows dalam memori sistem. Mereka mewakili entitas seperti perangkat, driver, file, kunci registri, peristiwa, semaphores, proses, dan utas.

Sebagian besar objek kernel tidak permanen. Untuk mencegah Windows menghapus objek kernel nonpermanen saat pengandar mode kernel menggunakannya, driver memperoleh referensi yang dihitung ke objek. Ketika driver tidak lagi membutuhkan objek , driver melepaskan referensinya ke objek .

Jika driver tidak merilis semua referensinya ke objek, jumlah referensi objek tidak pernah mencapai nol, dan Object Manager tidak pernah menghapusnya. Anda tidak dapat menggunakan kembali sumber daya yang bocor sampai sistem operasi dimulai ulang.

Jenis kesalahan referensi lain terjadi jika driver di bawah mereferensikan objek. Dalam hal ini, driver merilis lebih banyak referensi ke objek daripada driver yang benar-benar memegang. Kesalahan ini dapat menyebabkan Object Manager menghapus objek sebelum waktunya, sementara klien lain masih mencoba mengakses objek.

Kebocoran dan referensi yang kurang dari objek kernel bisa menjadi bug yang sulit untuk dilacak. Misalnya, objek proses atau objek perangkat mungkin memiliki puluhan ribu referensi. Mungkin sulit untuk mengidentifikasi sumber bug referensi objek dalam keadaan ini.

Di Windows 7 dan versi Windows yang lebih baru, Anda dapat menyediakan tag untuk referensi objek untuk membuat bug ini lebih mudah ditemukan. Rutinitas berikut mengaitkan tag dengan akuisisi dan rilis referensi ke objek kernel:

ObDereferenceObjectDeferDeleteWithTag

ObDereferenceObjectWithTag

ObReferenceObjectByHandleWithTag

ObReferenceObjectByPointerWithTag

ObReferenceObjectWithTag

Misalnya, ObReferenceObjectWithTag dan ObDereferenceObjectWithTag, yang tersedia di Windows 7 dan versi Windows yang lebih baru, adalah versi rutinitas ObReferenceObject dan ObDereferenceObject yang ditingkatkan, yang tersedia di Windows 2000 dan versi Windows yang lebih baru. Rutinitas yang disempurnakan ini memungkinkan Anda untuk menyediakan nilai tag kustom empat byte sebagai parameter input. Anda dapat menggunakan alat penelusuran kesalahan Windows untuk memeriksa jejak referensi objek yang berisi nilai tag untuk setiap panggilan . ObReferenceObject dan ObDereferenceObject tidak mengaktifkan pemanggil untuk menentukan tag kustom, tetapi, di Windows 7 dan versi Windows yang lebih baru, rutinitas ini menambahkan tag default (dengan nilai tag "Dflt") ke jejak. Oleh karena itu, panggilan ke ObReferenceObject atau ObDereferenceObject memiliki efek yang sama dengan panggilan ke ObReferenceObjectWithTag atau ObDereferenceObjectWithTag yang menentukan nilai tag "Dflt". (Dalam program Anda, nilai tag ini muncul sebagai 0x746c6644 atau 'tlfD'.)

Untuk melacak potensi kebocoran objek atau referensi yang kurang, identifikasi serangkaian panggilan ObReferenceObjectXxxWithTag dan ObDereferenceObjectXxxWithTag terkait di driver Anda yang menaikkan dan mengurangi jumlah referensi objek tertentu. Pilih nilai tag umum (misalnya, "Lky8") untuk digunakan untuk semua panggilan dalam set ini. Setelah driver Anda selesai menggunakan objek, jumlah penurunan harus sama persis dengan jumlah kenaikan. Jika angka-angka ini tidak cocok, driver Anda memiliki bug referensi objek. Debugger dapat membandingkan jumlah kenaikan dan penurunan untuk setiap nilai tag dan memberi tahu Anda jika tidak cocok. Dengan kemampuan ini, Anda dapat dengan cepat menentukan sumber ketidakcocokan jumlah referensi.

Untuk melihat jejak referensi objek di alat penelusuran kesalahan Windows, gunakan ekstensi debugger !obtrace kernel-mode. Jika pelacakan referensi objek aktif, Anda dapat menggunakan ekstensi !obtrace untuk menampilkan tag referensi objek. Secara default, pelacakan referensi objek nonaktif. Gunakan Global Flags Editor (Gflags) untuk mengaktifkan pelacakan referensi objek. Untuk informasi selengkapnya tentang Gflags, lihat Mengonfigurasi Pelacakan Referensi Objek.

Output ekstensi !obtrace menyertakan kolom "Tag", seperti yang ditunjukkan contoh berikut:

0: kd> !obtrace 0x8a226130
Object: 8a226130
 Image: leakyapp.exe
Sequence   (+/-)   Tag    Stack
--------   -----   ----   --------------------------------------------
      36    +1     Dflt      nt!ObCreateObject+1c4
                             nt!NtCreateEvent+93
                             nt!KiFastCallEntry+12a

      37    +1     Dflt      nt!ObpCreateHandle+1c1
                             nt!ObInsertObjectEx+d8
                             nt!ObInsertObject+1e
                             nt!NtCreateEvent+ba
                             nt!KiFastCallEntry+12a

      38    -1     Dflt      nt!ObfDereferenceObjectWithTag+22
                             nt!ObInsertObject+1e
                             nt!NtCreateEvent+ba
                             nt!KiFastCallEntry+12a

      39    +1     Lky8      nt!ObReferenceObjectByHandleWithTag+254
                             leakydrv!LeakyCtlDeviceControl+6c
                             nt!IofCallDriver+63
                             nt!IopSynchronousServiceTail+1f8
                             nt!IopXxxControlFile+6aa
                             nt!NtDeviceIoControlFile+2a
                             nt!KiFastCallEntry+12a

      3a    -1     Dflt      nt!ObfDereferenceObjectWithTag+22
                             nt!ObpCloseHandle+7f
                             nt!NtClose+4e
                             nt!KiFastCallEntry+12a
 
--------   -----   ----   --------------------------------------------
References: 3, Dereferences 2
Tag: Lky8 References: 1 Dereferences: 0 Over reference by: 1

Baris terakhir dalam contoh ini menunjukkan bahwa jumlah referensi dan dereferensi yang terkait dengan tag "Lky8" tidak cocok dan bahwa hasil dari ketidakcocokan ini adalah referensi berlebihan oleh satu (yaitu, kebocoran).

Jika hasilnya kurang referensi, baris terakhir dari output !obtrace mungkin sebagai berikut:

Tag: Lky8 References: 1 Dereferences: 2 Under reference by: 1

Secara default, sistem operasi menghemat memori dengan menghapus jejak referensi objek untuk objek setelah membebaskan objek. Menyimpan jejak dalam memori bahkan setelah sistem membebaskan objek dapat berguna saat melacak referensi yang kurang. Untuk tujuan ini, alat Gflags menyediakan opsi "Permanen", yang mempertahankan jejak dalam memori saat komputer dimatikan dan dimulai lagi.

Windows XP memperkenalkan pelacakan referensi objek. Karena awalnya jejak tidak menyertakan tag, pengembang harus menggunakan teknik yang kurang nyaman untuk mengidentifikasi bug referensi objek. Debugger dapat melacak referensi grup objek, yang dipilih pengembang berdasarkan jenis objek. Satu-satunya cara pengembang dapat mengidentifikasi berbagai sumber referensi dan dereferensi objek adalah dengan membandingkan tumpukan panggilan mereka. Meskipun contoh !obtrace sebelumnya hanya berisi lima tumpukan, jenis objek tertentu, seperti objek proses (EPROCESS), mungkin direferensikan dan didereferensikan ribuan kali. Dengan ribuan tumpukan untuk diperiksa, mungkin sulit untuk mengidentifikasi sumber kebocoran objek atau kurang referensi tanpa menggunakan tag.