📄 opcodestack.java
字号:
else flags &= ~flagBit; } /** * @return Returns the isNull. */ public boolean isNull() { return (flags & IS_NULL_FLAG) != 0; } } @Override public String toString() { return stack.toString() + "::" + lvValues.toString(); } public OpcodeStack() { stack = new ArrayList<Item>(); lvValues = new ArrayList<Item>(); lastUpdate = new ArrayList<Integer>(); } boolean needToMerge = true; boolean reachOnlyByBranch = false; public static String getExceptionSig(DismantleBytecode dbc, CodeException e) { if (e.getCatchType() == 0) return "Ljava/lang/Throwable;"; Constant c = dbc.getConstantPool().getConstant(e.getCatchType()); if (c instanceof ConstantClass) return "L"+((ConstantClass)c).getBytes(dbc.getConstantPool())+";"; return "Ljava/lang/Throwable;"; } public void mergeJumps(DismantleBytecode dbc) { if (!needToMerge) return; needToMerge = false; boolean stackUpdated = false; if (convertJumpToOneZeroState == 3 || convertJumpToZeroOneState == 3) { pop(); Item top = new Item("I"); top.setCouldBeZero(true); push(top); convertJumpToOneZeroState = convertJumpToZeroOneState = 0; stackUpdated = true; } List<Item> jumpEntry = null; if (jumpEntryLocations.get(dbc.getPC())) jumpEntry = jumpEntries.get(dbc.getPC()); if (jumpEntry != null) { if (DEBUG) { System.out.println("XXXXXXX " + reachOnlyByBranch); System.out.println("merging lvValues at jump target " + dbc.getPC() + " -> " + Integer.toString(System.identityHashCode(jumpEntry),16) + " " + jumpEntry); System.out.println(" current lvValues " + lvValues); } List<Item> jumpStackEntry = jumpStackEntries.get(dbc.getPC()); if (reachOnlyByBranch) { lvValues = new ArrayList<Item>(jumpEntry); if (!stackUpdated) { if (jumpStackEntry != null) stack = new ArrayList<Item>(jumpStackEntry); else stack.clear(); } } else { mergeLists(lvValues, jumpEntry, false); if (!stackUpdated && jumpStackEntry != null) mergeLists(stack, jumpStackEntry, false); } if (DEBUG) System.out.println(" merged lvValues " + lvValues); } else if (reachOnlyByBranch && !stackUpdated) { stack.clear(); boolean foundException = false; for(CodeException e : dbc.getCode().getExceptionTable()) { if (e.getHandlerPC() == dbc.getPC()) { push(new Item(getExceptionSig(dbc, e))); foundException = true; } } if (!foundException) push(new Item("Ljava/lang/Throwable;")); } reachOnlyByBranch = false; } int convertJumpToOneZeroState = 0; int convertJumpToZeroOneState = 0; private void setLastUpdate(int reg, int pc) { while (lastUpdate.size() <= reg) lastUpdate.add(0); lastUpdate.set(reg, pc); } public int getLastUpdate(int reg) { if (lastUpdate.size() <= reg) return 0; return lastUpdate.get(reg); } public int getNumLastUpdates() { return lastUpdate.size(); } public void sawOpcode(DismantleBytecode dbc, int seen) { int register; String signature; Item it, it2, it3; Constant cons; if (dbc.isRegisterStore()) setLastUpdate(dbc.getRegisterOperand(), dbc.getPC()); mergeJumps(dbc); needToMerge = true; switch (seen) { case ICONST_1: convertJumpToOneZeroState = 1; break; case GOTO: if (convertJumpToOneZeroState == 1 && dbc.getBranchOffset() == 4) convertJumpToOneZeroState = 2; else convertJumpToOneZeroState = 0; break; case ICONST_0: if (convertJumpToOneZeroState == 2) convertJumpToOneZeroState = 3; else convertJumpToOneZeroState = 0; break; default:convertJumpToOneZeroState = 0; } switch (seen) { case ICONST_0: convertJumpToZeroOneState = 1; break; case GOTO: if (convertJumpToZeroOneState == 1 && dbc.getBranchOffset() == 4) convertJumpToZeroOneState = 2; else convertJumpToZeroOneState = 0; break; case ICONST_1: if (convertJumpToZeroOneState == 2) convertJumpToZeroOneState = 3; else convertJumpToZeroOneState = 0; break; default:convertJumpToZeroOneState = 0; } try { switch (seen) { case ALOAD: pushByLocalObjectLoad(dbc, dbc.getRegisterOperand()); break; case ALOAD_0: case ALOAD_1: case ALOAD_2: case ALOAD_3: pushByLocalObjectLoad(dbc, seen - ALOAD_0); break; case DLOAD: pushByLocalLoad("D", dbc.getRegisterOperand()); break; case DLOAD_0: case DLOAD_1: case DLOAD_2: case DLOAD_3: pushByLocalLoad("D", seen - DLOAD_0); break; case FLOAD: pushByLocalLoad("F", dbc.getRegisterOperand()); break; case FLOAD_0: case FLOAD_1: case FLOAD_2: case FLOAD_3: pushByLocalLoad("F", seen - FLOAD_0); break; case ILOAD: pushByLocalLoad("I", dbc.getRegisterOperand()); break; case ILOAD_0: case ILOAD_1: case ILOAD_2: case ILOAD_3: pushByLocalLoad("I", seen - ILOAD_0); break; case LLOAD: pushByLocalLoad("J", dbc.getRegisterOperand()); break; case LLOAD_0: case LLOAD_1: case LLOAD_2: case LLOAD_3: pushByLocalLoad("J", seen - LLOAD_0); break; case GETSTATIC: { FieldAnnotation field = FieldAnnotation.fromReferencedField(dbc); Item i = new Item(dbc.getSigConstantOperand(), field, Integer.MAX_VALUE); if (field.getFieldName().equals("separator") && field.getClassName().equals("java.io.File")) { i.setSpecialKind(Item.FILE_SEPARATOR_STRING); } push(i); break; } case LDC: case LDC_W: case LDC2_W: cons = dbc.getConstantRefOperand(); pushByConstant(dbc, cons); break; case INSTANCEOF: pop(); push(new Item("I")); break; case IFEQ: case IFNE: case IFLT: case IFLE: case IFGT: case IFGE: case IFNONNULL: case IFNULL: seenTransferOfControl = true; { Item top = pop(); // if we see a test comparing a special negative value with 0, // reset all other such values on the opcode stack if (top.valueCouldBeNegative() && (seen == IFLT || seen == IFLE || seen == IFGT || seen == IFGE)) { int specialKind = top.getSpecialKind(); for(Item item : stack) if (item != null && item.getSpecialKind() == specialKind) item.setSpecialKind(0); for(Item item : lvValues) if (item != null && item.getSpecialKind() == specialKind) item.setSpecialKind(0); } } addJumpValue(dbc.getBranchTarget()); break; case LOOKUPSWITCH: case TABLESWITCH: seenTransferOfControl = true; pop(); addJumpValue(dbc.getBranchTarget()); int pc = dbc.getBranchTarget() - dbc.getBranchOffset(); for(int offset : dbc.getSwitchOffsets()) addJumpValue(offset+pc); break; case ARETURN: case DRETURN: case FRETURN: case IRETURN: case LRETURN: seenTransferOfControl = true; reachOnlyByBranch = true; pop(); break; case MONITORENTER: case MONITOREXIT: case POP: case PUTSTATIC: pop(); break; case IF_ACMPEQ: case IF_ACMPNE: case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT: case IF_ICMPLE: case IF_ICMPGT: case IF_ICMPGE: seenTransferOfControl = true; pop(2); addJumpValue(dbc.getBranchTarget()); break; case POP2: it = pop(); if (it.getSize() == 1) pop(); break; case PUTFIELD: pop(2); break; case IALOAD: case SALOAD: pop(2); push(new Item("I")); break; case DUP: handleDup(); break; case DUP2: handleDup2(); break; case DUP_X1: handleDupX1(); break; case DUP_X2: handleDupX2(); break; case DUP2_X1: handleDup2X1(); break; case IINC: register = dbc.getRegisterOperand(); it = getLVValue( register ); it2 = new Item("I", dbc.getIntConstant()); pushByIntMath( IADD, it2, it); pushByLocalStore(register); break; case ATHROW: pop(); seenTransferOfControl = true; reachOnlyByBranch = true; break; case CHECKCAST: { String castTo = dbc.getClassConstantOperand(); if (castTo.charAt(0) != '[') castTo = "L" + castTo + ";"; it = new Item(pop()); it.signature = castTo; push(it); break; } case NOP: break; case RET: case RETURN: seenTransferOfControl = true; reachOnlyByBranch = true; break; case GOTO: case GOTO_W: //It is assumed that no stack items are present when seenTransferOfControl = true; reachOnlyByBranch = true; addJumpValue(dbc.getBranchTarget()); stack.clear(); break; case SWAP: handleSwap(); break; case ICONST_M1: case ICONST_0: case ICONST_1: case ICONST_2: case ICONST_3: case ICONST_4: case ICONST_5: push(new Item("I", (seen-ICONST_0))); break; case LCONST_0: case LCONST_1: push(new Item("J", (long)(seen-LCONST_0))); break; case DCONST_0: case DCONST_1: push(new Item("D", (double)(seen-DCONST_0))); break; case FCONST_0: case FCONST_1: case FCONST_2: push(new Item("F", (float)(seen-FCONST_0))); break; case ACONST_NULL: push(new Item()); break; case ASTORE: case DSTORE: case FSTORE: case ISTORE: case LSTORE: pushByLocalStore(dbc.getRegisterOperand()); break; case ASTORE_0: case ASTORE_1: case ASTORE_2: case ASTORE_3: pushByLocalStore(seen - ASTORE_0); break; case DSTORE_0: case DSTORE_1: case DSTORE_2: case DSTORE_3: pushByLocalStore(seen - DSTORE_0); break; case FSTORE_0: case FSTORE_1: case FSTORE_2: case FSTORE_3: pushByLocalStore(seen - FSTORE_0); break; case ISTORE_0: case ISTORE_1: case ISTORE_2: case ISTORE_3: pushByLocalStore(seen - ISTORE_0); break; case LSTORE_0: case LSTORE_1: case LSTORE_2: case LSTORE_3: pushByLocalStore(seen - LSTORE_0); break; case GETFIELD: { Item item = pop(); int reg = item.getRegisterNumber(); push(new Item(dbc.getSigConstantOperand(), FieldAnnotation.fromReferencedField(dbc), reg)); } break; case ARRAYLENGTH: pop(); push(new Item("I")); break; case BALOAD: { pop(2); Item v = new Item("I"); v.setSpecialKind(Item.SIGNED_BYTE); push(v); break; } case CALOAD: pop(2); push(new Item("I")); break; case DALOAD: pop(2); push(new Item("D")); break; case FALOAD: pop(2); push(new Item("F")); break; case LALOAD: pop(2); push(new Item("J")); break; case AASTORE: case BASTORE: case CASTORE: case DASTORE: case FASTORE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -