Example usage for org.objectweb.asm.tree ClassNode accept

List of usage examples for org.objectweb.asm.tree ClassNode accept

Introduction

In this page you can find the example usage for org.objectweb.asm.tree ClassNode accept.

Prototype

public void accept(final ClassVisitor classVisitor) 

Source Link

Document

Makes the given class visitor visit this class.

Usage

From source file:net.dv8tion.ClassTransformer.java

License:Apache License

/**
 * Helper method to modify the getAllUsernames method in ServerConfigurationManager.
 * Takes into account obfuscated method names based on boolean.
 * /*from  w  ww.j  a  v a2s .c  o m*/
 * Replaces the call "return astring" at the end of ServerConfigurationManager's
 * getAllUsernames method with "return NameLoader.loadNames(astring)"
 * Because of how The JVM and ByteCode work with arrays, we do not need to
 * remove any instructions, only inject code. The array "astring" in the
 * call "return astring" will be provided as the param for the loadNames method.
 * 
 * @param className
 *            The class name, proceeded by the package it is in, if it is in one.
 * @param classData
 *            The byte code of the class.
 * @param obfuscated
 *            Is the code obfuscated?
 * @return
 *         Returns the modified byte code of the class.
 */
public byte[] patchClassWithASM(String className, byte[] classData, boolean obfuscated) {
    String methodName = obfuscated ? "d" : "getAllUsernames";

    ClassNode classNode = new ClassNode(Opcodes.ASM4);
    ClassReader classReader = new ClassReader(classData);
    classReader.accept(classNode, ClassReader.EXPAND_FRAMES);

    Iterator<MethodNode> methods = classNode.methods.iterator();
    while (methods.hasNext()) {
        MethodNode m = methods.next();
        int arrayReturn_index = -1;

        if ((m.name.equals(methodName) && m.desc.equals("()[Ljava/lang/String;"))) {
            AbstractInsnNode currentNode = null;
            Iterator<AbstractInsnNode> iter = m.instructions.iterator();

            int index = -1;

            while (iter.hasNext()) {
                index++;
                currentNode = iter.next();

                if (currentNode.getOpcode() == Opcodes.ARETURN) {
                    arrayReturn_index = index;
                }
            }

            //Calls NameLoader.loadNames(String[]) 
            m.instructions.insertBefore(m.instructions.get(arrayReturn_index),
                    new MethodInsnNode(Opcodes.INVOKESTATIC, "net/dv8tion/NameLoader", "loadNames",
                            "([Ljava/lang/String;)[Ljava/lang/String;"));

            System.out.println("[IRC NameBridge] Patching Complete!");
            break;
        }
    }
    //ASM specific for cleaning up and returning the final bytes for JVM processing.
    //Use 0 here instead of like ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS because
    //We need to have ASM recalculate things.  
    ClassWriter writer = new ClassWriter(0);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.epoxide.surge.asm.ASMUtils.java

License:Creative Commons License

/**
 * Converts a ClassNode into a byte array which can then be returned by your transformer.
 *
 * @param classNode: An instance of the ClassNode you wish to convert into a byte array.
 * @param flags: The flags to use when converting the ClassNode. These are generally
 *        COMPUTE_FRAMES and COMPUTE_MAXS.
 * @return byte[]: A byte array representation of the ClassNode.
 *///from   w  w  w  .j a  v  a 2 s. c o m
public static byte[] createByteArrayFromClass(ClassNode classNode, int flags) {

    final ClassWriter classWriter = new ClassWriter(flags);
    classNode.accept(classWriter);

    return classWriter.toByteArray();
}

From source file:net.fabricmc.base.transformer.AccessTransformer.java

License:Apache License

@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
    if (!name.startsWith("net.minecraft")) {
        return bytes;
    }//from w  w  w. ja v  a 2s.  c  o  m
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);
    boolean isClassProtected = classNode.access == Opcodes.ACC_PROTECTED;
    boolean isClassPrivate = classNode.access == Opcodes.ACC_PRIVATE;
    if (isClassProtected || isClassPrivate) {
        classNode.access = Opcodes.ACC_PUBLIC;
    }
    for (MethodNode method : classNode.methods) {
        boolean isProtected = method.access == Opcodes.ACC_PROTECTED;
        boolean isPrivate = method.access == Opcodes.ACC_PRIVATE;
        if (isProtected || isPrivate) {
            method.access = Opcodes.ACC_PUBLIC;
        }
    }
    for (FieldNode field : classNode.fields) {
        boolean isProtected = field.access == Opcodes.ACC_PROTECTED;
        boolean isPrivate = field.access == Opcodes.ACC_PRIVATE;
        if (isProtected || isPrivate) {
            field.access = Opcodes.ACC_PUBLIC;
        }
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.fabricmc.weave.merge.ClassMerger.java

License:Apache License

public byte[] merge(byte[] classClient, byte[] classServer) {
    ClassReader readerC = new ClassReader(classClient);
    ClassReader readerS = new ClassReader(classServer);
    ClassWriter writer = new ClassWriter(0);

    ClassNode nodeC = new ClassNode(Opcodes.ASM5);
    readerC.accept(nodeC, 0);/*  w  w  w.j av a2 s .  c o  m*/

    ClassNode nodeS = new ClassNode(Opcodes.ASM5);
    readerS.accept(nodeS, 0);

    ClassNode nodeOut = new ClassNode(Opcodes.ASM5);
    nodeOut.version = nodeC.version;
    nodeOut.access = nodeC.access;
    nodeOut.name = nodeC.name;
    nodeOut.signature = nodeC.signature;
    nodeOut.interfaces = nodeC.interfaces;
    nodeOut.superName = nodeC.superName;
    nodeOut.sourceFile = nodeC.sourceFile;
    nodeOut.sourceDebug = nodeC.sourceDebug;
    nodeOut.outerClass = nodeC.outerClass;
    nodeOut.outerMethod = nodeC.outerMethod;
    nodeOut.outerMethodDesc = nodeC.outerMethodDesc;

    nodeOut.invisibleAnnotations = nodeC.invisibleAnnotations;
    nodeOut.invisibleTypeAnnotations = nodeC.invisibleTypeAnnotations;
    nodeOut.visibleAnnotations = nodeC.visibleAnnotations;
    nodeOut.visibleTypeAnnotations = nodeC.visibleTypeAnnotations;
    nodeOut.attrs = nodeC.attrs;

    new Merger<InnerClassNode>(nodeC.innerClasses, nodeS.innerClasses) {
        @Override
        public String getName(InnerClassNode entry) {
            return entry.name;
        }

        @Override
        public void applySide(InnerClassNode entry, String side) {
        }
    }.merge(nodeOut.innerClasses);

    new Merger<FieldNode>(nodeC.fields, nodeS.fields) {
        @Override
        public String getName(FieldNode entry) {
            return entry.name + "," + entry.desc + "," + entry.signature;
        }

        @Override
        public void applySide(FieldNode entry, String side) {
            AnnotationVisitor av = entry.visitAnnotation("Lnet/fabricmc/api/Sided;", true);
            visitSideAnnotation(av, side);
        }
    }.merge(nodeOut.fields);

    new Merger<MethodNode>(nodeC.methods, nodeS.methods) {
        @Override
        public String getName(MethodNode entry) {
            return entry.name + "," + entry.desc + "," + entry.signature;
        }

        @Override
        public void applySide(MethodNode entry, String side) {
            AnnotationVisitor av = entry.visitAnnotation("Lnet/fabricmc/api/Sided;", true);
            visitSideAnnotation(av, side);
        }
    }.merge(nodeOut.methods);

    nodeOut.accept(writer);
    return writer.toByteArray();
}

From source file:net.lyonlancer5.mcmp.karasu.asm.KarasuTransformer.java

License:Apache License

private static byte[] transform(int index, byte[] classBeingTransformed) {
    try {/*from ww  w.j  av a 2 s. c o  m*/
        ClassNode e = new ClassNode();
        ClassReader classReader = new ClassReader(classBeingTransformed);
        classReader.accept(e, 0);
        switch (index) {
        case 0:
            transformEntityLivingBase(e);
        default:
            ClassWriter classWriter = new ClassWriter(1);
            e.accept(classWriter);
            return classWriter.toByteArray();
        }
    } catch (Exception var6) {
        var6.printStackTrace();
        return classBeingTransformed;
    }
}

From source file:net.malisis.core.asm.MalisisClassTransformer.java

License:Open Source License

@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
    ArrayList<AsmHook> hooks = listHooks.get(transformedName);
    if (hooks == null || hooks.size() == 0)
        return bytes;

    LogManager.getLogger(logString).info("Found hooks for {} ({})", transformedName, name);

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);// w  w  w. j  ava 2  s.c o m

    for (AsmHook hook : hooks) {
        MethodNode methodNode = AsmUtils.findMethod(classNode, hook.getMethodName(),
                hook.getMethodDescriptor());
        if (methodNode != null) {
            if (!hook.walkSteps(methodNode))
                LogManager.getLogger(logString).error("The instruction list was not found in {}:{}{}",
                        hook.getTargetClass(), hook.getMethodName(), hook.getMethodDescriptor());

            if (hook.isDebug() == true && !MalisisCore.isObfEnv) {
                System.err.println(AsmUtils.getMethodNodeAsString(methodNode));
            }
        } else {
            LogManager.getLogger(logString).error("Method not found : {}:{}{}", hook.getTargetClass(),
                    hook.getMethodName(), hook.getMethodDescriptor());
        }
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS /* | ClassWriter.COMPUTE_FRAMES */);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.minecraftforge.fml.common.asm.transformers.AccessTransformer.java

