Search in sources :

Example 31 with Field

use of net.runelite.asm.Field in project runelite by runelite.

the class EnumDeobfuscator method makeEnum.

private void makeEnum(ClassFile cf) {
    // make class an enum
    cf.setEnum();
    // enums super class is java/lang/Enum
    assert cf.getParentClass().getName().equals("java/lang/Object");
    cf.setSuperName("java/lang/Enum");
    // all static fields of the type of the class become enum members
    for (Field field : cf.getFields()) {
        if (field.isStatic() && field.getType().equals(new Type("L" + cf.getName() + ";"))) {
            field.setEnum();
        }
    }
    for (Method method : cf.getMethods()) {
        if (!method.getName().equals("<init>")) {
            continue;
        }
        // Add string as first argument, which is the field name,
        // and ordinal as second argument
        Signature signature = new Signature.Builder().setReturnType(method.getDescriptor().getReturnValue()).addArgument(Type.STRING).addArgument(Type.INT).addArguments(method.getDescriptor().getArguments()).build();
        method.setDescriptor(signature);
        // Remove instructions up to invokespecial
        Instructions ins = method.getCode().getInstructions();
        Instruction i;
        do {
            i = ins.getInstructions().get(0);
            ins.remove(i);
        } while (i.getType() != InstructionType.INVOKESPECIAL);
        // load this
        ins.addInstruction(0, new ALoad(ins, 0));
        // load constant name
        ins.addInstruction(1, new ALoad(ins, 1));
        // ordinal
        ins.addInstruction(2, new ILoad(ins, 2));
        // invoke enum constructor
        ins.addInstruction(3, new InvokeSpecial(ins, ENUM_INIT));
        // Shift all indexes after this up +2 because of the new String and int argument
        for (int j = 4; j < ins.getInstructions().size(); ++j) {
            i = ins.getInstructions().get(j);
            if (i instanceof LVTInstruction) {
                LVTInstruction lvt = ((LVTInstruction) i);
                int idx = lvt.getVariableIndex();
                if (idx != 0) {
                    lvt.setVariableIndex(idx + 2);
                }
            }
        }
    }
    // Order of fields being set in clinit, which is the order
    // the enum fields are actually in
    List<Field> order = new ArrayList<>();
    for (Method method : cf.getMethods()) {
        if (!method.getName().equals("<clinit>")) {
            continue;
        }
        Instructions ins = method.getCode().getInstructions();
        int count = 0;
        // sometimes there is new new invokespecial invokespecial putfield
        // for eg enum member field30(1, 2, String.class, new class5());
        boolean seenDup = false;
        for (int j = 0; j < ins.getInstructions().size(); ++j) {
            Instruction i = ins.getInstructions().get(j);
            if (i.getType() == InstructionType.DUP && !seenDup) {
                // XXX this should actually be the field name, but it seems to have no effect on fernflower
                ins.addInstruction(j + 1, new LDC(ins, "runelite"));
                ins.addInstruction(j + 2, new LDC(ins, count++));
                seenDup = true;
            } else if (i.getType() == InstructionType.INVOKESPECIAL) {
                Instruction next = ins.getInstructions().get(j + 1);
                // check if this is the invokespecial on the enum, putstatic comes next
                if (next.getType() == InstructionType.PUTSTATIC) {
                    InvokeSpecial is = (InvokeSpecial) i;
                    PutStatic ps = (PutStatic) next;
                    net.runelite.asm.pool.Method pmethod = new net.runelite.asm.pool.Method(is.getMethod().getClazz(), is.getMethod().getName(), new Signature.Builder().setReturnType(is.getMethod().getType().getReturnValue()).addArgument(Type.STRING).addArgument(Type.INT).addArguments(is.getMethod().getType().getArguments()).build());
                    is.setMethod(pmethod);
                    Field field = ps.getMyField();
                    assert field != null;
                    order.add(field);
                    seenDup = false;
                }
            }
        }
    }
    // Enum fields must be first. Also they are in order in clinit.
    // Sort fields
    Collections.sort(cf.getFields(), (f1, f2) -> {
        int idx1 = order.indexOf(f1);
        int idx2 = order.indexOf(f2);
        if (idx1 == -1) {
            idx1 = Integer.MAX_VALUE;
        }
        if (idx2 == -1) {
            idx2 = Integer.MAX_VALUE;
        }
        return Integer.compare(idx1, idx2);
    });
}
Also used : InvokeSpecial(net.runelite.asm.attributes.code.instructions.InvokeSpecial) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) ArrayList(java.util.ArrayList) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) Instruction(net.runelite.asm.attributes.code.Instruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) PutStatic(net.runelite.asm.attributes.code.instructions.PutStatic) Field(net.runelite.asm.Field) InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) Signature(net.runelite.asm.signature.Signature) ALoad(net.runelite.asm.attributes.code.instructions.ALoad)

