Как работает 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.

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