Как работает CorFlags.exe / 32BIT +?

Думаю, мой вопрос касается загрузчика CLR . Я хочу понять механику функций CorFlags.exe /32BIT+ .

Мы знаем, что при запуске сборки, собранной с флагом Any CPU, установленным в 64-разрядной Windows, он запускается как 64-битный процесс. Если вы запустите CorFlags /32BIT+ на этой сборке, он запустится как 32-разрядный процесс. Я думаю, что это увлекательная особенность.

У меня так много вопросов об этом:

  1. Как это реализовано?
  2. Включен ли загрузчик ОС?
  3. Возможно ли создать собственное приложение (я думаю, неуправляемый), который загружает 32-битную или 64-битную CLR по желанию?

Есть ли статья, книга, блог и т. Д., Которые объясняют внутреннюю работу этой функции?

Это не очень хорошо документировано в любом месте, о котором я знаю, я могу указать только на соответствующую статью MSDN. Да, ваше предположение верно, загрузчик в Windows XP и выше осведомлены об управляемых исполняемых файлах. Он автоматически загружает платформу загрузчика .NET (c: \ windows \ system32 \ mscoree.dll), соответствующей точкой входа является _CorValidateImage () . Раздел Замечания в связанной статье MSDN описывает механизм, который превращает 32-разрядный .exe-файл в 64-разрядный процесс:

В Windows XP и более поздних версиях загрузчик операционной системы проверяет управляемые модули, изучая бит COM Descriptor Directory в заголовке формата общего объектного файла (COFF). Установленный бит указывает управляемый модуль. Если загрузчик обнаруживает управляемый модуль, он загружает MsCorEE.dll и вызывает _CorValidateImage, который выполняет следующие действия:

  • Подтверждает, что изображение является допустимым управляемым модулем.
  • Изменяет точку входа в изображении на точку входа в среде выполнения общего языка (CLR).
  • Для 64-разрядных версий Windows изменяет изображение, которое находится в памяти, преобразуя его из PE32 в формат PE32 +.
  • Возвращается к загрузчику при загрузке изображений управляемого модуля.

Для исполняемых изображений загрузчик операционной системы затем вызывает функцию _CorExeMain, независимо от точки входа, указанной в исполняемом файле. Для образов сборки DLL загрузчик вызывает функцию _CorDllMain.

_CorExeMain или _CorDllMain выполняет следующие действия:

  • Инициализирует CLR.
  • Располагает управляемую точку входа из заголовка CLR сборки.
  • Начинает выполнение.

Загрузчик вызывает функцию _CorImageUnloading, когда изображения управляемых модhive выгружаются. Однако эта функция не выполняет никаких действий; он просто возвращается.

Чтобы добавить ответ Ганса, есть также код режима ядра 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 просто сообщает, является ли assembly только CIL (не смешанная или родная), и в этом случае assembly уже является специфичной для архитектуры), а ComPlusNativeReady – 1, только если / 32BIT + не установлен ( 32BITREQ или 32BITPREF в новой версии CorFlags ). Эти флаги проверяются во время nt!PspAllocateProcess и на их основе создается 32-bit или 64-bit процесс.

Я писал об этом с некоторыми подробностями.

Давайте будем гением компьютера.