Example 32 with Field

use of net.runelite.asm.Field in project runelite by runelite.

the class InvokeVirtual method map.

@Override
public void map(ParallelExecutorMapping mapping, InstructionContext ctx, InstructionContext other) {
    InvokeVirtual otherIv = (InvokeVirtual) other.getInstruction();
    List<net.runelite.asm.Method> myMethods = this.getMethods(), otherMethods = otherIv.getMethods();
    assert MappingExecutorUtil.isMaybeEqual(method.getType(), otherIv.method.getType());
    assert myMethods.size() == otherMethods.size();
    for (int i = 0; i < myMethods.size(); ++i) {
        net.runelite.asm.Method m1 = myMethods.get(i), otherMethod = null;
        ClassFile c1 = m1.getClassFile();
        if (myMethods.size() == 1) {
            otherMethod = otherMethods.get(0);
        } else {
            for (int j = 0; j < myMethods.size(); ++j) {
                net.runelite.asm.Method m2 = otherMethods.get(j);
                ClassFile c2 = m2.getClassFile();
                if (MappingExecutorUtil.isMaybeEqual(c1, c2)) {
                    if (otherMethod != null) {
                        otherMethod = null;
                        break;
                    }
                    otherMethod = m2;
                }
            }
        }
        if (otherMethod != null) {
            mapping.map(this, m1, otherMethod);
        }
    }
    /* map arguments */
    assert ctx.getPops().size() == other.getPops().size();
    for (int i = 0; i < ctx.getPops().size(); ++i) {
        StackContext s1 = ctx.getPops().get(i), s2 = other.getPops().get(i);
        InstructionContext base1 = MappingExecutorUtil.resolve(s1.getPushed(), s1);
        InstructionContext base2 = MappingExecutorUtil.resolve(s2.getPushed(), s2);
        if (base1.getInstruction() instanceof GetFieldInstruction && base2.getInstruction() instanceof GetFieldInstruction) {
            GetFieldInstruction gf1 = (GetFieldInstruction) base1.getInstruction(), gf2 = (GetFieldInstruction) base2.getInstruction();
            Field f1 = gf1.getMyField(), f2 = gf2.getMyField();
            if (f1 != null && f2 != null) {
                mapping.map(this, f1, f2);
            }
        }
    }
    /* map field that was invoked on */
    StackContext object1 = ctx.getPops().get(method.getType().size()), object2 = other.getPops().get(otherIv.method.getType().size());
    InstructionContext base1 = MappingExecutorUtil.resolve(object1.getPushed(), object1);
    InstructionContext base2 = MappingExecutorUtil.resolve(object2.getPushed(), object2);
    if (base1.getInstruction() instanceof GetFieldInstruction && base2.getInstruction() instanceof GetFieldInstruction) {
        GetFieldInstruction gf1 = (GetFieldInstruction) base1.getInstruction(), gf2 = (GetFieldInstruction) base2.getInstruction();
        Field f1 = gf1.getMyField(), f2 = gf2.getMyField();
        if (f1 != null && f2 != null) {
            mapping.map(this, f1, f2);
        }
    }
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) ClassFile(net.runelite.asm.ClassFile) Method(net.runelite.asm.pool.Method) Field(net.runelite.asm.Field) StackContext(net.runelite.asm.execution.StackContext) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 33 with Field

use of net.runelite.asm.Field in project runelite by runelite.

the class LCmp method map.

