虚拟内存
Windows 的内存可以被分为两个层面:物理内存和虚拟内存。
如图 1.2.1
所示,
Windows
让所有的进程都“相信”自己拥有独立的
4GB
内存空间。但是,我们计算机中那根实际的内存条可能只有512MB
,怎么可能为所有进程都分配
4GB
的内存呢?
这一切都是通过虚拟内存管理器的映射做到的。
虽然每个进程都“相信”自己拥有 4GB
的空间,但实际上它们运行时真正能用到的空间根本没有那么多。内存管理器只是分给进程了一片“假地址”,或者说是“虚拟地址”,让进程们“认为”这些“虚拟地址”都是可以访问的。如果进程不使用这些“虚拟地址”,它们对进程来说就只是一笔“无形的数字财富”;当需要进行实际的内存操作时,内存管理器才会把“虚拟地址”和“物理地址”联系起来。
PE文件与虚拟内存之间的映射
(1)文件偏移地址(File Offset)
数据在
PE
文件中的地址叫文件偏移地址,个人认为叫做文件地址更加准确。这是文件在磁盘上存放时相对于文件开头的偏移。
2)装载基址(Image Base)
PE
装入内存时的基地址。默认情况下,
EXE
文件在内存中的基地址是
0x00400000
,
DLL文件是 0x10000000
。这些位置可以通过修改编译选项更改。
3)虚拟内存地址(Virtual Address,VA)
PE
文件中的指令被装入内存后的地址。
4)相对虚拟地址(Relative Virtual Address,RVA)
相对虚拟地址是内存地址相对于映射基址的偏移量。
虚拟内存地址、装载基址、相对虚拟内存地址三者之间有如下关系。
VA= Image Base+ RVA
如图
1.2.2
所示,在默认情况下,一般
PE
文件的
0
字节将对映到虚拟内存的 0x00400000位置,这个地址就是所谓的装载基址(Image Base)。
文件偏移是相对于文件开始处
0
字节的偏移,
RVA
(相对虚拟地址)则是相对于装载基址
0x00400000 处的偏移。由于操作系统在进行装载时“基本”上保持
PE
中的各种数据结构,所以文件偏移地址和 RVA
有很大的一致性。