如何查找本机 DLL 文件是编译为 x64还是 x86?

我想确定从托管代码应用程序(C # )编译的本机程序集是 x64还是 x86。

我认为它一定在 PE 头部的某个地方,因为操作系统加载程序需要知道这些信息,但是我找不到它。当然,我更喜欢在托管代码中完成这项工作,但是如果有必要,我可以使用本机 C + + 。

119127 次浏览

显然你可以在 Portable Executable 的头部找到它。Exe 实用程序能够显示它是否针对 x64。希望这能帮助您找到更多关于它的信息。

64位二进制文件以 PE32 + 格式存储。请尝试读取 http://www.masm32.com/board/index.php?action=dlattach;topic=6687.0;id=3486

对于非托管 DLL 文件,首先需要检查它是否是16位 DLL 文件(希望不是)。 然后检查 IMAGE\_FILE_HEADER.Machine字段。

其他人已经花时间解决了这个问题,所以我在这里重复一遍:

要区分32位和64位 PE 文件,应该检查 IMAGE _ FILE _ HEADER. Machine 字段。基于 Microsoft PE 和 COFF 规格如下,我已列出 这个字段的所有可能值: Http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v8.doc

IMAGE _ FILE _ MACHINE _ UNKNOWN 0x0假定此字段的内容适用于任何机器类型

图片来源: IMAGE _ FILE _ MACHINE _ AM330x1d3 Matsushita AM33

IMAGE _ FILE _ MACHINE _ AMD640x8664 x64

IMAGE _ FILE _ MACHINE _ ARM 0x1c0 ARM little endian

EBC 0xebc EFI 字节码

IMAGE _ FILE _ MACHINE _ I3860x14c Intel 386或更高版本的处理器和兼容处理器

IMAGE _ FILE _ MACHINE _ IA640x200 Intel Itanium 处理器系列

三菱 M32R 小端点

IMAGE _ FILE _ MACHINE _ MIPS160x266 MIPS16

基于 FPU 的 IMAGE _ FILE _ MACHINE _ MIPSFPU 0x366 MIPS

基于 FPU 的 IMAGE _ FILE _ MACHINE _ MIPSFPU160x466 MIPS16

电源 PC 小端点

IMAGE _ FILE _ MACHINE _ POWERPCFP 0x1f1具有浮点支持的电源 PC

IMAGE _ FILE _ MACHINE _ R40000x166 MIPS little endian

IMAGE _ FILE _ MACHINE _ SH30x1a2 Hitachi SH3

IMAGE _ FILE _ MACHINE _ SH3DSP 0x1a3日立 SH3 DSP

日立 SH4

日立 SH5

图像 _ 文件 _ 机器 _ 拇指0x1c2拇指

IMAGE _ FILE _ MACHINE _ WCEMIPSV20x169 MIPS little-endian WCE v2

是的,你可以检查 IMAGE _ FILE _ MACHINE _ AMD64 | IMAGE _ FILE _ MACHINE _ IA64为64位,IMAGE _ FILE _ MACHINE _ I386为32位。

您可以找到 IMAGE_FILE_HEADER解决方案的 这里是 C # 示例实现

有一个简单的方法可以做到这一点与 CorFlags。打开 VisualStudio 命令提示符并键入“ corFlag [ your Assembly ]”。你会得到这样的东西:

C: Program Files (x86) Microsoft Visual Studio 9.0 VC > corFlag “ C: Windows Microsoft.NET Framework v2.0.50727 System. Data.dll”

Microsoft (R) . NET Framework CorFlags 转换工具.Version 3.5.21022.8 版权(c)微软公司。 保留所有权利。

版本: v2.0.50727 CLR 标题: 2.5 PE32 CorFlags: 24 0 32BIT: 0 签署: 1

你看到的是 PE 和32BIT。

  • 任何 CPU :

    PE32
    32BIT: 0

  • X86 :

    PE32
    32BIT: 1

  • X64:

    PE32 +
    32BIT: 0

您也可以使用 垃圾桶。使用 /headers/all标志及其列出的第一个文件头。

dumpbin /headers cv210.dll

64位

Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.




Dump of file cv210.dll


PE signature found


File Type: DLL


FILE HEADER VALUES
8664 machine (x64)
6 number of sections
4BBAB813 time date stamp Tue Apr 06 12:26:59 2010
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
2022 characteristics
Executable
Application can handle large (>2GB) addresses
DLL

32位

Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.




Dump of file acrdlg.dll


PE signature found


File Type: DLL


FILE HEADER VALUES
14C machine (x86)
5 number of sections
467AFDD2 time date stamp Fri Jun 22 06:38:10 2007
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2306 characteristics
Executable
Line numbers stripped
32 bit word machine
Debug information stripped
DLL

‘ find’可以让生活稍微轻松一点:

dumpbin /headers cv210.dll |find "machine"
8664 machine (x64)

IMAGE_OPTIONAL_HEADERMagic字段(尽管在 Windows 可执行图像(DLL/EXE 文件)中头部没有任何可选项)将告诉您 PE 的体系结构。

下面是一个从文件中获取体系结构的示例。

public static ushort GetImageArchitecture(string filepath) {
using (var stream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (var reader = new System.IO.BinaryReader(stream)) {
//check the MZ signature to ensure it's a valid Portable Executable image
if (reader.ReadUInt16() != 23117)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);


// seek to, and read, e_lfanew then advance the stream to there (start of NT header)
stream.Seek(0x3A, System.IO.SeekOrigin.Current);
stream.Seek(reader.ReadUInt32(), System.IO.SeekOrigin.Begin);


// Ensure the NT header is valid by checking the "PE\0\0" signature
if (reader.ReadUInt32() != 17744)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);


// seek past the file header, then read the magic number from the optional header
stream.Seek(20, System.IO.SeekOrigin.Current);
return reader.ReadUInt16();
}
}

