【发布时间】:2021-10-26 21:31:10
【问题描述】:
我从Microsoft documentation 知道,对于 64 位图像,图像基址设置为 0x140000000,它是可执行文件首次加载到内存中的基址。
所以我的问题如下
- 0x140000000 地址和虚拟地址第一页的开始 (0x0000000) 之前的内容
- 首先加载可执行文件是什么意思?是程序的入口点(当然不是main函数)还是别的什么
【问题讨论】:
标签: windows portable-executable
我从Microsoft documentation 知道,对于 64 位图像,图像基址设置为 0x140000000,它是可执行文件首次加载到内存中的基址。
所以我的问题如下
【问题讨论】:
标签: windows portable-executable
0x140000000 地址和虚拟地址第一页的开始 (0x0000000) 之前的内容
在那里分配的任何内容,例如 DLL、文件映射、堆内存,或者此内存都可以是空闲的。第一页始终无法访问。
可执行文件首先加载是什么意思?是程序的入口点(当然不是main函数)还是别的什么
加载意味着映射到内存中。映射到内存后,解析导入,静态链接的DLL映射到内存,执行它们的入口点,然后才到达可执行入口点。如果可执行文件具有 TLS 回调,则可执行文件入口点并不是真正从可执行文件执行的第一个函数。
【讨论】:
malloc,确实会导致堆溢出。在分配较低地址之前,您可能会用完物理内存/交换。您可以通过使用VirtualAlloc 来保留可执行映射上方的整个范围进行实验,然后您将看到malloc 返回低地址。或者您可以通过/LARGEADDRESSAWARE:NO 看到它。
我不知道 64 位默认值如此之高的技术原因,也许只是为了确保您的应用程序没有模块中的数据/代码的 32 位指针截断错误?而且需要注意的是,这个默认值来自微软的编译器,Windows 本身会接受一个较低的值。 32 位应用程序的默认值为 0x00400000,还有actual hardware and technical reasons for that。
在大多数操作系统中,从 0 开始的第一页是禁区,以防止取消引用 NULL 指针时出现问题。前几兆字节可能映射了 BIOS/固件或其他遗留的东西。
第一次加载意味着加载器会将文件映射到从该地址开始的内存中。首先是 MZ 部分(DOS 标头和存根代码)和PE header。之后是 PE 标头中列出的各个部分。
如今大多数应用程序都在使用 ASLR,因此基地址将是随机的,而不是 PE 中列出的首选地址。 ntdll 和 kernel32 在 exe 之前映射,因此如果您选择它们的基地址,您也将被重新定位。
【讨论】: