当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何查找本机DLL文件是否编译为x64或x86?》经验,为你挑选了5个好方法。

我想确定本机程序集是否从托管代码应用程序(C#)编译为x64或x86 .

我认为它必须在PE头中的某处,因为OS加载器需要知道这些信息,但我找不到它.当然我更喜欢在托管代码中执行它,但如果有必要,我可以使用本机C++.



1> Mark McDonal..:

你也可以使用DUMPBIN.使用/headersor /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)


稍微用户友好;)
DUMPBIN不适用于.NET EXE.我有一个64位的.NET EXE,DUMPBIN说它是32位("14C机器(x86)"),但corflags说是任何CPU("PE:PE32,32BIT:0").Dependency Walker也误导了它.
它需要`mspdb100.dll` :(

2> BLogan..:

使用CorFlags可以轻松实现此目的.打开Visual Studio命令提示符并键入"corflags [your assembly]".你会得到这样的东西:

c:\ Program Files(x86)\ Microsoft Visual Studio 9.0\VC> corflags"C:\ Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll"

Microsoft(R).NET Framework CorFlags转换工具.版本3.5.21022.8版权所有(c)Microsoft Corporation.版权所有.

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

你正在专注于PE和32BIT.

任何CPU:

PE:PE32
32BIT:0

x86:

PE:PE32
32BIT:1

64位:

PE:PE32 +
32BIT:0


@BLogan你应该看看我对Steven Behnke的评论.我知道corflags实用程序,但它不适用于本机程序集.
Corflags输出在后期版本(Windows SDK 8或更高版本)中的变化.现在代替32BIT,它有32BITREQUIRED和32BITPREFERRED.请参阅位于C:\ Program Files(x86)\ Windows Kits\8.0\Include\um\CorHdr.h的CorHdr.h中的说明.据我所知,32BITREQUIRED取代了32BIT.另请参阅这个[问题]的答案(http://stackoverflow.com/questions/13767010/where-can-i-find-a-reference-for-what-every-bit-of-the-corflags-value-means ).

3> Zanon..:

这个技巧有效,只需要记事本.

使用文本编辑器(如记事本)打开dll文件,找到第一次出现的字符串PE.以下字符定义dll是32位还是64位.

32位:

PE  L

64位:

PE  d†



4> Jason Larke..:

Magic领域IMAGE_OPTIONAL_HEADER(虽然没有什么可选的有关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++中,但如果你有几分钟的时间来查找结构,那么移植到C#应该不会太难WinNT.h.如果人们有兴趣我会用C#写一个端口,但除非人们真的想要它,否则我不会花太多时间来强调它.

#include 

#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图像的指针(因此您可以选择如何获取它们的毒药;内存映射或将整个内容读入内存......无论如何).


AnyCPU意味着:AnyCPU,因此它在PE头中列为0x10B,以便向后兼容32位.要检查它与直接32位之间的区别,你需要找出CorFlags在PE中获取其"32BIT"标志的位置,我不知道我的头脑.

5> ShuggyCoUk..:

对于非托管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_AM33 0x1d3松下AM33

IMAGE_FILE_MACHINE_AMD64 0x8664 x64

IMAGE_FILE_MACHINE_ARM 0x1c0 ARM小端

IMAGE_FILE_MACHINE_EBC 0xebc EFI字节码

IMAGE_FILE_MACHINE_I386 0x14c Intel 386或更高版本处理器和兼容处理器

IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium处理器系列

IMAGE_FILE_MACHINE_M32R 0x9041三菱M32R小端

IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

带FPU的IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS

带FPU的IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16

IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC little endian

IMAGE_FILE_MACHINE_POWERPCFP 0x1f1具有浮点支持的Power PC

IMAGE_FILE_MACHINE_R4000 0x166 MIPS小端

IMAGE_FILE_MACHINE_SH30x1a2日立SH3

IMAGE_FILE_MACHINE_SH3DSP 0x1a3日立SH3 DSP

IMAGE_FILE_MACHINE_SH40x1a6日立SH4

IMAGE_FILE_MACHINE_SH50x1a8日立SH5

IMAGE_FILE_MACHINE_THUMB 0x1c2 Thumb

IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS little-endian WCE v2

是的,您可以检查84位的IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64和32位的IMAGE_FILE_MACHINE_I386.

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有