加载初始化CRL原理

    CRL负责管理包含在程序集中的代码的执行。我们可以通过%windir%/system32目录下查找MSCorEE.dll文件来判断一个机器中是否安装了.NET框架。如果一个机器中存在该文件,则证明该机器上已经安装了.NET框架。

    1.托管EXE加载并初始化CLR的过程。当编译器/链接器创建一个可执行程序集时, x86 stub函数将被嵌入到PE文件的.text部分:JMP_CorExeMain。由于_CorExeMain函数是从MSCorEE.dll动态连接库中导入的,所以MSCorEE.dll将在程序集文件的导入(.idata)部分引用。MSCorEE.dll表示微软组件对象运行时执行引擎(Microsoft Component Object Runtime Execution Engine)。当托管EXE文件被调用时,Windows将像对待通常(非托管)的EXE文件一样对待它。Windows加载器先加载该文件,然后检查其.idata部分发现MSCorEE.dll需要被加载到进程的地址空间。于是加载器获取MSCorEE.dll中的_CorExeMain函数的地址,同时修正托管EXE文件中的sub函数的JMP指令。之后,进程的主线程开始执行修正后的x86 stub函数,该stub函数立即跳转到MSCorEE.dll中的_CorExeMain函数上。_CorExeMain函数接着初始化CLR,并查看可执行程序集的CLR表头以确定要执行的托管入口点方法。入口点方法找到以后,起IL代码随之被编译为本地CPU指令。最后,CLR跳转到编译后的本地指令上(使用进程的主线程)。直到这时,托管应用程序才算开始真正运行。如下图所示:

 

       2.托管DLL的情形类似。当生成托管DLL时,编译器/链接器将会为DLL程序集PE文件的.text部分产生一个类似的6字节的x86 stub函数:JMP_CorDllMain。_CorDllMain函数也是从MSCorEE.dll中导入的,因此托管DLL中的.idata部分也包含有对MSCorEE.dll的引用。当Windows加载托管DLL时,它将自动加载MSCorEE.dll(如果还没被加载),然后获取_CorDllMain函数的地址,并修正托管Dll中的x86 stub函数的JMP指令。之后,调用LoadLibrary加载托管DLL的线程将跳转到该托管DLL的x86 stub函数上,该stub函数接着又立即跳转到MSCorEE.dll中的_CorDllMain函数上。_CorDllMain初始化CLR(如果还没被初始化)后便立即返回,应用程序也返回到正常状态并继续运行。(这里特指非托管代码加载托管DLL。如果是托管代码调用托管DLL的话,它通常首先检测DLL中的元数据,然后便以即时编译的方式执行其内方法的IL代码,stub函数及其跳转过程将被忽略)

      值得注意的是,托管PE总是使用32位(而非64位)的PE文件格式。在64位的Windows系统上,操作系统加载器检测到32位的托管PE文件后会自动创建64位的地址空间。

 

参考:《Microsoft .NEt框架程序设计》

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值