Proyek ini menggunakan MSVC C ++ STL di driver kernel Windows. Dalam solusi ini jxystl.lib diimplementasikan sebagai kernel yang disesuaikan, tipe kumpulan/tag sadar, perpustakaan template dan implementasi MSVC. Yang, di bawah kap, menggunakan MSVC C ++ STL.
# include < wdm.h >
# include < jxy/string.hpp >
extern " C "
NTSTATUS DriverEntry (
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
jxy::wstring<PagedPool, ' 0GAT ' > helloWorld;
try
{
helloWorld. assign ( L" Hello, World! " );
}
catch ( const std::bad_alloc&)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
return STATUS_SUCCESS;
} 1: kd> dv
DriverObject = 0xffffca83`5380d300 Driver "Driverstlkrn"
RegistryPath = 0xffffca83`5227f000 "REGISTRYMACHINESYSTEMControlSet001Servicesstlkrn"
helloWorld = "Hello, World!"
| Standar | Didukung | Catatan |
|---|---|---|
| CPP11 | TIDAK | belum teruji, milage Anda bervariasi |
| CPP14 | Ya | |
| CPP17 | Ya | |
| CPP20 | Ya |
Driver uji dalam solusi ini, stdtest.sys , menampung unit tes untuk proyek. Tes unit dijalankan di kernel dengan verifier driver. Kerangka kerja tes unit adalah tulang telanjang tetapi cukup untuk berolahraga jxystl.lib .
Driver lain yang diimplementasikan dalam solusi ini, stdkrn.sys , menempatkan jxystl.lib untuk digunakan dalam skenario praktis. Ini menggunakan berbagai fasilitas dan wadah namespace std (dibungkus di bawah jxy namespace). Driver ini mendaftar untuk pemberitahuan proses, utas, dan gambar; Kemudian gunakan C ++ modern untuk melacak konteks proses, konteks utas, dan konteks modul.
vcrtlPenanganan pengecualian memungkinkan objek C ++ untuk bersantai saat pengecualian dilemparkan. Ini adalah fitur inti dari C ++ yang mendapat sedikit perhatian untuk pengemudi kernel. Microsoft tidak mendukung pengecualian C ++ untuk driver kernel.
Penanganan pengecualian C ++ dimungkinkan oleh libraray VCRTL Avakar. Proyek ini akan jauh lebih banyak pekerjaan tanpa kontribusi Avakar yang luar biasa. Untuk informasi tentang penanganan pengecualian di driver Windows, kunjungi Avakar's VCRTL Github. Juga, halaman ini memberikan detail yang sangat baik tentang penanganan pengecualian pada AMD64.
jxystlAlokasi kernel Windows dikaitkan dengan kumpulan memori. Selanjutnya, penandaan biliar dibangun ke dalam kernel Windows. Tagging kolam memfasilitasi pelacakan alokasi yang dibuat oleh pengemudi. Fasilitas penandaan ini memungkinkan debugging dan pemantauan alokasi.
jxy Namespace, dalam solusi ini, memberdayakan pengembangan driver Windows menggunakan objek namespace std dengan pengetikan dan penandaan kolam.
Perpustakaan memilih untuk tidak mengimplementasikan operator new / delete "global". Ini hanya mengimplementasikan operator new / delete dengan pengetikan dan kemampuan penandaan. Ini membutuhkan menentukan jenis dan tag kumpulan. Jika beberapa fungsionalitas digunakan, yang akan membutuhkan "alokasi global" itu tidak akan terhubung. Ini adalah keputusan desain yang disengaja sehingga tidak ada alokasi global yang digunakan, semua alokasi harus menentukan jenis dan tag kumpulan.
jxy Namespace mengimplementasikan alokasi dan penghapusan yang sesuai dengan standar untuk digunakan dalam wadah templat. Alokasi dan penghapus ini adalah tipe/tag pool. Mereka memerlukan menentukan jenis kumpulan dan tag dan mencegah konversi/rebin kembali melintasi jenis alat dan tag - mereka harus digunakan sebagai pengganti alokasi STL.
jxy::allocator<T, PagedPool, ' 0GAT ' >;
jxy::default_delete<T, PagedPool, ' 0GAT ' >; jxystl.lib mengimplementasikan fungsionalitas "isi" yang diperlukan untuk penggunaan wadah STL MSVC. Implementasi (di msvcfill.cpp ) mempertimbangkan kernel. Fungsionalitas ini memungkinkan wadah MSVC STL untuk menautkan ke fungsionalitas yang sesuai dengan kernel. Ini juga berarti bahwa jika beberapa fungsionalitas wadah std digunakan yang tidak memiliki fungsionalitas "mengisi" di baliknya - penghubung akan gagal. Ini adalah keputusan desain yang disengaja sehingga setiap implementasi dipikirkan untuk digunakan dalam kernel.
Inisialisasi CRT dan fungsi ATEXIT sengaja tidak didukung. Urutan inisialisasi CRT tidak jelas dan tidak jelas. Ketika driver kernel memuat data global harus diatur dengan jelas dan dirobohkan selama beban dan pembongkaran driver. Inisialisasi CRT global "menyembunyikan" inisialisasi ini dengan cara yang tidak jelas. Selanjutnya, fungsionalitas CRT ATEXIT tidak didukung. Emisi sinkronisasi yang diperlukan memungkinkan inisialisasi statis lokal dari objek C ++ tidak dilakukan oleh kompiler. Dan akan memperkenalkan sinkronisasi yang tidak jelas dalam kernel. Kurangnya inisialisasi CRT dan dukungan ATEXIT adalah keputusan desain yang disengaja. Saya sangat menyarankan untuk menghindarinya saat mengembangkan pengemudi kernel.
Sebagai contoh, jxy namespace "membungkus" std::vector dan kekuatan penggunaan jenis dan tag:
namespace jxy
{
template < typename T,
POOL_TYPE t_PoolType,
ULONG t_PoolTag,
typename TAllocator = jxy::allocator<T, t_PoolType, t_PoolTag>>
using vector = std::vector<T, TAllocator>;
}
jxy::vector< int , PagedPool, ' 0GAT ' > integers; stlkrn!DriverEntry+0xea:
0: kd> dx integers
integers : { size=10 } [Type: std::vector<int,jxy::details::allocator<int,1,809976148> >]
[<Raw View>] [Type: std::vector<int,jxy::details::allocator<int,1,809976148> >]
[capacity] : 10
[allocator] : {...} [Type: std::_Compressed_pair<jxy::details::allocator<int,1,809976148>,std::_Vector_val<std::_Simple_types<int> >,1>]
[0] : 1 [Type: int]
[1] : 2 [Type: int]
[2] : 3 [Type: int]
[3] : 4 [Type: int]
[4] : 5 [Type: int]
[5] : 6 [Type: int]
[6] : 7 [Type: int]
[7] : 8 [Type: int]
[8] : 9 [Type: int]
[9] : 10 [Type: int]
Di bawah ini adalah tabel fungsionalitas di bawah jxy namespace:
| JXY | STL setara | Termasuk | Catatan |
|---|---|---|---|
jxy::allocator | std::allocator | <jxy/memory.hpp> | |
jxy::default_delete | std::default_delete | <jxy/memory.hpp> | |
jxy::unique_ptr | std::unique_ptr | <jxy/memory.hpp> | |
jxy::shared_ptr | std::shared_ptr | <jxy/memory.hpp> | |
jxy::basic_string | std::basic_string | <jxy/string.hpp> | |
jxy::string | std::string | <jxy/string.hpp> | |
jxy::wstring | std::wstring | <jxy/string.hpp> | |
jxy::vector | std::vector | <jxy/vector.hpp> | |
jxy::map | std::map | <jxy/map.hpp> | |
jxy::multimap | std::miltimap | <jxy/map.hpp> | |
jxy::mutex | std::mutex | <jxy/locks.hpp> | Menggunakan KGUARDED_MUTEX |
jxy::shared_mutex | std::shared_mutex | <jxy/locks.hpp> | Menggunakan EX_PUSH_LOCK |
jxy::unique_lock | std::unique_lock | <jxy/locks.hpp> | |
jxy::shared_lock | std::shared_lock | <jxy/locks.hpp> | |
jxy::scope_resource | Tidak ada | <jxy/scope.hpp> | Mirip dengan std::experimental::unique_resource |
jxy::scope_exit | Tidak ada | <jxy/scope.hpp> | Mirip dengan std::experimental::scope_exit |
jxy::thread | std::thread | <jxy/thread.hpp> | |
jxy::deque | std::deque | <jxy/deque.hpp> | |
jxy::queue | std:queue | <jxy/queue.hpp> | |
jxy::priority_queue | std::priority_queue | <jxy/queue.hpp> | |
jxy::set | std::set | <jxy/set.hpp> | |
jxy::multiset | std::multiset | <jxy/set.hpp> | |
jxy::stack | std::stack | <jxy/stack.hpp> |
stltest.sys Proyek stltest mengimplementasikan pengemudi yang menjalankan beberapa tes terhadap JXYSTL, penggunaan STL, dan pengecualian di kernel Windows.
stlkrn.sys Proyek stlkrn adalah driver Windows yang menggunakan jxystl.lib untuk mengimplementasikan proses, utas, dan pelacakan modul di kernel Windows.
stlkrn.sys register untuk proses, utas, dan pemberitahuan gambar menggunakan fungsionalitas yang diekspor oleh ntoskrnl . Menggunakan callback ini melacak proses, utas, dan beban gambar di berbagai objek yang menggunakan jxy::map , jxy::shared_mutex , jxy::wstring , dan banyak lagi.
Pengemudi memiliki dua singleton. jxy::ProcessMap dan jxy::ThreadMap , ini dibangun ketika driver memuat ( DriverEntry ) dan dirobohkan ketika pengemudi membongkar ( DriverUnload ). Perlu dicatat di sini setiap proses yang dilacak dalam jxy::ProcessMap (diimplementasikan sebagai jxy::ProcessContext ) juga mengelola jxy::ThreadMap . Setiap "konteks" ( jxy::ProcessContext , jxy::ThreadContext , dan jxy::ModuleContext ) adalah objek bersama (direferensikan) ( jxy::shared_ptr ). Oleh karena itu, konteks utas yang ada dalam peta utas singleton adalah konteks yang sama terkait dengan konteks proses.
Komponen kunci stlkrn.sys :
| Obyek | Tujuan | Sumber | Catatan |
|---|---|---|---|
jxy::ProcessContext | Informasi untuk proses yang berjalan pada sistem. | process_context.hpp/cpp | Menggunakan jxy::wstring . Memiliki thread ( jxy::ThreadMap ) dan module ( jxy::ModuleMap ) anggota peta. |
jxy::ThreadContext | Informasi untuk utas yang berjalan pada sistem. | thread_context.hpp/cpp | Menggunakan std::atomic . |
jxy::ModuleContext | Informasi untuk gambar yang dimuat dalam proses tertentu. | module_context.hpp/cpp | Menggunakan jxy::wstring dan jxy::shared_mutex . |
jxy::ProcessMap | Singleton, peta berbagi jxy::ProcessContext objek ke PID. | process_map.hpp/cpp | Singleton diakses melalui jxy::GetProcessMap . Menggunakan jxy::shared_mutex dan jxy::map . |
jxy::ThreadMap | Peta dibagikan jxy::ThreadContext objek ke tid. | thread_map.hpp/cpp | Global Thread Table (Singleton) diakses melalui jxy::GetThreadMap . Setiap jxy::ProcessContext juga memiliki peta utas yang diakses melalui jxy::ProcessContext::GetThreads . Menggunakan jxy::shared_mutex dan jxy::map . |
jxy::GetModuleMap | Peta dibagikan jxy::ModuleContext ke Luasan Gambar yang Dimuat (Alamat Basis dan Akhir). | module_map.hpp/cpp | Setiap konteks proses memiliki anggota peta modul. Gambar yang dimuat untuk proses yang diberikan dilacak menggunakan objek ini. Menggunakan jxy::shared_mutex dan jxy::map |
std::unordered_map akan menjadi pilihan yang lebih baik daripada pohon yang dipesan ( std::map ) untuk peta objek. Ada alasan mengapa ini tidak digunakan (lihat bagian TODO ).
stlkrn!jxy::nt::CreateProcessNotifyRoutine+0xa6:
3: kd> dx proc
proc : {...} [Type: std::shared_ptr<jxy::ProcessContext>]
[<Raw View>] [Type: std::shared_ptr<jxy::ProcessContext>]
[ptr] : 0xffffaa020d73cf70 [Type: jxy::ProcessContext *]
[control block] : custom deleter, custom allocator [Type: std::_Ref_count_resource_alloc<jxy::ProcessContext *,jxy::details::default_delete<jxy::ProcessContext,1,1668307018>,jxy::details::allocator<jxy::ProcessContext,1,1668307018> > (derived from std::_Ref_count_base)]
[+0x000] m_ProcessId : 0x2760 [Type: unsigned int]
[+0x004] m_SessionId : 0x2 [Type: unsigned int]
[+0x008] m_ParentProcessId : 0xcc4 [Type: unsigned int]
[+0x010] m_FileName : "DeviceHarddiskVolume4WindowsSystem32cmd.exe" [Type: std::basic_string<unsigned short,std::char_traits<unsigned short>,jxy::details::allocator<unsigned short,1,1852856394> >]
[+0x030] m_FilePart : "cmd.exe" [Type: std::basic_string<unsigned short,std::char_traits<unsigned short>,jxy::details::allocator<unsigned short,1,1886410826> >]
[+0x050] m_CreatorProcessId : 0x1b08 [Type: unsigned int]
[+0x054] m_CreatorThreadId : 0x26a0 [Type: unsigned int]
[+0x058] m_Threads [Type: jxy::ThreadMap]
[+0x070] m_Modules [Type: jxy::ModuleMap]
Saya ingin memasukkan std::unordered_map pada awalnya, namun menggunakan ceilf . Aritmatika titik mengambang di kernel Windows hadir dengan beberapa tantangan. Jadi, untuk saat ini dihilangkan sampai solusi yang tepat dirancang.
Solusi ini adalah proyek gairah. Saat ini tidak dimaksudkan untuk kode produksi. x64 diuji dengan baik dan stabil, stlkrn.sys melewati opsi verifier driver penuh (termasuk simulasi sumber daya rendah acak). Penanganan pengecualian pada atau di atas pengiriman telah diuji, tetapi tidak dalam kasus penggunaan praktis. x86 belum diuji. Ada fungsionalitas di bawah jxy namespace yang tidak lengkap/tidak digunakan/tidak teruji. Jilid Anda mungkin bervariasi - Saya ingin melanjutkan pekerjaan ini dari waktu ke waktu, jika ada masalah/bug yang ditemukan merasa bebas untuk membuka masalah terhadap repo ini.
Proyek ini memberikan dukungan STL di kernel Windows dengan menggunakan sebanyak mungkin fasilitas STL. Ada solusi lain untuk penggunaan STL dalam pengembangan kernel. Bagian ini akan menguraikan alternatif, pertama saya akan meringkas pekerjaan ini:
Proyek ini:
new atau delete yang diimplementasikan.atexit . Urutan inisialisasi CRT tidak jelas, inisialisasi pengemudi dan robekan harus jelas . Fungsi atexit dapat memperkenalkan balapan data untuk kode kernel, atexit tidak diimplementasikan.Hypervisor Bareflank:
Bareflank mengimplementasikan dukungan untuk menjalankan C ++ di hypervisor mereka. Mereka memiliki dukungan STL dan CRT penuh. Ini adalah proyek komprehensif yang memungkinkan fitur STANDHORA dari standar dalam mode kernel (termasuk pengecualian). Seperti yang saya pahami, solusi mereka, NonPagedPool pada alokasi new / delete global. Saya harus memuji Bareflank dengan implementasinya, itu dipikirkan dengan baik dan lintas platform. Namun implementasi Windows dibangun melalui Cygwin dan "Shims" untuk mendukung kernel Windows. Sebagai perbandingan, proyek ini bertujuan untuk mempertimbangkan kernel Windows. Ini memungkinkan menentukan tag dan jenis kumpulan (Paged vs non-PAGED) dan berharap untuk meminimalkan "tepi tajam" yang terkait dengan penggunaan C ++ dan STL dalam mode kernel. Semua yang dikatakan, Bareflank sangat mengesankan untuk apa yang dilakukan. Untuk presentasi yang sangat baik tentang dukungan Bareflank terhadap C ++ saya sangat merekomendasikan menonton presentasi Dr. Rian Quinn di CPPCON 2016.
Win32kernelstl:
Proyek Win32Kernelstl memungkinkan Anda untuk menggunakan fungsionalitas STL secara langsung di kernel. Proyek ini mengimplementasikan Global new / delete dan memaksa NonPagedPool , ini mengimplementasikan dukungan inisialisasi CRT, dan bugchecks ketika pengecualian CPP dilemparkan. Tidak ada upaya untuk melakukan pengecualian CPP. Karena asumsi itu membuat saya merasa tidak praktis untuk kasus penggunaan yang serius. Kode ini cukup jelas dan didokumentasikan, saya sarankan memberikan proyek ini untuk mendidik sekitar dukungan C ++ di kernel. Satu catatan, kode CRT di Win32KernelSTL mengimplementasikan atexit tetapi perlu diingat tidak ada sinkronisasi yang dipancarkan oleh kompiler di sini (berbeda dengan mode pengguna). Jadi statis lokal yang membutuhkan penyisipan entri dalam daftar atexit dapat berlomba menyebabkan init ganda atau bebas ganda.
Driver plus plus:
Proyek ini mengimplementasikan fasilitas C ++ yang diperlukan untuk menarik sejumlah solusi C ++ ke dalam mode kernel ( EASTL , msgpack , dll.). Driver Plus Plus mengimplementasikan inisialisasi CRT dan dukungan new / delete global (yang memaksa NonPagedPool ). Sekali lagi ini bertentangan dengan tujuan proyek ini. Namun, proyek ini memang memungkinkan banyak fasilitas C ++ yang hebat untuk digunakan dalam mode kernel. Itu memang membuat modifikasi pada solusi C ++ yang ditariknya ke shim untuk mendukung kasus penggunaannya. Driver Plus Plus juga membuat asumsi di atexit seperti yang disebutkan sebelumnya.
KTL - DYMOK93
KTL (Windows Kernel Template Library oleh DymOK93) mengimplementasikan sejumlah C ++ modern yang baik dan secara aktif mengembangkan lebih banyak dukungan untuk digunakan dalam kernel Windows. Ini juga memiliki dukungan untuk RAII di sekitar banyak primitif kernel, menyediakan dukungan asli ANSI_STRING dan UNICODE_STRING , ini menyediakan beberapa pembungkus yang berguna untuk mendaftarkan panggilan balik kernel, dan lebih banyak fitur kenyamanan di sekitar kernel Windows. Ini mengimplementasikan Global new / delete dan memiliki definisi preprocessor ( KTL_USING_NON_PAGED_NEW_AS_DEFAULT ) untuk beralih antara paged default atau non-paging, yang bagus. Namun, menggunakan tag pool tunggal ( KTL_HEAP_TAG ). Lebih lanjut, templat alokasi yang ada tidak memungkinkan pengembang untuk menentukan tag kumpulan, jadi menggunakan perpustakaan ini AS-IS menyebabkan semua alokasi ditandai dengan tag pool yang sama. Yang mengatakan, akan masuk akal untuk mengimplementasikan alokasi khusus yang memberdayakan penandaan alokasi. Perpustakaan memang memiliki dukungan pengecualian, meskipun hanya x64. Dukungan pengecualian di KTL didasarkan pada Avakar dengan peningkatan dan perbaikan. Saya memuji pekerjaan di sini dan saya terkesan dengan jumlah fasilitas yang ada, itu cukup dikemas dan di bawah pengembangan aktif. Saya ingin mengeksplorasi menggunakannya lebih banyak di masa depan, dan berpotensi berkolaborasi pada dukungan pengecualian yang lebih baik untuk stlkrn dan KTL . Implementasi fungsionalitas STL, kurangnya dukungan penandaan kolam asli, dan alokasi global bertentangan dengan ideologi proyek ini.
KTL - Meesong:
KTL (Windows Kernel Template Library oleh Meesong) Menyusun kembali sejumlah fungsi C ++ modern untuk digunakan dalam kernel Windows. Ini juga mengimplementasikan Global new / delete tetapi melakukan pekerjaan yang layak dalam menyediakan fasilitas untuk menentukan tag dan jenis pool jika memungkinkan. Namun ini berarti alokasi global mungkin menyembunyikan alokasi di kumpulan yang tidak jelas. Lebih lanjut, alokasi template dalam proyek ini membawa biaya dua poin untuk objek Allocator dan Deallocator, saya juga khawatir bahwa konversi antara jenis pengalokasi dapat memungkinkan untuk allocs/tag cross pool/tag. Secara keseluruhan saya terkesan dengan jumlah fasilitas yang diterapkan di sini. Implementasi fungsionalitas STL dan alokasi global bertentangan dengan ideologi proyek ini.
Kernel-Bridge:
Kernel-Bridge mengimplementasikan beberapa fasilitas hebat untuk pengembangan kernel Windows. Perpustakaan menyediakan pembungkus untuk mendaftar untuk Windows Callbacks menggunakan objek C ++. Saya ingin menemukan lebih banyak waktu untuk menggunakan dan menyelidiki solusi ini. Itu menerapkan dukungan CRT. Fungsi atexit yang diimplementasikan tidak dinamis - menggunakan array statis, jika kehabisan slot, gagal. Default new / delete Forces NonPagedPool . Itu tidak memiliki dukungan pengecualian penuh, itu akan bugcheck jika pengecualian CPP dilemparkan - itu tidak akan melepas objek pada tumpukan.
Repositori ini diambil dari beberapa karya yang sudah ada sebelumnya. Kredit kepada penulisnya.