.Net 程序在执行的时候要预先加载CLR ,Windows 如何知道并加载CLR?
新建控制台应用程序,编译好
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
用dumpbin 导出PE格式文件(包括PE 镜像文件)
分析导出的文件
OPTIONAL HEADER VALUES
......
27FE entry point (004027FE)
......
可以看到entry point的地址为0x004027FE,查看.text段,可以从RAM DATA 段发现一些信息
004027E0: 00 00 5F 43 6F 72 45 78 65 4D 61 69 6E 00 6D 73 .._CorExeMain.ms
004027F0: 63 6F 72 65 65 2E 64 6C 6C 00 00 00 00 00 FF 25 coree.dll.....?%
00402800: 00 20 40 00 . @.
最后一行实际上表示地址:0x40200 指向PE镜像文件的如下部分,可以看到它指向的是mscoree.dll (Micorsoft 对象运行时执行引擎,Micorsoft Object Runtime Execution Engine),此dll主要作用就是启动CLR。
Section contains the following imports:
mscoree.dll
402000 Import Address Table
403038 Import Name Table
0 time date stamp
0 Index of first forwarder reference
0 _CorExeMain
可以看出_CorExeMain (.NET 库对应的是_CorDllMain)是加载程序集时候第一个调用的函数。接着根据PE中元数据,找到正确版本CLR加载并初始化。CLR初始化好后,在PE镜像文件的头中就可以找到应用程序的入口点(Main),然后JIT 开始编译并执行入口点。
终结
- PE文件的头部包含了一个域叫做AddressOfEntryPoint,表示PE文件的入口点位置。在.Net 程序中这个点指向.text段的一小段存根代码。当编译器生产.Net程序的时候还会在PE文件中增加一个数据目录项(data directory)包含了CLR头的位置和大小。
- Windows 加载器查看Entry Point 地址,找到.text 段
- 根据地址上的指令 跳转到mscoree.dll 中的导入函数
- 执行mscoree.dll中的_CorExeMain,启动CLR,并将执行控制转移到程序入口。
应用程序域
为了节省构造和管理进程的开销,.Net 使用应用程序域这一概念。
可以用命令查看
0:004> .loadby sos clr
0:004> !dumpdomain
系统应用程序域
System Domain: 5ff6f308
LowFrequencyHeap: 5ff6f62c
HighFrequencyHeap: 5ff6f678
StubHeap: 5ff6f6c4
Stage: OPEN
Name: None
作用:
1. 创建共享应用程序域和默认应用程序域
2. 将mscorlib.dll加载到应用程序域中
3. 记录其他应该用程序域(如加载/卸载)
4. 记录字符串常量池
5. 初始化特定类型异常(如:内存耗尽异常,栈溢出异常以及执行引擎异常)
共享应用程序域
Shared Domain: 5ff6efb8
LowFrequencyHeap: 5ff6f62c
HighFrequencyHeap: 5ff6f678
StubHeap: 5ff6f6c4
Stage: OPEN
Name: None
Assembly: 012378d0 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
ClassLoader: 012239f8
Module Name
5bb01000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
作用
- 加载mscorlib.dll
- 加载基本类型(String , enum , Value , Array)
- 非用户代码加载到共享应用程序域
默认应用程序域
Domain 1: 0120bfe8
LowFrequencyHeap: 0120c454
HighFrequencyHeap: 0120c4a0
StubHeap: 0120c4ec
Stage: OPEN
SecurityDescriptor: 0120d278
Name: CRLLoad.exe
Assembly: 012378d0 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
ClassLoader: 012239f8
SecurityDescriptor: 01235bc0
Module Name
5bb01000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Assembly: 0123d238 [D:\My\CRLLoad\CRLLoad\bin\Debug\CRLLoad.exe]
ClassLoader: 012237f0
SecurityDescriptor: 0123d1b0
Module Name
00f13fbc D:\My\CRLLoad\CRLLoad\bin\Debug\CRLLoad.exe
作用
- 隔离自己的应用程序