kvm 验证-模拟字节码执行

上篇文章介绍了kvm进行验证的大部分过程.本文来介绍字节码执行的过程.

kvm内部定义了枚举,来支持字节码的类型验证.代码如下:

enum {
    ITEM_Bogus,       /* 未使用 */
    ITEM_Integer,
    ITEM_Float,
    ITEM_Double,
    ITEM_Long,
    ITEM_Null,        /* aconst_null的返回值 */
    ITEM_InitObject,  /* "this" is in <init> method, before call to super() */

    ITEM_Object,      /* Extra info field gives name. */
    ITEM_NewObject,   /* Like object, but uninitialized. */

    
    ITEM_Long_2,      /* 2nd word of long in register */
    ITEM_Double_2,    /* 2nd word of double in register */

    ITEM_Category1,
    ITEM_Category2,
    ITEM_DoubleWord,
    ITEM_Reference
};

常数操作,xcont_xxx

该部分介绍nop和形如xcont_xxx的字节码.

代码如下:


            case NOP: {
                ip++;
                break;

            }

            case ACONST_NULL: { // 将null推送至栈顶
                Vfy_push(ITEM_Null);
                ip++;
                break;

            }

            case ICONST_M1:// 将int型-1推送至栈顶
            case ICONST_0: // 将int型0推送至栈顶。
            case ICONST_1: // 将int型1推送至栈顶。
            case ICONST_2: //  将int型2推送至栈顶。
            case ICONST_3: // 将int型3推送至栈顶。
            case ICONST_4: // 将int型4推送至栈顶。
            case ICONST_5: { // 将int型5推送至栈顶。
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

            case LCONST_0: // 将long型0推送至栈顶。
            case LCONST_1: { // 将long型1推送至栈顶。
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;

            }

#if IMPLEMENTS_FLOAT

            case FCONST_0: // 将float型0推送至栈顶。
            case FCONST_1: // 将float型1推送至栈顶。
            case FCONST_2: { // 将float型2推送至栈顶。
                Vfy_push(ITEM_Float);
                ip++;
                break;

            }

            case DCONST_0: // 将double型0推送至栈顶。
            case DCONST_1: { // 将double型1推送至栈顶。
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;

            }

#endif /* IMPLEMENTS_FLOAT */

            case BIPUSH: { // 将单字节的常量值(-128~127)推送至栈顶。
                Vfy_push(ITEM_Integer);
                ip += 2;
                break;
            }

            case SIPUSH: { // 将一个短整型常量值(-32768~32767)推送至栈顶。
                ip++;
                Vfy_push(ITEM_Integer);
                ip += 2;
                break;

            }

这里可以看出,由于是验证字节码类型,因此只需将类型保存至操作数栈,然后结合上文介绍的,根据stackmap对比局部变量表,操作数栈来进行验证即可.

ldc,ldc_w,ldc2_w

ldc 是 将int,float或String型常量值从常量池中推送至栈顶。其擦作数栈的格式是如下:

在这里插入图片描述
ldc_w 是将int,float或String型常量值从常量池中推送至栈顶(宽索引)。当ldc 中的index超过256时,就需要使用该指令(index为8位,因此其访问的范围不能超过256).其操作数栈的格式如下:

在这里插入图片描述
其最终读取的index为(indexbyte1<< 8) | indexbyte2

ldc2_w 是将long或double型常量值从常量池中推送至栈顶(宽索引)。其操作数栈的格式为:

在这里插入图片描述
其最终读取的index为(indexbyte1<< 8) | indexbyte2.

因此,这部分的代码为:

case LDC: // 将int,float或String型常量值从常量池中推送至栈顶。
            case LDC_W: // 将int,float或String型常量值从常量池中推送至栈顶(宽索引)。
            case LDC2_W: { // 将long或double型常量值从常量池中推送至栈顶(宽索引)。
                POOLTAG tag;
                POOLINDEX index;

               /*
                * Get the constant pool index and advance the ip to the next instruction
                */
                if (opcode == LDC) {                        /* LDC */
                    index = Vfy_getUByte(ip + 1); // 读取1个字节
                    ip += 2; // LDC 所占的字节码为2个
                } else {                                    /* LDC_W or LDC2_W */
                    index = Vfy_getUShort(ip + 1); // 读取2个字节
                    ip += 3; // LDC_W,LDC2_W 所占的字节码为3个
                }

               /*
                * Get the tag 获得产量池中的类型
                */
                tag = Pol_getTag(vPool, index);

               /*
                * Check for the right kind of LDC and push the required type
                */

                if (opcode == LDC2_W) {                     /* LDC2_W  处理LDC2_W */
                    if (tag == CONSTANT_Long) {
                        Vfy_push(ITEM_Long);
                        Vfy_push(ITEM_Long_2);
                        break;
                    }
#if IMPLEMENTS_FLOAT
                    if (tag == CONSTANT_Double) {
                        Vfy_push(ITEM_Double);
                        Vfy_push(ITEM_Double_2);
                        break;
                    }
#endif
                } else {                                    /* LDC or LDC_W 处理LDC或者LDC_W */
                    if (tag == CONSTANT_String) {
                        Vfy_push(Vfy_getStringVerifierType());
                        break;
                    }

                    if (tag == CONSTANT_Integer) {
                        Vfy_push(ITEM_Integer);
                        break;
                    }
#if IMPLEMENTS_FLOAT
                    if (tag == CONSTANT_Float) {
                        Vfy_push(ITEM_Float);
                        break;
                    }
#endif
                }
                // 其他类型,抛出异常
                Vfy_throw(VE_BAD_LDC);
            }

xlode,xload_index

此处介绍形如xlode,xload_xx的字节码.

xload 是将指定的x类型局部变量推送至栈顶。
xload_index 是将第index个类型局部变量推送至栈顶。

其中,x可被i,l,f,d,a所替换,分别代表int,long,float,double,引用类型.

index 可被0,1,2,3所替换.

对于xload而言,则字节码的格式所下,以iload为例:

在这里插入图片描述

因此,此部分的代码如下:

case ILOAD_0:
            case ILOAD_1:
            case ILOAD_2:
            case ILOAD_3:
            case ILOAD: {
                SLOTINDEX index;
                if (opcode == ILOAD) {// 如果是xload的话,则需要读取index
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - ILOAD_0; // xload_index 其操作码是相连的,如果相减可以获得其最终的index.如ILOAD_0为0x1A,ILOAD_3为0x1D,其相减为3.
                    ip++;
                }
                Vfy_getLocal(index, ITEM_Integer);// 验证局部变量表中国类型为int
                Vfy_push(ITEM_Integer);// 向操作数栈中压入int
                break;
            }

            case LLOAD_0:
            case LLOAD_1:
            case LLOAD_2:
            case LLOAD_3:
            case LLOAD: {
                SLOTINDEX index;
                if (opcode == LLOAD) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - LLOAD_0;
                    ip++;
                }
                Vfy_getLocal(index,     ITEM_Long);
                Vfy_getLocal(index + 1, ITEM_Long_2);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                break;

            }

