我想分析.Net程序集與C#,VB.NET或其他語言無關。
我知道Roslyn和NRefactory,但他們似乎只能在C#源代碼級別上工作?
CodePlex上還有一個「Common Compiler Infrastructure: Code Model and AST API」項目,聲稱它「支持以獨立於語言的結構化形式表示代碼塊的分層對象模型」,該聲音完全符合我的需求。
但是,我無法找到任何有用的文檔或代碼,實際上是這樣做的。
任何意見如何歸檔?
Can Mono.Cecil可能會做些什麼?從沒有源代碼的.Net程序集(IL代碼)獲取AST
回答
據我所知,從二進制(無源代碼)開始構建AST是不可能的,因爲AST本身是由解析器生成的,作爲源代碼編譯過程的一部分。 Mono.Cecil不會幫助,因爲您只能修改操作碼/元數據,而不能分析程序集。
但是既然是.NET,你可以在ildasm的幫助下從DLL中轉儲IL代碼。然後,您可以將生成的源代碼傳遞給任何具有CIL字典的解析器,並從解析器中獲取AST。問題是,據我所知,解析器只有一個公開可用的CIL語法,所以你並沒有真正的選擇。而且ECMA-355足夠大,所以編寫自己的語法是個不錯的主意。 所以我建議你只有一個解決方案:
- 將程序集傳遞給ildasm.exe以獲取CIL。
- 然後通過CIL到ANTLR v3分析器與this CIL文法有線了(注意這是一個有點過時了 - 在2004年創建的語法和最新CIL規範是2006年,但CIL並沒有真正改變太多)
- 之後,你可以自由地訪問AST由ANTLR
請注意,您將需要ANTLR v3的不V4,因爲語法的第3版本寫的,這是幾乎不可能將它移植到無ANTLR語法的良好的知識v4的產生。
你也可以嘗試尋找到新的Microsoft ryujit編譯器源在github上(CoreCLR的一部分) - 我不知道它的幫助,但在理論上它必須包含CIL的語法和解析器實現,因爲它的工作原理CIL代碼。但是它是用CPP編寫的,由於它處於積極的開發階段,因此代碼量巨大,缺乏文檔,因此可能更容易陷入ANTLR。
如果您將.net二進制文件視爲一個字節流,您應該能夠「解析」它就好了。
您只需編寫一個語法標記本質上是字節的語法。通過定義詞法分析器來讀取單個字節作爲標記,您當然可以使用幾乎任何詞法分析器/分析器工具來構建經典的詞法分析器/分析器。
然後,您可以使用用於解析引擎的標準AST構建機器(對YACC自動使用ANTLR4自動構建AST)來構建AST。
你會發現,當然,「解析」是不夠的;如果您要對相應的代碼進行認真分析,您仍然需要構建符號表,並執行控制和數據流分析。查看我在LifeAfterParsing上的散文。
您還可能需要考慮爲特定編程語言提供關鍵運行時功能的「區分」功能,這些編程語言實際上會生成CIL代碼。這些將使您的分析儀依賴於語言。是的,你仍然可以分享對通用CIL有效的分析部分。
.NET二進制文件格式沒有限定爲上下文無關(或對上下文敏感),因此YACC和ANTLR都不能爲其生成解析器。 – 2015-02-22 20:56:34
它在哪裏違反c-free或c-sensitive? – 2015-02-22 22:21:29
1)使用RVA(相對虛擬地址)指定模塊內各種結構的位置,找到文件內的偏移量需要通過節表進行映射。 2)每個表的行數出現在其中的任何一個之前,這些計數會影響某些列的寬度。 3)我已經檢查過的大多數dll都將元數據放置在函數體之後(儘管這不是必需的),所以如果您僅以前向方式(例如使用生成的解析器)讀取它,則不會知道何時你已經遇到了一個方法體,直到你通過它爲止。 – 2015-02-23 11:13:58
您可以做到這一點,ILSpy的源代碼中也有一個(儘管很小)example of this。
var assembly = AssemblyDefinition.ReadAssembly("path/to/assembly.dll");
var astBuilder = new AstBuilder(new DecompilerContext(assembly.MainModule));
decompiler.AddAssembly(assembly);
astBuilder.SyntaxTree...
CCI的代碼模型是某處IL反彙編器和完整的C#反編譯工具之間:它使你的代碼中的一些結構(例如if
語句和表達式),但它也包含像push
和pop
一些低級別的堆棧操作。
CCI包含一個顯示此項的示例:PeToText。
例如,要獲取代碼模型的Program
類型的第一個方法(在全局命名空間),你可以使用這樣的代碼:
string fileName = "whatever.exe";
using (var host = new PeReader.DefaultHost())
{
var module = (IModule)host.LoadUnitFrom(fileName);
var type = (ITypeDefinition)module.UnitNamespaceRoot.Members
.Single(m => m.Name.Value == "Program");
var method = (IMethodDefinition)type.Members.First();
var methodBody = new SourceMethodBody(method.Body, host, null, null);
}
爲了證明,如果你反編譯以上代碼,並顯示它使用PeToText,你會得到:
Microsoft.Cci.ITypeDefinition local_3;
Microsoft.Cci.ILToCodeModel.SourceMethodBody local_5;
string local_0 = "C:\\code\\tmp\\nuget tmp 2015\\bin\\Debug\\nuget tmp 2015.exe";
Microsoft.Cci.PeReader.DefaultHost local_1 = new Microsoft.Cci.PeReader.DefaultHost();
try
{
push (Microsoft.Cci.IModule)local_1.LoadUnitFrom(local_0).UnitNamespaceRoot.Members;
push Program.<>c.<>9__0_0;
if (dup == default(System.Func<Microsoft.Cci.INamespaceMember, bool>))
{
pop;
push Program.<>c.<>9.<Main0>b__0_0;
Program.<>c.<>9__0_0 = dup;
}
local_3 = (Microsoft.Cci.ITypeDefinition)System.Linq.Enumerable.Single<Microsoft.Cci.INamespaceMember>(pop, pop);
local_5 = new Microsoft.Cci.ILToCodeModel.SourceMethodBody((Microsoft.Cci.IMethodDefinition)System.Linq.Enumerable.First<Microsoft.Cci.ITypeDefinitionMember>(local_3.Members).Body, local_1, (Microsoft.Cci.ISourceLocationProvider)null, (Microsoft.Cci.ILocalScopeProvider)null, 0);
}
finally
{
if (local_1 != default(Microsoft.Cci.PeReader.DefaultHost))
{
local_1.Dispose();
}
}
值得注意的是所有這些push
,pop
和dup
語句和lambda緩存條件。
- 1. 顯示.net程序集的IL代碼?
- 2. 從AST生成源代碼
- 3. SDK從.net程序集中提取代碼以重新創建源代碼?
- 4. 如何運行我從Android源代碼獲取的應用程序源代碼?
- 5. 我無法從c源代碼使用cdt plugin eclipse獲取AST
- 6. 從源代碼到AST到CodeDom
- 7. 獲取源代碼。
- 8. RedGate Reflector從.net程序集恢復源代碼
- 9. 在C#中執行.NET IL代碼#
- 10. 轉換Jython的源代碼/ ast
- 11. 從asp.net代碼獲取一些網站的源代碼
- 12. c#.net源代碼
- 13. 從庫中獲取錯誤並且沒有源代碼
- 14. 從代碼生成工具獲取對程序集的引用
- 15. InvalidProgramException(無效的IL代碼)?
- 16. 將AST編譯回源代碼
- 17. 獲取LAUNCHER2源代碼?
- 18. UIWebView獲取HTML源代碼
- 19. 獲取Android源代碼
- 20. SymbolSource獲取源代碼
- 21. 獲取Android源代碼
- 22. 獲取頁面源代碼
- 23. 獲取iframe源代碼?
- 24. python:如何從代碼對象獲取源代碼?
- 25. 如何從Google代碼獲取源代碼?
- 26. 如何使用Tortoise SVN從谷歌代碼獲取源代碼?
- 27. 是否有可能將.NET IL代碼編譯爲機器代碼?
- 28. 無需源代碼本地化.NET程序集
- 29. 獲取從代碼
- 30. 從點擊應用程序獲取源代碼
如果你只想獲得IL,這種方法太複雜了。使用塞西爾會簡單得多。 – svick 2015-05-16 13:26:54