C#语句可以生成非连接的MSIL
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#语句可以生成非连接的MSIL相关的知识,希望对你有一定的参考价值。
问题是关于C# language specification和CIL language specification,以及Microsoft和Mono的C#编译器行为。
我正在构建一些代码分析工具(无论如何),它们在CIL上运行。
考虑到一些代码示例,我注意到代码语句(try / catch,ifelse,ifthen,loops,...)生成MSIL的连接块。
但我想确定我不能编写产生非连接MSIL的C#代码构造。更具体地说,我可以编写任何转换为(类似)的C#statement:
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
声明从0001
到0009
,而if
的结果是0011
的结果;两个return
语句都是相同的代码,所以有一个“洞”包含nop
和if
主体和结果之间的无条件分支。
更一般地说,你不应该对C#编译器生成的IL的布局做任何假设。除了IL产生的IL合法且安全,可验证之外,编译器不做任何其他保证。
你说你正在编写一些代码分析工具;作为C#分析器重要部分的作者,以及在Coverity从事第三方分析工具的人,提出建议:对于您通常想要回答C#程序的大多数问题,Roslyn生成的解析树是您希望分析的实体,而不是IL。解析树是一个具体的语法树;它与源代码中的每个字符都是一对一的。将优化的IL映射回原始源代码可能非常困难,并且在IL分析中很容易产生误报。
换句话说:源到IL是语义保留但信息丢失;您通常希望分析其中包含最多信息的工件。
如果由于某种原因必须在IL级别操作分析器,那么您的首要任务应该是找到基本块的边界,特别是在分析可达性属性时。
“基本块”是IL的连续块,其中块的端点不“继续”到下面的指令 - 因为它是例如分支,返回或抛出 - 并且没有分支到块除了第一条指令以外的任何地方。
然后,您可以为每种方法形成基本块的图形,指示哪些方法可以将控制转移到哪些其他块。这“提高了分析的水平”;现在你要分析基本块图的效果,而不是分析一系列IL指令的效果。
如果你说更多关于你正在做什么样的分析,我可以进一步建议。
理论上是(这来自我的经验)。您的分析工具不直接处理c#,但仅适用于IL代码。 IL可以由任何人制作,不仅可以由visual studio制作,也可以由visual basic,python等其他语言编译器制作。网...和混淆器!混淆器是真正的罪魁祸首:当其他编译器试图遵守规范时,混淆器会尽力利用规范和目标运行时。
混淆的代码可能违反某些常识模式。考虑这种情况:某些智能混淆器产生非法的msil,但是抖动消化它,因为它发生了无效部分最终没有被执行。
在构建分析工具时,除非您的目标是构建反混淆器,否则无法处理这些情况。
以上是关于C#语句可以生成非连接的MSIL的主要内容,如果未能解决你的问题,请参考以下文章