How to detect X32 on Windows?

前端 未结 5 1409
广开言路
广开言路 2020-12-22 03:04

X32 allows one to write programs using 32-bit integers, longs and pointers that run on x86_64 processors. Using X32 has a number of benefits under certain use cases. (X32 is

5条回答
  •  有刺的猬
    2020-12-22 03:45

    Windows doesn't have an x32 ABI. However it has a feature that gives you memory only in the low 2GB of address space. Just disable the /LARGEADDRESSAWARE flag (by default it's enabled for 64-bit binaries) and then you can use 32-bit pointers inside your 64-bit application

    User space pointers in those binaries will have the top bits zeroed, so it's essentially just similar to x32 ABI on Linux. long in Windows has always been a 32-bit type, thus it's also the same as in x32 ABI where long and pointers are 32-bit wide

    By default, 64-bit Microsoft Windows-based applications have a user-mode address space of several terabytes. For precise values, see Memory Limits for Windows and Windows Server Releases. However, applications can specify that the system should allocate all memory for the application below 2 gigabytes. This feature is beneficial for 64-bit applications if the following conditions are true:

    • A 2 GB address space is sufficient.
    • The code has many pointer truncation warnings.
    • Pointers and integers are freely mixed.
    • The code has polymorphism using 32-bit data types.

    All pointers are still 64-bit pointers, but the system ensures that every memory allocation occurs below the 2 GB limit, so that if the application truncates a pointer, no significant data is lost. Pointers can be truncated to 32-bit values, then extended to 64-bit values by either sign extension or zero extension.

    Virtual Address Space

    But nowadays even on Linux kernel developers are discussing to drop x32 Support


    Detecting whether /LARGEADDRESSAWARE is enabled or not is a little bit trickier. Since it's a link-time option, you can't check it during compile-time with any macros. However you can work around that by adding a new config (e.g. x32) to your VS project and in that config

    • Add a macro (e.g. _WIN_X32_ABI) so that you can check the config at compile-time

    • Add a post-build event which runs the following commands

        call "$(DevEnvDir)..\tools\vsvars32.bat
        editbin /largeaddressaware:no $(TargetPath)
      

    Alternatively set the option programmatically from a VS extension using VCLinkerTool.LargeAddressAware property. Now just build with this config and you'll get an "x32 ABI" executable

    To check the flag of another process or executable file just read the IMAGE_FILE_LARGE_ADDRESS_AWARE flag in LOADED_IMAGE::Characteristics. Determining the flag for the current process is probably trickier so it's better to just use the macro created above to do it at compile time


    Intel compiler also has an option to use the ILP32 model on 64-bit Windows/Linux/macOS called -auto-ilp32 and /Qauto-ilp32:

    Instructs the compiler to analyze the program to determine if there are 64-bit pointers that can be safely shrunk into 32-bit pointers and if there are 64-bit longs (on Linux* systems) that can be safely shrunk into 32-bit longs.

    There's also -auto-p32 to shrink only pointers and not 64-bit long

    However I couldn't find a way to check that behavior, as well as how to determine whether pointers have been shrunk to 32-bit or not. I've tried -auto-ilp32 -xCORE-AVX512 -O2 -ipo on Godbolt but it seem doesn't affect the result. If any one knows how to output an executable with 32-bit pointers please tell me

提交回复
热议问题