2011-08-03 17 views
7

Tôi quan tâm đến việc xem đầu ra lắp ráp x86 thực tế bằng chương trình C# (không phải hướng dẫn bytecode CLR). Có cách nào tốt để làm điều này?Truy xuất đầu ra JIT

Trả lời

4

Bạn nên sử dụng WinDbg với SOS/SOSEX, đảm bảo rằng phương pháp bạn muốn xem mã x86 là JITted trong bảng phương thức và sau đó xem gỡ bỏ thực tế với lệnh u. Vì vậy, bạn sẽ thấy mã thực tế.

Như những người khác được đề cập ở đây, với ngen bạn có thể thấy mã không khớp chính xác với kết quả biên dịch JIT thực tế. Với Visual Studio nó cũng có thể bởi vì biên dịch của JIT phụ thuộc rất nhiều vào thực tế nếu trình gỡ lỗi có mặt hay không.

UPD: Một số làm rõ. WinDbg cũng là một trình gỡ lỗi, nhưng nó là gốc một.

Here bạn có thể đọc kỹ về kỹ thuật này.

7

Trong khi gỡ lỗi ứng dụng của bạn trong Visual Studio, bạn có thể nhấp chuột phải vào mã mà bạn đã dừng (sử dụng điểm ngắt) và nhấp vào "Chuyển sang tháo gỡ". Bạn có thể gỡ lỗi thông qua các hướng dẫn gốc.

Để làm điều đó với tệp * .exe trên đĩa, có thể bạn sử dụng NGen để tạo ra đầu ra gốc và sau đó tháo rời (mặc dù tôi chưa bao giờ thử điều đó, vì vậy tôi không thể đảm bảo rằng nó sẽ hoạt động).

Dưới đây là một số opcodes mẫu từ hoạt động số học đơn giản mà được viết bằng 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

Lưu ý rằng bạn cần thực hiện theo các bước [tại đây] (https://stackoverflow.com/a/4678883/238419) nếu bạn muốn xem mã được tối ưu hóa thực tế –

2

Bạn có thể sử dụng Visual Studio Debugger bằng cách đặt một breakpoint và sau đó xem cửa sổ Dissassembly (Alt + Ctrl + D) hoặc thử Native Image Generator Tool (ngen.exe).

1

Bạn có thể thực hiện kết xuất bộ nhớ. Tuy nhiên, lưu ý rằng mã trong bộ nhớ không nhất thiết phải chứa mọi phương thức.

Ngừng thực hiện AOT hoặc Tạo mã theo thời gian, có thể khác với mã JIT.

4

Là @IvanDanilov answered, bạn có thể sử dụng WinDbg và SOS. Tôi đang trả lời riêng để cung cấp một bước đi.

Trong ví dụ này, tôi muốn xem tháo của phương pháp AreEqual() từ:

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

bước:

  1. mở WinDbg. Từ trình đơn Tệp, chọn "Mở thực thi ...". Duyệt đến vị trí của EXE (trong trường hợp của tôi là C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release\TestArrayCompare.exe).
  2. Thêm thư mục chứa tệp PDB vào đường dẫn biểu tượng.Ví dụ:

     
    .sympath "C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release" 
    
  3. Trong cửa sổ Command WinDbg của, thiết lập một breakpoint khi clr.dll được nạp qua:

     
    sxe ld:clr 
    
  4. Tiếp tục bằng cách chạy 'Go' lệnh: g

  5. Tại clr.dll ModLoad, tải SOS: .loadby sos clr
  6. Chạy BPMD để phá vỡ phương pháp mà bạn sử dụng sh để xem việc tháo gỡ. Ví dụ:

     
    0:000> !BPMD TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Adding pending breakpoints... 
    
  7. Tiếp tục một lần nữa bằng cách chạy lệnh 'Go': g

  8. Run Name2EE để xem mô tả phương pháp. Ví dụ:

     
    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. Chạy lệnh BPMD trong dòng "Chưa được JITTED". Ví dụ:

     
    0:000> !bpmd -md 00a637a4 
    MethodDesc = 00a637a4 
    Adding pending breakpoints... 
    
  10. Tiếp tục một lần nữa: g

  11. Bạn sẽ thấy "JITted ..." trong cửa sổ lệnh. Chạy lại lệnh Name2EE để xem địa chỉ của mã JIT. Ví dụ:

     
    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. Sử dụng lệnh u để tháo rời, bắt đầu từ địa chỉ mã được liệt kê. Ví dụ:

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

(Đối với ở trên, tôi đã sử dụng WinDbg 6.3.9600.17200 X86 từ Windows 8.1 SDK.)

Một tài liệu tham khảo có ích là SOS.dll (SOS Debugging Extension) reference page on MSDN.