#if IMPLEMENTS_FLOAT

            case FLOAD_0:
            case FLOAD_1:
            case FLOAD_2:
            case FLOAD_3:
            case FLOAD: {
                SLOTINDEX index;
                if (opcode == FLOAD) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - FLOAD_0;
                    ip++;
                }
                Vfy_getLocal(index, ITEM_Float);
                Vfy_push(ITEM_Float);
                break;
            }

            case DLOAD_0:
            case DLOAD_1:
            case DLOAD_2:
            case DLOAD_3:
            case DLOAD: {
                SLOTINDEX index;
                if (opcode == DLOAD) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - DLOAD_0;
                    ip++;
                }
                Vfy_getLocal(index, ITEM_Double);
                Vfy_getLocal(index + 1, ITEM_Double_2);
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                break;

            }

#endif /* IMPLEMENTS_FLOAT */

            case ALOAD_0:
            case ALOAD_1:
            case ALOAD_2:
            case ALOAD_3:
            case ALOAD: {
                SLOTINDEX    index;
                VERIFIERTYPE refType;
                if (opcode == ALOAD) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - ALOAD_0;
                    ip++;
                }
                refType = Vfy_getLocal(index, ITEM_Reference);
                Vfy_push(refType);
                break;

            }

xaload

xaload可以替换为i,l,f,d,a,b,c,s.意指将对应类型数组指定索引的值推送至栈顶。其中类型分别为:int,long,float,double,引用,boolean或byte,char,short.

以iaload为例,其操作数栈执行前后为:

操作前:xxx,arraryref,index
操作后:xxx,value

因此,代码如下:

case IALOAD: {
                Vfy_pop(ITEM_Integer); // 此处对应为index
                Vfy_pop(Vfy_getIntArrayVerifierType()); // 此处对应为int arrary
                Vfy_push(ITEM_Integer); // 将int值压栈
                ip++;
                break;

            }

            case BALOAD: {
                VERIFIERTYPE dummy     = Vfy_pop(ITEM_Integer);
                VERIFIERTYPE arrayType = Vfy_pop(Vfy_getObjectVerifierType());
                if (arrayType != Vfy_getByteArrayVerifierType() &&
                    arrayType != Vfy_getBooleanArrayVerifierType() &&
                    arrayType != ITEM_Null) {
                    Vfy_throw(VE_BALOAD_BAD_TYPE);
                }
                Vfy_push(ITEM_Integer);
                ip++;
                (void)dummy;
                break;
            }

            case CALOAD: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getCharArrayVerifierType());
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

            case SALOAD: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getShortArrayVerifierType());
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

            case LALOAD: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getLongArrayVerifierType());
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;
            }

#if IMPLEMENTS_FLOAT

            case FALOAD: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getFloatArrayVerifierType());
                Vfy_push(ITEM_Float);
                ip++;
                break;

            }

            case DALOAD: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getDoubleArrayVerifierType());
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;

            }

#endif /* IMPLEMENTS_FLOAT */

            case AALOAD: {

                VERIFIERTYPE dummy     = Vfy_pop(ITEM_Integer);
                VERIFIERTYPE arrayType = Vfy_pop(Vfy_getObjectVerifierType());
                VERIFIERTYPE arrayElementType;
                // 如果该数组不是object数组的子类
                if (!Vfy_isAssignable(arrayType, Vfy_getObjectArrayVerifierType())) {
                    Vfy_throw(VE_AALOAD_BAD_TYPE);
                }

/* Alternative implementation:
                VERIFIERTYPE dummy     = Vfy_pop(ITEM_Integer);
                VERIFIERTYPE arrayType = Vfy_pop(Vfy_getObjectArrayVerifierType());
                VERIFIERTYPE arrayElementType;
*/

                arrayElementType = Vfy_getReferenceArrayElementType(arrayType);
                Vfy_push(arrayElementType);
                ip++;
                (void)dummy;
                break;
            }

xstrore_index, xstrore

xstrore中的x为i,l,f,d,a.将栈顶指定类型数值存入指定局部变量。以istore为例,其格式如下:

在这里插入图片描述

xstrore_index中的x为i,l,f,d,a.index为0,1,2,3. 意为将将栈顶对应类型数值存入第index个局部变量。

因此,代码如下:

case ISTORE_0:
            case ISTORE_1:
            case ISTORE_2:
            case ISTORE_3:
            case ISTORE: {
                SLOTINDEX index;
                if (opcode == ISTORE) {
                    index = Vfy_getUByte(ip + 1);// 获得下标
                    ip += 2;
                } else {
                    index = opcode - ISTORE_0;
                    ip++;
                }
                Vfy_pop(ITEM_Integer);
                Vfy_setLocal(index, ITEM_Integer);
                break;

            }

            case LSTORE_0:
            case LSTORE_1:
            case LSTORE_2:
            case LSTORE_3:
            case LSTORE: {
                SLOTINDEX index;
                if (opcode == LSTORE) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - LSTORE_0;
                    ip++;
                }
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_setLocal(index + 1, ITEM_Long_2);
                Vfy_setLocal(index, ITEM_Long);
                break;
            }

