@Override public SourceValue newOperation(final AbstractInsnNode insn) { int size; switch (insn.getOpcode()) { case LCONST_0: case LCONST_1: case DCONST_0: case DCONST_1: size = 2; break; case LDC: Object cst = ((LdcInsnNode) insn).cst; size = cst instanceof Long || cst instanceof Double ? 2 : 1; break; case GETSTATIC: size = Type.getType(((FieldInsnNode) insn).desc).getSize(); break; default: size = 1; } return new SourceValue(size, insn); }
private static BitSet getEntryPoints(MethodNode asmNode, Map<AbstractInsnNode, int[]> exitPoints) { InsnList il = asmNode.instructions; BitSet entryPoints = new BitSet(il.size()); for (int[] eps : exitPoints.values()) { if (eps != null) { for (int ep : eps) entryPoints.set(ep); } } for (TryCatchBlockNode n : asmNode.tryCatchBlocks) { entryPoints.set(il.indexOf(n.handler)); } return entryPoints; }
@Override public void transform(ClassNode clazz, MethodNode method, InsnMatcher matcher) { AbstractInsnNode[] match = Iterators.getOnlyElement(matcher.match("BIPUSH ISTORE", m -> { IntInsnNode push = (IntInsnNode) m[0]; if (push.operand != 50) { return false; } VarInsnNode store = (VarInsnNode) m[1]; LocalVariableNode node = AsmUtils.getLocalVariable(method, store.var, store); return node != null && node.name.equals("resource") && node.desc.equals("I"); })); method.instructions.remove(match[0]); method.instructions.remove(match[1]); }
private void replaceInvokeSpecial(ClassNode clazz, List<MethodNode> toReplace) { for (MethodNode method : clazz.methods) { for (Iterator<AbstractInsnNode> it = method.instructions.iterator(); it.hasNext();) { AbstractInsnNode insn = it.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode n : toReplace) { if (n.name.equals(mInsn.name) && n.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } }
@Override public SourceValue unaryOperation(final AbstractInsnNode insn, final SourceValue value) { int size; switch (insn.getOpcode()) { case LNEG: case DNEG: case I2L: case I2D: case L2D: case F2L: case F2D: case D2L: size = 2; break; case GETFIELD: size = Type.getType(((FieldInsnNode) insn).desc).getSize(); break; default: size = 1; } return new SourceValue(size, insn); }
@SuppressWarnings(UNCHECKED) Set<LocalVariableNode> analyzeMethod() { // si seulement 1 variable locale ("this") ou si seulement des "variables locales" pour les paramètres et pour "this", // alors on passe à la méthode suivante if (localVariables.isEmpty()) { return Collections.emptySet(); } for (final Iterator<AbstractInsnNode> it = methodNode.instructions.iterator(); it .hasNext();) { analyzeInstruction(it.next()); if (localVariables.isEmpty()) { // si toutes les variables ont été utilisées, inutile de continuer à lire les instructions return Collections.emptySet(); } } return localVariables; }
private List<TryCatchBlock> getTryHandlers(AbstractInsnNode insn) { List<TryCatchBlock> handlers = new ArrayList<>(); Set<String> seen = new HashSet<>(); // The try-catch blocks are ordered by precedence. for (TryCatchBlock tryCatchBlock : getPotentialTryHandlers(insn)) { if (tryCatchBlock.getType() == null) { handlers.add(tryCatchBlock); return handlers; } if (!seen.contains(tryCatchBlock.getType())) { seen.add(tryCatchBlock.getType()); handlers.add(tryCatchBlock); } } if (isSynchronized()) { // Add synchronized exceptional exit for synchronized-method instructions without a default. assert handlers.isEmpty() || handlers.get(handlers.size() - 1).getType() != null; handlers.add(EXCEPTIONAL_SYNC_EXIT); } return handlers; }
@Override public BasicValue binaryOperation(final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2) throws AnalyzerException { /* * We're looking for the assignment of a local holder objectref to a member variable. * If we spot that, then the local holder can't be replaced, since we don't (yet) * have the mechanics to replace the member variable with the holder's members or * to assign all of them when this happens. */ if (insn.getOpcode() == Opcodes.PUTFIELD) { if (value2.isReference() && (value1 instanceof ReplacingBasicValue)) { final ReplacingBasicValue possibleThis = (ReplacingBasicValue) value1; if (possibleThis.isThis() && (value2 instanceof ReplacingBasicValue)) { // if this is a reference for a holder class, we can't replace it if (HOLDERS.get(value2.getType().getDescriptor()) != null) { final ReplacingBasicValue localRef = (ReplacingBasicValue) value2; localRef.setAssignedToMember(); } } } } return super.binaryOperation(insn, value1, value2); }
@SuppressWarnings(UNCHECKED) void analyzeInnerClass(ClassNode innerClass) { if (methodNode.name.equals(innerClass.outerMethod) && methodNode.desc.equals(innerClass.outerMethodDesc)) { // s'il y a une classe interne créée dans cette méthode // utilisant éventuellement une variable finale de cette méthode, // alors on cherche les constantes de variables (et uniquement celles-ci) dans toutes ses méthodes // (si ce n'est pas une constante, alors elle serait déjà détectée utilisée dans la méthode) for (final MethodNode innerMethodNode : (List<MethodNode>) innerClass.methods) { for (final Iterator<AbstractInsnNode> it = innerMethodNode.instructions .iterator(); it.hasNext();) { // CHECKSTYLE:OFF final AbstractInsnNode instruction = it.next(); // CHECKSTYLE:ON analyzeConstantInstruction(instruction); if (localVariables.isEmpty()) { // si toutes les variables ont été utilisées, inutile de continuer à lire les instructions return; } } } } }
public static void setSuper(ClassNode node, String superClass) { String replacedSuper = ""; if (node.superName != "") { replacedSuper = node.superName; } if (replacedSuper != "") { ListIterator<?> mli = node.methods.listIterator(); while (mli.hasNext()) { MethodNode mn = (MethodNode) mli.next(); ListIterator<?> ili = mn.instructions.iterator(); while (ili.hasNext()) { AbstractInsnNode ain = (AbstractInsnNode) ili.next(); if (ain.getOpcode() == Opcodes.INVOKESPECIAL) { MethodInsnNode min = (MethodInsnNode) ain; if (min.owner.equals(replacedSuper)) { min.owner = superClass; } } } } } node.superName = superClass; }
private static void findID(ClassNode classNode) throws Throwable { for (MethodNode methodNode : classNode.methods) { Iterator<AbstractInsnNode> insnIterator = methodNode.instructions.iterator(); while (insnIterator.hasNext()) { AbstractInsnNode insnNode = insnIterator.next(); String str; if ((insnNode.getType() == 9)) { Object cst = ((LdcInsnNode) insnNode).cst; if (cst instanceof String) { str = ((LdcInsnNode) insnNode).cst.toString(); Matcher matcher = NONCEID_PATTERN.matcher(str); if (matcher.find()) { possiblenonces.add(str); } } } } } }
protected void transformParticle(ClassNode classNode, MethodNode method, AbstractInsnNode instruction, int firstInsn) { InsnList toInsert = new InsnList(); toInsert.add(new VarInsnNode(FLOAD, 4)); toInsert.add(new VarInsnNode(FLOAD, 5)); toInsert.add(new VarInsnNode(FLOAD, 6)); toInsert.add(new VarInsnNode(FLOAD, 7)); toInsert.add(new VarInsnNode(FLOAD, 8)); toInsert.add(new VarInsnNode(FLOAD, firstInsn)); toInsert.add(new VarInsnNode(FLOAD, firstInsn+1)); toInsert.add(new VarInsnNode(FLOAD, firstInsn+2)); toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(ParticleTransformer.class), "rotateParticle", "(FFFFFFFF)V", false)); toInsert.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ParticleTransformer.class), "rotX", "F")); toInsert.add(new VarInsnNode(FSTORE, 4)); toInsert.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ParticleTransformer.class), "rotZ", "F")); toInsert.add(new VarInsnNode(FSTORE, 5)); toInsert.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ParticleTransformer.class), "rotYZ", "F")); toInsert.add(new VarInsnNode(FSTORE, 6)); toInsert.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ParticleTransformer.class), "rotXY", "F")); toInsert.add(new VarInsnNode(FSTORE, 7)); toInsert.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ParticleTransformer.class), "rotXZ", "F")); toInsert.add(new VarInsnNode(FSTORE, 8)); method.instructions.insertBefore(instruction, toInsert); }
public AbstractInsnNode methodInvokeInsn() { return new MethodInsnNode( INVOKESPECIAL, context.thisClassType().getInternalName(), methodName(), methodType().getDescriptor(), false); }
public static AbstractInsnNode boxedNumberToLuaFormatString() { return new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Conversions.class), "stringValueOf", Type.getMethodDescriptor( Type.getType(String.class), Type.getType(Number.class)), false); }
public TagTypeSwitchPanel(JList<AbstractInsnNode> list, Handle handle) { this.list = list; this.handle = handle; //setMaximumSize(new Dimension(300, 300)); // content.setMaximumSize(new Dimension(300, 300)); // scroll.setMaximumSize(new Dimension(300, 300)); content.setLayout(new GridLayout(0, 2)); populate(OpcodeUtil.OPS_TAG, s -> OpcodeUtil.nameToTag(s)); setLayout(new BorderLayout()); JScrollPane scroll = new JScrollPane(content); add(scroll, BorderLayout.CENTER); }
@Override public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value) throws AnalyzerException { /* * We're looking for the assignment of an operator member variable that's a holder to a local * objectref. If we spot that, we can't replace the local objectref (at least not * until we do the work to replace member variable holders). * * Note that a GETFIELD does not call newValue(), as would happen for a local variable, so we're * emulating that here. */ if ((insn.getOpcode() == Opcodes.GETFIELD) && (value instanceof ReplacingBasicValue)) { final ReplacingBasicValue possibleThis = (ReplacingBasicValue) value; if (possibleThis.isThis()) { final FieldInsnNode fieldInsn = (FieldInsnNode) insn; if (HOLDERS.get(fieldInsn.desc) != null) { final BasicValue fetchedField = super.unaryOperation(insn, value); final ReplacingBasicValue replacingValue = ReplacingBasicValue.create(fetchedField.getType(), null, -1, valueList); replacingValue.setAssignedToMember(); return replacingValue; } } } return super.unaryOperation(insn, value); }
@Override public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) { int size; int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { size = 1; } else { String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc : ((MethodInsnNode) insn).desc; size = Type.getReturnType(desc).getSize(); } return new SourceValue(size, insn); }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformRenderParticle = new MethodTransformer() { @Override public MethodName getName() { return Names.Particle_renderParticle; } @Override public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); for (AbstractInsnNode instruction : method.instructions.toArray()) { if (instruction.getOpcode() == BIPUSH && instruction.getNext().getOpcode() == GETSTATIC) { CLTLog.info("Found BIPUSH in method " + getName().all()); instruction = instruction.getPrevious(); transformParticle(classNode, method, instruction, 15); break; } } } }; return new MethodTransformer[] {transformRenderParticle}; }
private MethodInsnNode getMethodInstruction(MethodNode mn, String owner, String method) { for (int i = 0; i < mn.instructions.size(); i++) { AbstractInsnNode ins = mn.instructions.get(i); if (ins instanceof MethodInsnNode) { MethodInsnNode mi = (MethodInsnNode) ins; if (mi.name.equals(method)) { if ((owner == null) || mi.owner.equals(owner)) { return mi; } } } } return null; }
/** * Moves the insns down one in the list. * * @param list * Complete list of opcodes. * @param insn * Sublist to be moved. */ public static void moveDown(InsnList list, List<AbstractInsnNode> insns) { AbstractInsnNode prev = insns.get(insns.size() - 1).getNext(); if (prev == null) return; InsnList x = new InsnList(); for (AbstractInsnNode ain : insns) { list.remove(ain); x.add(ain); } list.insert(prev, x); }
@Override public void transform(ClassNode clazz, MethodNode method, InsnMatcher matcher) { AbstractInsnNode ret = AsmUtils.getPreviousRealInsn(method.instructions.getLast()); AbstractInsnNode aload = ret.getPrevious(); InsnList list = new InsnList(); list.add(new TypeInsnNode(Opcodes.NEW, "com/wyverngame/anvil/api/server/action/AnvilBehaviour")); list.add(new InsnNode(Opcodes.DUP)); method.instructions.insertBefore(aload, list); method.instructions.insertBefore(ret, new MethodInsnNode(Opcodes.INVOKESPECIAL, "com/wyverngame/anvil/api/server/action/AnvilBehaviour", "<init>", "(Lcom/wurmonline/server/behaviours/Behaviour;)V", false)); }
@Override public SourceValue binaryOperation(final AbstractInsnNode insn, final SourceValue value1, final SourceValue value2) { int size; switch (insn.getOpcode()) { case LALOAD: case DALOAD: case LADD: case DADD: case LSUB: case DSUB: case LMUL: case DMUL: case LDIV: case DDIV: case LREM: case DREM: case LSHL: case LSHR: case LUSHR: case LAND: case LOR: case LXOR: size = 2; break; default: size = 1; } return new SourceValue(size, insn); }
private String[] from(Map<String, List<AbstractInsnNode>> blocks) { String[] a = new String[blocks.size()]; int i = 0; for (String s : blocks.keySet()) { a[i] = s; i++; } return a; }
@Override public void returnOperation(final AbstractInsnNode insn, final BasicValue value, final BasicValue expected) throws AnalyzerException { if (!isSubTypeOf(value, expected)) { throw new AnalyzerException(insn, "Incompatible return type", expected, value); } }
public static @Nullable LocalVariableNode getLocalVariable(MethodNode method, int index, AbstractInsnNode scope) { for (LocalVariableNode var : method.localVariables) { if (var.index == index) { for (AbstractInsnNode node = var.start; node != var.end; node = node.getNext()) { if (node == scope) { return var; } } } } return null; }
private void populate(InsnList opcodes) { int selected = -1, labelCount = 0;; DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(); for (int i = 0; i < opcodes.size(); i++) { AbstractInsnNode ain = opcodes.get(i); if (ain.getType() == AbstractInsnNode.LABEL) { LabelNode label = (LabelNode) ain; String s = i + "."; if (list != null) { s += " : " + list.getLabelName(ain); } labels.put(s, label); model.addElement(s); if (label.equals(initial)) { selected = labelCount; } labelCount++; } } combo.setModel(model); combo.setSelectedIndex(selected); combo.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { updater.accept(labels.get(e.getItem())); if (list != null) { list.repaint(); } } }); }
private void processLocalVariablesAtControlEdge(AbstractInsnNode insn, IRBuilder builder) { assert isControlFlowInstruction(insn) && !isReturn(insn); if (!(insn.getNext() instanceof LabelNode)) { return; } // If the label is the end of any local-variable scopes read the locals to ensure liveness. LabelNode label = (LabelNode) insn.getNext(); for (Local local : state.getLocalsToClose(label)) { builder.addDebugLocalRead(local.slot.register, local.info); } }
private void processLocalVariablesAtExit(AbstractInsnNode insn, IRBuilder builder) { assert isReturn(insn) || isThrow(insn); // Read all locals live at exit to ensure liveness. for (Local local : state.getLocals()) { if (local.info != null) { builder.addDebugLocalRead(local.slot.register, local.info); } } }
public static AbstractInsnNode StringBuilder_toString() { return new MethodInsnNode( INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "toString", Type.getMethodDescriptor( Type.getType(String.class)), false); }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformRenderParticle = new MethodTransformer() { @Override public MethodName getName() { return Names.Particle_renderParticle; } @Override public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); for (AbstractInsnNode instruction : method.instructions.toArray()) { if (instruction.getOpcode() == ISHR) { CLTLog.info("Found ISHR in method " + getName().all()); instruction = instruction.getPrevious().getPrevious(); transformParticle(classNode, method, instruction, 14); break; } } } }; return new MethodTransformer[] {transformRenderParticle}; }
public static AbstractInsnNode set() { return new MethodInsnNode( INVOKEVIRTUAL, Type.getInternalName(Variable.class), "set", Type.getMethodDescriptor( Type.VOID_TYPE, Type.getType(Object.class)), false); }
/** * Rewrites the method bytecode to remove the "Stub!" exception. */ private void fixMethodBody(MethodNode methodNode, ClassNode classNode) { if ((methodNode.access & Opcodes.ACC_NATIVE) != 0 || (methodNode.access & Opcodes.ACC_ABSTRACT) != 0) { // Abstract and native method don't have bodies to rewrite. return; } if ((classNode.access & Opcodes.ACC_ENUM) != 0 && ENUM_METHODS.contains(methodNode.name)) { // Don't break enum classes. return; } Type returnType = Type.getReturnType(methodNode.desc); InsnList instructions = methodNode.instructions; List localVariables = methodNode.localVariables; List tryCatchBlocks = methodNode.tryCatchBlocks; if (localVariables != null && !localVariables.isEmpty()) { localVariables.clear(); } if (tryCatchBlocks != null && !tryCatchBlocks.isEmpty()) { tryCatchBlocks.clear(); } if (methodNode.name.equals(CONSTRUCTOR)) { // Keep the call to parent constructor, delete the exception after that. boolean deadCode = false; for (AbstractInsnNode instruction : instructions.toArray()) { if (!deadCode) { if (instruction.getOpcode() == Opcodes.INVOKESPECIAL) { instructions.insert(instruction, new InsnNode(Opcodes.RETURN)); // Start removing all following instructions. deadCode = true; } } else { instructions.remove(instruction); } } } else { instructions.clear(); if (returnDefaultValues || methodNode.name.equals(CLASS_CONSTRUCTOR)) { if (INTEGER_LIKE_TYPES.contains(returnType)) { instructions.add(new InsnNode(Opcodes.ICONST_0)); } else if (returnType.equals(Type.LONG_TYPE)) { instructions.add(new InsnNode(Opcodes.LCONST_0)); } else if (returnType.equals(Type.FLOAT_TYPE)) { instructions.add(new InsnNode(Opcodes.FCONST_0)); } else if (returnType.equals(Type.DOUBLE_TYPE)) { instructions.add(new InsnNode(Opcodes.DCONST_0)); } else { instructions.add(new InsnNode(Opcodes.ACONST_NULL)); } instructions.add(new InsnNode(returnType.getOpcode(Opcodes.IRETURN))); } else { instructions.insert(throwExceptionsList(methodNode, classNode)); } } }
public static AbstractInsnNode tailCall(int kind) { return tailCall_method(kind).toMethodInsnNode(); }
@Override public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value) throws AnalyzerException { return value; }
public static AbstractInsnNode index() { return dynamic(OP_INDEX, 2); }