📄 verify3b.c
字号:
break; case IF_ACMPEQ: case IFNONNULL: case IF_ACMPNE: case IFNULL: case IF_ICMPEQ: case IFEQ: case IF_ICMPNE: case IFNE: case IF_ICMPGT: case IFGT: case IF_ICMPGE: case IFGE: case IF_ICMPLT: case IFLT: case IF_ICMPLE: case IFLE: newpc = pc + 1; newpc = pc + getWord(code, newpc); nextBlock = inWhichBlock(newpc, blocks, v->numBlocks); if (!mergeBasicBlocks(v, curBlock, nextBlock)) { return verifyErrorInVerifyMethod3b(v, curBlock, "error merging operand stacks"); } /* if the condition is false, then the next block is the one that will be executed */ curIndex++; if (curIndex >= v->numBlocks) { return verifyErrorInVerifyMethod3b(v, curBlock, "execution falls off the end of a basic block"); } else if (!mergeBasicBlocks(v, curBlock, blocks[curIndex])) { return verifyErrorInVerifyMethod3b(v, curBlock, "error merging operand stacks"); } break; case LOOKUPSWITCH: /* default branch...between 0 and 3 bytes of padding are added so that the * default branch is at an address that is divisible by 4 */ n = (pc + 1) % 4; if (n) n = pc + 5 - n; else n = pc + 1; newpc = pc + getDWord(code, n); nextBlock = inWhichBlock(newpc, blocks, v->numBlocks); if (!mergeBasicBlocks(v, curBlock, nextBlock)) { return verifyErrorInVerifyMethod3b(v, curBlock, "error merging into the default branch of a lookupswitch instruction"); } /* get number of key/target pairs */ n += 4; low = getDWord(code, n); /* branch into all targets */ /* NOTE: the cast is there only to keep gcc happy */ for (n += 4, high = n + 8*low; n < (uint32)high; n += 8) { newpc = pc + getDWord(code, n+4); nextBlock = inWhichBlock(newpc, blocks, v->numBlocks); if (!mergeBasicBlocks(v, curBlock, nextBlock)) { return verifyErrorInVerifyMethod3b(v, curBlock, "error merging into a branch of a lookupswitch instruction"); } } break; case TABLESWITCH: /* default branch...between 0 and 3 bytes of padding are added so that the * default branch is at an address that is divisible by 4 */ n = (pc + 1) % 4; if (n) n = pc + 5 - n; else n = pc + 1; newpc = pc + getDWord(code, n); /* get the high and low values of the table */ low = getDWord(code, n + 4); high = getDWord(code, n + 8); n += 12; /* high and low are used as temps in this loop that checks * the validity of all the branches in the table */ /* NOTE: the cast is there only to keep gcc happy */ for (high = n + 4*(high - low + 1); n < (uint32)high; n += 4) { newpc = pc + getDWord(code, n); nextBlock = inWhichBlock(newpc, blocks, v->numBlocks); if (!mergeBasicBlocks(v, curBlock, nextBlock)) { return verifyErrorInVerifyMethod3b(v, curBlock, "error merging into a branch of a tableswitch instruction"); } } break; /* the rest of the ways to end a block */ case RETURN: case ARETURN: case IRETURN: case FRETURN: case LRETURN: case DRETURN: case ATHROW: curIndex++; continue; default: for (n = pc + 1; n < codelen; n++) { if (v->status[n] & IS_INSTRUCTION) break; } if (n == codelen) { return verifyErrorInVerifyMethod3b(v, curBlock, "execution falls off the end of a code block"); } else if (!mergeBasicBlocks(v, curBlock, blocks[curIndex+1])) { return verifyErrorInVerifyMethod3b(v, curBlock, "error merging operand stacks"); } } for (curIndex = 0; curIndex < v->numBlocks; curIndex++) { if (blocks[curIndex]->status & CHANGED) break; } } DBG(VERIFY3, dprintf(" Verifier Pass 3b: Complete\n"); ); gc_free(curBlock); return(true);}/* * merges two operand stacks. just to repeat what the JVML 2 spec says about this: * Merge the state of the operand stack and local variable array at the end of the * execution of the current instruction into each of the successor instructions. In * the special case of control transfer to an exception handler, the operand stack is * set to contain a single object of the exception type indicated by the exception * handler information. * - if this if the first time the successor instruction has been visited, record * that the operand stack and local variable values calculated in steps 2 and 3 * are the state of the operand stack and local variable array prior to executing * the successor instruction. Set the "changed" bit for the successor instruction. * - if the successor instruction has been seen before, merge the operand stack and * local variable values calculated in steps 2 and 3 into the values already there. * set the "changed" bit if there is any modification to the values. * * to merge two operand stacks, the number of values on each stack must be identical. * the types of values on the stacks must also be identical, except that differently * typed reference values may appear at corresponding places on the two stacks. in this * case, the merged operand stack contains a reference to an instance of the first common * superclass of the two types. such a reference type always exists because the type Object * is a superclass of all class and interface types. if the operand stacks cannot be merged, * verification of the method fails. * * to merge two local variable array states, corresponding pairs of local variables are * compared. if the two types are not identical, then unless both contain reference values, * the verification records that the local variable contains an unusable value. if both of * the pair of local variables contain reference values, the merged state contains a reference * to an instance of the first common superclass of the two types. */staticboolmergeBasicBlocks(Verifier* v, BlockInfo* fromBlock, BlockInfo* toBlock){ uint32 n; /* Ensure that no uninitiazed object instances are in the local variable array * or on the operand stack during a backwards branch */ if (toBlock->startAddr < fromBlock->startAddr) { for (n = 0; n < v->method->localsz; n++) { if (fromBlock->locals[n].tinfo & TINFO_UNINIT) { return verifyError(v, "uninitialized object reference in a local variable during a backwards branch"); } } for (n = 0; n < fromBlock->stacksz; n++) { if (fromBlock->opstack[n].tinfo & TINFO_UNINIT) { return verifyError(v, "uninitialized object reference on operand stack during a backwards branch"); } } } if (!(toBlock->status & VISITED)) { DBG(VERIFY3, dprintf(" visiting block starting at %d for the first time\n", toBlock->startAddr); ); copyBlockState(v->method, fromBlock, toBlock); toBlock->status |= CHANGED; return(true); } DBG(VERIFY3, dprintf("%snot a first time merge\n", indent); dprintf("%s from block (%d - %d):\n", indent, fromBlock->startAddr, fromBlock->lastAddr); printBlock(v->method, fromBlock, indent2); dprintf("%s to block (%d - %d):\n", indent, toBlock->startAddr, toBlock->lastAddr); printBlock(v->method, toBlock, indent2); dprintf("\n"); ); if (fromBlock->stacksz != toBlock->stacksz) { return verifyError(v, "merging two operand stacks of unequal size"); } /* merge the local variable arrays */ for (n = 0; n < v->method->localsz; n++) { if (mergeTypes(v, &fromBlock->locals[n], &toBlock->locals[n])) { toBlock->status |= CHANGED; } } /* merge the operand stacks */ for (n = 0; n < fromBlock->stacksz; n++) { /* if we get unstable here, not really a big deal until we try to use it. * i mean, we could get an unstable value and then immediately pop it off the stack, * for instance. */ if (mergeTypes(v, &fromBlock->opstack[n], &toBlock->opstack[n])) { toBlock->status |= CHANGED; } } DBG(VERIFY3, dprintf("%s result block:\n", indent); printBlock(v->method, toBlock, indent2); ); return(true);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -