簡體   English   中英

C#語句可以生成非連接的MSIL

[英]Can a C# statement generate non connected MSIL

問題是關於C#語言規范CIL語言規范 ,以及Microsoft和Mono的C#編譯器行為。

我正在構建一些代碼分析工具(無論如何),它們在CIL上運行。

考慮到一些代碼示例,我注意到代碼語句(try / catch,ifelse,ifthen,loops,...)生成MSIL的連接塊。

但我想確定我不能編寫產生非連接MSIL的C#代碼構造。 更具體地說,我可以編寫任何轉換為​​(類似)的C# 語句

IL_0000: 
IL_0001: 
IL_0002: 

// hole

IL_001a: 
IL_001b:

我已經嘗試過使用goto和嵌套循環的一些奇怪的東西,但也許我沒有像一些用戶那樣瘋狂。

當然,這很簡單。 就像是:

static void M(bool x)
{
    if (x)
        return;
    else
        M(x);
    return;
}

如果你在調試模式下編譯它,你得到

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: brfalse.s IL_0008
    IL_0006: br.s IL_0011
    IL_0008: ldarg.0
    IL_0009: call void A::M(bool)
    IL_000e: nop
    IL_000f: br.s IL_0011
    IL_0011: ret

if語句從00010009if的結果是轉到0011 ; 兩個return語句都是相同的代碼,因此在if主體和結果之間有一個包含nop和無條件分支的“hole”。

更一般地說,你不應該對C#編譯器生成的IL的布局做任何假設。 除了IL產生的IL合法且安全,可驗證之外,編譯器不做任何其他保證。


你說你正在編寫一些代碼分析工具; 作為C#分析器重要部分的作者,以及在Coverity從事第三方分析工具的人,提出建議:對於您通常想要回答C#程序的大多數問題,Roslyn生成的解析樹是您希望分析的實體,而不是IL。 解析樹是一個具體的語法樹; 它與源代碼中的每個字符都是一對一的。 將優化的IL映射回原始源代碼可能非常困難,並且在IL分析中很容易產生誤報。

換句話說:源到IL是語義保留但信息丟失; 您通常希望分析其中包含最多信息的工件。

如果由於某種原因必須在IL級別操作分析器,那么您的首要任務應該是找到基本塊的邊界,特別是在分析可達性屬性時。

“基本塊”是IL的連續塊,其中塊的端點不“繼續”到下面的指令 - 因為它是例如分支,返回或拋出 - 並且沒有分支到塊除了第一條指令以外的任何地方。

然后,您可以為每種方法形成基本塊的圖形,指示哪些方法可以將控制轉移到哪些其他塊。 這“提高了分析的水平”; 現在你要分析基本塊圖的效果,而不是分析一系列IL指令的效果。

如果你說更多關於你正在做什么樣的分析,我可以進一步建議。

理論上是(這來自我的經驗)。 您的分析工具不直接處理c#,但僅適用於IL代碼。 IL可以由任何人制作,不僅可以由visual studio制作,也可以由visual basic,python等其他語言編譯器制作。 網...和混淆器! 混淆器是真正的罪魁禍首:當其他編譯器試圖遵守規范時,混淆器會盡力利用規范和目標運行時。

混淆的代碼可能違反某些常識模式。 考慮這種情況:某些智能混淆器產生非法的msil,但是抖動消化它,因為它發生了無效部分最終沒有被執行。

在構建分析工具時,除非您的目標是構建反混淆器,否則無法處理這些情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM