Как работает CorFlags.exe/32BIT +?
Я думаю, мой вопрос касается CLR Loader. Я хочу понять механику CorFlags.exe /32BIT+
.
Мы знаем, что при запуске сборки, собранной с флагом Any CPU, установленным в 64-разрядной Windows, он запускается как 64-разрядный процесс. Если вы запустите CorFlags /32BIT+
на этой сборке, он запустится как 32-разрядный процесс. Я думаю, что это увлекательная функция.
У меня так много вопросов об этом:
- Как это реализовано?
- Включен ли загрузчик ОС?
- Возможно ли создать собственное приложение (я думаю, неуправляемый), который загружает 32-битную или 64-битную CLR по желанию?
Есть ли статья, книга, блог и т.д., которые объясняют внутреннюю работу этой функции?
Ответы
Ответ 1
Это не хорошо документировано в любом месте, о котором я знаю, я могу указать только на соответствующую статью MSDN. Да, ваше предположение верно, загрузчик в Windows XP и выше осведомлены об управляемых исполняемых файлах. Он автоматически загружает платформу загрузчика .NET(c:\windows\system32\mscoree.dll), соответствующая точка входа _ CorValidateImage(). Раздел "Примечания" в связанной статье MSDN описывает механизм, который превращает 32-разрядный .exe файл в 64-разрядный процесс:
В Windows XP и более поздних версиях загрузчик операционной системы проверяет управляемые модули, изучая бит COM-дескриптора COM в заголовке формата общего объектного файла (COFF). Установленный бит указывает управляемый модуль. Если загрузчик обнаруживает управляемый модуль, он загружает MsCorEE.dll и вызывает _CorValidateImage, который выполняет следующие действия:
- Подтверждает, что изображение является допустимым управляемым модулем.
- Изменяет точку входа в изображении на точку входа в среде общего языка (CLR).
- Для 64-разрядных версий Windows изменяет изображение, которое находится в памяти, преобразуя его из формата PE32 в PE32 +.
- Возврат к загрузчику при загрузке изображений управляемого модуля.
Для исполняемых изображений загрузчик операционной системы затем вызывает _CorExeMain, независимо от точки входа, указанной в исполняемом файле. Для образов сборки DLL загрузчик вызывает _CorDllMain функция.
_CorExeMain или _CorDllMain выполняет следующие действия:
- Инициализирует CLR.
- Располагает управляемую точку входа из заголовка CLR сборки.
- Начинается выполнение.
Загрузчик вызывает функцию _CorImageUnloading в управляемом модуле изображения выгружаются. Однако эта функция не выполняет никаких действие; он просто возвращается.
Ответ 2
Чтобы добавить ответ Ганса, есть также код режима ядра 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
.
Я написал об этом с некоторыми подробностями.