上篇文章介绍了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;
}