開放源碼的.NET 反編譯工具 .NET IL調試工具 學習微軟中間語言(MSIL)的絕佳工具 Dotnet IL Editor 推薦


Dotnet IL Editor是一款.NET平台反編譯工具,可以反編譯.NET程序集文件為IL代碼,並且可以執行,調試反編譯后生成的IL代碼。它的設計出發點比較直觀,新建一個項目,添加程序集文件,設置斷點(F9),然后就可以調試反編譯后的程序集文件,Step Into,Step Out均可,以此原理,可以找到系統的瓶頸代碼,也可以深入的學習MSIL微軟中間語言。

先建立一個C#控制台項目,設計一個數字相加的方法,並在Main方法中調用它

image

程序總共不到10行,把數字1和2相加,輸出到控制台。

 public class TestEditor
    {
        public static int Sum(int a, int b)
        {
            return a + b;
        }

        public static void Main(string [] args)
        {
            Console.WriteLine(Sum(1,2));
            Console.ReadLine();
        }
    }

執行程序Dile.exe, 新建一個項目,在項目瀏覽器中點右鍵添加程序集,一層層的展開該程序集,如下圖所示

image

與Visual Studio的解決方案瀏覽器相似,它按照命名空間展開,列出了程序集中的方法,雙擊該方法,可以在編輯器中打開IL源代碼,IL編輯器窗口是只讀的。

 

探索.NET代碼的奧秘

記得.NET教材中有一條原理知識,類型默認繼承自object類,當沒有為類型定義構造方法(ctor)時,.NET編譯器會為它生成一個默認的構造方法,該方法不帶參數。如果在阻止默認生成的構造方法,只需要為類型定義一個方法,即可阻止編譯器的這個行為。

為什么不現在就試一下這條原理是否正缺,或是有什么遺漏的地方。於是修改類型定義的方法,給它加上一個帶參數的構造方法,該方法為一個空方法,帶參數以區別是.NET生成還是我們手動添加的。源代碼是這樣的

 public class TestEditor
    {
        public TestEditor(string str)
        {
            
        }

        public static int Sum(int a, int b)
        {
            return a + b;
        }

        public static void Main(string [] args)
        {
            Console.WriteLine(Sum(1,2));
            Console.ReadLine();
        }
    }

TestEditor類型現在有一個自定義的構造方法,帶一個字符串參數。再次到IL Editor中打開,看看它生成的IL代碼

image

果然如此,生成的IL代碼中,沒有默認的構造方法,取而代之的是我們定義的構造方法。

 

再來驗證一條知識點,const常量會被以常量的形式編譯到程序集中,因而它的效率很高。再修改C#源代碼,編譯,IL Editor中打開,C#的源代碼現在看起來是這樣的

public class TestEditor
    {
        public  const string ProductName="Enterprise Solution";
        public TestEditor(string str)
        {
            
        }

        public static int Sum(int a, int b)
        {
            return a + b;
        }

        public static void Main(string [] args)
        {
            string productionName = ProductName;
            Console.WriteLine(productionName);
            Console.WriteLine(Sum(1,2));
            Console.ReadLine();
        }
    }

再來看生成的IL代碼,它顯示的結果如下

image

反編譯后的結果與我們曾看到過的知識點一樣,驗證所學無誤。

在源代碼中,控制台主方法中,它調用1+2求和的方法,也是以常量的形式編譯進程序集。

Console.WriteLine(Sum(1,2));

對應的.NET IL代碼是

    ldc.i4.1
    ldc.i4.2
    call int32 ILEditorLibrary.TestEditor::Sum(int32, int32)
    call void [mscorlib]System.Console::WriteLine(int32)

IL是基於堆棧的語言,先壓入值1,再壓入值2,再對二者求和,最后調用方法顯示到控制台上。

 

調試IL代碼

IL Editor的調試功能是它的亮點之一,可以在打開的IL代碼中直接設置斷點(F9, Toogle breakpoint),然后點擊工具欄中的Run,啟動調試。調試程序的幾個要點,看堆棧Stack, 看變量值Watch,IL Editor都可以做到。

IL堆棧窗口

image

IL參數窗口,可顯示當前被調用的方法的傳入參數

image

IL Watch窗口

image

表達式可以支持自定義的表達式,這個功能與VS中的即時窗口類似,輸入表量或表達式,右邊計算出結果。

IL Editor的作者列舉出了一些經過測試,演示的表達式代碼,他們是

5 * -6
1 + 2 * 3 - 10 / 5 * 5
(1 + 2 * 3 - 10 / 5 * 5).ToString()
(-5).ToString()
new object() + "a"
"abc".Length.ToString()
System.Type.GetType("System.String").GUID.ToByteArray()
TestApplication.DebugTest.CreateOperatorTest4("op1") | true
TestApplication.DebugTest.ParamsTest2()
TestApplication.DebugTest.ParamsTest2(5, 6)
System.String.Format("{0}{1}{2}{3}{4}", "a", "b", "c", "d", "e")
new object[] {4, "a", 5}
((System.Exception){exception}).Message
TestApplication.GenericClass<int, System.DateTime>.StaticMethod<string>("test")
new TestApplication.TestClass<int, string>[] {new TestApplication.TestClass<int, string>(1, "one")}
TestApplication.GenericClass<int, string>.NestedGenericClass<System.Type>.StaticMixedMethod<System.DateTime>(System.DateTime.Now, 5, null)

是的,你可以直接在窗口中輸入,IL會對表達式求值,返回結果顯示到右邊。

 

最后看到執行結果

image

控制上顯示輸出值,與在VS中調試C#源代碼的體驗完全相同。

 

學習IL指令集

IL Editor的作者肯定想到IL語言不容易記住和熟悉,當你在IL Editor中移動鼠標時,隨着鼠標當前行顯示的IL代碼的不同,在IL Instructions窗口中,會及時的顯示它的方法注釋,並顯示MSDN地址,可以直接點擊進入該IL方法的文檔。

設計的非常貼心周到。

image

Click here直接挑到MSDN網頁中。

http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Nop.aspx

對於我們習慣的語言來說,還沒有看到有相關的設置,可以用來設置跳轉到中文版的MSDN上。

image

 

命令行調用

IL Editor支持命令行方式的調用,命令行的參數列表如下所示

dile [/p "Project name"] [/a "assembly path"] [/l "project name.dileproj"]

    /p    Optional. When DILE is loaded, a new project will be created with the given name.
    /a    Optional, can be repeated. When DILE is loaded, a new project will be created and the given assemblies will be added to it.
    /l    Optional. DILE will load the given dileproj file. If this parameter is given then /p and /a will be ignored. If a parameter is followed by a name/path which contains spaces then it should be written between quotes

創建一個Test project的項目
dile /p "Test project"

 

創建一個Test project的項目,並給它添加程序集

dile /p "Test project" /a TestAssembly.exe

 

創建一個新項目,並從兩個不同的地方加載程序集

dile /a TestAssembly.exe /a "c:\assemblies\My test.dll"

 

加載一個現有的項目

dile /l TestProject.dileproj

 

最后,附上項目主頁地址

項目主頁: http://dile.sourceforge.net/

作者博客地址:http://pzsolt.blogspot.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM