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

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

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

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

  1. Как это реализовано?
  2. Включается ли загрузчик ОС?
  3. Можно ли создать собственное приложение (я думаю, неуправляемое), которое по желанию загружает 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 процесс создан.

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

Другие вопросы по тегам