Introduction
A Dynamic-link library created in Microsoft Visual C++ has default base address 0x10000000 (Visual C# has default base address 0x400000). That means, when the process starts, the system loader tries to load the DLL to this address in the process memory. However, if a number of DLLs have the same base address, only one of them is loaded to its default address. For all other DLLs, the loader makes the relocation: changes the memory addresses in DLL commands according to the new base address where the DLL is loaded. This process is also known as DLL collisions.
Main disadvantages of the DLL relocations are:
- It takes additional time.
- The DLL code kept in process memory is changed. That means, when the Memory Manager needs memory pages for something else, it saves pages with the DLL code to the system-paging file. This may reduce the working speed of large program.
- Changing the DLL load base address may lead to current memory segment change. For unmanaged DLLs, this affects the near type pointers variables address calculation. Near type pointers have as zero offset reference the address of the current memory segment first address location.
For a given application, there is a constant number of DLLs usually used. A solution to avoid DLLs collisions while the application runs is to change the compiler default base address (the preferred base address) for each DLL.
The RebaseDlls
application is a Win32 MFC console program, which modifies the preferred base address for each DLL file present within a working folder or given in application command line. The RebaseDlls
application calculates the preferred DLL base addresses within a given addresses range [Min, Max]. The generated DLL base addresses assure contiguous DLL memory spaces for each DLL file present in the working folder or given in the command line. The memory size between 2 consecutive addresses is computed according to the DLL required load memory space (64K multiple).
Min A1 A2 A3 A4 ……………….. Max
|-------|---------------|-------------|-------------------|-----------------------------|
Dll1 Dll2 Dll3 Dll4 ……………….
Background
For more basic information about rebasing DLLs, please consult the Code Project links: link 1 and link 2. In these articles, it is also presented how to check the value of a DLL base address (Dependency Walker - Microsoft Visual Studio 6.0 utility).
An interesting article about DLL collisions can be found at link 3. This article was the inspiration source for RebaseDlls
application.
Using the Code
Application Usage
The RebaseDlls
application command line options are:
-folder:
This option contains the absolute path to the folder where the DLL files to be rebased are located.
-rec:
This option enables the recursive folders search within the given working folder (boolean values: 0 / 1). The default value is 0 (no recursive search).
-log:
This option enables the creation of a logfile where details about the DLL rebase operations are stored (boolean value 0 / 1). The default value is 1 (create logfile). The logfile is created in the current RebaseDlls application folder.
-files:
This option contains the absolute paths for DLL files to be rebased. The files series have to be semicolon separated.
The -folder:
and the-files:
options cannot both be skipped. At least one has to be filled.
The -rec:
and/or -log:
options can be skipped.
Command Line Examples
RebaseDlls -folder:C:\Temp -rec:1 -log:0
This RebaseDlls
command line processes all DLLs files contained into the C:\Temp folder and all the folders inside it. There is no logfile generated.
RebaseDlls -files:C:\File1.dll;C:\File2.dll
This RebaseDlls
command line processes the DLLs files mentioned in the command line (the "-files:
" option): C:\File1.dll and C:\File2.dll. There is a logfile generated (by default).
RebaseDlls -files:C:\File1.dll;C:\File2.dll -folder:C:\Temp
This RebaseDlls
command line processes the DLLs files mentioned in the command line (the "-files:
" option): C:\File1.dll and C:\File2.dll and all the DLL files included in the C:\Temp folder. No recursive folder search (default). Logfile created (default).
The RebaseDlls
application ends with a report that contains short useful information about the whole rebase process. The RebaseDlls
logfiles contain information about each DLL rebase operation performed.
Application Details
The address range for an application that is not reserved by any version of Windows is from 0x00400000 to 0x80000000. The system DLLs for Windows are currently based in memory from 0x70000000 to 0x78000000 on the Intel processors and from 0x68000000 to 0x78000000 on the MIPS processors. Other standard DLLs (for OLE support) are apparently in the range 0x50000000 to 0x5f000000. When selecting base addresses for DLLs, Microsoft suggests that you select them from the top of the allowed address range downwards, in order to avoid conflicts with memory allocated dynamically by the application (which is allocated from the bottom up).
In conclusion, the most suitable address range for DLLs is from 0x60000000 through 0x6f000000. Microsoft, proposes to reduce the range further to 0x60000000 through 0x68000000 in order to accommodate with MIPS processors too, but this is not the case taken into account by RebaseDlls
application. The RebaseDlls
application calculates preferred DLL base addresses within the address range of 0x60000000 to 0x70000000 (larger than the one proposed by Microsoft). The range allows to use up to 256 MB memory space for rebased DLLs. The addresses range can be modified within the source code:
#define STARTBASE 0x60000000L
#define MAXADDRESS 0x70000000L
Heaving in view that the RebaseDlls
application has been applied to a number of DLL files usually used by a given application, there is a slight possibility that in the module where these DLLs are to be loaded, another third-party DLL is already loaded at the same memory address. Such a scenario implies the existence of third-party (non Windows) DLLs having the preferred base addresses within the RebaseDlls
re-base range: 0x60000000 to 0x70000000. The incidence of this scenario is very low.
The ReBaseImage
function delivered within the Microsoft Platform SDK does the whole DLL rebase work. Because not everyone has the SDK installed, I've included in the project zip the ImageHlp.lib required for an appropriate RebaseDll
C++ project compilation.
Test Scenarios
Check the DLLs base addresses before and after RebaseDlls
application runs. You'll see (using Dependency Walker utility) the differences concerning each DLL file base address.
Before running RebaseDll
, check the addresses where each DLL has been loaded at in the working module. You'll see (using a system view utility like Iarsn TaskInfo application) some of your DLLs suffered collisions and they have been relocated to other addresses different than the preferred addresses. Do the same thing after running the RebaseDlls
. You'll see that the addresses where your DLLs have been loaded at in the working module correspond with the ones mentioned in the RebaseDlls
logfile. No collisions in this case.
Points of Interest
Both for unmanaged and managed DLLs, the DLL load operation speed has been improved by re-basing the DLLs. For the unmanaged DLLs, there is more one benefit: avoids near pointers base address modifications caused by possible DLL relocations.
History
- 23rd April 2009 - Article creation
- 27th April, 2009 - Article text updated - minor changes and corrections made