#if IMPLEMENTS_FLOAT

            case FSTORE_0:
            case FSTORE_1:
            case FSTORE_2:
            case FSTORE_3:
            case FSTORE: {
                SLOTINDEX index;
                if (opcode == FSTORE) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - FSTORE_0;
                    ip++;
                }
                Vfy_pop(ITEM_Float);
                Vfy_setLocal(index, ITEM_Float);
                break;
            }

            case DSTORE_0:
            case DSTORE_1:
            case DSTORE_2:
            case DSTORE_3:
            case DSTORE: {
                SLOTINDEX index;
                if (opcode == DSTORE) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - DSTORE_0;
                    ip++;
                }
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_setLocal(index + 1, ITEM_Double_2);
                Vfy_setLocal(index, ITEM_Double);
                break;
            }

#endif /* IMPLEMENTS_FLOAT */

            case ASTORE_0:
            case ASTORE_1:
            case ASTORE_2:
            case ASTORE_3:
            case ASTORE: {
                SLOTINDEX index;
                VERIFIERTYPE arrayElementType;
                if (opcode == ASTORE) {
                    index = Vfy_getUByte(ip + 1);
                    ip += 2;
                } else {
                    index = opcode - ASTORE_0;
                    ip++;
                }
                arrayElementType = Vfy_pop(ITEM_Reference);
                Vfy_setLocal(index, arrayElementType);
                break;
            }

Vfy_setLocal方法如下:

void Vfy_setLocal(SLOTINDEX index, VERIFIERTYPE typeKey) {
	// 如果index 大于等于栈帧,则抛出异常
    if (index >= vFrameSize) {
        Vfy_throw(VE_LOCALS_OVERFLOW);
    }

    // 如果index处为ITEM_Long_2,ITEM_Double_2,那么就将index处,设置为未使用
    if (vLocals[index] == ITEM_Long_2
#if IMPLEMENTS_FLOAT
        || vLocals[index] == ITEM_Double_2
#endif
        ) {
        if (index < 1) {
            Vfy_throw(VE_LOCALS_UNDERFLOW);
        }
        vLocals[index - 1] = ITEM_Bogus;
    }

    // 如果index处为ITEM_Long,ITEM_Double,则将index+1处设置为未使用
    if (vLocals[index] == ITEM_Long
#if IMPLEMENTS_FLOAT
        || vLocals[index] == ITEM_Double
#endif
        ) {
        if (index >= vFrameSize - 1) {
            Vfy_throw(VE_LOCALS_OVERFLOW);
        }
        vLocals[index + 1] = ITEM_Bogus;
    }
    // 将指定类型保存到局部变量表中
    vLocals[index] = typeKey;
}

xastore

xastore中的x可替换为i,b,c,s,l,f,d,a,意为从操作数栈读取指定类型存入到数组中.其操作栈的变化为,以iastore为例:

操作前:xxx,arraryref,index,value
操作后:xxx

代码为:

case IASTORE: {
                Vfy_pop(ITEM_Integer); // value
                Vfy_pop(ITEM_Integer); // index
                Vfy_pop(Vfy_getIntArrayVerifierType()); // int数组
                ip++;
                break;

            }

            case BASTORE: {
                VERIFIERTYPE dummy1    = Vfy_pop(ITEM_Integer);
                VERIFIERTYPE dummy2    = Vfy_pop(ITEM_Integer);
                VERIFIERTYPE arrayType = Vfy_pop(Vfy_getObjectVerifierType());
                if (arrayType != Vfy_getByteArrayVerifierType() &&
                    arrayType != Vfy_getBooleanArrayVerifierType() &&
                    arrayType != ITEM_Null) {
                    Vfy_throw(VE_BASTORE_BAD_TYPE);
                }
                ip++;
                (void)dummy1;
                (void)dummy2;
                break;
            }

            case CASTORE: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getCharArrayVerifierType());
                ip++;
                break;

            }

            case SASTORE: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getShortArrayVerifierType());
                ip++;
                break;

            }

            case LASTORE: {
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getLongArrayVerifierType());
                ip++;
                break;

            }