目前仅有的两个架构常量是:

0x10b - PE32
0x20b - PE32+

干杯

更新 我已经有一段时间没有发布这个答案了,但是我仍然看到它时不时得到一些赞同,所以我觉得值得更新。我写了一个方法来获得一个 Portable Executable映像的架构,它还检查它是否被编译为 AnyCPU。不幸的是,答案是在 C + + 中,但是如果您有几分钟时间查找 WinNT.h中的结构,那么移植到 C # 应该不会太难。如果人们感兴趣,我会用 C # 编写一个端口,但是除非人们真的想要它,否则我不会花太多时间去强调它。

#include <Windows.h>


#define MKPTR(p1,p2) ((DWORD_PTR)(p1) + (DWORD_PTR)(p2))


typedef enum _pe_architecture {
PE_ARCHITECTURE_UNKNOWN = 0x0000,
PE_ARCHITECTURE_ANYCPU  = 0x0001,
PE_ARCHITECTURE_X86     = 0x010B,
PE_ARCHITECTURE_x64     = 0x020B
} PE_ARCHITECTURE;


LPVOID GetOffsetFromRva(IMAGE_DOS_HEADER *pDos, IMAGE_NT_HEADERS *pNt, DWORD rva) {
IMAGE_SECTION_HEADER *pSecHd = IMAGE_FIRST_SECTION(pNt);
for(unsigned long i = 0; i < pNt->FileHeader.NumberOfSections; ++i, ++pSecHd) {
// Lookup which section contains this RVA so we can translate the VA to a file offset
if (rva >= pSecHd->VirtualAddress && rva < (pSecHd->VirtualAddress + pSecHd->Misc.VirtualSize)) {
DWORD delta = pSecHd->VirtualAddress - pSecHd->PointerToRawData;
return (LPVOID)MKPTR(pDos, rva - delta);
}
}
return NULL;
}


