微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 CIL 代码反编译为一些高级代码 - 在数据流分析过程中是否需要引入新变量?

如何解决将 CIL 代码反编译为一些高级代码 - 在数据流分析过程中是否需要引入新变量?

我正在编写一个从 .NET CIL 代码到某种高级语言的编译器。过程类似于反编译。我做了一些控制流分析——检测循环、ifs 等等。在数据流分析方面,我通过模拟一些涉及评估堆栈的指令完成了简单的表达式传播 - 我将评估堆栈视为隐藏变量,将更复杂的表达式推送到其上,并且每当有对某个变量的任何赋值指令时(例如 { {1}} 或 starg) - 我弹出并将传播的表达式从堆栈分配给此变量,并将此表达式转换为高级语言代码中的语句。当然,现在它是如此简单,以至于它会产生故障。考虑一个用 C# 编写的函数

stloc

函数编译为 IL:

int GCD(int n1,int n2)
{
    while(n2 != 0)
    {
        int c = n1 % n2;
        n1 = n2;
        n2 = c;
    }

    return n1;
}

通过这种简单的传播,我们将 .method private hidebysig instance int32 GCD ( int32 n1,int32 n2 ) cil managed { .maxstack 8 IL_0000: br.s IL_000a IL_0002: ldarg.1 // load n1 on eval stack IL_0003: ldarg.2 // load n2 on eval stack IL_0004: rem // pop n1 and n2 from stack,compute n1 % n2 and push it on stack IL_0005: ldarg.2 // load n2 on stack IL_0006: starg.s n1 // pop n2 from stack and store it in n1 IL_0008: starg.s n2 // pop n1 % n2 from stack and store it in n2 IL_000a: ldarg.2 IL_000b: brtrue.s IL_0002 IL_000d: ldarg.1 IL_000e: ret } 压入堆栈,然后将 n1 % n2 加载到堆栈上,然后我们有 n2 指令,因此我们从堆栈中弹出表达式并将赋值转换为语句。然后我们再次弹出,并执行相同的操作。结果代码如下所示:

starg

翻译后的代码已经改变了语义并且没有做它应该做的事情,因为 GCD(n1,n2) { while (n2) { n1 = n2; n2 = (n1 % n2); } return n1; } 在计算 n1 之前已经改变了。需要将 n1 % n2 的中间结果存储在某个地方,例如局部变量,就像在原始 C# 代码中一样。这表明我必须做一些与消除死代码相反的事情,可能被称为“必要的代码引入”。我搜索了一些关于在反编译中引入新变量的方法的资料,但我没有找到任何资料。你有什么想法吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。