#if IMPLEMENTS_FLOAT

            case FASTORE: {
                Vfy_pop(ITEM_Float);
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getFloatArrayVerifierType());
                ip++;
                break;

            }

            case DASTORE: {
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_pop(ITEM_Integer);
                Vfy_pop(Vfy_getDoubleArrayVerifierType());
                ip++;
                break;

            }

#endif /* IMPLEMENTS_FLOAT */

            case AASTORE: {
                VERIFIERTYPE value            = Vfy_pop(Vfy_getObjectVerifierType());
                VERIFIERTYPE dummy            = Vfy_pop(ITEM_Integer);
                VERIFIERTYPE arrayType        = Vfy_pop(Vfy_getObjectArrayVerifierType());
                VERIFIERTYPE arrayElementType;

               /*
                * The value to be stored must be some kind of object and the
                * array must be some kind of reference array.
                */
                if (
                    !Vfy_isAssignable(value,     Vfy_getObjectVerifierType()) ||
                    !Vfy_isAssignable(arrayType, Vfy_getObjectArrayVerifierType())
                   ) {
                    Vfy_throw(VE_AASTORE_BAD_TYPE);
                }

               /*
                * Get the actual element type of the array
                */
                arrayElementType = Vfy_getReferenceArrayElementType(arrayType);

               /*
                * This part of the verifier is far from obvious, but the logic
                * appears to be as follows:
                *
                * 1, Because not all stores into a reference array can be
                *    statically checked then they never are in the case
                *    where the array is of one dimension and the object
                *    being inserted is a non-array, The verifier will
                *    ignore such errors and they will all be found at runtime.
                *
                * 2, However, if the array is of more than one dimension or
                *    the object being inserted is some kind of an array then
                *    a check is made by the verifier and errors found at
                *    this time (statically) will cause the method to fail
                *    verification. Presumable not all errors will will be found
                *    here and so some runtime errors can occur in this case
                *    as well.
                */
                if (!Vfy_isArray(arrayElementType) && !Vfy_isArray(value)) {
                    /* Success */
                } else if (Vfy_isAssignable(value, arrayElementType)) {
                    /* Success */
                } else {
                    Vfy_throw(VE_AASTORE_BAD_TYPE);
                }
                ip++;
                (void)dummy;
                break;
            }

pop,pop2

pop–>将操作数栈的栈顶元素出栈
pop2 --> 将操作数栈的栈顶一个或两个元素出栈.

 case POP: {
                Vfy_popCategory1();
                ip++;
                break;

    }

case POP2: {
    Vfy_popCategory2_secondWord();
    Vfy_popCategory2_firstWord();
    ip++;
    break;

}

其中Vfy_popCategory1代码如下:

VERIFIERTYPE Vfy_popCategory1() {
    VERIFIERTYPE resultKey;
    if (vSP == 0) { /* vSP is unsigned, See bug 4323211 */
        Vfy_throw(VE_STACK_UNDERFLOW);
    }
    // sp是指向栈顶的下一个位置。
    resultKey = vStack[vSP - 1];
    vSP--;

    if (resultKey == ITEM_Integer ||
#if IMPLEMENTS_FLOAT
        resultKey == ITEM_Float ||
#endif
        resultKey == ITEM_Null ||
        resultKey > 255 ||
        resultKey == ITEM_InitObject ||
       (resultKey & ITEM_NewObject_Flag)) {
       /* its okay */
    } else {
        Vfy_throw(VE_STACK_EXPECT_CAT1);
    }
    return resultKey;
}

