第二章 中间表示

  1. java字节码作为中间表示(使用javap命令查看)
Classfile /home/jiansun/mydemo/sootdemo/Add.class
  Last modified 2019-8-7; size 488 bytes
  MD5 checksum 74331c11abb06b528003d93bae6e9d83
  Compiled from "Add.java"
public class Add
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#17         // java/lang/Object."<init>":()V
   #2 = Methodref          #5.#18         // Add.addTwoNum:(II)I
   #3 = Fieldref           #19.#20        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #21.#22        // java/io/PrintStream.println:(I)V
   #5 = Class              #23            // Add
   #6 = Class              #24            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               addTwoNum
  #14 = Utf8               (II)I
  #15 = Utf8               SourceFile
  #16 = Utf8               Add.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = NameAndType        #13:#14        // addTwoNum:(II)I
  #19 = Class              #25            // java/lang/System
  #20 = NameAndType        #26:#27        // out:Ljava/io/PrintStream;
  #21 = Class              #28            // java/io/PrintStream
  #22 = NameAndType        #29:#30        // println:(I)V
  #23 = Utf8               Add
  #24 = Utf8               java/lang/Object
  #25 = Utf8               java/lang/System
  #26 = Utf8               out
  #27 = Utf8               Ljava/io/PrintStream;
  #28 = Utf8               java/io/PrintStream
  #29 = Utf8               println
  #30 = Utf8               (I)V
{
  public Add();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        13
         2: istore_2
         3: bipush        17
         5: istore_3
         6: iload_2
         7: iload_3
         8: invokestatic  #2                  // Method addTwoNum:(II)I
        11: istore_1
        12: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: iload_1
        16: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
        19: return
      LineNumberTable:
        line 4: 0
        line 5: 3
        line 6: 6
        line 7: 12
        line 8: 19

  public static int addTwoNum(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=2
         0: bipush        7
         2: istore_2
         3: bipush        8
         5: istore_3
         6: iload_0
         7: iload_1
         8: iadd
         9: iconst_2
        10: imul
        11: ireturn
      LineNumberTable:
        line 11: 0
        line 12: 3
        line 13: 6
}
SourceFile: "Add.java"
  1. baf中间表示
    • 把200多种不同的字节码精简为60种
    • 没有常量池,直接通过函数名和字段名访问方法和字段
    • 使用word/dword显式定义局部变量(64/32位)
    • 无需过多关注变量类型,例如int、short、long等相加的指令,在baf中统称为相加指令
public class Add extends java.lang.Object
{

    public void <init>()
    {
        word r0;

        r0 := @this: Add;
        load.r r0;
        specialinvoke <java.lang.Object: void <init>()>;
        return;
    }

    public static void main(java.lang.String[])
    {
        word r0;

        r0 := @parameter0: java.lang.String[];
        push 13;
        push 17;
        staticinvoke <Add: int addTwoNum(int,int)>;
        store.i r0;
        staticget <java.lang.System: java.io.PrintStream out>;
        load.i r0;
        virtualinvoke <java.io.PrintStream: void println(int)>;
        return;
    }

    public static int addTwoNum(int, int)
    {
        word i0, i1, b2;

        i0 := @parameter0: int;
        i1 := @parameter1: int;
        push 7;
        store.b b2;
        push 8;
        store.b b2;
        load.i i0;
        load.i i1;
        add.i;
        push 2;
        mul.i;
        return.i;
    }
}
  1. jimple作为中间表示

    soot中Jimple语句类型

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

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

    • 监控语句:EnterMonitorStmt , ExitMonitorStmt.

    • ThrowStmt , RetStmt

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

  • Java字节码有大约200个不同的字节码指令,BAF大约有60个,而JIMPLE有15个。

  • 因为其紧凑型,利于分析和优化。

  • 有类型和命名的局部变量可以改进分析

  • 运算符是无类型的,而baf的运算符是有类型的(add.i,add.f,add.d或add.l)。在转换成baf时,不再需要有类型的运算符(因为局部变量有类型)。

Map m = new HashMap();
m.get("key");

//becomes the following JIMPLE code:

java.util.HashMap $r1, r2;
$r1 = new java.util.HashMap;
specialinvoke $r1.<java.util.HashMap: void <init>()>();
r2 = $r1;
//这里知道了r2的类型是hashmap,如果不知道的话,interfaceinvoke可以映射到实现Map接口的任何方法。
interfaceinvoke r2.<java.util.Map:     
java.lang.Object get(java.lang.Object)>("key");
  • 局部变量都在方法的顶部声明,包括引用数据类型和基本数据类型。
  • identity语句定义了使用特殊值预加载的局部变量,如this或方法参数
  • jimple类似于简单的Java代码(所以叫做jimple)
  • 赋值语句占主导地位


    1565142816842.png

​ jimple代码优化之后,可以重新转化成字节码文件,在虚拟中运行。

public class Add extends java.lang.Object
{

    public void <init>()
    {
        Add r0;

        r0 := @this: Add;
        specialinvoke r0.<java.lang.Object: void <init>()>();
        return;
    }

    public static void main(java.lang.String[])
    {
        java.lang.String[] r0;
        byte b0, b1;
        int i2;
        java.io.PrintStream $r1;

        r0 := @parameter0: java.lang.String[];
        b0 = 13;
        b1 = 17;
        i2 = staticinvoke <Add: int addTwoNum(int,int)>(b0, b1);
        $r1 = <java.lang.System: java.io.PrintStream out>;
        virtualinvoke $r1.<java.io.PrintStream: void println(int)>(i2);
        return;
    }

    public static int addTwoNum(int, int)
    {
        int i0, i1, $i4, $i5;
        byte b2, b3;

        i0 := @parameter0: int;
        i1 := @parameter1: int;
        b2 = 7;
        b3 = 8;
        $i4 = i0 + i1;
        $i5 = $i4 * 2;
        return $i5;
    }
}
  1. Grimp是更易阅读的中间表示(更像是反编译的java代码,grimp作为反编译器的基础)


    1565145414041.png

    grimp允许使用new操作,因此更接近java源代码

public class Add extends java.lang.Object
{

    public void <init>()
    {
        Add r0;

        r0 := @this: Add;
        specialinvoke r0.<java.lang.Object: void <init>()>();
        return;
    }

    public static void main(java.lang.String[])
    {
        java.lang.String[] r0;
        byte b0, b1;
        int i2;
        java.io.PrintStream $r1;

        r0 := @parameter0: java.lang.String[];
        b0 = 13;
        b1 = 17;
        i2 = staticinvoke <Add: int addTwoNum(int,int)>(b0, b1);
        $r1 = <java.lang.System: java.io.PrintStream out>;
        virtualinvoke $r1.<java.io.PrintStream: void println(int)>(i2);
        return;
    }

    public static int addTwoNum(int, int)
    {
        int i0, i1, $i4, $i5;
        byte b2, b3;

        i0 := @parameter0: int;
        i1 := @parameter1: int;
        b2 = 7;
        b3 = 8;
        $i4 = i0 + i1;
        $i5 = $i4 * 2;
        return $i5;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 一:java概述: 1,JDK:Java Development Kit,java的开发和运行环境,java的开发...
    慕容小伟阅读 1,763评论 0 10
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,365评论 0 4
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,253评论 0 16
  • 第01章 JAVA简介第02章 基础语法第02章 递归补充第03章 面向对象第04章 异常处理第05章 数组第06...
    顺毛阅读 508评论 0 1