13

我想我的问题是关于CLR Loader 的。我想了解CorFlags.exe /32BIT+功能背后的机制。

我们知道,当启动在 64 位 Windows 上设置了Any CPU标志的程序集时,它会作为 64 位进程启动。如果CorFlags /32BIT+在该程序集上运行,它将作为 32 位进程启动。我认为这是一个令人着迷的功能。

我有很多关于它的问题:

  1. 它是如何实施的?
  2. OS Loader 是否参与其中?
  3. 是否可以构建一个自定义应用程序(我猜是非托管应用程序),它可以随意加载 32 位或 64 位 CLR?

是否有文章、书籍、博客等解释了此功能的内部工作原理?

4

2 回答 2

7

这在我所知道的任何地方都没有很好的记录,我只能将您指向相关的 MSDN 文章。是的,您的假设是正确的,Windows XP 及更高版本中的加载程序具有托管可执行文件的意识。它会自动加载 .NET 加载程序 shim (c:\windows\system32\mscoree.dll),相关入口点是_CorValidateImage()。链接的 MSDN 文章中的备注部分描述了将 32 位 .exe 文件转换为 64 位进程的机制:

在 Windows XP 和更高版本中,操作系统加载程序通过检查通用对象文件格式 (COFF) 标头中的 COM 描述符目录位来检查托管模块。设置位指示受管模块。如果加载器检测到托管模块,它会加载 MsCorEE.dll 并调用 _CorValidateImage,后者执行以下操作:

  • 确认映像是有效的托管模块。
  • 将映像中的入口点更改为公共语言运行时 (CLR) 中的入口点。
  • 对于 64 位版本的 Windows,通过将内存中的图像从 PE32 转换为 PE32+ 格式来修改它。
  • 加载托管模块映像时返回到加载程序。

对于可执行映像,操作系统加载程序然后调用 _CorExeMain 函数,而不管可执行文件中指定的入口点。对于 DLL 程序集映像,加载程序调用 _CorDllMain 函数。

_CorExeMain 或 _CorDllMain 执行以下操作:

  • 初始化 CLR。
  • 从程序集的 CLR 标头中找到托管入口点。
  • 开始执行。

卸载托管模块映像时,加载程序调用 _CorImageUnloading 函数。但是,此函数不执行任何操作;它只是返回。

于 2012-05-01T01:09:24.653 回答
2

为了补充 Hans 的答案,还有一些响应该标志的 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

标志ComPlusILOnlyComPlusNativeReady与 .NET 相关,ComPlusILOnly只是告诉程序集是否仅为CIL(不是混合或本机 - 在这种情况下,程序集已经是特定于体系结构的),并且ComPlusNativeReady仅在未设置 /32BIT+ 时为 1(32BITREQ 或 32BITPREF 在较新CorFlags 版本)。在创建过程中nt!PspAllocateProcess并基于它们检查这些标志。32-bit64-bit

我写了一些细节。

于 2015-04-18T19:10:23.463 回答