Vfy_popCategory2_secondWord代码如下:

VERIFIERTYPE Vfy_popCategory2_secondWord() {
    VERIFIERTYPE resultKey;
    if (vSP <= 1) {
        Vfy_throw(VE_STACK_UNDERFLOW);
    }

    resultKey = vStack[vSP - 1];
    vSP--;

    return resultKey;
}

Vfy_popCategory2_firstWord代码如下:

VERIFIERTYPE Vfy_popCategory2_firstWord() {
    VERIFIERTYPE resultKey;
    if (vSP <= 0) {
        Vfy_throw(VE_STACK_UNDERFLOW);
    }

    resultKey = vStack[vSP - 1];
    vSP--;

   /*
    * The only think known about this operation is that it
    * cannot result in an ITEM_Long_2 or ITEM_Double_2 being
    * popped.
    * 注意,此时的resultKey 必须是ITEM_Long或ITEM_Double
    */

    if ((resultKey == ITEM_Long_2) || (resultKey == ITEM_Double_2)) {
        Vfy_throw(VE_STACK_BAD_TYPE);
    }

    return resultKey;
}

dup

复制操作数栈栈顶的值,并插入到栈顶.其操作数栈的变化为:

操作前:xxx,value
操作后:xxx,value, value

因此,此处的代码为:

case DUP: {
            VERIFIERTYPE type = Vfy_popCategory1();// 将栈顶弹出
            Vfy_push(type);// 压入两次
            Vfy_push(type);
            ip++;
            break;

        }

DUP_X1, DUP_X2

复制操作数栈栈顶的值,并插入到栈顶以下2个值以后.其操作数栈的变化为:

操作前:xxx,value2,value1
操作后:xxx,value1,value2,value1

代码为:

 case DUP_X1:{
                VERIFIERTYPE type1 = Vfy_popCategory1();
                VERIFIERTYPE type2 = Vfy_popCategory1();
                Vfy_push(type1);
                Vfy_push(type2);
                Vfy_push(type1);
                ip++;
                break;
}

case DUP_X2: {
        VERIFIERTYPE cat1type = Vfy_popCategory1();
        VERIFIERTYPE second   = Vfy_popDoubleWord_secondWord(); // Vfy_popCategory2_secondWord
        VERIFIERTYPE first    = Vfy_popDoubleWord_firstWord(); // Vfy_popCategory2_firstWord
        Vfy_push(cat1type);
        Vfy_push(first);
        Vfy_push(second);
        Vfy_push(cat1type);
        ip++;
        break;
    }

dup2

复制操作数栈栈顶的1个或2个值,并插入到栈顶.其操作数栈的变化为:

操作前:xxx,value2,value1
操作后:xxx,value2,value1,value2,value1

代码为:

 case DUP2: {
                VERIFIERTYPE second = Vfy_popDoubleWord_secondWord();
                VERIFIERTYPE first  = Vfy_popDoubleWord_firstWord();
                Vfy_push(first);
                Vfy_push(second);
                Vfy_push(first);
                Vfy_push(second);
                ip++;
                break;
}

dup2_x1, dup2_x2

dup2_x1 复制操作数栈栈顶1个或2个值,并插入到栈顶以下2个或3个值之后.其操作数栈的变化为:

当栈顶为long或double.

操作前:xxx,value2,value1
操作后:xxx,value1,value2,value1

其他类型为:

操作前:xxx,value3,value2,value1
操作后:xxx,value2,value1, value3,value2, value1
case DUP2_X1: {
                VERIFIERTYPE second   = Vfy_popDoubleWord_secondWord();
                VERIFIERTYPE first    = Vfy_popDoubleWord_firstWord();
                VERIFIERTYPE cat1type = Vfy_popCategory1();
                Vfy_push(first);
                Vfy_push(second);
                Vfy_push(cat1type);
                Vfy_push(first);
                Vfy_push(second);
                ip++;
                break;
}

dup2_x2 复制操作数栈栈顶1个或2个值,并插入到栈顶以下2个或3个或者3个值之后.其操作数栈的变化为:

当栈顶,栈顶-1的元素都为long,double时:

操作前:xxx,value4,value3,value2,value1
操作后:xxx,value2,value1,value4,value3,value2,value1

当value2, value3为long,double,而value1为其他类型时

操作前:xxx,value3,value2,value1
操作后:xxx,value1,value3,value2,value1

当value1,value2为long,double,而value3为其他类型时:

操作前:xxx,value3,value2,value1
操作后:xxx,value1,value2, value3,value2,value1

当value1, value2为Long,double时为:

操作前:xxx,value2,value1
操作后:xxx,value1,value2, value1

代码为:

case DUP2_X2: {
                VERIFIERTYPE item1second = Vfy_popDoubleWord_secondWord();
                VERIFIERTYPE item1first  = Vfy_popDoubleWord_firstWord();
                VERIFIERTYPE item2second = Vfy_popDoubleWord_secondWord();
                VERIFIERTYPE item2first  = Vfy_popDoubleWord_firstWord();
                Vfy_push(item1first);
                Vfy_push(item1second);
                Vfy_push(item2first);
                Vfy_push(item2second);
                Vfy_push(item1first);
                Vfy_push(item1second);
                ip++;
                break;
}

swap

交换栈顶元素

操作前:xxx,value2,value1
操作后:xxx,value1,value2
 case SWAP: {
                VERIFIERTYPE type1 = Vfy_popCategory1();
                VERIFIERTYPE type2 = Vfy_popCategory1();
                Vfy_push(type1);
                Vfy_push(type2);
                ip++;
                break;
         }       

运算操作

这部分代码比较简单,如下:

           case IADD:
            case ISUB:
            case IMUL:
            case IDIV:
            case IREM:
            case ISHL:
            case ISHR:
            case IUSHR:
            case IOR:
            case IXOR:
            case IAND: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(ITEM_Integer);
                Vfy_push(ITEM_Integer);
                ip++;
                break;
            }

            case INEG: // 取反
                Vfy_pop(ITEM_Integer);
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            case LADD:
            case LSUB:
            case LMUL:
            case LDIV:
            case LREM:
            case LAND:
            case LOR:
            case LXOR: {
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;

            }

            case LNEG: {
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;
            }

            case LSHL:
            case LSHR:
            case LUSHR: {
                Vfy_pop(ITEM_Integer);
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;

            }

#if IMPLEMENTS_FLOAT

            case FADD:
            case FSUB:
            case FMUL:
            case FDIV:
            case FREM: {
                Vfy_pop(ITEM_Float);
                Vfy_pop(ITEM_Float);
                Vfy_push(ITEM_Float);
                ip++;
                break;

            }

            case FNEG: {
                Vfy_pop(ITEM_Float);
                Vfy_push(ITEM_Float);
                ip++;
                break;
            }

            case DADD:
            case DSUB:
            case DMUL:
            case DDIV:
            case DREM: {
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;

            }

            case DNEG: {
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;
            }

iinc

局部变量自增.其格式:

在这里插入图片描述
因此,代码为:

case IINC: {
                SLOTINDEX index = Vfy_getUByte(ip + 1);
                ip += 3;
                Vfy_getLocal(index, ITEM_Integer);
                Vfy_setLocal(index, ITEM_Integer);
                break;

            }

转换操作