PE_ARCHITECTURE GetImageArchitecture(void *pImageBase) {
// Parse and validate the DOS header
IMAGE_DOS_HEADER *pDosHd = (IMAGE_DOS_HEADER*)pImageBase;
if (IsBadReadPtr(pDosHd, sizeof(pDosHd->e_magic)) || pDosHd->e_magic != IMAGE_DOS_SIGNATURE)
return PE_ARCHITECTURE_UNKNOWN;


// Parse and validate the NT header
IMAGE_NT_HEADERS *pNtHd = (IMAGE_NT_HEADERS*)MKPTR(pDosHd, pDosHd->e_lfanew);
if (IsBadReadPtr(pNtHd, sizeof(pNtHd->Signature)) || pNtHd->Signature != IMAGE_NT_SIGNATURE)
return PE_ARCHITECTURE_UNKNOWN;


// First, naive, check based on the 'Magic' number in the Optional Header.
PE_ARCHITECTURE architecture = (PE_ARCHITECTURE)pNtHd->OptionalHeader.Magic;


// If the architecture is x86, there is still a possibility that the image is 'AnyCPU'
if (architecture == PE_ARCHITECTURE_X86) {
IMAGE_DATA_DIRECTORY comDirectory = pNtHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
if (comDirectory.Size) {
IMAGE_COR20_HEADER *pClrHd = (IMAGE_COR20_HEADER*)GetOffsetFromRva(pDosHd, pNtHd, comDirectory.VirtualAddress);
// Check to see if the CLR header contains the 32BITONLY flag, if not then the image is actually AnyCpu
if ((pClrHd->Flags & COMIMAGE_FLAGS_32BITREQUIRED) == 0)
architecture = PE_ARCHITECTURE_ANYCPU;
}
}


return architecture;
}

该函数接受一个指向内存中 PE 映像的指针(因此您可以选择如何获得它们的; 内存映射或将整个内存读入内存... ... 等等)。

用十六进制编辑器打开 dll,如 HxD

如果第9行有一个“ dt”,那么它就是64位。

如果第9行有一个“ L”,它就是32位。

我在 Powershell 脚本中重写了 C + + 解的第一个答案。脚本可以确定这种类型的.exe 和.dll 文件:

#Description       C# compiler switch             PE type       machine corflags
#MSIL              /platform:anycpu (default)     PE32  x86     ILONLY
#MSIL 32 bit pref  /platform:anycpu32bitpreferred PE32  x86     ILONLY | 32BITREQUIRED | 32BITPREFERRED
#x86 managed       /platform:x86                  PE32  x86     ILONLY | 32BITREQUIRED
#x86 mixed         n/a                            PE32  x86     32BITREQUIRED
#x64 managed       /platform:x64                  PE32+ x64     ILONLY
#x64 mixed         n/a                            PE32+ x64
#ARM managed       /platform:arm                  PE32  ARM     ILONLY
#ARM mixed         n/a                            PE32  ARM

这个解决方案比 corflags.exe 和通过 Assembly 加载汇编具有一些优势。在 C # 中加载-您将永远不会得到 BadImageFormatException 或关于无效标头的消息。

