List of usage examples for org.objectweb.asm.tree MethodInsnNode setOpcode
public void setOpcode(final int opcode)
From source file:com.github.fge.grappa.transform.process.SuperCallRewriter.java
License:Apache License
private static void process(ParserClassNode classNode, RuleMethod method, MethodInsnNode insn) { if ("<init>".equals(insn.name)) return;// w w w .j av a 2 s. c om String superMethodName = getSuperMethodName(method, insn); RuleMethod superMethod = classNode.getRuleMethods().get(superMethodName + insn.desc); if (superMethod == null) return; if (!superMethod.isBodyRewritten()) return; // since the super method is rewritten we do need to generate it superMethod.dontSkipGeneration(); // we have a call to a super method that was rewritten, so we need to // change the call to the generated method insn.setOpcode(INVOKEVIRTUAL); insn.name = superMethodName; insn.owner = classNode.name; method.setBodyRewritten(); }
From source file:com.lodgon.parboiled.transform.SuperCallRewriter.java
License:Apache License
private void process(ParserClassNode classNode, RuleMethod method, MethodInsnNode insn) { if ("<init>".equals(insn.name)) return;/*ww w . j a va 2 s . c om*/ String superMethodName = getSuperMethodName(method, insn); RuleMethod superMethod = classNode.getRuleMethods().get(superMethodName.concat(insn.desc)); if (superMethod == null) return; if (!superMethod.isBodyRewritten()) return; // since the super method is rewritten we do need to generate it superMethod.dontSkipGeneration(); // we have a call to a super method that was rewritten, so we need to change the call to the generated method insn.setOpcode(INVOKEVIRTUAL); insn.name = superMethodName; insn.owner = classNode.name; method.setBodyRewritten(); }
From source file:com.microsoft.Malmo.OverclockingClassTransformer.java
License:Open Source License
private static void overclockRenderer(ClassNode node, boolean isObfuscated) { // We're attempting to turn this line from Minecraft.runGameLoop: // this.updateDisplay(); // into this: // TimeHelper.updateDisplay(); // TimeHelper's method then decides whether or not to pass the call on to Minecraft.updateDisplay(). final String methodName = isObfuscated ? "as" : "runGameLoop"; final String methodDescriptor = "()V"; // No params, returns void. System.out.println("MALMO: Found Minecraft, attempting to transform it"); for (MethodNode method : node.methods) { if (method.name.equals(methodName) && method.desc.equals(methodDescriptor)) { System.out.println("MALMO: Found Minecraft.runGameLoop() method, attempting to transform it"); for (AbstractInsnNode instruction : method.instructions.toArray()) { if (instruction.getOpcode() == Opcodes.INVOKEVIRTUAL) { MethodInsnNode visitMethodNode = (MethodInsnNode) instruction; if (visitMethodNode.name.equals(isObfuscated ? "h" : "updateDisplay")) { visitMethodNode.owner = "com/microsoft/Malmo/Utils/TimeHelper"; if (isObfuscated) { visitMethodNode.name = "updateDisplay"; }// www.ja v a 2 s .c o m visitMethodNode.setOpcode(Opcodes.INVOKESTATIC); method.instructions.remove(visitMethodNode.getPrevious()); // ALOAD 0 not needed for static invocation. System.out.println("MALMO: Hooked into call to Minecraft.updateDisplay()"); } } } } } }
From source file:hellfirepvp.astralsorcery.core.patch.helper.PatchKeyboardEvent.java
License:Open Source License
@Override public void patch(ClassNode cn) { MethodNode mn = getMethod(cn, "runTick", "func_71407_l", "()V"); MethodInsnNode m = getFirstMethodCall(mn, "net/minecraft/client/Minecraft", "runTickKeyboard", "func_184118_az", "()V"); m.setOpcode(Opcodes.INVOKESTATIC); m.owner = "hellfirepvp/astralsorcery/common/event/ClientKeyboardInputEvent"; m.name = "fireKeyboardEvent"; m.desc = "(Lnet/minecraft/client/Minecraft;)V"; }
From source file:jvstm.atomic.ProcessParNestAnnotations.java
License:Open Source License
protected static void processClassFile(File classFile) { alreadyProcessed = new ArrayList<String>(); callablesCreated = new HashMap<String, String>(); InputStream is = null;//from w w w. ja v a2 s .c om try { // get an input stream to read the bytecode of the class is = new FileInputStream(classFile); ClassNode cn = new ClassNode(ASM4); ClassReader cr = new ClassReader(is); cr.accept(cn, 0); List<MethodNode> parNestedMethods = new ArrayList<MethodNode>(); MethodNode combinerMethod = null; MethodNode execMethod = null; List<MethodNode> staticMethodsToAdd = new ArrayList<MethodNode>(); boolean parallelSpawn = extendsParallelSpawn(cn); boolean unsafeSpawn = extendsUnsafeSpawn(cn); if (parallelSpawn || unsafeSpawn) { Iterator<MethodNode> methodIter = cn.methods.iterator(); while (methodIter.hasNext()) { MethodNode mn = methodIter.next(); if (mn.name.equals("exec") && execMethod == null) { execMethod = mn; continue; } if (mn.invisibleAnnotations == null) { continue; } for (AnnotationNode an : mn.invisibleAnnotations) { if (an.desc.equals(PAR_NEST.getDescriptor())) { // Ensure the method can be called from outside mn.access = (mn.access & ~ACC_PRIVATE) | ACC_PUBLIC; parNestedMethods.add(mn); String uniqueMethodName = createUniqueMethodName(mn.name); String callableClass; if (parallelSpawn) { callableClass = cn.name + "$nested$work$unit$" + uniqueMethodName; } else { callableClass = cn.name + "$unsafe$work$unit$" + uniqueMethodName; } callablesCreated.put(mn.name, callableClass); boolean readOnlyCallable = (an.values == null) ? false : (Boolean) an.values.get(1); generateCallable(classFile, cn.name, callableClass, mn, readOnlyCallable, unsafeSpawn); staticMethodsToAdd.add(generateStaticCallableCreation(cn, cn.name, callableClass, mn)); break; } else if (an.desc.equals(COMBINER.getDescriptor())) { if (combinerMethod != null) { throw new RuntimeException("Class: " + cn.name + " contains two @Combiner methods: " + combinerMethod.name + " and " + mn.name); } combinerMethod = mn; } } } // TODO Verify the @Combiner method // The return should be of the same type of the parameterization // of the ParallelSpawn for (MethodNode methodToAdd : staticMethodsToAdd) { cn.methods.add(methodToAdd); } if (alreadyProcessed.size() == 0) { throw new RuntimeException( "Class: " + cn.name + " must have at least one method annotated with @ParNested"); } if (combinerMethod == null) { throw new RuntimeException( "Class: " + cn.name + " must have one method annotated with @Combiner"); } List<Integer> localVariablesIdx = new ArrayList<Integer>(); int numberLocalVariables = 0; int listIndex = execMethod.maxLocals; execMethod.maxLocals++; InsnList preamble = new InsnList(); preamble.add(new TypeInsnNode(NEW, ARRAY_LIST.getInternalName())); preamble.add(new InsnNode(DUP)); preamble.add(new MethodInsnNode(INVOKESPECIAL, ARRAY_LIST.getInternalName(), "<init>", "()V")); preamble.add(new VarInsnNode(ASTORE, listIndex)); Iterator<AbstractInsnNode> execInstIter = execMethod.instructions.iterator(); while (execInstIter.hasNext()) { AbstractInsnNode instr = execInstIter.next(); // Look out for calls to methods if (instr.getOpcode() == INVOKEVIRTUAL || instr.getOpcode() == INVOKESPECIAL) { MethodInsnNode methodInstr = (MethodInsnNode) instr; // Is method being called annotated with @ParNested for (MethodNode parNestedMethod : parNestedMethods) { if (parNestedMethod.name.equals(methodInstr.name)) { numberLocalVariables++; } } } } for (int i = 0; i < numberLocalVariables; i++) { localVariablesIdx.add(i, execMethod.maxLocals); execMethod.maxLocals++; } int callablesManipulated = 0; execInstIter = execMethod.instructions.iterator(); while (execInstIter.hasNext()) { AbstractInsnNode instr = execInstIter.next(); // Look out for calls to methods if (instr.getOpcode() != INVOKEVIRTUAL && instr.getOpcode() != INVOKESPECIAL) { continue; } MethodInsnNode methodInstr = (MethodInsnNode) instr; // Is method being called annotated with @ParNested boolean isParNestedMethod = false; for (MethodNode parNestedMethod : parNestedMethods) { if (parNestedMethod.name.equals(methodInstr.name)) { isParNestedMethod = true; break; } } if (!isParNestedMethod) { continue; } // Let's change this call // If it was a call to: @ParNested public int add(int i1, // int i2) // add(foo, bar) -> add$static$callable$creator(this, foo, // bar) // the 'this' will be already in the right place in the // stack // because the method being called now is static whereas // previously // it was not methodInstr.setOpcode(INVOKESTATIC); methodInstr.name = methodInstr.name + "$static$callable$creator"; for (MethodNode staticCreated : staticMethodsToAdd) { if (staticCreated.name.equals(methodInstr.name)) { methodInstr.desc = staticCreated.desc; break; } } InsnList midterm = new InsnList(); // Store the callable instantiated in local variable midterm.add(new VarInsnNode(ASTORE, localVariablesIdx.get(callablesManipulated))); // Load the list midterm.add(new VarInsnNode(ALOAD, listIndex)); // Load the callable midterm.add(new VarInsnNode(ALOAD, localVariablesIdx.get(callablesManipulated))); // Add it to the list midterm.add(new MethodInsnNode(INVOKEVIRTUAL, ARRAY_LIST.getInternalName(), "add", "(Ljava/lang/Object;)Z")); // Pop the boolean that results from the add(Object) // May reuse a POP if the previous call had a return if (methodInstr.getNext().getOpcode() != POP) { midterm.add(new InsnNode(POP)); } // Add this set of instructions after the call to the // constrution of the callable execMethod.instructions.insert(methodInstr, midterm); callablesManipulated++; } // Insert the preamble in the start execMethod.instructions.insert(preamble); InsnList finish = new InsnList(); // Push 'this' for the call to the combiner method finish.add(new VarInsnNode(ALOAD, 0)); // Call the static method current() of jvstm.Transaction finish.add(new MethodInsnNode(INVOKESTATIC, TRANSACTION.getInternalName(), "current", "()Ljvstm/Transaction;")); // Load the callables list finish.add(new VarInsnNode(ALOAD, listIndex)); // Call the manage parnested method finish.add(new MethodInsnNode(INVOKEVIRTUAL, TRANSACTION.getInternalName(), "manageNestedParallelTxs", "(Ljava/util/List;)Ljava/util/List;")); // Call the combiner method finish.add(new MethodInsnNode(INVOKEVIRTUAL, cn.name, combinerMethod.name, combinerMethod.desc)); // Return what the combiner returns finish.add(new InsnNode(ARETURN)); // Remove the "return null" that's supposed to be at the end of // the exec method execInstIter = execMethod.instructions.iterator(); while (execInstIter.hasNext()) { AbstractInsnNode curNode = execInstIter.next(); if (!execInstIter.hasNext()) { // Insert the finish in the end execMethod.instructions.insert(curNode.getPrevious().getPrevious(), finish); execMethod.instructions.remove(curNode.getPrevious()); execMethod.instructions.remove(curNode); break; } } } ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cn.accept(cw); writeClassFile(classFile, cw.toByteArray()); } catch (IOException e) { throw new Error("Error processing class file", e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } }
From source file:net.minecraftforge.fml.common.asm.transformers.AccessTransformer.java
License:Open Source License
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; }/* w w w. j ava2 s .c o m*/ } } } } }
From source file:net.minecrell.ice.launch.transformers.AccessTransformer.java
License:Open Source License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null || !modifiers.containsKey(transformedName)) { return bytes; }/*ww w. java 2 s . com*/ ClassNode classNode = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(classNode, 0); for (Modifier m : modifiers.get(transformedName)) { if (m.isClass) { // Class classNode.access = m.transform(classNode.access); } else if (m.desc == null) { // Field for (FieldNode fieldNode : classNode.fields) { if (m.wildcard || fieldNode.name.equals(m.name)) { fieldNode.access = m.transform(fieldNode.access); if (!m.wildcard) break; } } } else { List<MethodNode> overridable = null; for (MethodNode methodNode : classNode.methods) { if (m.wildcard || (methodNode.name.equals(m.name) && methodNode.desc.equals(m.desc))) { boolean wasPrivate = (methodNode.access & ACC_PRIVATE) != 0; methodNode.access = m.transform(methodNode.access); // Constructors always use INVOKESPECIAL // if we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL // so that overridden methods will be called. Only need to scan this class, because obviously the method was private. if (!methodNode.name.equals("<init>") && wasPrivate && (methodNode.access & ACC_PRIVATE) == 0) { if (overridable == null) { overridable = new ArrayList<>(3); } overridable.add(methodNode); } if (!m.wildcard) break; } } if (overridable != null) { for (MethodNode methodNode : classNode.methods) { for (Iterator<AbstractInsnNode> itr = methodNode.instructions.iterator(); itr.hasNext();) { AbstractInsnNode insn = itr.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode replace : overridable) { if (replace.name.equals(mInsn.name) && replace.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } } } } ClassWriter writer = new ClassWriter(0); classNode.accept(writer); return writer.toByteArray(); }
From source file:net.minecrell.quartz.launch.transformers.AccessTransformer.java
License:MIT License
@Override protected void transform(String name, String transformedName, ClassNode classNode) { List<MethodNode> overridable = null; for (Map.Entry<String, AccessMapping> entry : mappings.getAccessMappings().row(transformedName) .entrySet()) {/*from www . j ava 2 s . c o m*/ String target = entry.getKey(); AccessMapping accessMapping = entry.getValue(); if (target.isEmpty()) { // Class mapping accessMapping.transform(classNode); } else if (target.indexOf('(') >= 0) { int len = target.length(); // Method mapping for (MethodNode methodNode : classNode.methods) { // Fast check before we look more intensively if (methodNode.name.length() + methodNode.desc.length() != len || !(target.startsWith(methodNode.name) && target.endsWith(methodNode.desc))) continue; boolean wasPrivate = Access.PRIVATE.is(methodNode.access); accessMapping.transform(methodNode); // Constructors always use INVOKESPECIAL // If we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL // So that overridden methods will be called. Only need to scan this class, because obviously the method was private. if (wasPrivate && accessMapping.getAccess() != Access.PRIVATE && !methodNode.name.equals("<init>")) { if (overridable == null) { overridable = new ArrayList<>(3); } overridable.add(methodNode); } break; } } else { // Field mapping for (FieldNode fieldNode : classNode.fields) { if (target.equals(fieldNode.name)) { accessMapping.transform(fieldNode); break; } } } } if (overridable != null) { for (MethodNode methodNode : classNode.methods) { for (Iterator<AbstractInsnNode> itr = methodNode.instructions.iterator(); itr.hasNext();) { AbstractInsnNode insn = itr.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode replace : overridable) { if (replace.name.equals(mInsn.name) && replace.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } } }
From source file:net.minecrell.quartz.mappings.transformer.AccessTransformer.java
License:Open Source License
@Override public ClassNode transform(String name, String transformedName, ClassNode classNode) { List<MethodNode> overridable = null; for (Map.Entry<String, AccessTransform> entry : this.mapper.getAccessTransforms().row(transformedName) .entrySet()) {//from ww w. j a v a 2s .co m String target = entry.getKey(); AccessTransform access = entry.getValue(); if (target.isEmpty()) { // Class mapping classNode.access = access.transform(classNode.access); } else if (target.indexOf('(') >= 0) { int len = target.length(); // Method mapping for (MethodNode methodNode : classNode.methods) { // Fast check before we look more intensively if (methodNode.name.length() + methodNode.desc.length() != len || !(target.startsWith(methodNode.name) && target.endsWith(methodNode.desc))) continue; boolean wasPrivate = AccessModifier.PRIVATE.is(methodNode.access); methodNode.access = access.transform(methodNode.access); // Constructors always use INVOKESPECIAL // If we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL // So that overridden methods will be called. Only need to scan this class, because obviously the method was private. if (wasPrivate && access.getAccess() != AccessModifier.PRIVATE && !methodNode.name.equals("<init>")) { if (overridable == null) { overridable = new ArrayList<>(3); } overridable.add(methodNode); } break; } } else { // Field mapping for (FieldNode fieldNode : classNode.fields) { if (target.equals(fieldNode.name)) { fieldNode.access = access.transform(fieldNode.access); break; } } } } if (overridable != null) { for (MethodNode methodNode : classNode.methods) { for (Iterator<AbstractInsnNode> itr = methodNode.instructions.iterator(); itr.hasNext();) { AbstractInsnNode insn = itr.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode replace : overridable) { if (replace.name.equals(mInsn.name) && replace.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } } return classNode; }
From source file:org.evosuite.testcarver.instrument.Instrumenter.java
License:Open Source License
@SuppressWarnings("unchecked") private void transformWrapperCalls(MethodNode mn) { Iterator<AbstractInsnNode> iterator = mn.instructions.iterator(); List<Class<?>> wrapperClasses = getWrapperClasses(); while (iterator.hasNext()) { AbstractInsnNode insn = iterator.next(); if (insn instanceof MethodInsnNode) { MethodInsnNode methodInsnNode = (MethodInsnNode) insn; if (methodInsnNode.name.equals("<init>")) { String ownerName = methodInsnNode.owner.replace('/', '.'); for (Class<?> wrapperClass : wrapperClasses) { if (wrapperClass.getName().equals(ownerName)) { logger.debug("Replacing call " + methodInsnNode.name); methodInsnNode.owner = "org/evosuite/testcarver/wrapper/" + methodInsnNode.owner; break; }// w ww. j a va 2 s . c o m } } else { String ownerName = methodInsnNode.owner.replace('/', '.'); for (Class<?> wrapperClass : wrapperClasses) { if (wrapperClass.getName().equals(ownerName)) { if (methodInsnNode.getOpcode() == Opcodes.INVOKESTATIC) { logger.debug("Replacing call " + methodInsnNode.name); methodInsnNode.owner = PackageInfo.getEvoSuitePackageWithSlash() + "/testcarver/wrapper/" + methodInsnNode.owner; } Type[] parameterTypes = Type.getArgumentTypes(methodInsnNode.desc); try { Class<?>[] parameterClasses = new Class<?>[parameterTypes.length]; int pos = 0; for (Type parameter : parameterTypes) { switch (parameter.getSort()) { case Type.OBJECT: parameterClasses[pos++] = Class.forName(parameter.getClassName()); break; case Type.BOOLEAN: parameterClasses[pos++] = boolean.class; break; case Type.BYTE: parameterClasses[pos++] = byte.class; break; case Type.CHAR: parameterClasses[pos++] = char.class; break; case Type.DOUBLE: parameterClasses[pos++] = double.class; break; case Type.FLOAT: parameterClasses[pos++] = float.class; break; case Type.INT: parameterClasses[pos++] = int.class; break; case Type.LONG: parameterClasses[pos++] = long.class; break; case Type.SHORT: parameterClasses[pos++] = short.class; break; } } Method method = wrapperClass.getMethod(methodInsnNode.name, parameterClasses); if (Modifier.isFinal(method.getModifiers())) { if (methodInsnNode.getOpcode() != Opcodes.INVOKESTATIC) { methodInsnNode.setOpcode(Opcodes.INVOKESTATIC); Type[] args = Type.getArgumentTypes(methodInsnNode.desc); Type returnType = Type.getReturnType(methodInsnNode.desc); Type[] newargs = new Type[args.length + 1]; newargs[0] = Type.getObjectType(methodInsnNode.owner); for (int i = 0; i < args.length; i++) newargs[i + 1] = args[i]; methodInsnNode.desc = Type.getMethodDescriptor(returnType, newargs); methodInsnNode.owner = PackageInfo.getEvoSuitePackageWithSlash() + "/testcarver/wrapper/" + methodInsnNode.owner; } else { methodInsnNode.name += "_final"; } logger.debug( "Method is final: " + methodInsnNode.owner + "." + methodInsnNode.name); } else { logger.debug("Method is not final: " + methodInsnNode.owner + "." + methodInsnNode.name); } } catch (Exception e) { logger.warn("Error while instrumenting: " + e); } break; } } // } else if(methodInsnNode.name.equals("getTime")) { // if(methodInsnNode.owner.equals("java/util/Calendar")) { // logger.debug("Replacing call "+methodInsnNode.name); // methodInsnNode.owner = "org/evosuite/testcarver/wrapper/java/util/Calendar"; // methodInsnNode.name = "getTime"; // methodInsnNode.desc = "(Ljava/util/Calendar;)Ljava/util/Date;"; // methodInsnNode.setOpcode(Opcodes.INVOKESTATIC); // } // } } } else if (insn.getOpcode() == Opcodes.NEW || insn.getOpcode() == Opcodes.CHECKCAST) { TypeInsnNode typeInsnNode = (TypeInsnNode) insn; Type generatedType = Type.getType(typeInsnNode.desc); String name = generatedType.getInternalName().replace('/', '.'); logger.debug("Checking for replacement of " + name); for (Class<?> wrapperClass : wrapperClasses) { if (wrapperClass.getName().equals(name)) { logger.debug("Replacing new " + name); typeInsnNode.desc = PackageInfo.getEvoSuitePackageWithSlash() + "/testcarver/wrapper/" + generatedType.getInternalName(); break; } } } } }