License:Open Source License

@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
    if (bytes == null) {
        return null;
    }//from ww w .j a  v a 2s.com

    if (DEBUG) {
        FMLRelaunchLog.fine("Considering all methods and fields on %s (%s)\n", transformedName, name);
    }
    if (!modifiers.containsKey(transformedName)) {
        return bytes;
    }

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    Collection<Modifier> mods = modifiers.get(transformedName);
    for (Modifier m : mods) {
        if (m.modifyClassVisibility) {
            classNode.access = getFixedAccess(classNode.access, m);
            if (DEBUG) {
                System.out.println(String.format("Class: %s %s -> %s", name, toBinary(m.oldAccess),
                        toBinary(m.newAccess)));
            }
            continue;
        }
        if (m.desc.isEmpty()) {
            for (FieldNode n : classNode.fields) {
                if (n.name.equals(m.name) || m.name.equals("*")) {
                    n.access = getFixedAccess(n.access, m);
                    if (DEBUG) {
                        System.out.println(String.format("Field: %s.%s %s -> %s", name, n.name,
                                toBinary(m.oldAccess), toBinary(m.newAccess)));
                    }

                    if (!m.name.equals("*")) {
                        break;
                    }
                }
            }
        } else {
            List<MethodNode> nowOverridable = Lists.newArrayList();
            for (MethodNode n : classNode.methods) {
                if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*")) {
                    n.access = getFixedAccess(n.access, m);

                    // constructors always use INVOKESPECIAL
                    if (!n.name.equals("<init>")) {
                        // 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.
                        boolean wasPrivate = (m.oldAccess & ACC_PRIVATE) == ACC_PRIVATE;
                        boolean isNowPrivate = (m.newAccess & ACC_PRIVATE) == ACC_PRIVATE;

                        if (wasPrivate && !isNowPrivate) {
                            nowOverridable.add(n);
                        }

                    }

                    if (DEBUG) {
                        System.out.println(String.format("Method: %s.%s%s %s -> %s", name, n.name, n.desc,
                                toBinary(m.oldAccess), toBinary(m.newAccess)));
                    }

                    if (!m.name.equals("*")) {
                        break;
                    }
                }
            }

            replaceInvokeSpecial(classNode, nowOverridable);
        }
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.minecraftforge.fml.common.asm.transformers.FieldRedirectTransformer.java

