org.devinprogress.YAIF.Transformer.ASMHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.devinprogress.YAIF.Transformer.ASMHelper.java

Source

package org.devinprogress.YAIF.Transformer;

import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;

import java.lang.reflect.Method;
import java.util.*;

// Author: Recursive G
// Source released under GPLv2
// Full document under resources/LICENSE

public class ASMHelper {
    private Object obj;
    //Map<DeobfuscatedClassName,Map<methodName+Desc,processMethod>>
    private Map<String, Map<String, Method>> map;

    public ASMHelper(Object o) {
        obj = o;
        map = new HashMap<String, Map<String, Method>>();
    }

    public void hookMethod(String className, String srgName, String mcpName, String desc,
            String targetTransformer) {
        if (!map.containsKey(className))
            map.put(className, new HashMap<String, Method>());
        Method m = null;
        try {
            m = obj.getClass().getDeclaredMethod(targetTransformer, MethodNode.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        map.get(className).put(srgName + desc, m);
        map.get(className).put(mcpName + desc, m);
    }

    public byte[] transform(String obfClassName, String className, byte[] bytes) {
        if (!map.containsKey(className))
            return bytes;
        Map<String, Method> transMap = map.get(className);

        ClassReader cr = new ClassReader(bytes);
        ClassNode cn = new ClassNode();
        cr.accept(cn, 0);

        for (MethodNode mn : cn.methods) {
            //System.out.println(String.format("Examing Method: %s%s",mn.name,mn.desc));
            String methodName = FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(obfClassName, mn.name, mn.desc);
            String methodDesc = FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(mn.desc);
            if (transMap.containsKey(methodName + methodDesc)) {
                try {
                    //System.out.println(String.format("Invoking Method: %s%s",mn.name,mn.desc));
                    transMap.get(methodName + methodDesc).invoke(obj, mn);
                } catch (Exception e) {
                    e.printStackTrace();
                    return bytes;
                }
            }
        }

        ClassWriter cw = new ClassWriter(0);
        cn.accept(cw);
        return cw.toByteArray();
    }

    public static AbstractInsnNode getNthInsnNode(MethodNode mn, int opcode, int N) {
        AbstractInsnNode n = mn.instructions.getFirst();
        int count = 0;
        while (n != null) {
            if (n.getOpcode() == opcode) {
                count++;
                if (count == N)
                    break;
            }
            n = n.getNext();
        }
        return n;
    }

    public static void InsertInvokeStaticAfter(MethodNode mn, AbstractInsnNode n, String targetClass,
            String targetMethod, String desc) {
        mn.instructions.insert(n,
                new MethodInsnNode(Opcodes.INVOKESTATIC, targetClass.replace('.', '/'), targetMethod, desc, false));
    }
}