我想我的问题是关于CLR Loader。我想了解CorFlags.exe /32BIT+
功能背后的机制。
我们知道当一个人启动使用64位Windows上设置的 Any CPU 标志编译的程序集时,它将以64位进程启动。如果在该程序集上运行CorFlags /32BIT+
,它将以32位进程启动。我认为这是一个引人入胜的特征。
我有很多问题:
是否有文章,书籍,博客等解释了此功能的内部工作原理?
答案 0 :(得分:6)
在我所知的任何地方都没有详细记录,我只能向您指出相关的MSDN文章。是的,您的假设是正确的,Windows XP及更高版本中的加载程序具有托管可执行文件的意识。它自动加载.NET加载程序填充程序(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函数 图像被卸载。但是,此功能不执行任何操作 行动;它只是回归。
答案 1 :(得分: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
标志ComPlusILOnly
和ComPlusNativeReady
与.NET相关,ComPlusILOnly
只是告诉程序集是否仅CIL(不是混合或本机 - 在这种情况下是程序集已经是特定于体系结构的),并且ComPlusNativeReady
仅在未设置/ 32BIT +(32BITREQ or 32BITPREF in newer CorFlags version)时为1。这些标记会在nt!PspAllocateProcess
期间进行检查,并根据这些标记创建32-bit
或64-bit
进程。
I wrote about it有一些细节。