<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何判斷一個(gè) Dot Net 程序是 32 位還是 64 位?

          共 9039字,需瀏覽 19分鐘

           ·

          2021-06-18 04:28

          緣起

          前陣子,朋友遇到一個(gè) .net 程序啟動(dòng)不起來的問題。根據(jù)之前的經(jīng)驗(yàn),一般是依賴的動(dòng)態(tài)庫加載失敗導(dǎo)致的?;蛘哒也坏剑ㄒ蕾嚨膭?dòng)態(tài)庫沒有放到相應(yīng)的目錄下,一般放到應(yīng)用程序所在目錄即可),或者不匹配(64 位的程序加載 32 位的動(dòng)態(tài)庫,或者 32 位的程序加載 64 位的動(dòng)態(tài)庫)。整個(gè)排查過程并不復(fù)雜,本文不打算介紹整個(gè)排查過程,而是想介紹一些 .net 程序的基本常識(shí)(比如,以 Any CPU 編譯出來的程序,是 32 位的還是 64 位的?),還會(huì)介紹幾個(gè)我認(rèn)為不錯(cuò)的查看工具。

          在介紹查看方法之前,先介紹一些基本常識(shí)。

          Any CPU

          做過 .net 開發(fā)的小伙伴一定接觸過 Any CPU ,新建一個(gè) c# 測試工程,默認(rèn)的編譯選項(xiàng)就是這個(gè)。

          csharp-compile-option

          目標(biāo)平臺(tái)(G) 和 首選 32 位(P) 兩個(gè)選項(xiàng)共同決定了傳遞給 csc.exe 的 /platform 選項(xiàng)的值。

          目標(biāo)平臺(tái)(G) 是 Any CPU的情況下,如果勾選了 首選 32 位(P),那么 /platform 的值是 anycpu32bitpreferred,如果未勾選,那么 /platform 的值是 anycpu。

          說明: 首選 32 位(P) 選項(xiàng)在 dll 工程中不允許修改。雖然編譯的時(shí)候不能改,但是我們可以手動(dòng)修改編譯后的文件。:)

          /platform 選項(xiàng)對(duì)生成的模塊的影響以及在運(yùn)行時(shí)的影響,參考下表:

          /platform 開關(guān)生成的托管模塊x86 Windowsx64 WindowsARM Windows RT
          anycpu(默認(rèn))PE32 / 任意 CPU 架構(gòu)作為 32 位應(yīng)用程序運(yùn)行作為 64 位應(yīng)用程序運(yùn)行作為 32 位應(yīng)用程序運(yùn)行
          anycpu32bitpreferredPE32 / 任意 CPU 架構(gòu)作為 32 位應(yīng)用程序運(yùn)行作為 WoW64 位應(yīng)用程序運(yùn)行作為 32 位應(yīng)用程序運(yùn)行
          x86PE32 / X86作為 32位應(yīng)用程序運(yùn)行作為 WoW64 位應(yīng)用程序運(yùn)行不運(yùn)行
          x64PE32+ / X64不運(yùn)行作為 64 位應(yīng)用程序運(yùn)行不運(yùn)行
          ARMPE32 / ARM不運(yùn)行不運(yùn)行作為 32 位應(yīng)用程序運(yùn)行

          說明:以上表格摘錄自 《CLR via c#》(第4版)第一章

          PE 頭相關(guān)字段

          一般,一個(gè)標(biāo)準(zhǔn)的 PE 文件由四大部分組成: DOS 頭,PE 頭,節(jié)表,節(jié)內(nèi)容。這里只關(guān)心 PE頭中相關(guān)字段。

          32 位 PE 頭定義如下:

          typedef struct _IMAGE_NT_HEADERS {
              DWORD Signature;
              IMAGE_FILE_HEADER FileHeader;
              IMAGE_OPTIONAL_HEADER32 OptionalHeader;
          } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

          其中,Signature 的內(nèi)容是 PE\0\0,非常好認(rèn)。

          FileHeader 對(duì)應(yīng)的結(jié)構(gòu)體定義如下:

          typedef struct _IMAGE_FILE_HEADER {
              WORD    Machine;
              WORD    NumberOfSections;
              DWORD   TimeDateStamp;
              DWORD   PointerToSymbolTable;
              DWORD   NumberOfSymbols;
              WORD    SizeOfOptionalHeader;
              WORD    Characteristics;
          } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
          • Machine ,對(duì)于 32 位程序,這個(gè)值一般是 0x14c,對(duì)于 64 位程序一般是 0x8664。但對(duì)于 .net 程序,不能以此字段作為判斷依據(jù)。

          OptionalHeader 對(duì)應(yīng)的結(jié)構(gòu)體定義如下:

          typedef struct _IMAGE_OPTIONAL_HEADER32 {
              WORD        Magic;
              // ... 省略無關(guān)字段
              IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 一共16項(xiàng)
          } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
          • Magic 如果為 010B,表示這是一個(gè) PE32 文件,如果為 020B 表示這是一個(gè) PE32+ 文件,也就是 64 位的 PE 文件。

            與 FileHeader.Machine 一樣,對(duì)于 .net 程序,不能以此字段作為判斷依據(jù)。

          • DataDirectory 中一共有 16 項(xiàng)。其中,最后一項(xiàng)是保留項(xiàng),第 14 項(xiàng)(索引從 0 開始)指向了 CLR 的結(jié)構(gòu)。

          這個(gè)結(jié)構(gòu)是 IMAGE_COR20_HEADER,定義如下:

          typedef struct IMAGE_COR20_HEADER
          {

              // Header versioning
              DWORD                   cb;              
              WORD                    MajorRuntimeVersion;
              WORD                    MinorRuntimeVersion;
              
              // Symbol table and startup information
              IMAGE_DATA_DIRECTORY    MetaData;        
              DWORD                   Flags; // 這個(gè)字段的意義,參考 ReplacesCorHdrNumericDefines           
            
           // The main program if it is an EXE (not used if a DLL?)
              // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint.
           // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint
           // (depricated for DLLs, use modules constructors intead). 
              union {
                  DWORD               EntryPointToken;
                  DWORD               EntryPointRVA;
              };
              
              // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and
              // code:PEFile.GetResource and accessible from managed code from
           // System.Assembly.GetManifestResourceStream.  The meta data has a table that maps names to offsets into
           // this blob, so logically the blob is a set of resources. 
              IMAGE_DATA_DIRECTORY    Resources;
           // IL assemblies can be signed with a public-private key to validate who created it.  The signature goes
           // here if this feature is used. 
              IMAGE_DATA_DIRECTORY    StrongNameSignature;

              IMAGE_DATA_DIRECTORY    CodeManagerTable;   // Depricated, not used 
           // Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points)
              IMAGE_DATA_DIRECTORY    VTableFixups;
              IMAGE_DATA_DIRECTORY    ExportAddressTableJumps;

           // null for ordinary IL images.  NGEN images it points at a code:CORCOMPILE_HEADER structure
              IMAGE_DATA_DIRECTORY    ManagedNativeHeader;
              
          } IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER;

          其中,Flags 的值可以參考如下枚舉:

          typedef enum ReplacesCorHdrNumericDefines
          {
          // COM+ Header entry point flags.
              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,
              
          // 省略一些無關(guān)的內(nèi)容
          } ReplacesCorHdrNumericDefines;

          說明:以上定義可以在 CorHdr.h 中找到。

          了解了以上知識(shí),就可以手動(dòng)查看 PE 文件來進(jìn)行判斷了。但是手動(dòng)判斷既容易錯(cuò),又麻煩,還得時(shí)不時(shí)得翻看一下 PE 文件格式,很不方便。除了通過手動(dòng)查看 PE 文件來查看,還可以通過工具來查看。本文簡單介紹幾個(gè)常用工具及其查看方法。

          查看工具

          • CorFlags.exe

            view-net-bitness-in-corflags

            除了查看,CorFlags.exe 也可以修改對(duì)應(yīng)的標(biāo)記位。具體用法可以直接在命令行中輸入 CorFlags.exe 進(jìn)行查看。

          • dumpbin

            dumpbin 可以查看很多信息,對(duì)于 .net 程序,可以使用 dumpbin /clrheader 選項(xiàng)查看 clr 頭信息。如下圖:

            上圖是兩個(gè)以不同編譯選項(xiàng)生成的程序的對(duì)比效果,我第一次查看 dumpbin 的顯示結(jié)果沒看懂,對(duì)比后才明白。

          • cff explorer

            帶圖形界面的 PE 工具,不僅可以查看,也可以修改,很方便。

            view-net-bitness-in-cff-explorer

          除了這幾個(gè)工具,還有很多其它工具也可以查看,就不一一列舉了。

          參考資料

          • 《CLR via c#》(第4版)
          • https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-image-only
          • https://www.cnblogs.com/seacryfly/articles/CorFlags.html
          • https://ntcore.com/files/dotnetformat.htm
          • CorHdr.h


          瀏覽 119
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  97香蕉网 | 亚洲AV无码成人精品区在线欢看 | 色就是色,欧美 | 黄色考逼视频免费观看网站www | 国产黄色电影免费在线观看 |