case I2L: {
                Vfy_pop(ITEM_Integer);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;

            }

            case L2I: {
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

#if IMPLEMENTS_FLOAT

            case I2F: {
                Vfy_pop(ITEM_Integer);
                Vfy_push(ITEM_Float);
                ip++;
                break;

            }

            case I2D: {
                Vfy_pop(ITEM_Integer);
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;

            }

            case L2F: {
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_push(ITEM_Float);
                ip++;
                break;

            }

            case L2D: {
                Vfy_pop(ITEM_Long_2);
                Vfy_pop(ITEM_Long);
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;

            }

            case F2I: {
                Vfy_pop(ITEM_Float);
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

            case F2L: {
                Vfy_pop(ITEM_Float);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;

            }

            case F2D: {
                Vfy_pop(ITEM_Float);
                Vfy_push(ITEM_Double);
                Vfy_push(ITEM_Double_2);
                ip++;
                break;

            }

            case D2I: {
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

            case D2L: {
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_push(ITEM_Long);
                Vfy_push(ITEM_Long_2);
                ip++;
                break;

            }

            case D2F: {
                Vfy_pop(ITEM_Double_2);
                Vfy_pop(ITEM_Double);
                Vfy_push(ITEM_Float);
                ip++;
                break;

            }

#endif /* IMPLEMENTS_FLOAT */

            case I2B:
            case I2C:
            case I2S: {
                Vfy_pop(ITEM_Integer);
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

比较操作

case FCMPL:
            case FCMPG: {
                Vfy_pop(ITEM_Float);
                Vfy_pop(ITEM_Float);
                Vfy_push(ITEM_Integer);
                ip++;
                break;

            }

case DCMPL:
case DCMPG: {
    Vfy_pop(ITEM_Double_2);
    Vfy_pop(ITEM_Double);
    Vfy_pop(ITEM_Double_2);
    Vfy_pop(ITEM_Double);
    Vfy_push(ITEM_Integer);
    ip++;
    break;

}

if_icmp

int数值的条件分支判断.

其格式为:

在这里插入图片描述
其结构为:

IF_ICMPEQ
IF_ICMPNE
IF_ICMPLT
IF_ICMPGE
IF_ICMPGT
IF_ICMPLE

其操作数栈为:

执行前: xxxx,value2,value1
执行后: xxxx

如果比较结果为真,则使用branchbyte1和branchbyte2用于构建一个16位有符号的分支偏移量,构建方式为 (branchbyte1 << 8) | branchbyte2.

因此,代码为:

case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE: {
    Vfy_pop(ITEM_Integer);
    Vfy_pop(ITEM_Integer);
    Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1)));
    ip += 3;
    break;
}

if

整数与零比较的条件分支判断.其格式为:

在这里插入图片描述

其操作数栈为:

执行前: xxxx,value
执行后: xxxx

value必须为int型,指令执行时,value从操作数栈中出栈,然后与零值进行比较.如果比较结果为真,则使用branchbyte1和branchbyte2用于构建一个16位有符号的分支偏移量,构建方式为 (branchbyte1 << 8) | branchbyte2.

代码为:

case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE: {
    Vfy_pop(ITEM_Integer);
    Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1)));
    ip += 3;
    break;
}

IF_ACMPEQ,IF_ACMPNE

比较两个引用类型
代码为:

case IF_ACMPEQ:
case IF_ACMPNE: {
    Vfy_pop(ITEM_Reference);
    Vfy_pop(ITEM_Reference);
    Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1)));
    ip += 3;
    break;
}

IFNULL,IFNONNULL

代码为:

case IFNULL:
case IFNONNULL:
    Vfy_pop(ITEM_Reference);
    Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1)));
    ip += 3;
    break;

GOTO

分支跳转

其格式为:

在这里插入图片描述
branchbyte1和branchbyte2用于构建一个16位有符号的分支偏移量,构建方式为 (branchbyte1 << 8) | branchbyte2.

代码为:

 case GOTO: {
                Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1)));
                ip += 3;
                noControlFlow = TRUE;
                break;
 }

GOTO_W

格式为:

在这里插入图片描述
branchbyte1, branchbyte2, branchbyte3, branchbyte4用于构建一个32位有符号的分支偏移量,构建方式为 (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4.

 case GOTO_W: {
                Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getCell(ip + 1)));
                ip += 5;
                noControlFlow = TRUE;
                break;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值