《程序员的自我修养》Windows下的动态链接

内容总结:

在这里插入图片描述
导出表
当一个PE需要将一些函数或变量提供给其他PE文件使用时,我们把这种行为叫做符号导出(Symbol Exporting),最典型的情况就是一个DLL将符号导出给EXE文件使用。在 Windows PE中,所有导出的符号被集中存放在了被称作导出表(Export Table)的结构中。事实上导出表从最简单的结构上来看,它提供了一个符号名与符号地址的映射关系,即可以通过某个符号查找相应的地址基本上这些每个符号都是个ASCII字符串,我们知道符号名可能跟相应的函数名或者变量名相同,也可能不同,因为有符号修饰这个机制存在。

EXP文件
在创建DLL的同时也会得到一个EXP文件,这个文件实际上是链接器在创建DLL时的临时文件。链接器在创建DLL时与静态链接时一样采用两遍扫描过程,DLL一般都有导出符号,链接器在第一遍时会遍历所有的目标文件并且收集所有导出符号信息并且创建DLL的导出表。为了方便起见,链接器把这个导出表放到一个临时的目标文件叫做“edata的段中,这个目标文件就是EXP文件,EXP文件实际上是一个标准的PE/COFF目标文件,只不过它的扩展名不是obj而是exp。

导出重定向
DLL有一个很有意思的机制叫做导出重定向(Export Forwarding)顾名思义就是将某个导出符号重定向到另外一个DLL。比如在 Windows XP系统中, KERNEL332DLL中的 HeapAlloc函数被重新定向到了 NTDLLDLL中的 RtlAllocHeap函数,调用 HeapAlloc函数相当于调用 RtlAllocHeap函数。导出重定向的实现机制也很简单,正常情况下,导出表的地址数组中包含的是函数的RVA,但是如果这个RVA指向的位置位于导出表中,那么表示这个符号被重定向了,被重定向了的符号的RVA并不代表该函数的地址,而是指向一个ASCI的字符串,这个字符串在导出表中,它是符号重定向后的DLL文件名和符号名。

序号
一个DLL中每一个导出的函数都有一个对应的序号(Ordinal Number)一个导出函数甚至可以没有函数名,但它必须有一个唯一的序号另一方面,当我们从一个DLL导入一个函数时,可以使用函数名,也可以使用序号。序号表示被导出函数地址在DLL导出表中的位置。一般来说,那些仅供内部使用的导出函数,它只有序号没有函数名,这样外部使用者就无法推测它的含义和使用方法,以防止误用。对于大多数 Windows API函数来说,它们的函数名在各个 Windows版本之间是保持不变的但是它们的序号是在不停地变化的。所以,如果我们导入 Windows API的话,绝对不能使用序号作为导入方法。在产生一个DLL文件时,我们可以在链接器的def文件中定义导出函数的序号

三种可能的原因导致了 DLL Hell的发生:
1. 由使用旧版本的DLL替代原来一个新版本的DLL而引起。这个原因最普遍,是Windows9x用户通常遇到的问题DLL错误之一
2. 由新版DLL中的函数无意发生改变而引起。尽管在设计DLL时候应该“向下”兼容,然而要保证DLL完全“向下”兼容却是不可能的。
3. 由新版DLL的安装引入一个新Bug.这个原因发生的概率最小,但是它仍然会发生。
解决 DLL Hell的方法
1. 静态链接(Static linking):它会丧失使用动态链接带来的好处
2. 防止DLL覆盖(DLL Stomping)
3. 避免DLL冲突(Conflicting DLLs)

《程序员的自我修养》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值