沒有在偏移量 0 處映射 Win32 便攜式可執行文件的可能原因是什麼? (What are possible reasons for not mapping Win32 Portable Executable images at offset 0?)


問題描述

沒有在偏移量 0 處映射 Win32 便攜式可執行文件的可能原因是什麼? (What are possible reasons for not mapping Win32 Portable Executable images at offset 0?)

I've been looking into Window's PE format lately and I have noticed that in most examples, people tend to set the ImageBase offset value in the optional header to something unreasonably high like 0x400000.

What could make it unfavorable not to map an image at offset 0x0?


參考解法

方法 1:

First off, that's not a default of Windows or the PE file format, it is the default for the linker's /BASE option when you use it to link an EXE.  The default for a DLL is 0x10000000.

Selecting /BASE:0 would be bad choice, no program can ever run at that base address.  The first 64 KB of the address space is reserved and can never be mapped.  Primarily to catch null pointer dereference bugs.  And expanded to 64KB to catch pointer bugs in programs that started life in 16-bits and got recompiled to 32-bits.

Why 0x40000 and not 0x10000 is the default is a historical accident as well and goes back to at least Windows 95.  Which reserved the first 4 megabytes of the address space for the "16-bit/MS-DOS Compatibility Arena".  I don't remember much about it, Windows 9x had a very different 16-bit VM implementation from NT.  You can read some more about it in this ancient KB article.  It certainly isn't relevant anymore these days, a 64-bit OS will readily allocate heap memory in the space between 0x010000 and 0x400000.

There isn't any point in changing the /BASE option for an EXE.  However, there's lots of point changing it for a DLL.  They are much more effective if they don't overlap and thus don't have to be relocated, they won't take any space in the paging file and can be shared between processes.  There's even an SDK tool for it so you can change it after building, rebase.exe

方法 2:

Practically, the impact of setting /BASE to 0 depends on the Address Space Layout Randomization (ASLR) setting of your image (which is also put by the Linker - /DYNAMICBASE:NO).

Should your image have /BASE:0 and ASLR is on (/DYNAMICBASE:YES), then your image will start and run because the loader will automatically load it at a "valid" address.

Should your image have /BASE:0 and ASLR is off (/DYNAMICBASE:NO), then your image will NOT start because the loader will NOT load it at the desired based address (which is, as explained above, unvalid/reserved).

方法 3:

If you map it to address 0 then that means the code expects to be running starting at address zero.

For the OS, address zero is NULL, which is an invalid address. (Not "fundamentally", but for modern-day OSes, it is.)

Also, in general you don't want anything in the lower 16 MiB of memory (even virtual), for numerous reasons.

But what's the alternative? It has to be mapped somewhere, so they chose 0x400000... no particular reason for that particular address, probably. It was probably just handy.

方法 4:

Microsoft chose that address as the default starting address specified by the linker at which the PE file will be memory mapped. The linker assumes this address and and can optimize the executable with that assumption. When the file is memory mapped at that address the code can be run without needing to modify any internal offsets.

If for some reason the file cannot be loaded to that location (another exe/dll already loaded there) relocations will need to occur before the executable can run which will increase load times.

Lower memory addresses are usually assumed to contain low level system routines and are generally left alone. The only real requirement for the ImageBase address is that it is a multiple of 0x10000.

Recommended reading:

  • http://msdn.microsoft.com/en-us/library/ms809762.aspx

(by KierrowHans Passantmoxuser541686Dave Rager)

參考文件

  1. What are possible reasons for not mapping Win32 Portable Executable images at offset 0? (CC BY-SA 3.0/4.0)

#mapping #offset #executable #portability #winapi






相關問題

Hibernate 單向父/子關係 - delete() 對子表執行更新而不是刪除 (Hibernate Unidirectional Parent/Child relationship - delete() performs update on child table instead of delete)

TIGER shapefile - 使用和解釋 (TIGER shapefiles - using and interpreting)

查找位置的城市和郵政編碼 (Finding City and Zip Code for a Location)

如何使 Vim 插件 NERDTree 的 <CR> 表現得更像 `go`? (How to make Vim plugin NERDTree's <CR> behave more like `go`?)

在 NHibernate 上的多對多關係上添加自定義列 (Add custom columns on many to many relationship on NHibernate)

在大型 .NET 項目中管理 DTO 和映射 (Managing DTOs and mapping in large .NET project)

使用 Fluent NHibernate 進行繼承映射 (Inheritance Mapping with Fluent NHibernate)

Biztalk映射問題,請想法 (Biztalk Mapping Problem, Ideas please)

BizTalk 數據庫查找 functoid 固定條件 (BizTalk Database Lookup functoid fixed condition)

EntityFramework FluentAPI 映射問題 (EntityFramework FluentAPI mapping issue)

將外鍵添加到現有數據庫 (Adding foreign keys to an already existing database)

如何重命名對像數組中對象的所有鍵? (How does one rename all of an object's keys within an array of objects?)







留言討論