Как работает CorFlags.exe /32BIT+?
Я думаю, мой вопрос о загрузчике CLR. Я хочу понять механику CorFlags.exe /32BIT+
функциональность.
Мы знаем, что когда запускается сборка, скомпилированная с флагом Any CPU, установленным в 64-битной Windows, она запускается как 64-битный процесс. Если один прогон CorFlags /32BIT+
на этой сборке он запустится как 32-битный процесс. Я думаю, что это захватывающая особенность.
У меня так много вопросов по этому поводу:
- Как это реализовано?
- Включается ли загрузчик ОС?
- Можно ли создать собственное приложение (я думаю, неуправляемое), которое по желанию загружает 32-битную или 64-битную CLR?
Есть ли статья, книга, блог и т. Д., Которые объясняют внутреннюю работу этой функции?
2 ответа
Это не очень хорошо задокументировано в любом месте, о котором я знаю, я могу лишь указать вам на соответствующую статью MSDN. Да, ваше предположение верно, загрузчик в Windows XP и выше осведомлен об управляемых исполняемых файлах. Он автоматически загружает подкладку загрузчика.NET (c:\windows\system32\mscoree.dll), соответствующей точкой входа является _CorValidateImage (). Раздел "Примечания" в связанной статье MSDN описывает механизм, который превращает 32-разрядный файл.exe в 64-разрядный процесс:
В Windows XP и более поздних версиях загрузчик операционной системы проверяет наличие управляемых модулей, проверяя бит каталога дескрипторов COM в заголовке формата общего объектного файла (COFF). Установленный бит указывает на управляемый модуль. Если загрузчик обнаруживает управляемый модуль, он загружает MsCorEE.dll и вызывает _CorValidateImage, который выполняет следующие действия:
- Подтверждает, что образ является допустимым управляемым модулем.
- Изменяет точку входа в изображении на точку входа в общеязыковой среде выполнения (CLR).
- Для 64-разрядных версий Windows изменяет образ в памяти, преобразовывая его из формата PE32 в PE32+.
- Возвращает к загрузчику, когда загружены образы управляемого модуля.
Для исполняемых образов загрузчик операционной системы затем вызывает функцию _CorExeMain независимо от точки входа, указанной в исполняемом файле. Для образов сборки DLL загрузчик вызывает функцию _CorDllMain.
_CorExeMain или _CorDllMain выполняет следующие действия:
- Инициализирует CLR.
- Находит управляемую точку входа из заголовка CLR сборки.
- Начинается казнь.
Загрузчик вызывает функцию _CorImageUnloading, когда образы управляемого модуля выгружаются. Однако эта функция не выполняет никаких действий; это просто возвращается.
Чтобы добавить ответ Ханса, есть также код режима ядра Windows, который отвечает на этот флаг. Каждый загруженный исполняемый файл имеет структуру ядра, SECTION_IMAGE_INFORMATION
, связанный с этим. Вот информация о его символах:
0: kd> dt nt!_SECTION_IMAGE_INFORMATION
+0x000 TransferAddress : Ptr64 Void
+0x008 ZeroBits : Uint4B
+0x010 MaximumStackSize : Uint8B
+0x018 CommittedStackSize : Uint8B
+0x020 SubSystemType : Uint4B
+0x024 SubSystemMinorVersion : Uint2B
+0x026 SubSystemMajorVersion : Uint2B
+0x024 SubSystemVersion : Uint4B
+0x028 GpValue : Uint4B
+0x02c ImageCharacteristics : Uint2B
+0x02e DllCharacteristics : Uint2B
+0x030 Machine : Uint2B
+0x032 ImageContainsCode : UChar
+0x033 ImageFlags : UChar
+0x033 ComPlusNativeReady : Pos 0, 1 Bit
+0x033 ComPlusILOnly : Pos 1, 1 Bit
+0x033 ImageDynamicallyRelocated : Pos 2, 1 Bit
+0x033 ImageMappedFlat : Pos 3, 1 Bit
+0x033 BaseBelow4gb : Pos 4, 1 Bit
+0x033 Reserved : Pos 5, 3 Bits
Флаги ComPlusILOnly
а также ComPlusNativeReady
связаны с.NET, ComPlusILOnly
просто сообщает, является ли сборка только CIL (не смешанной или нативной - в этом случае сборка уже зависит от архитектуры), и ComPlusNativeReady
равен 1, только если /32BIT+ не установлен ( 32BITREQ или 32BITPREF в более новой версии CorFlags). Эти флаги проверяются во время nt!PspAllocateProcess
и на их основе 32-bit
или же 64-bit
процесс создан.
Я написал об этом с некоторыми подробностями.