Retrieve JIT output

后端 未结 5 2047
Happy的楠姐
Happy的楠姐 2020-12-03 15:00

I\'m interested in viewing the actual x86 assembly output by a C# program (not the CLR bytecode instructions). Is there a good way to do this?

5条回答
  •  抹茶落季
    2020-12-03 15:37

    As @IvanDanilov answered, you can use WinDbg and SOS. I am answering separately to provide a walk-through.

    In this example, I want to view the disassembly of the AreEqual() method from:

    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'.");
                }
            }
        }
    }
    

    Steps:

    1. Open WinDbg. From the File menu, select "Open Executable...". Browse to the location of the EXE (in my case, C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release\TestArrayCompare.exe).
    2. Add the directory containing the PDB file to the symbol path. For example:

      .sympath "C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release"
      
    3. In WinDbg's Command window, set a breakpoint when clr.dll is loaded via:

      sxe ld:clr
      
    4. Continue by running the 'Go' command: g

    5. At the clr.dll ModLoad, load SOS: .loadby sos clr
    6. Run BPMD to break on the method for which you wish to see the disassembly. For example:

      0:000> !BPMD TestArrayCompare.exe TestArrayCompare.Program.AreEqual
      Adding pending breakpoints...
      
    7. Continue again by running the 'Go' command: g

    8. Run Name2EE to see the method descriptor. For example:

      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. Run the BPMD command in the "Not JITTED yet" line. For example:

      0:000> !bpmd -md 00a637a4
      MethodDesc = 00a637a4
      Adding pending breakpoints...
      
    10. Continue again: g

    11. You should see "JITTED ..." in the Command window. Re-run the Name2EE command to see the address of the JIT code. For example:

      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. Use the u command to disassemble, starting at the listed code address. For example:

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

    (For the above, I was using WinDbg 6.3.9600.17200 X86 from the Windows 8.1 SDK.)

    One handy reference is the SOS.dll (SOS Debugging Extension) reference page on MSDN.

提交回复
热议问题