2011-08-03 4 views
7

私は実際のx86アセンブリ出力をC#プログラム(CLRバイトコード命令ではありません)で表示することに興味があります。これを行う良い方法はありますか?JIT出力を取得する

答えて

4

SOS/SOSEXでWinDbgを使用し、x86コードがメソッドテーブルにJITされていることを確認してから、uコマンドで実際のアンアセンブリを確認してください。したがって、実際のコードが表示されます。

ここで述べた他のものと同様に、ngenを使用すると、実際のJITコンパイル結果と正確に一致しないコードを参照することができます。 Visual Studioでは、JITのコンパイルはデバッガが存在するかどうかに大きく依存するため、可能です。

UPD:若干の説明。 WinDbgもデバッガですが、ネイティブです。

Hereこのテクニックについて詳しく読むことができます。

7

Visual Studioでアプリケーションをデバッグしているときに、停止したコード(ブレークポイントを使用)を右クリックし、[逆アセンブリに移動]をクリックします。ネイティブ命令でデバッグできます。

ディスク上の* .exeファイルを使用している場合は、NGenを使用してネイティブ出力を生成してから逆アセンブルすることができます(これは決して試したことがないので動作するとは限りません)。ここで

は、C#で書かれた簡単な算術演算からいくつかのサンプルオペコードです:

 
      int x = 5; 
mov   dword ptr [ebp-40h],5 
      int y = 6; 
mov   dword ptr [ebp-44h],6 
      int z = x + y; 
mov   eax,dword ptr [ebp-40h] 
add   eax,dword ptr [ebp-44h] 
mov   dword ptr [ebp-48h],eax 
+0

実際の最適化コードを表示するには、[here](https://stackoverflow.com/a/4678883/238419)の手順に従う必要があることに注意してください –

2

あなたが(ブレークポイントを配置し、その後、Dissassemblyウィンドウを表示してAltキー+ Ctrlキー+ DをVisual Studioのデバッガを使用することができます)またはNative Image Generator Tool(ngen.exe)を試してください。

1

メモリダンプを実行できます。ただし、メモリ内のコードには必ずしもすべてのメソッドが含まれているわけではありません。

ngenは、AOT、またはAhead-of-Timeコード生成を実行します。これは、JITコードとは異なる場合があります。

4

@IvanDanilov answeredとして、WinDbgとSOSを使用できます。ウォークスルーを提供するために私は別に答えています。

using System; 

namespace TestArrayCompare 
{ 
    class Program 
    { 
     static bool AreEqual(byte[] a1, byte[] a2) 
     { 
      bool result = true; 
      for (int i = 0; i < a1.Length; ++i) 
      { 
       if (a1[i] != a2[i]) 
        result = false; 
      } 
      return result; 
     } 

     static void Main(string[] args) 
     { 
      byte[] a1 = new byte[100]; 
      byte[] a2 = new byte[100]; 
      if (AreEqual(a1, a2)) 
      { 
       Console.WriteLine("`a1' equals `a2'."); 
      } 
      else 
      { 
       Console.WriteLine("`a1' does not equal `a2'."); 
      } 
     } 
    } 
} 

手順:

  1. 開くWinDbgのこの例では

    は、IからAreEqual()メソッドの分解を表示します。 「ファイル」メニューから「実行可能ファイルを開く...」を選択します。 EXE(私の場合はC:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release\TestArrayCompare.exe)の場所を参照してください。

  2. PDBファイルを含むディレクトリをシンボルパスに追加します。clr.dllg

  3. : 'GO' コマンドを実行して続行

     
    sxe ld:clr 
    
  4. :たとえば:clr.dllを介してロードされたときのWinDbgのコマンドウィンドウで

     
    .sympath "C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release" 
    
  5. 、ブレークポイントを設定ModLoad、load SOS:.loadby sos clr

  6. BPMDを実行すると、 shを分解して見てください。たとえば:

     
    0:000> !BPMD TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Adding pending breakpoints... 
    
  7. は 'GO' コマンドを実行して、もう一度続行:g

  8. 実行Name2EEメソッドの記述を参照してください。たとえば:

     
    0:000> !Name2EE TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Module:  00a62edc 
    Assembly: TestArrayCompare.exe 
    Token:  06000001 
    MethodDesc: 00a637a4 
    Name:  TestArrayCompare.Program.AreEqual(Byte[], Byte[]) 
    Not JITTED yet. Use !bpmd -md 00a637a4 to break on run. 
    
  9. は「まだJITコンパイルなし」のラインでBPMDコマンドを実行します。たとえば:

     
    0:000> !bpmd -md 00a637a4 
    MethodDesc = 00a637a4 
    Adding pending breakpoints... 
    
  10. は再び続行:g

  11. あなたはコマンドウィンドウで "JITコンパイルを..." が表示されるはずです。 Name2EEコマンドを再実行して、JITコードのアドレスを確認します。たとえば:

     
    0:000> !Name2EE TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Module:  00a62edc 
    Assembly: TestArrayCompare.exe 
    Token:  06000001 
    MethodDesc: 00a637a4 
    Name:  TestArrayCompare.Program.AreEqual(Byte[], Byte[]) 
    JITTED Code Address: 00b500c8 
    
  12. が記載されたコードのアドレスから始まる、分解しuコマンドを使用します。例えば:

     
    0:000> u 00b500c8 L20 
    00b500c8 55    push ebp 
    00b500c9 8bec   mov  ebp,esp 
    00b500cb 57    push edi 
    00b500cc 56    push esi 
    ... 
    

(上記の場合、私は、Windows 8.1 SDKからのWinDbg 6.3.9600.17200 X86を使用した。)

一つ便利参照はSOS.dll (SOS Debugging Extension) reference page on MSDNあります。

関連する問題