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 学习

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

  • 中间代码Jimple

    Soot -- 中间代码Jimple介绍 - CSDN博客

  • BAF to Jimple

    first steps: next steps: next steps: next steps: the end ...

  • jimple to BAF to bytecode

    first steps:word r0,r1,stack1#1,l2,stack3#1r0:=@this.test...

  • Jimple to grimple to byte code

    表达式聚合算法 表达式聚合背后的思想相对简单,但是在实践中我们发现很难正确地实现它。概述:该算法包括考虑单个use...

  • BAF码向jimple码转换

    承接上一篇:字节码向BAF码转换 BAF码: ``` public class test extends java...

  • 学习学习学习

    第三天了,连续三天,早上睁眼开始,看视频,做课件,连续作业,直到晚上十二点才睡觉。吃饭不规律,想起来就吃,感觉不饿...

  • 学习学习学习

    23岁的我,才真正明白,什么是学习,什么是努力,努力和不努力真的不同,就好比同样是一篇稿子,我用一周背下来,有的人...

  • 学习学习学习!

    妈妈总是让我学习,我只能用装当办法。 方法一: 方法二: 方法三: 方法四: ...

  • 学习学习学习

    001.今天看财富自由之路看了第二遍,而且看了一半,算是完成任务很开心。中间有想放弃的念头,坚持看完。眼睛痛,一直...

网友评论

    本文标题:Jimple 学习

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