Bilbro Bloggins

Musings of Brian Bilbro

Hidden secrets of W0W64 – Large Address Aware

We ran into an interesting problem at work.   We had recently migrated one of our larger .NET 3.5 applications to Windows 64-bit servers from Windows 32-bit servers.  Even though the application is built on .NET, we couldn’t run it completely in native 64-bit mode because of some third-party references we use.   Through that process we dug up a couple of handy nuggets of information regarding WOW64.

 

Quick Memory Recap

On Windows 32-bit platform, each process can only use up to 4 gig of RAM (2^32).  However, your application can only use 2 gig of that 4 gig because the other 2 gig is used by the Windows kernel.  There is a boot option in Windows to make the kernel space allocation to 1 gig so you can use 3 gig but there are risks to that approach.

There is still an advantage to moving a 32-bit app to a 64-bit platform even if it has to run in 32-bit mode(WOW64).  Running your 32-bit app on Windows 64-bit means the process can now use the full 4 gig of RAM per process because the Windows kernel functionality has been moved out of the process.

But, as always there are a few gotchas.  The application mentioned above has many components: .NET Remoting hosted in IIS, ASP.NET web site and web services and .NET Window services.   We found the components that were hosted by the ASP.NET framework were taking advantage of the > 2 gig memory space.   However, the .NET Windows service would start to throw Out of Memory exceptions as it approached 2 gigs.

 

editbin /LARGEADDRESSAWARE to the rescue

It turns out there is a header needed in your executable to flag that it is safe to allow the process to use more than 2 gigs.  If you have Visual Studio installed, you should have a utility called editbin.   Simply run the editbin utility on your .NET exe with the /LARGEADDRESSAWARE flag and it will modify your executable to include the header.

editbin /LARGEADDRESSAWARE C:\data\blog\WOW64Blog\WOW64Blog\bin\Debug\WOW64Blog.exe

click the image below to see a larger image:

editbinrun

 

Dumpbin (included with Visual Studio also) can be used to get information regarding an executable.  If you run the following command on your exe before adding the LARGEADDRESSAWARE header, it should look something like this.

dumpbin /HEADERS C:\data\blog\WOW64Blog\WOW64Blog\bin\Debug\WOW64Blog.exe

output:

Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.
Dump of file C:\data\blog\WOW64Blog\WOW64Blog\bin\Debug
LINK : fatal error LNK1104: cannot open file 'C:\data\blog\WOW64Blog\WOW64Blog\bin\Debug'
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.
Dump of file C:\data\blog\WOW64Blog\WOW64Blog\bin\Debug\WOW64Blog.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
             14C machine (x86)
               3 number of sections
        494A6185 time date stamp Thu Dec 18 09:43:17 2008
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
             102 characteristics
                   Executable
                   32 bit word machine
OPTIONAL HEADER VALUES
             10B magic # (PE32)
            8.00 linker version
             800 size of code
             800 size of initialized data
               0 size of uninitialized data
            266E entry point (0040266E)
            2000 base of code
            4000 base of data
          400000 image base (00400000 to 00407FFF)
            2000 section alignment
             200 file alignment
            4.00 operating system version
            0.00 image version
            4.00 subsystem version
               0 Win32 version
            8000 size of image
             200 size of headers
               0 checksum
               3 subsystem (Windows CUI)
            8540 DLL characteristics
                   Dynamic base
                   NX compatible
                   No structured exception handler
                   Terminal Server Aware
          100000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [       0] RVA [size] of Export Directory
            2618 [      53] RVA [size] of Import Directory
            4000 [     540] RVA [size] of Resource Directory
               0 [       0] RVA [size] of Exception Directory
               0 [       0] RVA [size] of Certificates Directory
            6000 [       C] RVA [size] of Base Relocation Directory
            25A8 [      1C] RVA [size] of Debug Directory
               0 [       0] RVA [size] of Architecture Directory
               0 [       0] RVA [size] of Global Pointer Directory
               0 [       0] RVA [size] of Thread Storage Directory
               0 [       0] RVA [size] of Load Configuration Directory
               0 [       0] RVA [size] of Bound Import Directory
            2000 [       8] RVA [size] of Import Address Table Directory
               0 [       0] RVA [size] of Delay Import Directory
            2008 [      48] RVA [size] of COM Descriptor Directory
               0 [       0] RVA [size] of Reserved Directory
