原创 C++应用程序在Windows下的编译、链接(四)动态链接
4动态链接
4.1概述
在静态链接阶段,链接器为PE文件生成了导入表,导出表,符号表,并调整了Call指令后面的操作数,在程序调用的时候,能够直接地或者间接地定位到IAT中的某个位置,在PE文件中,该位置包含符号的名称,当PE文件加载到内存以后,该位置应该修正为符号的地址。这些已有的信息和已经完成的工作是后续动态链接的基础。
动态链接的任务是:在程序的加载或者运行阶段,执行各个模块的基址重定位工作,并将IAT中的符号名称修正为动态链接库中被调用的符号的地址。
动态链接分为隐式动态链接和显式动态链接,无论是隐式动态链接还是显式动态链接,都会涉及到对WindowsAPI函数:LoadLibrary(),GetProcAddress(),FreeLibrary()的调用。它们之间的区别是:在执行隐式动态链接的时候,由Windows加载器负责完成对这些Windows API的调用;而在显式动态链接的时候,这些Windows API函数必须由程序员编写代码主动地调用。
隐式动态链接在程序加载到内存的时候完成,而显式动态链接则将这一过程推迟到程序运行的过程中。
动态链接的流程如下图所示:
由上图可以看出,动态链接的两个主要任务:动态链接库加载完毕以后的基址重定位,以及对导入表中函数名称的修正,即:将函数名称转换成函数的地址。
4.2程序加载及基址重定位
PE文件具有段结构,包含的主要的段有:代码段,数据段,导入表,导出表,符号表,基址重定位表等。当PE文件存储在文件中或者被加载到内存中的时候,这些段都需要遵循某个对齐规则。
PE中规定了三类对齐:数据在内存中的对齐,数据在文件中的对齐,资源数据在资源文件中的对齐。
数据在内存中的对齐。在内存中,PE文件以内存页的大小作为对齐粒度。在Windows操作系统中,内存以分页的方式进行管理。在32位Windows下,内存页的大小是4KB;在64位Windows下,内存页的大小是8KB。当PE文件被加载到内存以后,各段的起始地址必须是内存页大小的整数倍。
数据在文件中的对齐。在文件中,PE文件以一个扇区的大小作为对齐粒度。一个扇区的大小为512字节,十六进制表示为200h。在文件存储中,各段的地址偏移必须是200h的整数倍。
资源数据在资源文件中的对齐。在资源文件中,资源字节码以4字节作为对齐粒度。
由于在内存中PE文件以4KB作为对齐粒度,而在文件中以512字节作为对齐粒度,因此当PE文件被加载到内存以后,PE文件的尺寸要大于该文件在硬盘上的尺寸。在执行加载的时候,操作系统会读取PE文件的头信息,去除不需要加载到内存的部分,如:调试信息等,然后操作系统将整个PE文件映射到内存空间中。在将PE文件加载到内存以后,PE文件的结构和布局不会被改变。因此,PE文件在硬盘上的数据结构与在内存中的数据结构是相同的。具体的对比情况如下图所示:
当PE文件被windows加载器加载到内存以后,在内存中的版本被称为模块,每一个模块的起始内存地址被称为HMODULE。通过这个HMODULE可以获得该模块的数据内容。
当可执行程序被加载到内存以后,Windows会查询PE文件中的相关信息,获得该可执行程序所依赖的动态链接库,然后Windows将这些动态链接库也加载到内存中。如果某个要被加载地动态链接库已经位于内存中,那么操作系统就增加这个动态链接库的引用计数。当可执行程序和它所依赖的动态链接库都被加载到内存以后,Windows加载器开始执行基址重定位工作。Windows加载器加载可执行程序以及动态链接库的流程如下图所示:
当可执行文件以及它所依赖的动态链接库文件被加载到内存以后,如果该文件被加载的内存位置不是基于默认内存地址的位置(可执行程序是0x00400000h,动态链接库是0x10000000),那么windows加载器就必须执行基址重定位工作。该工作是在基址重定位表的支持下完成的。对于每一个需要进行重定位的内存地址,加载器都会给它加上一个差值作为修正。该差值为模块当前加载到内存的地址 – 模块默认加载位置的地址。具体的操作流程如下图所示:
当完成基址重定位工作以后,导出地址表(EAT)中的地址也被修正完毕。在PE文件中,这些地址是基于默认加载位置的地址,如果当前加载位置发生了变化,那么这些地址是要被修正的。参见2.4.7节。
4.3符号解析
符号解析是动态链接中最重要的一环,在该阶段,加载器读取PE文件中的导入地址表(IAT)的信息,取得每一个函数的名称,然后用该函数的名称去相关动态链接库中查询函数的地址,用获得的地址替换该函数名称。这一步工作是将函数名称替换为函数地址的过程。具体过程如下图所示:
由于一个可执行程序可能会依赖多个动态链接库,那么在导入表数组中就会包含多个数组元素,所以在符号解析的时候是一个循环处理。加载器对导入表数组执行循环,取得每一个数组元素,然后根据获得的Dll名称查找到相关的动态链接库的位置。获得了相关动态链接库的信息以后,加载器从导入地址表中取得一个符号的名称,以该符号名称为条件去对应的动态链接库中查询。经过对符号名称表,名称序号对应表,以及符号地址表的查询,最后获得符号的地址,将此地址写回到导入地址表原来符号名称的位置。
嗯,那个恭喜你,看完了。为了写这个东西,也把我累的够呛,哈哈。
原创 C++应用程序在Windows下的编译、链接(四)动态链接的更多相关文章
- 原创 C++应用程序在Windows下的编译、链接:第一部分 概述
本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 cl.exe是windows平台下的编译器,link.ex ...
- 原创 C++应用程序在Windows下的编译、链接:第三部分 静态链接(二)
3.5.2动态链接库的创建 3.5.2.1动态链接库的创建流程 动态链接库的创建流程如下图所示: 在系统设计阶段,主要的设计内容包括:类结构的设计以及功能类之间的关系,动态链接库的接口.在动态链接库中 ...
- 原创 C++应用程序在Windows下的编译、链接:第二部分COFF/PE文件结构
2.1概述 在windows操作系统下,可执行文件的存储格式是PE格式:在Linux操作系统下,可执行文件的存储格式的WLF格式.它们都是COFF格式文件的变种,都是从COFF格式的文件演化而来的. ...
- C++应用程序在Windows下的编译、链接(一)概述
C++应用程序在Windows下的编译.链接(一)概述 本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 c ...
- QT程序在windows下部署发布
转载:http://www.cnblogs.com/Fan_Fan/archive/2010/05/29/1746860.html QT程序在windows下部署发布 以下包括了部分网上收集的,以及q ...
- 解析 Qt 程序在Windows 下发布
原文请看:http://www.cnblogs.com/elect-fans/archive/2012/03/15/2408579.html Qt 程序在Windows下发布是本文要介绍的内容,不多说 ...
- 【FFmpeg】Windows下FFmpeg编译
由于FFmpeg是基于Linux开发的开源项目,源代码和Windows下最常见的Visual Studio提供的C/C++编译器不兼容,因此它不能使用MSVC++编译,需要在Windows下配置一个类 ...
- boost库在windows下的编译和使用
因为跨平台的原因,现在要使用到boost库,boost库非常大,现在处于摸索阶段. 首先来说boost库在window下的安装和使用. 一.下载 首先从boost官方主页http://www.boos ...
- ACE在windows下的编译及配置(VS2010)
ACE在windows下的编译及配置(VS2010) 分类: -[小西南]- 2013-08-06 16:17 2354人阅读 评论( ...
随机推荐
- ASP.NET MVC Model验证(二)
ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...
- xamarin MasterDetailPage点击Master时卡顿现象
在很多项目中经常会使用到MasterDetailPage的布局方式,而且一般做为主页面来开发,在开发中,发现一个并不算Bug的问题,但是却发生了,以此记录下来,方便大家探讨. 现象是这样的,我开发了一 ...
- iOS 开发不可缺少的工具
1.截屏利器:Snip 强大的滚动截屏功能,你值得拥有! Snip.png 传送门:http://www.snip.qq.com/ 2.Mac上最好的终端模拟器:iTerm2 iTeam.png 传送 ...
- 牛顿法求平方根 scala
你任说1个整数x,我任猜它的平方根为y,如果不对或精度不够准确,那我令y = (y+x/y)/2.如此循环反复下去,y就会无限逼近x的平方根.scala代码牛顿智商太高了println( sqr(10 ...
- 【Win 10 应用开发】文件读写的三种方案
本文老周就跟伙伴们探讨一下关于文件读写的方法.总得来说嘛,有三种方案可以用,而且每种方案都各有特色,也说不上哪种较好.反正你得记住老祖宗留给我们的大智慧——事无定法,灵活运用者为上. OK,咱们开始吧 ...
- word-break: break-all;、word-break: keep-all; 、word-wrap: break-word;和white-space:nowrap;都有什么作用
小颖最近心情不好,心情不好就容易做傻事,所以昨天就干了件傻事 小颖昨天脑子一抽去拔罐了,拔完我就~~~~~~~~~~~~疼死宝宝了,昨晚一晚都没睡好,都不敢平躺,难受一晚上,早上到公司后困得啊,也是傻 ...
- [.NET] WebApi 生成帮助文档及顺便自动创建简单的测试工具
==========最终的效果图========== ==========下面开始干活:生成帮助文档========== 一.创建 WebApi 项目 二.找到 HelpPageConfig.cs 并 ...
- Notepad2替代系统自带的记事本
事情是这样的,平时我经常把一些文字复制到记事本中编辑好了再复制到目标位置,可以在系统自带的记事本中替换删除一些内容,记事本小巧,占用很少的资源,我很喜欢:但今天复制的内容中有很多数字和一些我不想要的内 ...
- wordpress插件bug排查后记(记一次由于开启memecached引起的插件bug)
这篇文章是写给自己的. 周三的时候我在维护公司的一个wordpress项目页面时发现了一个非常奇怪的情况:当我尝试更新网站上的一个页面后,在wordpress后台的编辑器中发现其内容并没有按我预期的将 ...
- Docker for Windows使用简介
在上一篇文章中,通过演练指导的方式,介绍了在Docker中运行ASP.NET Core Web API应用程序的过程.本文将介绍Docker for Windows的使用. 先决条件 前两周时间,Do ...