@Override
public void map(ParallelExecutorMapping mappings, InstructionContext ctx, InstructionContext other) {
    List<Field> f1s = getComparedFields(ctx), f2s = getComparedFields(other);
    if (f1s == null || f2s == null || f1s.size() != f2s.size()) {
        return;
    }
    for (int i = 0; i < f1s.size(); ++i) {
        Field f1 = f1s.get(i), f2 = f2s.get(i);
        mappings.map(this, f1, f2);
    }
}
Also used : Field(net.runelite.asm.Field)

Example 34 with Field

use of net.runelite.asm.Field in project runelite by runelite.

the class MappingDumper method dumpJson.

@Test
public void dumpJson() throws IOException {
    ClassGroup group = JarUtil.loadJar(new File(properties.getRsClient()));
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    JsonObject jObject = new JsonObject();
    JsonArray jFields = new JsonArray();
    JsonArray jMethods = new JsonArray();
    for (ClassFile cf : group.getClasses()) {
        String implName = DeobAnnotations.getImplements(cf);
        String className = DeobAnnotations.getObfuscatedName(cf.getAnnotations());
        for (Field f : cf.getFields()) {
            String exportName = DeobAnnotations.getExportedName(f.getAnnotations());
            if (exportName == null) {
                continue;
            }
            String fieldName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
            Type obfType = DeobAnnotations.getObfuscatedType(f);
            Number getter = DeobAnnotations.getObfuscatedGetter(f);
            JsonObject jField = new JsonObject();
            jField.addProperty("name", exportName);
            jField.addProperty("owner", f.isStatic() ? "" : implName);
            jField.addProperty("class", className);
            jField.addProperty("field", fieldName);
            jField.addProperty("obfSignature", (obfType != null ? obfType.toString() : ""));
            jField.addProperty("signature", f.getType().toString());
            jField.addProperty("multiplier", (getter != null ? getter : 0));
            jField.addProperty("static", f.isStatic());
            jFields.add(jField);
        }
        for (Method m : cf.getMethods()) {
            String exportName = DeobAnnotations.getExportedName(m.getAnnotations());
            if (exportName == null) {
                continue;
            }
            String methodName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
            Signature obfSignature = DeobAnnotations.getObfuscatedSignature(m);
            String predicate = DeobAnnotations.getObfuscatedValue(m);
            JsonObject jMethod = new JsonObject();
            jMethod.addProperty("name", exportName);
            jMethod.addProperty("owner", m.isStatic() ? "" : implName);
            jMethod.addProperty("class", className);
            jMethod.addProperty("field", methodName);
            jMethod.addProperty("obfSignature", (obfSignature != null ? obfSignature.toString() : ""));
            jMethod.addProperty("signature", m.getDescriptor().toString());
            jMethod.addProperty("predicate", (predicate != null ? predicate : ""));
            jMethod.addProperty("static", m.isStatic());
            jMethods.add(jMethod);
        }
    }
    jObject.addProperty("runelite", "http://github.com/runelite");
    jObject.addProperty("run", Instant.now().toString());
    jObject.addProperty("gamepack", properties.getRsVersion());
    jObject.add("fields", jFields);
    jObject.add("methods", jMethods);
    System.out.println(gson.toJson(jObject));
}
Also used : ClassFile(net.runelite.asm.ClassFile) GsonBuilder(com.google.gson.GsonBuilder) Gson(com.google.gson.Gson) JsonObject(com.google.gson.JsonObject) Method(net.runelite.asm.Method) JsonArray(com.google.gson.JsonArray) Field(net.runelite.asm.Field) Type(net.runelite.asm.Type) ClassGroup(net.runelite.asm.ClassGroup) Signature(net.runelite.asm.signature.Signature) File(java.io.File) ClassFile(net.runelite.asm.ClassFile) Test(org.junit.Test)

Example 35 with Field

use of net.runelite.asm.Field in project runelite by runelite.

the class MappingDumper method dump.