function GetActualAddressFromRVA($st, $sec, $numOfSec, $dwRVA)
{
[System.UInt32] $dwRet = 0;
for($j = 0; $j -lt $numOfSec; $j++)
{
$nextSectionOffset = $sec + 40*$j;
$VirtualSizeOffset = 8;
$VirtualAddressOffset = 12;
$SizeOfRawDataOffset = 16;
$PointerToRawDataOffset = 20;


$Null = @(
$curr_offset = $st.BaseStream.Seek($nextSectionOffset + $VirtualSizeOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $VirtualSize = $b.ReadUInt32();
[System.UInt32] $VirtualAddress = $b.ReadUInt32();
[System.UInt32] $SizeOfRawData = $b.ReadUInt32();
[System.UInt32] $PointerToRawData = $b.ReadUInt32();


if ($dwRVA -ge $VirtualAddress -and $dwRVA -lt ($VirtualAddress + $VirtualSize)) {
$delta = $VirtualAddress - $PointerToRawData;
$dwRet = $dwRVA - $delta;
return $dwRet;
}
);
}
return $dwRet;
}


function Get-Bitness2([System.String]$path, $showLog = $false)
{
$Obj = @{};
$Obj.Result = '';
$Obj.Error = $false;


$Obj.Log = @(Split-Path -Path $path -Leaf -Resolve);


$b = new-object System.IO.BinaryReader([System.IO.File]::Open($path,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read, [System.IO.FileShare]::Read));
$curr_offset = $b.BaseStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin)
[System.Int32] $peOffset = $b.ReadInt32();
$Obj.Log += 'peOffset ' + "{0:X0}" -f $peOffset;


$curr_offset = $b.BaseStream.Seek($peOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $peHead = $b.ReadUInt32();


if ($peHead -ne 0x00004550) {
$Obj.Error = $true;
$Obj.Result = 'Bad Image Format';
$Obj.Log += 'cannot determine file type (not x64/x86/ARM) - exit with error';
};


if ($Obj.Error)
{
$b.Close();
Write-Host ($Obj.Log | Format-List | Out-String);
return $false;
};


[System.UInt16] $machineType = $b.ReadUInt16();
$Obj.Log += 'machineType ' + "{0:X0}" -f $machineType;


[System.UInt16] $numOfSections = $b.ReadUInt16();
$Obj.Log += 'numOfSections ' + "{0:X0}" -f $numOfSections;
if (($machineType -eq 0x8664) -or ($machineType -eq 0x200)) { $Obj.Log += 'machineType: x64'; }
elseif ($machineType -eq 0x14c)                             { $Obj.Log += 'machineType: x86'; }
elseif ($machineType -eq 0x1c0)                             { $Obj.Log += 'machineType: ARM'; }
else{
$Obj.Error = $true;
$Obj.Log += 'cannot determine file type (not x64/x86/ARM) - exit with error';
};


if ($Obj.Error) {
$b.Close();
Write-Output ($Obj.Log | Format-List | Out-String);
return $false;
};


$curr_offset = $b.BaseStream.Seek($peOffset+20, [System.IO.SeekOrigin]::Begin);
[System.UInt16] $sizeOfPeHeader = $b.ReadUInt16();


$coffOffset = $peOffset + 24;#PE header size is 24 bytes
$Obj.Log += 'coffOffset ' + "{0:X0}" -f $coffOffset;


$curr_offset = $b.BaseStream.Seek($coffOffset, [System.IO.SeekOrigin]::Begin);#+24 byte magic number
[System.UInt16] $pe32 = $b.ReadUInt16();
$clr20headerOffset = 0;
$flag32bit = $false;
$Obj.Log += 'pe32 magic number: ' + "{0:X0}" -f $pe32;
$Obj.Log += 'size of optional header ' + ("{0:D0}" -f $sizeOfPeHeader) + " bytes";


#COMIMAGE_FLAGS_ILONLY               =0x00000001,
#COMIMAGE_FLAGS_32BITREQUIRED        =0x00000002,
#COMIMAGE_FLAGS_IL_LIBRARY           =0x00000004,
#COMIMAGE_FLAGS_STRONGNAMESIGNED     =0x00000008,
#COMIMAGE_FLAGS_NATIVE_ENTRYPOINT    =0x00000010,
#COMIMAGE_FLAGS_TRACKDEBUGDATA       =0x00010000,
#COMIMAGE_FLAGS_32BITPREFERRED       =0x00020000,


$COMIMAGE_FLAGS_ILONLY        = 0x00000001;
$COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
$COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000;


$offset = 96;
if ($pe32 -eq 0x20b) {
$offset = 112;#size of COFF header is bigger for pe32+
}


$clr20dirHeaderOffset = $coffOffset + $offset + 14*8;#clr directory header offset + start of section number 15 (each section is 8 byte long);
$Obj.Log += 'clr20dirHeaderOffset ' + "{0:X0}" -f $clr20dirHeaderOffset;
$curr_offset = $b.BaseStream.Seek($clr20dirHeaderOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $clr20VirtualAddress = $b.ReadUInt32();
[System.UInt32] $clr20Size = $b.ReadUInt32();
$Obj.Log += 'clr20VirtualAddress ' + "{0:X0}" -f $clr20VirtualAddress;
$Obj.Log += 'clr20SectionSize ' + ("{0:D0}" -f $clr20Size) + " bytes";


if ($clr20Size -eq 0) {
if ($machineType -eq 0x1c0) { $Obj.Result = 'ARM native'; }
elseif ($pe32 -eq 0x10b)    { $Obj.Result = '32-bit native'; }
elseif($pe32 -eq 0x20b)     { $Obj.Result = '64-bit native'; }


$b.Close();
if ($Obj.Result -eq '') {
$Obj.Error = $true;
$Obj.Log += 'Unknown type of file';
}
else {
if ($showLog) { Write-Output ($Obj.Log | Format-List | Out-String); };
return $Obj.Result;
}
};


if ($Obj.Error) {
$b.Close();
Write-Host ($Obj.Log | Format-List | Out-String);
return $false;
};


[System.UInt32]$sectionsOffset = $coffOffset + $sizeOfPeHeader;
$Obj.Log += 'sectionsOffset ' + "{0:X0}" -f $sectionsOffset;
$realOffset = GetActualAddressFromRVA $b $sectionsOffset $numOfSections $clr20VirtualAddress;
$Obj.Log += 'real IMAGE_COR20_HEADER offset ' + "{0:X0}" -f $realOffset;
if ($realOffset -eq 0) {
$Obj.Error = $true;
$Obj.Log += 'cannot find COR20 header - exit with error';
$b.Close();
return $false;
};


if ($Obj.Error) {
$b.Close();
Write-Host ($Obj.Log | Format-List | Out-String);
return $false;
};


$curr_offset = $b.BaseStream.Seek($realOffset + 4, [System.IO.SeekOrigin]::Begin);
[System.UInt16] $majorVer = $b.ReadUInt16();
[System.UInt16] $minorVer = $b.ReadUInt16();
$Obj.Log += 'IMAGE_COR20_HEADER version ' + ("{0:D0}" -f $majorVer) + "." + ("{0:D0}" -f $minorVer);


$flagsOffset = 16;#+16 bytes - flags field
$curr_offset = $b.BaseStream.Seek($realOffset + $flagsOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $flag32bit = $b.ReadUInt32();
$Obj.Log += 'CorFlags: ' + ("{0:X0}" -f $flag32bit);


#Description       C# compiler switch             PE type       machine corflags
#MSIL              /platform:anycpu (default)     PE32  x86     ILONLY
#MSIL 32 bit pref  /platform:anycpu32bitpreferred PE32  x86     ILONLY | 32BITREQUIRED | 32BITPREFERRED
#x86 managed       /platform:x86                  PE32  x86     ILONLY | 32BITREQUIRED
#x86 mixed         n/a                            PE32  x86     32BITREQUIRED
#x64 managed       /platform:x64                  PE32+ x64     ILONLY
#x64 mixed         n/a                            PE32+ x64
#ARM managed       /platform:arm                  PE32  ARM     ILONLY
#ARM mixed         n/a                            PE32  ARM


$isILOnly = ($flag32bit -band $COMIMAGE_FLAGS_ILONLY) -eq $COMIMAGE_FLAGS_ILONLY;
$Obj.Log += 'ILONLY: ' + $isILOnly;
if ($machineType -eq 0x1c0) {#if ARM
if ($isILOnly) { $Obj.Result = 'ARM managed'; }
else { $Obj.Result = 'ARM mixed'; }
}
elseif ($pe32 -eq 0x10b) {#pe32
$is32bitRequired = ($flag32bit -band $COMIMAGE_FLAGS_32BITREQUIRED) -eq $COMIMAGE_FLAGS_32BITREQUIRED;
$is32bitPreffered = ($flag32bit -band $COMIMAGE_FLAGS_32BITPREFERRED) -eq $COMIMAGE_FLAGS_32BITPREFERRED;
$Obj.Log += '32BIT: ' + $is32bitRequired;
$Obj.Log += '32BIT PREFFERED: ' + $is32bitPreffered
if     ($is32bitRequired  -and $isILOnly  -and $is32bitPreffered) { $Obj.Result = 'AnyCpu 32bit-preffered'; }
elseif ($is32bitRequired  -and $isILOnly  -and !$is32bitPreffered){ $Obj.Result = 'x86 managed'; }
elseif (!$is32bitRequired -and !$isILOnly -and $is32bitPreffered) { $Obj.Result = 'x86 mixed'; }
elseif ($isILOnly)                                                { $Obj.Result = 'AnyCpu'; }
}
elseif ($pe32 -eq 0x20b) {#pe32+
if ($isILOnly) { $Obj.Result = 'x64 managed'; }
else { $Obj.Result = 'x64 mixed'; }
}


$b.Close();
if ($showLog) { Write-Host ($Obj.Log | Format-List | Out-String); }
if ($Obj.Result -eq ''){ return 'Unknown type of file';};
$flags = '';
if ($isILOnly) {$flags += 'ILONLY';}
if ($is32bitRequired) {
if ($flags -ne '') {$flags += ' | ';}
$flags += '32BITREQUIRED';
}
if ($is32bitPreffered) {
if ($flags -ne '') {$flags += ' | ';}
$flags += '32BITPREFERRED';
}
if ($flags -ne '') {$flags = ' (' + $flags +')';}
return $Obj.Result + $flags;
}

用法例子:

#$filePath = "C:\Windows\SysWOW64\regedit.exe";#32 bit native on 64bit windows
$filePath = "C:\Windows\regedit.exe";#64 bit native on 64bit windows | should be 32 bit native on 32bit windows


Get-Bitness2 $filePath $true;

如果不需要查看细节,可以省略第二个参数

这里描述了一种快速且可能是肮脏的方法: https://superuser.com/a/889267。在编辑器中打开 DLL 并检查“ PE”序列之后的第一个字符。

这个 恶作剧工作,只需要记事本。

使用文本编辑器(如记事本)打开 dll 文件,找到字符串 PE的第一个匹配项。下面的字符定义 dll 是32位还是64位。

32位:

PE  L

64位:

PE  d†

因为第三方工具总是在 %Program files (x86)%中安装(即使是 x64安装!)要求合适的 x32 | x64 fortran 运行时首先在 %path%上列出以正确运行,我将 C + + 强力弹解决方案收集到 matlab 中以返回:

  • 种类 : Executable|Library|Other
  • 代码类型 : Native|Mixed|Managed
  • 平台 : x32|x64|AnyCpu|x32Preferred|Other

一旦在内存中有了原始的 PE 结构,就很容易适应其他语言。

function [simplifiedInfo] = GetPortableExecutableSimplifiedInfo(filename)
%[
% Checking arguments
if (nargin <1), error('MATLAB:minrhs', 'Not enough input argments.'); end


% Initializing simplified info
simplifiedInfo.Kind = 'Other';
simplifiedInfo.CodeType = 'Other';
simplifiedInfo.Platform = 'Other';


% Obtaining raw info
[rawInfo, PEConstants] = GetPortableExecutableRawInfo(filename);


% Determining 'Kind' of PE
if (isfield(rawInfo, 'PEOptionalHeader') && (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_EXECUTABLE_IMAGE))
if (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_DLL)
simplifiedInfo.Kind = 'Library';
else
simplifiedInfo.Kind = 'Executable';
end
else
% No optional header or no IMAGE_FILE_EXECUTABLE_IMAGE flag ...
% Maybe just .obj or other thing
simplifiedInfo.Kind = 'Other';
end


% Determining 'CodeType'
% NB: 'COR20Header' is present for MSIL code, but not for native code
if (isfield(rawInfo, 'COR20Header'))
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_ILONLY)
simplifiedInfo.CodeType = 'Managed';
else
simplifiedInfo.CodeType = 'Mixed';
end
else
simplifiedInfo.CodeType = 'Native';
end


% Determining platform
if (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_AMD64)
simplifiedInfo.Platform = 'x64';
elseif (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_I386)
if (isfield(rawInfo, 'COR20Header'))
% PE contains MSIL code, need more checks
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITREQUIRED)
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITPREFERRED)
simplifiedInfo.Platform = 'x32Preferred';
else
simplifiedInfo.Platform = 'x32';
end
else
simplifiedInfo.Platform = 'AnyCpu';
end
else
% This is native code so ...
simplifiedInfo.Platform = 'x32';
end
else
% ARM, ...
simplifiedInfo.Platform = 'Other';
end
%]
end

内部 GetPortableExecutableRawInfo函数的源代码可以获得 给你