第二章 中間表示

  1. java字節(jié)碼作為中間表示(使用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多種不同的字節(jié)碼精簡(jiǎn)為60種
    • 沒有常量池,直接通過函數(shù)名和字段名訪問方法和字段
    • 使用word/dword顯式定義局部變量(64/32位)
    • 無需過多關(guān)注變量類型,例如int、short、long等相加的指令,在baf中統(tǒng)稱為相加指令
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語句類型

    • 負(fù)責(zé)過程內(nèi)控制流的語句:IfStmt , GotoStmt , TableSwitchStmt , LookupSwitchStmt

    • 負(fù)責(zé)過程間的控制流語句:InvokeStmt , ReturnStmt , ReturnVoidStmt.

    • 監(jiān)控語句:EnterMonitorStmt , ExitMonitorStmt.

    • ThrowStmt , RetStmt

  • jimple是類型化的、三地址的、基于語句的中間代碼

  • Java字節(jié)碼有大約200個(gè)不同的字節(jié)碼指令,BAF大約有60個(gè),而JIMPLE有15個(gè)。

  • 因?yàn)槠渚o湊型,利于分析和優(yōu)化。

  • 有類型和命名的局部變量可以改進(jìn)分析

  • 運(yùn)算符是無類型的,而baf的運(yùn)算符是有類型的(add.i,add.f,add.d或add.l)。在轉(zhuǎn)換成baf時(shí),不再需要有類型的運(yùn)算符(因?yàn)榫植孔兞坑蓄愋停?/p>

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可以映射到實(shí)現(xiàn)Map接口的任何方法。
interfaceinvoke r2.<java.util.Map:     
java.lang.Object get(java.lang.Object)>("key");
  • 局部變量都在方法的頂部聲明,包括引用數(shù)據(jù)類型和基本數(shù)據(jù)類型。
  • identity語句定義了使用特殊值預(yù)加載的局部變量,如this或方法參數(shù)
  • jimple類似于簡(jiǎn)單的Java代碼(所以叫做jimple)
  • 賦值語句占主導(dǎo)地位


    1565142816842.png

? jimple代碼優(yōu)化之后,可以重新轉(zhuǎn)化成字節(jié)碼文件,在虛擬中運(yùn)行。

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作為反編譯器的基礎(chǔ))


    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;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一:java概述: 1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)...
    慕容小偉閱讀 1,959評(píng)論 0 10
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,689評(píng)論 1 32
  • 一、基礎(chǔ)知識(shí):1、JVM、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機(jī)...
    殺小賊閱讀 2,576評(píng)論 0 4
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對(duì)于byte類型而言...
    龍貓小爺閱讀 4,476評(píng)論 0 16
  • 第01章 JAVA簡(jiǎn)介第02章 基礎(chǔ)語法第02章 遞歸補(bǔ)充第03章 面向?qū)ο蟮?4章 異常處理第05章 數(shù)組第06...
    順毛閱讀 566評(píng)論 0 1

友情鏈接更多精彩內(nèi)容