@Test
public void dump() throws IOException {
    ClassGroup group = JarUtil.loadJar(new File(properties.getRsClient()));
    final String GAP = "%-40s";
    int classes = 0, methods = 0, fields = 0;
    StringBuilder mBuilder = new StringBuilder();
    StringBuilder sBuilder = new StringBuilder();
    StringBuilder tmp;
    for (ClassFile cf : group.getClasses()) {
        String implName = DeobAnnotations.getImplements(cf);
        String className = DeobAnnotations.getObfuscatedName(cf.getAnnotations());
        if (implName != null) {
            mBuilder.append("\n").append(implName).append(" -> ").append(className).append("\n");
            ++classes;
        }
        for (Field f : cf.getFields()) {
            String exportName = DeobAnnotations.getExportedName(f.getAnnotations());
            if (exportName == null) {
                continue;
            }
            ++fields;
            String fieldName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
            Type type = f.getType();
            Number getter = DeobAnnotations.getObfuscatedGetter(f);
            String fieldType = typeToString(type);
            if (f.isStatic()) {
                tmp = sBuilder;
            } else {
                tmp = mBuilder;
            }
            tmp.append("\t").append(String.format(GAP, fieldType)).append(String.format(GAP, exportName)).append(className).append(".").append(fieldName);
            if (getter != null) {
                tmp.append(" * ").append(getter).append("\n");
            } else {
                tmp.append("\n");
            }
        }
        for (Method m : cf.getMethods()) {
            String exportName = DeobAnnotations.getExportedName(m.getAnnotations());
            if (exportName == null) {
                continue;
            }
            methods++;
            String methodName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
            Signature signature = DeobAnnotations.getObfuscatedSignature(m);
            String garbageValue = DeobAnnotations.getObfuscatedValue(m);
            if (signature == null) {
                signature = m.getDescriptor();
            }
            String returnType = typeToString(m.getDescriptor().getReturnValue());
            String[] paramTypes = new String[signature.size()];
            for (int i = 0; i < paramTypes.length; i++) {
                paramTypes[i] = typeToString(signature.getTypeOfArg(i));
            }
            if (m.isStatic()) {
                tmp = sBuilder;
            } else {
                tmp = mBuilder;
            }
            tmp.append("\t").append(String.format(GAP, returnType)).append(String.format(GAP, exportName)).append(className).append(".").append(methodName);
            tmp.append("(");
            for (int i = 0; i < paramTypes.length; i++) {
                tmp.append(paramTypes[i]);
                if (i == paramTypes.length - 1) {
                    if (garbageValue != null) {
                        tmp.append(" = ").append(garbageValue);
                    }
                } else {
                    tmp.append(", ");
                }
            }
            tmp.append(")\n");
        }
    }
    System.out.println("RuneLite http://github.com/runelite");
    System.out.println("Run " + Instant.now());
    System.out.println("Classes: " + classes + ", methods: " + methods + ", fields: " + fields);
    System.out.println("Gamepack " + properties.getRsVersion());
    System.out.println(mBuilder.toString());
    System.out.println("Static ->");
    System.out.println(sBuilder.toString());
}
Also used : Field(net.runelite.asm.Field) Type(net.runelite.asm.Type) ClassFile(net.runelite.asm.ClassFile) ClassGroup(net.runelite.asm.ClassGroup) Signature(net.runelite.asm.signature.Signature) Method(net.runelite.asm.Method) File(java.io.File) ClassFile(net.runelite.asm.ClassFile) Test(org.junit.Test)

Aggregations

Field (net.runelite.asm.Field)65 ClassFile (net.runelite.asm.ClassFile)39 Method (net.runelite.asm.Method)33 Instruction (net.runelite.asm.attributes.code.Instruction)19 InstructionContext (net.runelite.asm.execution.InstructionContext)19 GetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)17 Instructions (net.runelite.asm.attributes.code.Instructions)16 StackContext (net.runelite.asm.execution.StackContext)16 Type (net.runelite.asm.Type)15 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)12 LDC (net.runelite.asm.attributes.code.instructions.LDC)11 Code (net.runelite.asm.attributes.Code)10 SetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction)10 Signature (net.runelite.asm.signature.Signature)9 ClassGroup (net.runelite.asm.ClassGroup)8 FieldInstruction (net.runelite.asm.attributes.code.instruction.types.FieldInstruction)8 PutField (net.runelite.asm.attributes.code.instructions.PutField)8 Test (org.junit.Test)8 List (java.util.List)7 Annotation (net.runelite.asm.attributes.annotation.Annotation)7