Jimple 学习

作者: 佩玖吟 | 来源:发表于2021-08-10 21:09 被阅读0次

    jimple 是一种中间代码,用来简化分析,以及简化向 java 字节码的过渡。

    jimple 是一种类型化的、三地址的、基于语句的中间代码

    int i;
    

    将上面代码转化为 jimple 之后,类型依旧保留,并没有丢失

    int i;
    

    Jimple 只需要 15 条语句指令即可,而 Java 字节码所需的指令多达 200 条,使代码的操作更加方便。

    Jimple语句类型

    • 核心语句:NopStmt, DefinitionStmt(IdentityStmt, AssignStmt)

    • 负责过程内控制流的语句:IfStmt , GotoStmt , TableSwitchStmt , LookupSwitchStmt

    • 负责过程间的控制流语句:InvokeStmt , ReturnStmt , ReturnVoidStmt.

    • 监控语句:EnterMonitorStmt , ExitMonitorStmt.

    • ThrowStmt , RetStmt

    Jimple 转 Java

    public class Lab1 extends java.lang.Object
    {
    
        public void <init>()
        {
            Lab1 r0;
    
            r0 := @this: Lab1;
    
            specialinvoke r0.<java.lang.Object: void <init>()>();
    
            return;
        }
        ...
    

    这里类代码的Jimple不仅要将类名写完整,还要将继承的类显式写出来,以保全语义信息。

    源程序中没有显式给出构造函数,Jimple中的<init>是默认生成的构造函数,然后$r0指向this,再用specialinvoke调用其父类(这里是Object,见方法签名)的构造函数。

    JVM 里四种主要方法调用:

    • specialinvoke:用于调用构造方法、父类方法、私有方法
    • virtualinvoke:用于调用普通的成员方法,进行virtual dispatch
    • interfaceinvoke:用于调用继承的接口的方法,不能做优化,需要检查是否实现了接口中的方法
    • staticinvoke:用于调用静态方法

    在上面的 Jimple 代码中方法调用(invoke)的地方,尖括号<>之间的内容是方法签名(Method Signature),它一般会包含方法所在的类名、方法的返回值类型、形参列表中各个参数的类型,有些还会包含方法名。

     public static void main(java.lang.String[])
        {
            Lab1 $r0;
            java.lang.String[] r2;
    
            r2 := @parameter0: java.lang.String[]; //IdentityStmt
    
            $r0 = new Lab1;
    
            specialinvoke $r0.<Lab1: void <init>()>();
    
            virtualinvoke $r0.<Lab1: void foo(int,int)>(5, 8);
    
            return;
        }
    

    main 函数中 r2 := @parameter0: java.lang.String[]; 表示变量 r2 是该方法的第一个参数,其类型为 java.lang.String[],其中带 $ 的变量表示其在栈内位置,并不是源程序中的局部变量,源程序中的局部变量名与 Jimple 中的变量名相同。

    specialinvoke 对 Lab1 类进行初始化,virtualinvke 调用 foo 函数,传参为 5、8。

    所以可以得到源程序为

    public static void main(String[] args){
        new Lab1().foot(5, 8);
    }
    
    public void foo(int, int)
        {
            int i0, i1;
            Lab1 r0;
            boolean $z0;
            java.io.PrintStream $r1, $r2, $r3;
    
            r0 := @this: Lab1;
            i0 := @parameter0: int;
            i1 := @parameter1: int;
            if i0 != i1 goto label1;
            $r3 = <java.lang.System: java.io.PrintStream out>;
        
            virtualinvoke $r3.<java.io.PrintStream: void println(java.lang.String)>("a == b");
            goto label3;
        
         label1:
            $z0 = virtualinvoke r0.<Lab1: boolean lt(int,int)>(i0, i1);
            if $z0 == 0 goto label2;
            $r2 = <java.lang.System: java.io.PrintStream out>;
            virtualinvoke $r2.<java.io.PrintStream: void println(java.lang.String)>("a > b");
            goto label3;
        
         label2:
            $r1 = <java.lang.System: java.io.PrintStream out>;
            virtualinvoke $r1.<java.io.PrintStream: void println(java.lang.String)>("a < b");
         label3:
            return;
        }
    

    i0 和 i1 分别对应于传进来的两个参数,其中语句 if i0 != i1 goto label1; 判断两个参数是否相等。

    virtualinvoke $r3.<java.io.PrintStream: void println(java.lang.String)>("a == b"); 对应于 System.out.println 函数。

    对于 label1 中情况:

    首先调用 lt 函数,然后判断返回值是否为 0,然后调用 System.out.println 函数。

    对于 label2 中情况:

    直接调用 System.out.println 函数。

    所以可以得到源程序为

    public void foo(int a, int b) {
        if (a == b) {
            System.out.println("a == b");
        } else if (lt(a, b)) {
            System.out.println("a > b");
        } else {
            System.out.println("a < b");
        }
    }
    
    public boolean lt(int, int)
        {
            int i0, i1;
            Lab1 r0;
    
            r0 := @this: Lab1;
    
            i0 := @parameter0: int;
    
            i1 := @parameter1: int;
    
            if i0 <= i1 goto label1;
    
            return 1;
    
         label1:
            return 0;
        }
    

    ro 对应 Lab1 类,i0 和 i1 对应两个输入的参数,然后判断两个数值大小来进行返回,比较简单的大小判断,源程序为

    public boolean lt(int a, int b) {
        if (a > b) {
            return true;
        }
        return false;
    }
    

    相关文章

      网友评论

        本文标题:Jimple 学习

        本文链接:https://www.haomeiwen.com/subject/eevfbltx.html