Skip to content

ARM64ec PE files default to x86-64 when they should be aarch64 #8096

@Sonicadvance1

Description

@Sonicadvance1

Version and Platform (required):

  • Binary Ninja Version: 5.3.9409-dev Personal (0c30837b)
  • Edition: Non-Commercial
  • OS: Ubuntu
  • OS Version: Ubuntu 25.10
  • CPU Architecture: AArch64 (AmpereOne A192-32X)

Bug Description:
ARM64ec PE files are AArch64 files with x86-64 compatibility.
The COFF_Header machine field has IMAGE_FILE_MACHINE_AMD64 for compatibility, but one must continue to walking the PE64_Optional_Header in to the loadConfigTableEntry which points to eventually points to the CHPEMetadataPointer so you can get the CHPE metadata (symbol __chpe_metadata).

At this point, once you have confirmed that the CHPEMetadata entry exists, you can confirm that if the COFF header declares itself as AMD64 then it's /actually/ ARM64EC, and if the COFF header declares itself as ARM64 then it's actually ARM64X.

Some visibility in to the exact logic can be see in LLVM's source at llvm-project/llvm/include/llvm/Object/COFF.h in the getMachine() function. Additionally llvm-readobj can dump this information as well llvm-readobj --coff-load-config -r libarm64ecfex.dll as long as LLVM is 21 or newer.

Steps To Reproduce:

  1. Open an arm64ec dll and see it try and disassemble as x86-64
  2. Close that file, open with options and see it defaults to windows-x86_64

Expected Behavior:
I expect when loading a libarm64ecfex.dll file that is Arm64ec, that instead of default disassembling as x86-64, it instead default disassembles as aarch64.

Binary:

  1. https://github.com/FEX-Emu/FEX/actions/runs/24476520323 the wine_dll_artifacts are built from our CI for every commit (but self-deletes after a couple weeks)
  2. You can rip the DLL from our Ubuntu launchpad release builders. https://launchpad.net/~fex-emu/+archive/ubuntu/fex/+sourcepub/18299389/+listing-archive-extra
  1. Or use the direct attached zip. libarm64ecfex.dll.zip
  2. You could technically build an arm64ec binary yourself in msvc or llvm-mingw pretty easily but I don't have a direct example.

Additional Information:
Bonus points for parsing the CPHE config header CodeMap section, as this claims which sections in the COFF file are arm64ec, and which ones are x86-64 helper routines. Then having binja default disassemble those regions correctly with the different architectures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions