Этот проект использует MSVC C ++ STL в драйвере ядра Windows. В этом решении jxystl.lib реализован в виде ядра, настраиваемого, библиотеки шаблонов, библиотеки шаблонов и реализации MSVC. Который под капотом использует 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!"
| Стандартный | Поддерживается | Примечания |
|---|---|---|
| CPP11 | Нет | непроверенный, твоя солон |
| CPP14 | Да | |
| CPP17 | Да | |
| CPP20 | Да |
Тест -драйвер в этом решении, stdtest.sys , располагает модульные тесты для проекта. Модульные тесты проводятся в ядре с верификатором драйвера. Установка модульной тестирования - голые кости, но достаточна для упражнений jxystl.lib .
Другой драйвер, реализованный в этом решении, stdkrn.sys , ставит jxystl.lib для использования в практическом сценарии. Он использует различные объекты и контейнеры пространства имен std (обернутые под пространством имен jxy ). Этот драйвер регистрируется для уведомлений о процессе, потоке и изображениях; Затем использует современный C ++ для отслеживания контекстов процесса, контекстов потоков и контекстов модулей.
vcrtlОбработка исключений позволяет объектам C ++ разматываться при брошении на исключение. Это основная особенность C ++, которая получает мало внимания к драйверам ядра. Microsoft не поднимает исключения C ++ для драйверов ядра.
Обработка исключений C ++ стала возможной благодаря библиотеке Avakar VCRTL. Этот проект был бы гораздо большей работой без удивительного вклада Авакара. Для получения информации об обработке исключений в Windows драйверы отправляются в vcrtl github Авакара. Кроме того, эта страница дает отличные подробности об обращении исключений на AMD64.
jxystlРаспределение ядра Windows связано с пулом памяти. Кроме того, тегики в бассейне встроены в ядро Windows. Тегирование бассейна облегчает отслеживание распределений, сделанных водителями. Этот объект тегов позволяет отлаживать и мониторинг распределения.
Пространство имен jxy , в этом решении, дает возможность разработке драйверов Windows, используя объекты пространства имен std с типированием и тегом пула.
Библиотека предпочитает не внедрять «глобальные» new / delete операторы. Он реализует только new / delete операторы с возможностью типирования и тегов пула. Это требует определения типов пул и тегов. Если используется некоторые функции, которые потребуют «глобального распределения», он не будет связывать. Это преднамеренное решение о проектировании, так что никакие глобальные распределители не используются, все ассигнования должны указывать тип пула и тег.
Пространство имен jxy реализует выделения и удаления, что соответствует стандарту для использования в шаблонных контейнерах. Эти распределители и удаления осведомлены о типе бассейна/тега. Они требуют указания типа пула и тега и предотвращения преобразования/переподничества по типам и тегам инструментов - их следует использовать вместо распределителей STL.
jxy::allocator<T, PagedPool, ' 0GAT ' >;
jxy::default_delete<T, PagedPool, ' 0GAT ' >; jxystl.lib реализует необходимую функциональность «заполнить» для использования контейнеров MSVC STL. Реализации (в msvcfill.cpp ) внимательны к ядру. Эта функциональность позволяет контейнерам MSVC STL связываться с функциональностью, соответствующей ядрам. Это также означает, что если используется некоторые функции контейнера std , которая не имеет функциональности «заполнить» за ним - лингер потерпит неудачу. Это преднамеренное решение о проектировании, так что любые реализации продуманы для использования в ядре.
Инициализация КРТ и функциональность Atexit преднамеренно не поддерживаются. Порядок инициализации ЭЛТ неясен и не является неочевидным. Когда драйвер ядра загружает глобальные данные, должны быть четко настроены и снесены во время загрузки и разгрузки драйвера. Глобальная инициализация CRT «скрывает» эту инициализацию неочевидным способом. Кроме того, функциональность CRT Atexit не поддерживается. Эмиссия необходимой синхронизации, обеспечивающая локальную статическую инициализацию объектов C ++, не выполняется компилятором. И введет неочевидную синхронизацию в ядре. Отсутствие инициализации КРТ и поддержки Atexit является преднамеренным проектным решением. Я настоятельно рекомендую избегать его при разработке драйверов ядра.
В качестве примера, jxy -пространство имен «обертывает» std::vector и силы использования типов и тегов пул:
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]
Ниже приведена таблица функциональности в пространстве имен jxy :
| jxy | STL эквивалент | Включать | Примечания |
|---|---|---|---|
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> | Использует KGUARDED_MUTEX |
jxy::shared_mutex | std::shared_mutex | <jxy/locks.hpp> | Использует EX_PUSH_LOCK |
jxy::unique_lock | std::unique_lock | <jxy/locks.hpp> | |
jxy::shared_lock | std::shared_lock | <jxy/locks.hpp> | |
jxy::scope_resource | Никто | <jxy/scope.hpp> | Похоже на std::experimental::unique_resource |
jxy::scope_exit | Никто | <jxy/scope.hpp> | Подобно 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 Проект stltest реализует драйвер, который проходит некоторые тесты против JXYSTL, использования STL и исключения в ядре Windows.
stlkrn.sys Проект stlkrn - это драйвер Windows, который использует jxystl.lib для реализации процесса, потока и отслеживания модулей в ядре Windows.
stlkrn.sys регистрируется для процесса, потока и изображений с использованием функциональности, экспортируемых ntoskrnl . Используя эти обратные вызовы, он отслеживает процессы, потоки и нагрузки изображения в различных объектах, которые используют jxy::map , jxy::shared_mutex , jxy::wstring и многое другое.
У водителя есть два синглтона. jxy::ProcessMap и jxy::ThreadMap , они построены, когда драйвер загружается ( DriverEntry ) и снимается, когда драйвер разгружается ( DriverUnload ). Здесь стоит отметить, что каждый процесс, отслеживаемый в jxy::ProcessMap (реализован как jxy::ProcessContext ), также управляет jxy::ThreadMap . Каждый «контекст» ( jxy::ProcessContext , jxy::ThreadContext и jxy::ModuleContext ) является общим (ссылками) объектом ( jxy::shared_ptr ). Следовательно, контекст потока, который существует в синглтоне карты потока, является тем же контекстом, связанным с контекстом процесса.
Ключевые компоненты stlkrn.sys :
| Объект | Цель | Источник | Примечания |
|---|---|---|---|
jxy::ProcessContext | Информация для процесса, работающего в системе. | process_context.hpp/cpp | Использует jxy::wstring . Имеет Thread ( jxy::ThreadMap ) и модуль ( jxy::ModuleMap ) участники карты. |
jxy::ThreadContext | Информация о потоке, работающей в системе. | thread_context.hpp/cpp | Использует std::atomic . |
jxy::ModuleContext | Информация для изображения, загруженного в данном процессе. | module_context.hpp/cpp | Использует jxy::wstring и jxy::shared_mutex . |
jxy::ProcessMap | Singleton, карты обменивались jxy::ProcessContext объектов на PID. | process_map.hpp/cpp | Синглтон доступ к jxy::GetProcessMap . Использует jxy::shared_mutex и jxy::map . |
jxy::ThreadMap | Карты совместно используются jxy::ThreadContext объекты в Tid. | thread_map.hpp/cpp | Глобальная таблица потоков (Singleton) доступна через jxy::GetThreadMap . У каждого jxy::ProcessContext также есть карта потоков, доступную через jxy::ProcessContext::GetThreads . Использует jxy::shared_mutex и jxy::map . |
jxy::GetModuleMap | Карты совместно используются jxy::ModuleContext к загруженным экстентам изображения (базовый и конечный адрес). | module_map.hpp/cpp | Каждый контекст процесса имеет элемент карты модуля. Загруженные изображения для данного процесса отслеживаются с использованием этого объекта. Использует jxy::shared_mutex и jxy::map |
std::unordered_map был бы лучшим выбором по сравнению с упорядоченным деревом ( std::map ) для карт объекта. Есть причина, по которой это не используется (см. Раздел 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]
Я хотел включить std::unordered_map изначально, однако он использует ceilf . Арифметика с плавающей запятой в ядре Windows поставляется с некоторыми проблемами. Таким образом, сейчас он будет опущен до тех пор, пока не будет разработано подходящее решение.
Это решение - страстный проект. В настоящее время это не предназначено для производственного кода. x64 хорошо протестирован и стабилен, stlkrn.sys передает полные варианты проверки драйвера (включая рандомизированное моделирование низкого ресурса). Обработка исключений при отправке или выше была проверена, но не в практических случаях использования. x86 не был проверен. Существует функциональность в пространстве имен jxy , которое является неполным/неиспользованным/непроверенным. Ваша прокладка может различаться - я хотел бы продолжить эту работу со временем, если будут обнаружены какие -либо проблемы/ошибки, не стесняйтесь открывать проблемы против этого репо.
Этот проект обеспечивает поддержку STL в ядре Windows, используя как можно больше объекта STL. Есть и другие решения для использования STL в разработке ядра. В этом разделе будут описаны альтернативы, сначала я суммирую эту работу:
Этот проект:
new или delete не внедряется.atexit . Порядок инициализации CRT не является неочевидным, инициализация и разрыв драйвера и разрыв должны быть очевидны . Функциональность atexit может вводить гонки данных для кода ядра, atexit не реализован.Bareflank Hypervisor:
Bareflank реализует поддержку запуска C ++ в их гипервизоре. У них полная поддержка STL и CRT. Это комплексный проект, который позволяет множество функций стандарта в режиме ядра (включая исключения). Насколько я понимаю, их решение не заставляет NonPagedPool на глобальном new / delete распределении. Я должен поблагодарить Bareflank их реализацией, он хорошо продуман и кросс -платформ. Однако реализация Windows развивается через Cygwin и «прокладки» в поддержку ядра Windows. Для сравнения, этот проект направлен на то, чтобы быть внимательным к ядру Windows. Это позволяет определять теги и типы пула (по сравнению с страшными по сравнению с негибельными) и надеется минимизировать «острые края», связанные с использованием C ++ и STL в режиме ядра. Все, что сказано, Bareflank впечатляет для того, что есть. Для отличной презентации о поддержке Bareflank C ++ я настоятельно рекомендую посмотреть презентацию доктора Риана Куинна на CPPCON 2016.
Win32kernelstl:
Проект Win32kernelstl позволяет вам использовать функциональность STL непосредственно в ядре. Проект реализует глобальный new / delete и заставляет NonPagedPool , он реализует поддержку инициализации CRT и Bugchecks, когда исключение CPP брошено. Это не пытается сделать исключение CPP. Из -за предположений, которые это делает, я считаю его непрактичным для любых серьезных вариантов использования. Код достаточно ясен и документирован, я рекомендую дать этому проекту просмотр для обучения поддержки C ++ в ядре. В одном примечании, код CRT в Win32kernelstl действительно реализует atexit , но помните, что здесь нет синхронизации, излучаемой компилятором (в отличие от пользовательского режима). Таким образом, локальная статика, требующая введения записи в список atexit , может гонка, вызывая двойной или двойной.
Driver Plus Plus:
Этот проект реализует необходимый объект C ++ для втяжения ряда решений C ++ в режим ядра ( EASTL , msgpack и т. Д.). Driver Plus Plus реализует инициализацию CRT и глобальную new / поддержку delete (которая вызывает NonPagedPool ). Опять же, это противоречит целям этого проекта. Тем не менее, этот проект позволяет много отличного объекта C ++ для использования в режиме ядра. Он вносит модификации решений C ++, которые он притягивает, чтобы привести в поддержку его вариантов использования. Driver Plus также делает предположение вокруг atexit , как упоминалось ранее.
KTL - Dymok93
KTL (библиотека шаблонов Windows ядра от Dymok93) Повторяет хорошее количество современного C ++ и активно развивает большую поддержку для использования в ядре Windows. Он также имеет поддержку RAII во многих примитивах ядра, обеспечивает собственную поддержку ANSI_STRING и UNICODE_STRING , он предоставляет несколько полезных обертка для регистрации обратных вызовов ядра и более удобных функций вокруг ядра Windows. Он реализует Global new / delete и имеет определение препроцессора ( KTL_USING_NON_PAGED_NEW_AS_DEFAULT ) для переключения между страхом по умолчанию или без страхования, что является хорошим. Тем не менее, он использует один тег пула ( KTL_HEAP_TAG ). Кроме того, существующие шаблоны распределения не позволяют разработчику указать тег пула, поэтому использование этой библиотеки является причиной того, что все выделения будут помечены с одной и той же тегом пула. Тем не менее, было бы разумно реализовать пользовательский распределитель, который расширяет возможности помещения распределения. В библиотеке есть поддержка исключений, хотя и только x64. Поддержка исключения в KTL основана на Avakar's с улучшениями и исправлениями. Я рекомендую здесь работу, и я впечатлен количеством существующего объекта, оно разумно упаковано и находится в активной разработке. Я хотел бы изучить его больше в будущем и потенциально сотрудничать с лучшей поддержкой исключений как для stlkrn , так и KTL . Повторение функциональности STL, отсутствие поддержки нативного билера и глобальные распределители противоречат идеологиям этого проекта.
Ktl - meesong:
KTL (Библиотека шаблонов Windows ядра от Meesong) Повторно поднимает большое количество современных функций C ++ для использования в ядре Windows. Он также реализует Global new / delete но выполняет достойную работу по предоставлению объекта для указания бирж и типов пула, где это возможно. Однако это означает, что глобальный распределитель может скрыть ассигнование в неочевидном пуле. Кроме того, распределители шаблонов в этом проекте несут стоимость двух точек для объекта распределения и сделки, я также обеспокоен тем, что преобразование между типами распределения может разрешить перекрестные пулы/теги. В целом, я впечатлен количеством объекта, которое здесь реализовано. Повторная функциональность STL и глобальные распределители противоречат идеологиям этого проекта.
Мост ядра:
Ядра моста реализует отличный объект для разработки ядра Windows. Библиотека предоставляет обертки для регистрации для обратных вызовов Windows с использованием объектов C ++. Я хотел бы найти больше времени для использования и изучения этого решения. Он реализует поддержку CRT. Реализованная функция atexit не является динамической - она использует статический массив, если он заканчивается из слотов, он не работает. По умолчанию new / delete силы NonPagedPool . У него нет полной поддержки исключений, он будет Bugcheck, если исключение CPP будет добавлено - оно не будет разжигать объекты в стеке.
Этот репозиторий опирается на какую -то ранее существовавшую работу. Кредиты их авторам.