FIXED statement in EXP for 4% smaller EXE without .reloc table

In your EXE Global Embed “Creating the Export file” add a line with just “FIXED” and the Linker will not generate a Relocation section (.reloc) making the EXE smaller. The link will probably run a tiny bit faster. The EXE is loaded first and is never** relocated. Do NOT use for DLLs.

I tried it in DLLTutor and the EXE shrunk by only 1024 bytes. DumpBin verified the .reloc was gone. So I added it to some projects with big (too big) EXEs and see average 4% reduction in size:

EXP_FIXED_NoReloc_Test

Copy/Paste below into Global Embed: Creating the Export File
[ DEFINITION]
[SOURCE]
PROPERTY:BEGIN
PRIORITY 4000
PROPERTY:END
FIXED ; remove .reloc table … only use on EXE
[END]

FIXED is a common feature of Windows Linkers like the VS C++.

When /FIXED is specified, LINK does not generate a relocation section in the program. At run time, if the operating system is unable to load the program at the specified address, it issues an error message and does not load the program.

In An In-Depth Look into the Win32 Portable Executable File Format, Part 2
See section on “Base Relocations”

In Visual C++ 6.0, the linker omits relocations for EXEs when doing a release build. This is because EXEs are the first thing brought into an address space, and therefore are essentially guaranteed to load at the preferred load address. DLLs aren’t so lucky, so base relocations should always be left in, unless you have a reason to omit them with the /FIXED switch. In Visual Studio .NET, the linker omits base relocations for debug and release mode EXE files.

This article was from 2002. I am sure this has changed due to ASLR. I found it reassuring that FIXED used to be the norm for EXEs.

** ASLR can relocate EXEs but will NOT if FIXED is used. If you’ve figured out how to enable DYNAMICBASE you probably know this. ASLR = “Address Space Layout Randomization” a new security feature added in Vista.

I found FIXED looking at the strings in the Linker ClaLPE.DLL for undocumented stuff …

I also see ISOLATION_AWARE which I have not tried to make work, just did some Googling. I think it might be related to ISOLATIONAWARE_MANIFEST_RESOURCE_ID which allows a DLL to have its own MANIFEST that is different than the EXE (Application) MANIFEST.

E.g. Some code I work on has Visual Styles turned OFF in most EXEs. This may allow one DLL to have a MANIFEST to turn Styles ON so it can use the new v6 Common Controls DLL that has the new TaskDialog().

ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It should be used if the dll wants private dependencies other than the process default. For example, if an dll depends on comctl32.dll version 6.0.0.0. It should have a resource of type RT_MANIFEST, ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID to depend on comctl32.dll version 6.0.0.0, so that even if the process executable wants comctl32.dll version 5.1, the dll itself will still use the right version of comctl32.dll.

When LoadLibrary is called, before loading the dependencies of the dll, the NT library loader checks to see if the dll has a resource of type RT_MANIFEST, ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID. If it does, the loader calls CreateActCtx with the resource, and use the generated activation context to probe the dll’s static dependencies. This is reason why the dll can have private dependencies with the ISOLATIONAWARE_MANIFEST_RESOURCE_ID resource.

1 Like

Not quiet relate to this interesting article but of a similar nature. How does one get a Clarion DLL to manifest the V6 common controls DLL when called from a DOT NET csharp program. Every time i call the clarion DLL via invoke the clarion DLL does not use the Manifested dialogs and loses it styling and flat look and feel.

Start a new thread. Include screen captures. Note (or paste) your EXE Manifest

Thanks Carl, nice find!

I’ve whipped it into a small template and thrown in the 4Gb memory option. The template can be safely added to both EXE and DLL. You can add this to your own #TEMPLATE chain

#!
#!------------------------------------------------------------------------------------------
#EXTENSION(OptimizeExport, 'Optimizes the export file to attain a smaller exe size'), APPLICATION
#!------------------------------------------------------------------------------------------
#!
#! Auteur   : Eric Lankreijer
#! Date     : 17-08-2020 (created)
#! Version  : 1.0
#! Based on : Article from Carl Barnes posted on ClarionHub:
#!            https://clarionhub.com/t/fixed-statement-in-exp-for-4-smaller-exe-without-reloc-table/3450
#!
#!------------------------------------------------------------------------------------------
#!
  #DISPLAY('Reduces the EXE file size by adding FIXED to the export file')
  #DISPLAY('This will prevent generation of the Relocation section (.reloc)')
  #DISPLAY('That is not needed for EXE files')
  #DISPLAY()
  #DISPLAY('Current output type: ' & %ProgramExtension)
  #DISPLAY('    FIXED ' & CHOOSE(%ProgramExtension = 'EXE', 'will', 'will not') & ' be added to ' & %Application & '.exp')
  #DISPLAY()
  #PROMPT ('Enable 4Gb Memory usage', CHECK), %EnableExport4Gb, AT(10), DEFAULT(%False)
  #DISPLAY()
  #DISPLAY('By Eric Lankreijer')
  #DISPLAY()
  #DISPLAY('Based on an article by Carl Barnes posted on ClarionHub')
  #DISPLAY('https://clarionhub.com/t/fixed-statement-in-exp-for-4-smaller-exe-without-reloc-table/3450')
#!
#AT(%AfterCreatingExportFile), PRIORITY(4000), WHERE(%ProgramExtension = 'EXE')
FIXED ; remove .reloc table, only use on EXE
  #IF (%EnableExport4Gb)
LARGE_ADDRESS ; Allow 4Gb memory usage (Limited in WOW64, see Help)
  #ENDIF
#ENDAT
#!
2 Likes

Thanks! Can you post your results (EXE size change) from using FIXED?

FIXED should probably have a CHECK also so it can be turned Off and Large still used,

LARGE_ADDRESS should also only be put on EXE. It’s not a problem on a DLL but it does nothing. Also the (‘Enable 4Gb Memory usage’) text should mention ‘(EXP LARGE_ADDRESS )’.

The DLLs should be tested up at an LAA address by setting IMAGE_BASE=9xxx0000h. The risk is code is not expecting (or fails to work right) with am address > 2GB as a LONG is negative. You should probably mention this in the text. I would not turn this on casually, it would only be if I could not live with 2gb and I tested.

The 4gb is only under 64-bit windows. Under 32-bit its possible to get 3GB but unlikely as it requires a /3GB boot option, server software and minimal video.

What is the effect of the /LARGEADDRESSAWARE switch on a DLL?
Nothing.
Large-address-awareness is a process property, which comes from the EXE.

Bob Campbell has EXE’s with 400+ procedures. He posted his results of using FIXED:

  EXE #1 from 10,323,968 to  9,817,600 bytes saving 506,368 about 5.1%
  EXE #2 from 15,043,072 to 14,300,160 bytes saving 742,912 about 5.1%

Along with the disk space savings (of an used table) I like that I’m not waiting for the Linker to write that section every time I build the EXE.

I also found the below tool StripReloc that works like FIXED on an existing EXE. Its from the maker of InnoSetup. It is targeted at Delphi that does not have the FIXED linker switch.

StripReloc is a command line utility that removes the relocation (“.reloc”) section from Win32 PE EXE files, reducing their size. Most compilers/linkers (including Delphi) put a relocation section in EXE files, but this is actually not necessary since EXEs never get relocated. Hence, a relocation section only wastes space.

https://jrsoftware.org/striprlc.php

1 Like

If you want to make smaller EXE, you may use UPX tool. This tool decreasing the size more than %50. Also working for DLLs.
https://upx.github.io/

FIXED was broken in 11.0.13622 by SV when they added ASLR DYNAMIC_BASE. The EXE will fail to load.

I have not checked any 11.1 releases to see if they fixed their FIXED regression.

But what do smaller exe and DLL file sizes really do for you nowadays?
Whatever executable files are compressed, now must be decompressed at load-time, and this is an extra step and an extra place where bugs could be introduced.
I wonder what would be smaller: A zip file of UPX-pre-compressed DLLs/EXEs or a zip file of the original DLLs/EXEs. My guess would be that the original files would compress smaller, but I could be wrong. :slight_smile:
If your goal is obfuscation, there are tools for that.

2 Likes