参考资料:

  1. 《Windows Internals》

  2. Fibers

  知识点:

  ● 当一个进程在系统上启动时,内核将创建一个进程对象来代表它,并执行各种内核相关的初始化任务。然而,这些任务不会真正执行应用,而只是进行上下文和环境的准备工作。应用程序不像驱动(内核模式),它执行在用户模式下。因此,大部分初始化工作实际上都是在内核外完成的,且该工作是由Image Loader(Ldr)执行的。

  ● Image Loader存在于用户模式下的系统DLL Ntdll.dll中,而不在内核库中。Ntdll.dll总是会被加载,因此,Loader段代码总是存在运行进程中,且作为新应用程序运行在用户模式下的第一部分代码(即Loader运行在实际中应用程序代码之前,且对用户和开发者是不可见的)。

  ● 另外,尽管Loader的初始化任务是隐藏的,然而,应用程序确实在其运行时会跟它的接口进行交互。具体来说Loader的主要任务如下:

  ① 初始化应用程序的用户模式状态,比如创建初始堆和建立本地线程存储(TLS)和本地纤程存储(FLS)slots。

  ② 解析应用程序的Import Address Table(IAT)以查找它所需的所有DLLs,然后再递归地解析每个DLL的IAT。然后,解析DLLs的导出表Export Table以确保每个函数都存在。

  ③ 在需要时,加载和卸载DLLs,并维护一个所有被加载模块的列表。

  ④ 顾及hotpatching

  ⑤ 处理清单文件。

  ⑥ 为各shim读取应用程序兼容性数据库,并在需要时加载shim引擎DLL。

  ⑦ 使能API集和API重定向的支持(MinWin重构的核心部分之一)。

  ⑧ 使能动态运行时兼容性减少(通过SwitchBranch机制)。

  ● 在进程被创建后,Loader调用一个特殊的本地API以继续执行(基于一个在栈上的上下文帧)。上下文帧由内核创建,包含了实际的应用程序进入点。因此,由于Loader并未用标准的调用或跳转到运行时应用程序,我们不会把Loader初始化函数看做是进程栈trace上的调用树的一部分。

  

04-30 04:45