[Webinar] Streamline your web hosting managementRegister Today

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 677
  • Last Modified:

How to use /BASE (Base Address) linker option with VC compiler/linker

We have a big VC6 (and MFC) application including one executable and about 50 dlls. Some of these dlls were loaded statically at start of application. Most dlls were loaded dynamically at runtime which mostly causes more than one dll to get loaded at a time because of dependencies.

We now try to prevent the application from relocating the dlls. I got the sizes of the executables and all dlls including system dlls that were loaded with the executable. I also have the names and sizes of all dlls that might get loaded dynamically. I could create a text file like

app.exe        0x00040000 0x00500000        
dll1.dll          0x20000000 0x00300000
dll2.dll          0x20300000 0x00100000
dll3.dll          0x20400000 0x00200000

but I have some questions on that:

1. Do I have to include all system dlls such as mfc42.dll or user32.dll?
2. Is there any difference between the dlls loaded with the application and the dlls dynamically loaded?
3. Is the order of the dlls somehow important?
4. Which address is the best to start with the dlls?
  - I read somewhere that one should go down from 0x67d00000 -
5. Are there any disadvantages if the address assignment was done generously?
6. If there are some dlls that were loaded rarely, should I put them to the list or not?
7. Do I have to assign the /BASE option only when linking the executable or need
   all dlls get linked accordingly?

Regards, Alex

  • 5
  • 4
1 Solution
It looks like you need to use rebase program:

>> Most dlls were loaded dynamically at runtime which mostly causes more than one dll to get loaded at a time because of dependencies.
This doesn't happen, every Dll is loaded only once, LoadLibrary uses reference counting.
itsmeandnobodyelseAuthor Commented:
>>>> This doesn't happen, every Dll is loaded only once

Sorry, I explained it poorly. I meant that some dlls are loading some of the other dlls because they are included in the list of object/library modules of the dll.

So, most of the dlls were explicitly loaded by the executable but some because they are needed in a dll.
You can rebase all your own libraries with executable, both if they are direct exe dependencies or not.
Select start address for rebasing by such way, that memory region occupied by your libraries doesn't intersect with any system and third-party library.
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

itsmeandnobodyelseAuthor Commented:
I found the following rebase command in the link above (unfortunately I can't download as I am on a customer machine where downloads from Internet were not allowed).

-@rebase.exe -b 0x60000000 Server1.dll Server2.dll

Could you explain how rebase can find the applications's executable by that statement?

The base address list shown by dependency walker is strange. The executable *and* msvcirt.dll have same base address 0x00400000. Then, private and system dlls follow immediately using base addresses below 0x10000000 what would have been the expected  base start address for dlls. Then, there is a huge gap between 0x01770000 and 0x5D450000 where COMCTL32.dll was located. Then, a gap from 0x5D900000 to 0x71A00000. Finally a bunch of 24 system dlls including mfc43, ntkernel, user32, and so on...

If I would relocate comctl32.dll the region from 0x10000000 to 0x70000000 would be free for my private dlls, right?

Regards, Alex

We cannot set base address of system libraries, but generally they have some range which is not supposed to intersect with user libraries. Of course, there are gaps between libraries, because every program uses only part of system libraries. We cannot rebase system libraries.
The only thing we can do is to set base addresses of our own libraries, and ensure that all of them are placed to contingous memory block. Base address 0x60000000 is just recommended base address for user libraries. We can select something else. Server1.dll Server2.dll is list of dependency libraries - you can make your own list.

Rebase doesn't care about executable, it just sets starting address in the libraries. First library gets address from command line, second - address from command line + first library size etc.

If you have Jeffrey Richter's "Programming Applications for Microsoft Windows 2000", you can read more details about this.
Recommended place for rebasing is project makefile, since libraries size can be changed in ebery build.
itsmeandnobodyelseAuthor Commented:
>>>> it just sets starting address in the libraries

Bingo, that was the missing link. I always thought I have to specify the base addresses of the dlls when linking the executable ...

But what happens if a dll is used by different executables? And what happens with gaps? Do they have any influence on the size of the executable in memory?

Regards, Alex
Dll used by different executables is problem which has no solution (maybe using your own rebased copy of this Dll). System libraries use predefined range. If you use third-party libraries which are distributed with your program, you can rebase them as well. If you use third-party libraries which are not part of your distribution, I don't see acceptable solution.
itsmeandnobodyelseAuthor Commented:
>>>> Dll used by different executables is problem which has no solution

I just wondered. It's not actually a problem cause there are only tools which are using the same application dlls.

>>>> If you use third-party libraries which are distributed with your program, you can rebase them as well

Yes, I rebased all dlls in the start directory (118 files) and it worked. Beside of the executable, an OCX and ComCtl32.dll (???) there was no dll based below 0x621d0000. I used

    rebase -b 0x68000000 -d dll1.dll dll2.dll ...

from the commandline where I created the list of dlls by modifying a file list and added it via clipboard.

The output of the above command was

    REBASE: Total Size of mapping 0x05e30000
    REBASE: Range 0x621d0000 -0x68000000

Regards and thanks for your help


Featured Post

[Webinar] Kill tickets & tabs using PowerShell

Are you tired of cycling through the same browser tabs everyday to close the same repetitive tickets? In this webinar JumpCloud will show how you can leverage RESTful APIs to build your own PowerShell modules to kill tickets & tabs using the PowerShell command Invoke-RestMethod.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now