License:Open Source License

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (!this.clsName.equals(transformedName))
        return basicClass;

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(basicClass);
    classReader.accept(classNode, 0);/*w w  w .j av  a  2s  .  co m*/

    FieldNode fieldRef = null;
    for (FieldNode f : classNode.fields) {
        if (this.TYPE.equals(f.desc) && fieldRef == null) {
            fieldRef = f;
        } else if (this.TYPE.equals(f.desc)) {
            throw new RuntimeException("Error processing " + clsName + " - found a duplicate holder field");
        }
    }
    if (fieldRef == null) {
        throw new RuntimeException("Error processing " + clsName
                + " - no holder field declared (is the code somehow obfuscated?)");
    }

    MethodNode getMethod = null;
    for (MethodNode m : classNode.methods) {
        if (m.name.equals(this.bypass))
            continue;
        if (this.DESC.equals(m.desc) && getMethod == null) {
            getMethod = m;
        } else if (this.DESC.equals(m.desc)) {
            throw new RuntimeException("Error processing " + clsName + " - duplicate get method found");
        }
    }
    if (getMethod == null) {
        throw new RuntimeException(
                "Error processing " + clsName + " - no get method found (is the code somehow obfuscated?)");
    }

    for (MethodNode m : classNode.methods) {
        if (m.name.equals(this.bypass))
            continue;
        for (ListIterator<AbstractInsnNode> it = m.instructions.iterator(); it.hasNext();) {
            AbstractInsnNode insnNode = it.next();
            if (insnNode.getType() == AbstractInsnNode.FIELD_INSN) {
                FieldInsnNode fi = (FieldInsnNode) insnNode;
                if (fieldRef.name.equals(fi.name) && fi.getOpcode() == Opcodes.GETFIELD) {
                    it.remove();
                    MethodInsnNode replace = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classNode.name,
                            getMethod.name, getMethod.desc, false);
                    it.add(replace);
                }
            }
        }
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
}