SECTION HEADER #1
   .text name
     674 virtual size
    2000 virtual address (00402000 to 00402673)
     800 size of raw data
     200 file pointer to raw data (00000200 to 000009FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         Execute Read
  Debug Directories
        Time Type       Size      RVA  Pointer
    -------- ------ -------- -------- --------
    494A6185 cv           51 000025C4      7C4    Format: RSDS, {5EA6DDBE-E293-412D-8263-2E9BD5D63D6D}, 1, C:\data\blog\WOW64Blog\WOW64Blog\obj\Debug\WOW64Blog.pdb
SECTION HEADER #2
   .rsrc name
     540 virtual size
    4000 virtual address (00404000 to 0040453F)
     600 size of raw data
     A00 file pointer to raw data (00000A00 to 00000FFF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40000040 flags
         Initialized Data
         Read Only
SECTION HEADER #3
  .reloc name
       C virtual size
    6000 virtual address (00406000 to 0040600B)
     200 size of raw data
    1000 file pointer to raw data (00001000 to 000011FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
42000040 flags
         Initialized Data
         Discardable
         Read Only
  Summary
        2000 .reloc
        2000 .rsrc
        2000 .text

running dumpbin /headers on your exe after adding the LARGEADDRESSAWARE header the output should be similar to this:

Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.
Dump of file C:\data\blog\WOW64Blog\WOW64Blog\bin\Debug\WOW64Blog.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
             14C machine (x86)
               3 number of sections
        494A6185 time date stamp Thu Dec 18 09:43:17 2008
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
             122 characteristics
                   Executable
                   Application can handle large (>2GB) addresses
                   32 bit word machine
OPTIONAL HEADER VALUES
             10B magic # (PE32)
            8.00 linker version
             800 size of code
             800 size of initialized data
               0 size of uninitialized data
            266E entry point (0040266E)
            2000 base of code
            4000 base of data
          400000 image base (00400000 to 00407FFF)
            2000 section alignment
             200 file alignment
            4.00 operating system version
            0.00 image version
            4.00 subsystem version
               0 Win32 version
            8000 size of image
             200 size of headers
            DFDF checksum
               3 subsystem (Windows CUI)
            8540 DLL characteristics
                   Dynamic base
                   NX compatible
                   No structured exception handler
                   Terminal Server Aware
          100000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [       0] RVA [size] of Export Directory
            2618 [      53] RVA [size] of Import Directory
            4000 [     540] RVA [size] of Resource Directory
               0 [       0] RVA [size] of Exception Directory
               0 [       0] RVA [size] of Certificates Directory
            6000 [       C] RVA [size] of Base Relocation Directory
            25A8 [      1C] RVA [size] of Debug Directory
               0 [       0] RVA [size] of Architecture Directory
               0 [       0] RVA [size] of Global Pointer Directory
               0 [       0] RVA [size] of Thread Storage Directory
               0 [       0] RVA [size] of Load Configuration Directory
               0 [       0] RVA [size] of Bound Import Directory
            2000 [       8] RVA [size] of Import Address Table Directory
               0 [       0] RVA [size] of Delay Import Directory
            2008 [      48] RVA [size] of COM Descriptor Directory
               0 [       0] RVA [size] of Reserved Directory
SECTION HEADER #1
   .text name
     674 virtual size
    2000 virtual address (00402000 to 00402673)
     800 size of raw data
     200 file pointer to raw data (00000200 to 000009FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         Execute Read
  Debug Directories
        Time Type       Size      RVA  Pointer
    -------- ------ -------- -------- --------
    494A6185 cv           51 000025C4      7C4    Format: RSDS, {5EA6DDBE-E293-412D-8263-2E9BD5D63D6D}, 1, C:\data\blog\WOW64Blog\WOW64Blog\obj\Debug\WOW64Blog.pdb
SECTION HEADER #2
   .rsrc name
     540 virtual size
    4000 virtual address (00404000 to 0040453F)
     600 size of raw data
     A00 file pointer to raw data (00000A00 to 00000FFF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40000040 flags
         Initialized Data
         Read Only
SECTION HEADER #3
  .reloc name
       C virtual size
    6000 virtual address (00406000 to 0040600B)
     200 size of raw data
    1000 file pointer to raw data (00001000 to 000011FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
42000040 flags
         Initialized Data
         Discardable
         Read Only
  Summary
        2000 .reloc
        2000 .rsrc
        2000 .text
Near the top, In the FILE HEADER VALUES section you should see the comment “Application can handle large (>2GB) addresses”.  As a side-note, I found that text amusing as I was expecting something along the lines of “1 LARGEADDRESSAWARE”.

 

Compiling a .NET Windows app to run in WOW64.

As usual, it seems anything that runs in the ASP.NET framework has a leg up on Windows applications.  What determines if your ASP.NET runs in WOW64 or true 64-bit is based upon what framework you have installed (either 32-bit or 64-bit).   On Windows 2003 / IIS 6 this is a system wide configuration (i.e. you can’t run WOW64 and true 64-bit ASP.NET at the same time).  This has been corrected in Windows 2008 / IIS 7 which allows you to target each app pool to 32-bit or 64-bit framework.

But, back to the Windows world.   If you open Visual Studio, create a console app, reference a 32-bit component, deployed to Windows 64-bit server it will crash down in flames like the Hindenburg.  The reason is because Windows will try and run the application in 64-bit mode because Visual Studio by default sets the target platform to be “AnyCPU”.     This can be corrected by specifying your application as only targeting the 32-bit platform.

Within Visual Studio, navigate to Project->Properties->Build.

Change the Platform target to x86 and that will allow your exe to run in WOW64 mode when running on Windows 64-bit. 

PlatformTarget

 

64-bit is a good thing.  But you might find out you can’t easily switch your application to true 64-bit.   These secrets can allow you to take advantage of some of the 64-bit capabilities without having to wait until you have the time to completely migrate your application to native 64-bit.

» Similar Posts

  1. Yes, Virginia, you can write through the BDC – Part One.
  2. Creating a Lookup List for SharePoint with VSeWSS
  3. Yes, Virginia, you can write through the BDC – Part Two.

» Trackbacks & Pingbacks

    No trackbacks yet.
Trackback link for this post:
http://bilbrobloggins.com/trackback.ashx?id=15
 

» Comments

  1. Joshua avatar

    Nice trick. Should help us.

    Joshua — March 12, 2009 10:17 PM
  2. Website Photo Gallery Guy avatar

    Thanks for the very important comment about Server 2008/IIs7 and the option to set a website to run under 32 or 64-bit. Very important feature and very helpful to us. Thanks!

    In Server 2008, if you have a website that uses older DLL third party components that are built around 32-bit systems, just create an Application Pool for your website, assign your website to the pool, then open the pool, choose Advanced Settings, and in there set your 32-bit setting to true. That allows you to use the WoW64 technology with these older DLL's.

    Until the world moves into 64-bit, thats the best solution for older technologies. Sure helped us!

    Website Photo Gallery Guy — March 27, 2009 11:17 AM
  3. X64 victim avatar

    AWWWWWWWW MAN!!!! 3 DAYS I AM SEARCHING HOW TO MAKE WORKING MY 32BIT ASP.NET APPS!!

    THANK YOU SO MUCH Website Photo Gallery Guy

    KISS KISS ;)

    X64 victim — March 20, 2010 4:26 PM
  4. MickyD avatar

    great post. i knew there was a MS tool that did this but i forgot what it was, didnt really want to use some third party thing. thanks buddy.

    MickyD — November 19, 2011 3:07 AM

» Leave a Comment