理论
要加载动态链接库操作系统必须完成以下各步:
- 在磁盘上定位动态链接库可执行文件。
- 仔细查看已经加载进应用程序地址空间中的动态链接库列表,判断动态链接库是否已经加载了。
- 为动态链接库分配驻留内存,并将动态链接库二进制文件映射到内存中(在Windows NT中,映射跨越了段对象)。
- 为使动态链接库正常运行,执行一系列必要的处理(例如,解析动态链接库中做过的修正,等等)。
不同的参数决定了动态链接库的加载时间不同。以下给出了需要考虑的各种因素,事实上可能还有一些因素也会影响到动态链接库的加载时间:
- 底层软硬件:计算机本身的速度以及运行哪一种操作系统。
- 当前系统和应用程序的状态:在虚拟内存中系统的紧密情况,以及动态链接库是否可以被加载在首选基地址。
- 动态链接库本身:动态链接库本身有多大,动态链接库中有多少位置需要修正(结合两者综合考虑),此动态链接库是否隐式链接到另一个同样需要加载的动态链接库中。
由上述分析可知,对某一动态链接库进行基址重置绝不是影响动态链接库加载时间的唯一决定因素。在本文中,作者使用了很多数据,说明了动态链接库加载时间的变化范围以及应用程序可能对加载时间的影响程度。
读者应该注意到,对某一动态链接库进行基址重置,不仅可能造成加载时间的大幅度增加,还需要增加页文件(pagefile)的开销。加载动态链接库的第一步,需要创建区段对象(section object),区段对象是由动态链接库可执行文件支持的、内存中的一个相邻的区段。一旦动态链接库的某一页被从应用程序工作集中移去了,在下一次访问此页时,操作系统就会从动态链接库可执行文件中重新加载这一页。
当然,当动态链接库进行基址重置时,这一策略不再起作用,这主要是因为包含重定位地址的页与动态链接库可执行文件映射中的相应页不同。因此,一旦在加载可执行文件时,操作系统企图修正地址,就会拷贝相应的页(由于区段是通过COPY_ON_WRITE标志打开的)。在拷贝中进行的所有的修改,操作系统都会记住,从现在开始,页将在系统页文件中换入换出,而不再在可执行映象中进行页交换。
采用这种机制,潜在的性能命中有两种:首先,每个包含需要重定位地址的页都占用一页系统页文件(其结果是,减少了所有应用程序可用的虚拟内存数);另外,由于操作系统执行动态链接库页中的第一次修正操作,新的页必须从页文件中分配,并将整个页拷贝下来。
尽管扫描动态链接库重定位区段以及进行内存修正的算法都有很高的效率,执行修正操作还是会增加动态链接库的加载时间。(跨段操作的复杂性是需要修复地址数量的线性函数。)
地址修正
关于动态链接库基址重置的一类经常问到的问题是,“地址修正究竟是什么含义?程序员是否有办法调整代码,以减少可执行程序中的地址修正?”对于这两个问题的回答是,这一切在很大程度上依赖于可执行程序建立在哪一种平台上。在本文中,我们将平台限制在Intel 386,、486、和奔腾(Pentium)处理器上,讨论相应的可执行程序。(注意:为其他平台建立的可执行程序,相应的地址修复概念与本文讨论的概念不同。)
在386、486、或奔腾处理器上,两种情况可能导致某地址被标识为“可重定位”的状态:一是静态对象(static objects),另一种情况是绝对跳转(absolute jumps)。
首先,如果动态链接库引用了静态对象,就会使用对象的绝对地址(假设动态链接库被加载到首选地址中)。例如,在如下的代码段中:
LPSTR lpName="Name";
动态链接库的载入程序就会将“Name”字串分配到动态链接库数据段中,并将此字串的起始地址填写到lpName变量对应的位置中去。如果由于DLL不能被加载到基地址而使得“Name”字串必须重定位,lpName必须相应地进行调整。注意,在这种情况下,代码段中每个引用lpName的变量也必须作相应的地址修正。
可以重定位的对象包括文字字串(例如,在上例中的“Name”字串)、任何一种类型的全局或静态数据、包含静态分配的C++对象。应该注意到,特别是在C++中,可能存在着许多从一个静态对象到另一个静态对象的交叉索引。未初始化的数据不需要在重定位过程中修正地址,但指向未初始化静态数据的索引需要进行地址修正。
在i386可执行代码中,另一类可以进行重定位的项是绝对跳转和函数调用,包括系统函数调用。注意到程序开发人员很难通过修改程序代码来避免地址重定位,唯一可以采用的办法就是缩减静态分配数据的数目。要缩减静态分配数据,一种办法就是尽量避免使用名字进行资源索引,而应该通过坐标进行资源索引(因为,程序员在代码中显式使用的每一个名字都会自动变成一个可重定位的项)。
尽管如此,作者并不建议程序开发人员带着减少加载时间这一特殊目的开发动态链接库代码,除非存在以下两种情况:(1)静态分配对象的数据可以大幅度减少;(2)程序员依据此种方式进行编程时,不会影响其他编程中需要考虑到的因素。
除此之外,程序开发人员还可以通过简单的优化方法,减少加载时间。例如,可以将所有可以重新定位的数据集中到几页中。很显然,如果动态链接库需要进行基址重置,每页含有一个重定位项的两页,都需要有页文件来支持。如果所有的重定位项都出现在同一页中,只有一页需要页文件来支持,因此只有一页会受到影响。在必要的情况下,读者可以使用pragma (data_seg,数据段)伪指令,确保尽可能多的可重定位项被分配到尽可能少的页中去。
分享到:
相关推荐
本资料主要探讨如何用VC++来创建和使用DLL,特别是Win32动态连接库基址重置技术。 1. DLL基础 - DLL的本质:DLL是一类可执行文件,包含可供其他程序调用的函数和数据。它们不直接运行,而是由加载它的应用程序调用...
在易语言中,"模块基址获取"是一个重要的概念,尤其在涉及到动态链接库(DLL)或者程序模块的操作时,了解和掌握模块基址获取的方法是至关重要的。 模块基址,简单来说,就是程序或DLL在内存中的起始地址。在...
动态地址的处理-找基址动态地址的处理-找基址动态地址的处理-找基址动态地址的处理-找基址动态地址的处理-找基址
在易语言中,“取模块基址”是一个重要的概念,用于获取一个模块(如动态链接库DLL或可执行文件EXE)在内存中的起始地址,这个地址对于进行底层操作、动态链接、系统调用等高级功能至关重要。 首先,我们来详细解析...
在计算机程序中,模块基址是指一个可执行文件或动态链接库(DLL)在内存中的起始地址。在易语言中,理解并掌握模块基址的获取是进行底层编程、系统级交互以及动态链接库操作的关键技能。 易语言提供了一些内建的...
PE(Portable Executable)文件格式是Windows操作系统中用于存储可执行文件、动态链接库(DLLs)和对象文件的标准格式。它提供了操作系统加载程序所需的所有信息,包括但不限于入口点、段位置、资源数据、以及调试...
kernel32.dll是Windows系统的核心动态链接库,提供了许多与用户界面、进程和线程管理、内存管理等相关的API函数。在不同版本的Windows系统中,kernel32.dll的加载顺序和位置可能有所不同,因此,程序员需要一种通用...
例如,Win32应用程序采用了消息循环机制和动态链接技术,这些特性使得Win32汇编语言编程具有一定的特殊性。 - **内存管理**:Win32应用程序运行在80386(IA-32)保护模式下,采用平坦内存模型,即所有段寄存器的基址...
2. **进程注入**:为了操作其他进程的内存,基址获取器可能需要将自己的代码注入到目标进程中,这通常通过创建动态链接库(DLL)并使用`CreateRemoteThread`函数实现。在压缩包中的`ZFjzhuoqu32.dll`可能是这样的DLL...
在Windows 32位系统(Win32)环境下,汇编语言被广泛用于底层编程,如系统调用、驱动程序开发以及对性能要求极高的应用。 **Win32 API** Win32 API(应用程序接口)是微软为Windows操作系统提供的编程接口,允许...
在大多数情况下,程序的内存布局并非固定不变,尤其是对于动态链接库(DLL)和多线程应用,它们的地址可能会在每次运行时发生变化。因此,找到一个稳定且可预测的基址是至关重要的,这被称为“完美基址”。 首先,...
- 动态基址:在程序运行时由操作系统动态分配,通常用于动态链接库(DLL)或位置无关代码(PIC),以支持多任务和内存保护。 3. **内存调试与查找工具**: - OllyDbg:一款著名的Windows平台下的反汇编器和调试器...
描述中的"读取EXE+偏移类基址"和"读取DLL+偏移类基址"进一步细化了这个主题,意味着我们要讨论如何获取可执行文件(EXE)和动态链接库(DLL)的基地址,并结合内部偏移量来访问特定内存位置。 首先,我们需要了解...
在易语言中,“取模块基址”是获取程序模块(如动态链接库DLL或可执行文件EXE)在内存中的起始地址的操作,这对于理解和调试程序,或者进行系统级编程是非常重要的。下面我们将深入探讨易语言源码中如何实现取模块...
查找游戏基址是一项技术性很强的工作,需要耐心与细心,以及对游戏内部结构的深刻理解。掌握了这些方法,不仅能够提升游戏体验,还能在一定程度上促进游戏的公平性和安全性。然而,使用这些知识时,应当遵守法律法规...
标题“DNF查找基址”涉及的是编程领域中的动态地址查找技术,特别是在逆向工程和游戏修改中常用的一种技巧。DNF(Dynamic Name Function)通常指的是动态查找函数地址的方法,因为在某些程序中,函数地址可能会因为...
5. **WinAPI或DLL注入**:为了访问游戏进程的内存,可能需要使用Windows API函数(如CreateProcess、VirtualProtect等)或动态链接库(DLL)注入技术。 6. **编程语言基础**:此源码可能使用C++或其他编程语言编写...
《汇编语言的集合:8086与Win32》 汇编语言,作为计算机科学的基础,是直接对应机器指令的编程语言。它是一种低级语言,但因其与硬件的紧密关系,对于理解计算机系统的工作原理至关重要。本文将深入探讨8086汇编...
总的来说,这个压缩包提供的工具集可能包括了动态链接库(rw.dll)以实现内存操作,一个钩子工具(Hook内存读写.exe)来监控内存变化,以及一个反汇编文件(krnln.fnr)帮助理解程序逻辑。这些工具结合使用,可以...
### Win32汇编寄存器的详细说明 在探讨Win32环境下汇编语言中的寄存器使用之前,我们先来明确一下本文档的主要内容:文档主要关注于Win32汇编语言环境中寄存器的使用细节,尤其是针对不同特权级别(Ring)下寄存器...