CLR初始化及EXE加载的流程

When the compiler/linker creates an executable assembly, the following 6−byte x86 stub function is emitted into the PE file’s .text section:
JMP _CorExeMain
Because the _CorExeMain function is imported from Microsoft’s MSCorEE.dll dynamic−link library,MSCorEE.dll is referenced in the assembly file’s import (.idata) section. MSCorEE.dll stands for  Microsoft Component Object Runtime Execution Engine. When the managed EXE file is invoked,Windows treats it just like any normal (unmanaged) EXE file: the Windows loader loads the file and examines the .idata section to see that MSCorEE.dll should be loaded into the process’s address space. Then the loader obtains the address of the _CorExeMain function inside MSCorEE.dll and fixes up the stub function’s JMP instruction in the managed EXE file.
The process’s primary thread begins executing this x86 stub function, which immediately jumps to _CorExeMain in MSCorEE.dll. _CorExeMain initializes the CLR and then looks at the executable assembly’s CLR header to determine what managed entry point method should execute. The IL code for the method is then compiled into native CPU instructions, and the CLR jumps to the native code (using the process’s primary thread). At this point, the managed application’s code is running.
The situation is similar for a managed DLL. When building a managed DLL, the compiler/linker emits a similar 6−byte x86 stub function in the PE file’s .text section for a DLL assembly:
JMP _CorDllMain

The _CorDllMain function is also imported from the MSCorEE.dll, causing the DLL’s .idata section to reference MSCorEE.dll. When Windows loads the DLL, it will automatically load MSCorEE.dll (if it isn’t already loaded), obtain the address of the _CorDllMain function, and fix up the 6−byte x86 JMP stub in the managed DLL. The thread that called LoadLibrary to load the managed DLL now jumps to the x86 stub in the managed DLL assembly, which immediately jumps to the _CorDllMain function in MSCorEE.dll. _CorDllMain initializes the CLR (if it hasn’t already been initialized for the process) and then returns so that the application can continue executing as normal.

These 6−byte x86 stub functions are required to run managed assemblies on Windows 98,Windows 98 Standard Edition, Windows Me, Windows NT 4, and Windows 2000 because all these operating systems shipped long before the CLR became available. Note that the 6−byte stub function is specifically for x86 machines. This stub doesn’t work properly if the CLR is ported to run on other CPU architectures. Because Windows XP and the Windows .NET Server Family support both the x86 and the IA64 CPU architectures, Windows XP and the Windows .NET Server Family loader was modified to look specifically for managed assemblies.
On Windows XP and the Windows .NET Server Family, when a managed assembly is invoked (typically via CreateProcess or LoadLibrary), the OS loader detects that the file contains managed code by examining directory entry 14 in the PE file header. (See IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR in WinNT.h.) If this directory entry exists and is not 0, the loader ignores the file’s import (.idata) section and automatically loads MSCorEE.dll into the process’s address space. Once loaded, the OS loader makes the process’s thread jump directly to the correct function in MSCorEE.dll. The 6−byte x86 stub functions are ignored on machines running Windows XP and the Windows .NET Server Family.
One last note on managed PE files: they always use the 32 bit PE file format, not the 64−bit PE file format. On 64−bit Windows systems, the OS loader detects the managed 32−bit PE file and automatically knows to create a 64−bit address space.

图:

CLR初始化及EXE加载的流程_第1张图片

你可能感兴趣的:(CLR初始化及EXE加载的流程)