From source file:net.minecraftforge.fml.common.asm.transformers.SoundEngineFixTransformer.java

License:Open Source License

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (transformedName.equals("paulscode.sound.Source")) {
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(basicClass);
        classReader.accept(classNode, 0);

        classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC, "removed", "Z", null, null)); // adding field 'public boolean removed;'

        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        classNode.accept(writer);
        return writer.toByteArray();
    } else if (transformedName.equals("paulscode.sound.Library")) {
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(basicClass);
        classReader.accept(classNode, 0);

        MethodNode method = null;/*from w  w w  .  j  a v a  2s.  c  o m*/
        for (MethodNode m : classNode.methods) {
            if (m.name.equals("removeSource") && m.desc.equals("(Ljava/lang/String;)V")) // trying to find paulscode.sound.Library.removeSource(String)
            {
                method = m;
                break;
            }
        }
        if (method == null)
            throw new RuntimeException(
                    "Error processing " + transformedName + " - no removeSource method found");

        AbstractInsnNode referenceNode = null;

        for (Iterator<AbstractInsnNode> iterator = method.instructions.iterator(); iterator.hasNext();) {
            AbstractInsnNode insn = iterator.next();
            if (insn instanceof MethodInsnNode && ((MethodInsnNode) insn).owner.equals("paulscode/sound/Source") // searching for mySource.cleanup() node (line 1086)
                    && ((MethodInsnNode) insn).name.equals("cleanup")) {
                referenceNode = insn;
                break;
            }
        }

        if (referenceNode != null) {
            LabelNode after = (LabelNode) referenceNode.getNext();

            AbstractInsnNode beginning = referenceNode.getPrevious();

            int varIndex = ((VarInsnNode) beginning).var;

            method.instructions.insertBefore(beginning, new VarInsnNode(Opcodes.ALOAD, varIndex)); // adding extra if (mySource.toStream)
            method.instructions.insertBefore(beginning,
                    new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Source", "toStream", "Z"));
            LabelNode elseNode = new LabelNode();
            method.instructions.insertBefore(beginning, new JumpInsnNode(Opcodes.IFEQ, elseNode)); // if fails (else) -> go to mySource.cleanup();

            method.instructions.insertBefore(beginning, new VarInsnNode(Opcodes.ALOAD, varIndex)); // if (mySource.toStream) { mySource.removed = true; }
            method.instructions.insertBefore(beginning, new InsnNode(Opcodes.ICONST_1));
            method.instructions.insertBefore(beginning,
                    new FieldInsnNode(Opcodes.PUTFIELD, "paulscode/sound/Source", "removed", "Z"));

            method.instructions.insertBefore(beginning, new JumpInsnNode(Opcodes.GOTO, after)); // still inside if -> jump to sourceMap.remove( sourcename );

            method.instructions.insertBefore(beginning, elseNode);
        }

        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        classNode.accept(writer);
        return writer.toByteArray();
    } else if (transformedName.equals("paulscode.sound.StreamThread")) {
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(basicClass);
        classReader.accept(classNode, 0);

        MethodNode method = null;
        for (MethodNode m : classNode.methods) {
            if (m.name.equals("run") && m.desc.equals("()V")) // trying to find paulscode.sound.StreamThread.run();
            {
                method = m;
                break;
            }
        }
        if (method == null)
            throw new RuntimeException("Error processing " + transformedName + " - no run method found");

        AbstractInsnNode referenceNode = null;

        for (Iterator<AbstractInsnNode> iterator = method.instructions.iterator(); iterator.hasNext();) {
            AbstractInsnNode insn = iterator.next();
            if (insn instanceof MethodInsnNode && ((MethodInsnNode) insn).owner.equals("java/util/ListIterator") // searching for 'src = iter.next();' node (line 110)
                    && ((MethodInsnNode) insn).name.equals("next")) {
                referenceNode = insn.getNext().getNext();
                break;
            }
        }

        if (referenceNode != null) {
            int varIndex = ((VarInsnNode) referenceNode).var;

            LabelNode after = (LabelNode) referenceNode.getNext();
            method.instructions.insertBefore(after, new VarInsnNode(Opcodes.ALOAD, varIndex)); // add if(removed)
            method.instructions.insertBefore(after,
                    new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Source", "removed", "Z"));
            method.instructions.insertBefore(after, new JumpInsnNode(Opcodes.IFEQ, after));

            // if the source has been marked as removed, clean it up and set the variable to null so it will be removed from the list
            method.instructions.insertBefore(after, new VarInsnNode(Opcodes.ALOAD, varIndex)); // src.cleanup();
            method.instructions.insertBefore(after, new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
                    "paulscode/sound/Source", "cleanup", "()V", false));
            method.instructions.insertBefore(after, new InsnNode(Opcodes.ACONST_NULL)); // src = null;
            method.instructions.insertBefore(after, new VarInsnNode(Opcodes.ASTORE, varIndex));
        }

        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        classNode.accept(writer);
        return writer.toByteArray();
    }

    return basicClass;
}

From source file:net.minecraftforge.gradle.tasks.DeobfuscateJar.java

License:Open Source License

private byte[] stripSynthetics(String name, byte[] data) {
    ClassReader reader = new ClassReader(data);
    ClassNode node = new ClassNode();

    reader.accept(node, 0);/*ww w  .j ava2  s .  c o m*/

    if ((node.access & Opcodes.ACC_ENUM) == 0 && !node.superName.equals("java/lang/Enum")
            && (node.access & Opcodes.ACC_SYNTHETIC) == 0) {
        // ^^ is for ignoring enums.

        for (FieldNode f : ((List<FieldNode>) node.fields)) {
            f.access = f.access & (0xffffffff - Opcodes.ACC_SYNTHETIC);
            //getLogger().lifecycle("Stripping field: "+f.name);
        }

        for (MethodNode m : ((List<MethodNode>) node.methods)) {
            m.access = m.access & (0xffffffff - Opcodes.ACC_SYNTHETIC);
            //getLogger().lifecycle("Stripping method: "+m.name);
        }
    }

    ClassWriter writer = new ClassWriter(0);
    node.accept(writer);
    return writer.toByteArray();
}