List of usage examples for org.objectweb.asm.tree InsnList InsnList
InsnList
From source file:org.jooby.internal.apitool.Insns.java
License:Apache License
private static InsnList instructions(final MethodNode method, final AbstractInsnNode n) { InsnList instructions = new InsnList(); instructions.add(n);/*from w ww . j a v a 2s . co m*/ new Insn<>(method, n).next().forEach(instructions::add); return instructions; }
From source file:org.spongepowered.asm.mixin.injection.invoke.ModifyArgInjector.java
License:MIT License
/** * Do the injection/*from w w w .j a v a 2s . com*/ */ @Override protected void inject(Target target, MethodInsnNode node) { Type[] args = Type.getArgumentTypes(node.desc); int argIndex = this.findArgIndex(target, args); InsnList insns = new InsnList(); int extraLocals = 0; if (this.singleArgMode) { extraLocals = this.injectSingleArgHandler(target, args, argIndex, insns); } else { extraLocals = this.injectMultiArgHandler(target, args, argIndex, insns); } target.method.instructions.insertBefore(node, insns); target.method.maxLocals = Math.max(target.maxLocals, target.method.maxLocals + extraLocals); target.method.maxStack = Math.max(target.maxStack, target.method.maxStack + 2 - (extraLocals - 1)); }
From source file:org.spongepowered.asm.mixin.injection.invoke.RedirectInjector.java
License:MIT License
/** * Do the injection//from w ww. ja v a2s . c om */ @Override protected void inject(Target target, MethodInsnNode node) { boolean injectTargetParams = false; boolean targetIsStatic = node.getOpcode() == Opcodes.INVOKESTATIC; Type ownerType = Type.getType("L" + node.owner + ";"); Type returnType = Type.getReturnType(node.desc); Type[] args = Type.getArgumentTypes(node.desc); Type[] stackVars = targetIsStatic ? args : ObjectArrays.concat(ownerType, args); String desc = Injector.printArgs(stackVars) + returnType; if (!desc.equals(this.methodNode.desc)) { String alternateDesc = Injector.printArgs(ObjectArrays.concat(stackVars, target.arguments, Type.class)) + returnType; if (alternateDesc.equals(this.methodNode.desc)) { injectTargetParams = true; } else { throw new InvalidInjectionException(this.info, "@Redirect handler method has an invalid signature " + ", expected " + desc + " found " + this.methodNode.desc); } } InsnList insns = new InsnList(); int extraLocals = ASMHelper.getArgsSize(stackVars) + 1; int[] argMap = this.storeArgs(target, stackVars, insns, 0); if (injectTargetParams) { extraLocals += ASMHelper.getArgsSize(target.arguments); argMap = Ints.concat(argMap, target.argIndices); } this.invokeHandlerWithArgs(this.methodArgs, insns, argMap); target.method.instructions.insertBefore(node, insns); target.method.instructions.remove(node); target.method.maxLocals = Math.max(target.method.maxLocals, target.maxLocals + extraLocals); target.method.maxStack = Math.max(target.method.maxStack, target.maxStack + 1); }
From source file:org.spongepowered.asm.mixin.transformer.MixinTransformer.java
License:MIT License
/** * Get insns corresponding to the instance initialiser (hopefully) from the * supplied constructor.//from w w w .j ava 2 s. c om * * TODO Potentially rewrite this to be less horrible. * * @param mixin * @param ctor * @return initialiser bytecode extracted from the supplied constructor, or * null if the constructor range could not be parsed */ private InsnList getInitialiser(MixinTargetContext mixin, MethodNode ctor) { // Find the range of line numbers which corresponds to the constructor body Range init = this.getConstructorRange(ctor); if (!init.isValid()) { return null; } // Now we know where the constructor is, look for insns which lie OUTSIDE the method body int line = 0; InsnList initialiser = new InsnList(); boolean gatherNodes = false; int trimAtOpcode = -1; LabelNode optionalInsn = null; for (Iterator<AbstractInsnNode> iter = ctor.instructions.iterator(init.marker); iter.hasNext();) { AbstractInsnNode insn = iter.next(); if (insn instanceof LineNumberNode) { line = ((LineNumberNode) insn).line; AbstractInsnNode next = ctor.instructions.get(ctor.instructions.indexOf(insn) + 1); if (line == init.end && next.getOpcode() != Opcodes.RETURN) { gatherNodes = true; trimAtOpcode = Opcodes.RETURN; } else { gatherNodes = init.excludes(line); trimAtOpcode = -1; } } else if (gatherNodes) { if (optionalInsn != null) { initialiser.add(optionalInsn); optionalInsn = null; } if (insn instanceof LabelNode) { optionalInsn = (LabelNode) insn; } else { int opcode = insn.getOpcode(); if (opcode == trimAtOpcode) { trimAtOpcode = -1; continue; } for (int ivalidOp : MixinTransformer.INITIALISER_OPCODE_BLACKLIST) { if (opcode == ivalidOp) { // At the moment I don't handle any transient locals because I haven't seen any in the wild, but let's avoid writing // code which will likely break things and fix it if a real test case ever appears throw new InvalidMixinException(mixin, "Cannot handle " + ASMHelper.getOpcodeName(opcode) + " opcode (0x" + Integer.toHexString(opcode).toUpperCase() + ") in class initialiser"); } } initialiser.add(insn); } } } // Check that the last insn is a PUTFIELD, if it's not then AbstractInsnNode last = initialiser.getLast(); if (last != null) { if (last.getOpcode() != Opcodes.PUTFIELD) { throw new InvalidMixinException(mixin, "Could not parse initialiser, expected 0xB5, found 0x" + Integer.toHexString(last.getOpcode())); } } return initialiser; }
From source file:org.summer.aop.ltw.AspectWeaver.java
License:Open Source License
private void mergeInitializingInstructions(String superClassName, int maxStack, int maxLocals, String className, MethodNode methodNode, AbstractInsnNode firstSuperInsn) { InsnList superInsnList = new InsnList(); while (!(firstSuperInsn instanceof InsnNode) || (((InsnNode) firstSuperInsn).getOpcode() != RETURN && ((InsnNode) firstSuperInsn).getOpcode() != ATHROW)) { if (firstSuperInsn instanceof MethodInsnNode && ((MethodInsnNode) firstSuperInsn).owner.equals(superClassName)) ((MethodInsnNode) firstSuperInsn).owner = className; else if (firstSuperInsn instanceof FieldInsnNode && ((FieldInsnNode) firstSuperInsn).owner.equals(superClassName)) ((FieldInsnNode) firstSuperInsn).owner = className; superInsnList.add(firstSuperInsn); firstSuperInsn = firstSuperInsn.getNext(); }/* w w w. jav a2 s. c o m*/ firstSuperInsn = methodNode.instructions.getFirst(); while (!(firstSuperInsn instanceof MethodInsnNode) || !((MethodInsnNode) firstSuperInsn).owner.equals(superClassName) || ((MethodInsnNode) firstSuperInsn).getOpcode() != INVOKESPECIAL || !((MethodInsnNode) firstSuperInsn).name.equals("<init>")) { firstSuperInsn = firstSuperInsn.getNext(); } firstSuperInsn = firstSuperInsn.getNext(); methodNode.instructions.insertBefore(firstSuperInsn, superInsnList); methodNode.maxStack = Math.max(methodNode.maxStack, maxStack); methodNode.maxLocals = Math.max(methodNode.maxLocals, maxLocals); for (Iterator<?> it = methodNode.localVariables.iterator(); it.hasNext();) { LocalVariableNode localVar = (LocalVariableNode) it.next(); if (localVar.desc.equals("L" + superClassName + ";")) localVar.desc = "L" + className + ";"; } }
From source file:pku.sei.checkedcoverage.tracer.instrumentation.TracingMethodInstrumenter.java
License:Creative Commons License
@SuppressWarnings("unchecked") public void transform(final ListIterator<MethodNode> methodIt) { // do not modify abstract or native methods if ((this.methodNode.access & ACC_ABSTRACT) != 0 || (this.methodNode.access & ACC_NATIVE) != 0) return;/*ww w .jav a 2s. c o m*/ // check out what labels are jump targets (only these have to be traced) analyze(this.methodNode); this.instructionIterator = new FixedInstructionIterator(this.methodNode.instructions); // in the old method, initialize the new local variable for the threadtracer this.instructionIterator.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class), "getInstance", "()L" + Type.getInternalName(Tracer.class) + ";")); this.instructionIterator.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class), "getThreadTracer", "()L" + Type.getInternalName(ThreadTracer.class) + ";")); this.instructionIterator.add(new InsnNode(DUP)); this.instructionIterator.add(new VarInsnNode(ASTORE, this.tracerLocalVarIndex)); this.instructionIterator.add( new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class), "isPaused", "()Z")); final LabelNode noTracingLabel = new LabelNode(); this.instructionIterator.add(new JumpInsnNode(IFNE, noTracingLabel)); // create a copy of the (uninstrumented) instructions (later, while iterating through the instructions) final InsnList oldInstructions = new InsnList(); final Map<LabelNode, LabelNode> labelCopies = LazyMap.decorate(new HashMap<LabelNode, LabelNode>(), new Factory() { @Override public Object create() { return new LabelNode(); } }); // copy the try-catch-blocks final Object[] oldTryCatchblockNodes = this.methodNode.tryCatchBlocks.toArray(); for (final Object o : oldTryCatchblockNodes) { final TryCatchBlockNode tcb = (TryCatchBlockNode) o; final TryCatchBlockNode newTcb = new TryCatchBlockNode(labelCopies.get(tcb.start), labelCopies.get(tcb.end), labelCopies.get(tcb.handler), tcb.type); this.methodNode.tryCatchBlocks.add(newTcb); } // increment number of local variables by one (for the threadtracer) ++this.methodNode.maxLocals; // and increment all local variable indexes after the new one by one for (final Object o : this.methodNode.localVariables) { final LocalVariableNode localVar = (LocalVariableNode) o; if (localVar.index >= this.tracerLocalVarIndex) ++localVar.index; } // store information about local variables in the ReadMethod object List<LocalVariable> localVariables = new ArrayList<LocalVariable>(); for (final Object o : this.methodNode.localVariables) { final LocalVariableNode localVar = (LocalVariableNode) o; while (localVariables.size() <= localVar.index) localVariables.add(null); localVariables.set(localVar.index, new LocalVariable(localVar.index, localVar.name, localVar.desc)); } this.readMethod.setLocalVariables(localVariables.toArray(new LocalVariable[localVariables.size()])); localVariables = null; // each method must start with a (dedicated) label: assert this.readMethod.getInstructions().isEmpty(); traceLabel(null, InstructionType.METHODENTRY); assert this.readMethod.getInstructions().size() == 1 && this.readMethod.getInstructions().get(0) instanceof LabelMarker && ((LabelMarker) this.readMethod.getInstructions().get(0)).isAdditionalLabel(); this.readMethod.setMethodEntryLabel((LabelMarker) this.readMethod.getInstructions().get(0)); // needed later: final LabelNode l0 = new LabelNode(); this.instructionIterator.add(l0); // then, visit the instructions that were in the method before while (this.instructionIterator.hasNext()) { final AbstractInsnNode insnNode = this.instructionIterator.next(); switch (insnNode.getType()) { case AbstractInsnNode.INSN: transformInsn((InsnNode) insnNode); break; case AbstractInsnNode.INT_INSN: transformIntInsn((IntInsnNode) insnNode); break; case AbstractInsnNode.VAR_INSN: transformVarInsn((VarInsnNode) insnNode); break; case AbstractInsnNode.TYPE_INSN: transformTypeInsn((TypeInsnNode) insnNode); break; case AbstractInsnNode.FIELD_INSN: transformFieldInsn((FieldInsnNode) insnNode); break; case AbstractInsnNode.METHOD_INSN: transformMethodInsn((MethodInsnNode) insnNode); break; case AbstractInsnNode.JUMP_INSN: transformJumpInsn((JumpInsnNode) insnNode); break; case AbstractInsnNode.LABEL: transformLabel((LabelNode) insnNode); break; case AbstractInsnNode.LDC_INSN: transformLdcInsn((LdcInsnNode) insnNode); break; case AbstractInsnNode.IINC_INSN: transformIincInsn((IincInsnNode) insnNode); break; case AbstractInsnNode.TABLESWITCH_INSN: transformTableSwitchInsn((TableSwitchInsnNode) insnNode); break; case AbstractInsnNode.LOOKUPSWITCH_INSN: transformLookupSwitchInsn((LookupSwitchInsnNode) insnNode); break; case AbstractInsnNode.MULTIANEWARRAY_INSN: transformMultiANewArrayInsn((MultiANewArrayInsnNode) insnNode); break; case AbstractInsnNode.FRAME: // ignore break; case AbstractInsnNode.LINE: // ignore break; default: throw new RuntimeException("Unknown instruction type " + insnNode.getType() + " (" + insnNode.getClass().getSimpleName() + ")"); } oldInstructions.add(insnNode.clone(labelCopies)); } assert this.outstandingInitializations == 0; // add the (old) try-catch blocks to the readMethods // (can only be done down here since we use the information in the // labels map) for (final Object o : oldTryCatchblockNodes) { final TryCatchBlockNode tcb = (TryCatchBlockNode) o; this.readMethod.addTryCatchBlock(new TryCatchBlock(this.labels.get(tcb.start), this.labels.get(tcb.end), this.labels.get(tcb.handler), tcb.type)); } final LabelNode l1 = new LabelNode(); this.instructionIterator.add(l1); final int newPos = this.readMethod.getInstructions().size(); traceLabel(null, InstructionType.METHODEXIT); assert this.readMethod.getInstructions().size() == newPos + 1; final AbstractInstruction abnormalTerminationLabel = this.readMethod.getInstructions().get(newPos); assert abnormalTerminationLabel instanceof LabelMarker; this.readMethod.setAbnormalTerminationLabel((LabelMarker) abnormalTerminationLabel); this.methodNode.instructions.add(new InsnNode(ATHROW)); // add a try catch block around the method so that we can trace when this method is left // a thrown exception this.methodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, null)); // now add the code that is executed if no tracing should be performed this.methodNode.instructions.add(noTracingLabel); if (this.firstLine != -1) this.methodNode.instructions.add(new LineNumberNode(this.firstLine, noTracingLabel)); this.methodNode.instructions.add(new InsnNode(ACONST_NULL)); this.methodNode.instructions.add(new VarInsnNode(ASTORE, this.tracerLocalVarIndex)); this.methodNode.instructions.add(oldInstructions); // finally: create a copy of the method that gets the ThreadTracer as argument // this is only necessary for private methods or "<init>" if (this.tracer.wasRedefined(this.readMethod.getReadClass().getName()) && (this.methodNode.access & ACC_PRIVATE) != 0) { final Type[] oldMethodArguments = Type.getArgumentTypes(this.methodNode.desc); final Type[] newMethodArguments = Arrays.copyOf(oldMethodArguments, oldMethodArguments.length + 1); newMethodArguments[oldMethodArguments.length] = Type.getType(ThreadTracer.class); final String newMethodDesc = Type.getMethodDescriptor(Type.getReturnType(this.methodNode.desc), newMethodArguments); final MethodNode newMethod = new MethodNode(this.methodNode.access, this.methodNode.name, newMethodDesc, this.methodNode.signature, (String[]) this.methodNode.exceptions.toArray(new String[this.methodNode.exceptions.size()])); methodIt.add(newMethod); int threadTracerParamPos = ((this.readMethod.getAccess() & Opcodes.ACC_STATIC) == 0 ? 1 : 0); for (final Type t : oldMethodArguments) threadTracerParamPos += t.getSize(); final Map<LabelNode, LabelNode> newMethodLabels = LazyMap.decorate(new HashMap<LabelNode, LabelNode>(), new Factory() { @Override public Object create() { return new LabelNode(); } }); // copy the local variables information to the new method for (final Object o : this.methodNode.localVariables) { final LocalVariableNode lv = (LocalVariableNode) o; newMethod.localVariables.add(new LocalVariableNode(lv.name, lv.desc, lv.signature, newMethodLabels.get(lv.start), newMethodLabels.get(lv.end), lv.index)); } newMethod.maxLocals = this.methodNode.maxLocals; newMethod.maxStack = this.methodNode.maxStack; // copy the try-catch-blocks for (final Object o : this.methodNode.tryCatchBlocks) { final TryCatchBlockNode tcb = (TryCatchBlockNode) o; newMethod.tryCatchBlocks.add(new TryCatchBlockNode(newMethodLabels.get(tcb.start), newMethodLabels.get(tcb.end), newMethodLabels.get(tcb.handler), tcb.type)); } // skip the first 6 instructions, replace them with these: newMethod.instructions.add(new VarInsnNode(ALOAD, threadTracerParamPos)); newMethod.instructions.add(new InsnNode(DUP)); newMethod.instructions.add(new VarInsnNode(ASTORE, this.tracerLocalVarIndex)); newMethod.instructions.add(new JumpInsnNode(IFNULL, newMethodLabels.get(noTracingLabel))); final Iterator<AbstractInsnNode> oldInsnIt = this.methodNode.instructions.iterator(6); // and add all the other instructions while (oldInsnIt.hasNext()) { final AbstractInsnNode insn = oldInsnIt.next(); newMethod.instructions.add(insn.clone(newMethodLabels)); } } ready(); }
From source file:pl.asie.foamfix.coremod.patches.ReturnIfBooleanTruePatch.java
License:Open Source License
public ReturnIfBooleanTruePatch(String optionName, String... methods) { this.optionName = optionName; this.methods = ImmutableSet.copyOf(methods); list = new InsnList(); Label l = new Label(); LabelNode ln = new LabelNode(l); list.add(new FieldInsnNode(Opcodes.GETSTATIC, "pl/asie/foamfix/shared/FoamFixShared", "config", "Lpl/asie/foamfix/shared/FoamFixConfig;")); list.add(new FieldInsnNode(Opcodes.GETFIELD, "pl/asie/foamfix/shared/FoamFixConfig", optionName, "Z")); list.add(new JumpInsnNode(Opcodes.IFEQ, ln)); list.add(new InsnNode(Opcodes.RETURN)); list.add(ln);//from w w w .j ava 2 s . c o m list.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null)); }
From source file:pl.clareo.coroutines.core.ClassTransformer.java
License:Apache License
@SuppressWarnings("unchecked") private static InsnList createDebugFrame(MethodNode coroutine) { InsnList insn = new InsnList(); int nLocals = coroutine.maxLocals; String[] names = new String[nLocals]; List<LocalVariableNode> locals = coroutine.localVariables; fillVariableNames(names, locals);/*from w w w . ja v a 2s . c o m*/ insn.add(new TypeInsnNode(Opcodes.NEW, FRAME_NAME)); insn.add(new InsnNode(Opcodes.DUP)); insn.add(makeInt(nLocals)); insn.add(makeInt(nLocals)); insn.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/String")); for (LocalVariableNode local : locals) { int i = local.index; String name = names[i]; insn.add(new InsnNode(Opcodes.DUP)); insn.add(makeInt(i)); if (name != null) { insn.add(new LdcInsnNode(name)); } else { insn.add(new InsnNode(Opcodes.ACONST_NULL)); } insn.add(new InsnNode(Opcodes.AASTORE)); } insn.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, FRAME_NAME, "<init>", "(I[Ljava/lang/String;)V")); return insn; }
From source file:pl.clareo.coroutines.core.ClassTransformer.java
License:Apache License
private static InsnList createFrame(MethodNode coroutine) { InsnList insn = new InsnList(); insn.add(new TypeInsnNode(Opcodes.NEW, FRAME_NAME)); insn.add(new InsnNode(Opcodes.DUP)); insn.add(makeInt(coroutine.maxLocals)); insn.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, FRAME_NAME, "<init>", "(I)V")); return insn;/* ww w . j a v a 2s. c o m*/ }
From source file:pl.clareo.coroutines.core.ClassTransformer.java
License:Apache License
private static InsnList loggingInstructions(String ownerName, String loggerField, Level level, Object... messages) {/*from w w w. j a v a 2s . c o m*/ InsnList insn = new InsnList(); insn.add(new FieldInsnNode(Opcodes.GETSTATIC, ownerName, loggerField, "Ljava/util/logging/Logger;")); insn.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/util/logging/Level", level.getName(), "Ljava/util/logging/Level;")); // stack: * * insn.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/logging/Logger", "isLoggable", "(Ljava/util/logging/Level;)Z")); // stack: * LabelNode exitBranch = new LabelNode(); insn.add(new JumpInsnNode(Opcodes.IFEQ, exitBranch)); // stack: insn.add(new FieldInsnNode(Opcodes.GETSTATIC, ownerName, loggerField, "Ljava/util/logging/Logger;")); insn.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/util/logging/Level", level.getName(), "Ljava/util/logging/Level;")); // stack: * * insn.add(new TypeInsnNode(Opcodes.NEW, "java/lang/StringBuilder")); insn.add(new InsnNode(Opcodes.DUP)); // stack: * * * * String message0 = messages[0].toString(); insn.add(new LdcInsnNode(message0)); // stack: * * * * * insn.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V")); // stack: * * * for (int m = 1; m < messages.length; m++) { Object message = messages[m]; if (message instanceof Number) { insn.add(new VarInsnNode(Opcodes.ALOAD, ((Number) message).intValue())); } else { insn.add(new LdcInsnNode(message.toString())); } // stack: * * * * insn.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")); // stack: * * * } insn.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;")); insn.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/logging/Logger", "log", "(Ljava/util/logging/Level;Ljava/lang/String;)V")); // stack: insn.add(exitBranch); return insn; }