程序员的自我修养 第5章 Windows PE/COEF

在windows平台下,可执行性文件采用PE文件格式,而visual C++编译器产生的目标文件仍然使用COFF格式。
与ELF相同PE/COFF也是采用基于段的方式。
GCC中我们使用__attribute__((section("name")))指定段,visual C++中也可以使用#pragma编译器指示。

COFF

visual C++安装完成之后就有一个批处理文件用来建立运行这些工具所需的环境,位于如下路径。
在这里插入图片描述
可以使用如下命令进行编译
cl /c /Za simplesection.c
使用dumpbin来查看obj文件的结构
dumpbin /ALL simplesection.obj > simplesection.txt
dumpbin simplesection.obj /SUMMAY
在这里插入图片描述
COFF文件结构
和ELF文件类似,COFF文件也是有文件头和后面若干段组成,再加上文件末尾的符号表、调试信息的内容。COFF文件头包括了两部分,一个是描述文件总体结构和属性的映像头,一个是描述该文件中包含的段属性的段表。文件头后面紧跟着就是文件的各个段。

在这里插入图片描述
在这里插入图片描述
windows中定义了一个WinNT.h文件的结构IMAGE_FILE_HEADER
在这里插入图片描述
这个结构体和文件结构中存储,以及dumpbin显示是一一对应的
在这里插入图片描述
段表
映像头后面紧跟着就是COFF文件的段表,是一个IMAGE_SECTION_HEADER的结构数组
在这里插入图片描述
段表描述了每一个段的属性等信息。每一个段所拥有的属性包括段名、物理地址、虚拟地址、原始数据大小、段在文件中的位置、该段的重定位白鸥在文件中的位置、该段的行号表在文件中的位置、标志位等。

链接指示信息
.drectve段,是directive的缩写,内容是编译器传递给链接器的指令,即编译器希望告诉链接器应该怎样链接这个目标文件。
在RAW DATA #1部分,/default:"libcmt"链接指令,这就是cl希望传递给链接器的参数。
在这里插入图片描述
调试信息
调试信息位于.debug段。

.debug$S表示包含的是符号(Symbol)相关的调试信息。
,debug$P表示包含的是预编译头文件(Precompiled Header file)相关的调试信息段。
.debug$T表示包含类型(Type)相关的调试信息。

在这里插入图片描述
符号表
在这里插入图片描述
第三列:符号所在的位置
ABS表示符号是个绝对值,即一个常量,它不存在与任何段中。
SECT1表示符号锁表是的对象定义在COFF文件的第一个段中,本例中即是.drectve段。
UNDEF表示符号是未定义的,表示这个符号被定义在其他目标文件中。
第四列:符号类型
COFF文件类型只区分了两种,一个是notype,一个是函数类型为notype()
第五列是符号的可见范围
static表示符号是局部变量,只有目标文件内部是可见的
external表示符号是全局变量,可以被其他目标哦文件引用。
第六列是符号名

PE

PE 是基于COFF的扩展,比COFF多了好几个结构。最主要的而变化有两个,第一个是文件最开始的不是COFF头,而是DOS MZ可执行文件格式的文件头和桩代码,第二个变化是原来的COFF文件头中的IMAGE_FILE_HEADER部分扩展称为了PE文件头结构IMAGE_NT_HEADERS, 这个结构包含了原来的image hander,以及新增的PE扩展头部结构。
在这里插入图片描述
PE的设计之初必须兼容dos系统,所以PE文件中有image dos header和dos stub两个结构就是为了兼容而设计的。DOS下的可执行文件windows下的可执行文件扩展名一样,都是.exe,但是DOS下的可执行文件格式是MZ格式。
当PE可执行映象在DOS下被加载的时候,DOS系统检测该文件,发现最开始两个字节是MZ,就因为他是一个MZ可执行文件,然后DOS系统就将PE文件当做正常的MZ文件开始执行。DOS系统会读取e_cs和e_ip两个成员的值,以跳转到程序入口地址。但是e_cs和e_ip这两个成员并没有指向程序的真正入口地址,而是指向文件中的DOS stub。dos stub是一段可以在dos下运行的小段程序,这段程序的唯一作用就是向终端输出一行“This program cannot be run in DOS”然后退出程序,表示该程序不能再DOS下运行。

IMAGE_NT_HEADER是PE真正的文件头,它包含了一个标记和两个结构体(映像头、PE扩展头部结构)。
对于一个合法的PE来说,标记值为0x0004550,按照小段字节序,就是PE\0\0的ASCII码。
在这里插入图片描述
前面已经介绍了IMAGE_FILE_HEADERS
下面介绍IMAGE_OPTIONAL_HEADER,尽管是可选的,但是对于PE可执行文件来说(包括DLL)是必须要的。
在这里插入图片描述
optional header有很多成员,有些部分跟PE文件的装载与运行有关。

PE数据目录
当windows装载PE可执行文件时,往往可以很快的找到一些装载所需要的数据结构,比如导入表、导出表、资源、重定位表等。这些常用的数据的位置和长度都被保存在了数据目录结构中。即IMAGE_OPTIONAL_HEADER中的DataDirectory成员。
在这里插入图片描述
DataDirectory是一个IMAGE_DATA_DIRECTORY类型数组,每一个元素定义了两个成员,即虚拟地址和长度。
DataDirectory中每一个元素都对应一个包含一定含义的表。这些表可以是导出表、导入表、异常表、资源表、重定位表、调试信息表、线程私有存储等地址和长度。这些表多数与装载和DLL动态链接有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sundaygeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值