Search in sources :

Example 6 with GetFieldInstruction

use of net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction in project runelite by runelite.

the class FieldInliner method inlineUse.

public int inlineUse() {
    int count = 0;
    for (Field f : fields) {
        // replace getfield with constant push
        List<FieldInstruction> fins = fieldInstructions.get(f).stream().filter(f2 -> f2 instanceof GetFieldInstruction).collect(Collectors.toList());
        Object value = f.getValue();
        for (FieldInstruction fin : fins) {
            // remove fin, add push constant
            Instruction i = (Instruction) fin;
            Instruction pushIns = new LDC(i.getInstructions(), value);
            List<Instruction> instructions = i.getInstructions().getInstructions();
            int idx = instructions.indexOf(i);
            assert idx != -1;
            i.getInstructions().remove(i);
            instructions.add(idx, pushIns);
            ++count;
        }
        f.getClassFile().removeField(f);
    }
    return count;
}
Also used : Logger(org.slf4j.Logger) FieldInstruction(net.runelite.asm.attributes.code.instruction.types.FieldInstruction) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) Field(net.runelite.asm.Field) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) LoggerFactory(org.slf4j.LoggerFactory) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) Code(net.runelite.asm.attributes.Code) Multimap(com.google.common.collect.Multimap) Type(net.runelite.asm.Type) Deobfuscator(net.runelite.deob.Deobfuscator) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) ClassGroup(net.runelite.asm.ClassGroup) List(java.util.List) ClassFile(net.runelite.asm.ClassFile) HashMultimap(com.google.common.collect.HashMultimap) Method(net.runelite.asm.Method) LDC(net.runelite.asm.attributes.code.instructions.LDC) Instructions(net.runelite.asm.attributes.code.Instructions) Instruction(net.runelite.asm.attributes.code.Instruction) Field(net.runelite.asm.Field) LDC(net.runelite.asm.attributes.code.instructions.LDC) FieldInstruction(net.runelite.asm.attributes.code.instruction.types.FieldInstruction) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) FieldInstruction(net.runelite.asm.attributes.code.instruction.types.FieldInstruction) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 7 with GetFieldInstruction

use of net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction in project runelite by runelite.

the class PutField method isMaybeEqual.

private boolean isMaybeEqual(InstructionContext base1, InstructionContext base2) {
    if (base1.getInstruction() instanceof GetFieldInstruction && base2.getInstruction() instanceof GetFieldInstruction) {
        GetFieldInstruction gf1 = (GetFieldInstruction) base1.getInstruction(), gf2 = (GetFieldInstruction) base2.getInstruction();
        net.runelite.asm.Field f1 = gf1.getMyField();
        net.runelite.asm.Field f2 = gf2.getMyField();
        return MappingExecutorUtil.isMaybeEqual(f1, f2);
    }
    return true;
}
Also used : GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 8 with GetFieldInstruction

use of net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction in project runelite by runelite.

the class PutStatic method map.

@Override
public void map(ParallelExecutorMapping mapping, InstructionContext ctx, InstructionContext other) {
    net.runelite.asm.Field myField = this.getMyField();
    net.runelite.asm.Field otherField = ((PutStatic) other.getInstruction()).getMyField();
    assert MappingExecutorUtil.isMaybeEqual(myField.getType(), otherField.getType());
    mapping.map(this, myField, otherField);
    StackContext object1 = ctx.getPops().get(0), object2 = other.getPops().get(0);
    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();
        net.runelite.asm.Field f1 = gf1.getMyField();
        net.runelite.asm.Field f2 = gf2.getMyField();
        if (f1 != null && f2 != null) {
            mapping.map(this, f1, f2);
        }
    }
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) StackContext(net.runelite.asm.execution.StackContext) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 9 with GetFieldInstruction

use of net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction in project runelite by runelite.

the class Return method map.

@Override
public void map(ParallelExecutorMapping mappings, InstructionContext ctx, InstructionContext other) {
    StackContext s1 = ctx.getPops().get(0);
    StackContext s2 = other.getPops().get(0);
    InstructionContext i1 = MappingExecutorUtil.resolve(s1.getPushed(), s1);
    InstructionContext i2 = MappingExecutorUtil.resolve(s2.getPushed(), s2);
    if (i1.getInstruction() instanceof GetFieldInstruction && i2.getInstruction() instanceof GetFieldInstruction) {
        GetFieldInstruction f1 = (GetFieldInstruction) i1.getInstruction();
        GetFieldInstruction f2 = (GetFieldInstruction) i2.getInstruction();
        Field fi1 = f1.getMyField(), fi2 = f2.getMyField();
        if (fi1 != null && fi2 != null) {
            mappings.map(this, fi1, fi2);
        }
    }
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) Field(net.runelite.asm.Field) StackContext(net.runelite.asm.execution.StackContext) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 10 with GetFieldInstruction

use of net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction in project runelite by runelite.

the class PacketHandlerOrder method run.

@Override
public void run(ClassGroup group) {
    // This is run on the deobfuscated jar, so there are no symbols yet...
    // Find packetType and buffer classes
    PacketTypeFinder ptf = new PacketTypeFinder(group);
    ptf.find();
    BufferFinder bf = new BufferFinder(group);
    bf.find();
    HandlerFinder hf = new HandlerFinder(group, ptf.getPacketType());
    PacketHandlers handlers = hf.findHandlers();
    logger.info("Found {} packet handlers", handlers.getHandlers().size());
    for (PacketHandler handler : handlers.getHandlers()) {
        Execution e = hf.getExecution();
        e.reset();
        e.staticStep = true;
        e.step = false;
        e.noInvoke = true;
        // exception processing won't do non-local jumps, so
        // depending on whether methods are inlined or not
        // it may jump completely out of the handler into the
        // catch all for all packet handling
        // just disable exception execution
        e.noExceptions = true;
        assert e.frames.isEmpty();
        Frame f = handler.jumpFrame.dup();
        assert f.isExecuting();
        f.getMethodCtx().reset();
        e.clearExecutionVisitor();
        e.addExecutionVisitor(ictx -> {
            if (ictx.getInstruction() instanceof MappableInstruction) {
                if (ictx.getInstruction().getType() != InstructionType.INVOKESTATIC) {
                    if (!handler.mappable.contains(ictx.getInstruction())) {
                        handler.mappable.add(ictx.getInstruction());
                    }
                }
            }
            if (ictx.getInstruction().getType() == InstructionType.INVOKEVIRTUAL) {
                InvokeInstruction ii = (InvokeInstruction) ictx.getInstruction();
                // check if the invoke is on buffer/packetbuffer classes
                boolean matches = ii.getMethods().stream().filter(m -> m.getDescriptor().size() == 0).map(method -> method.getClassFile()).anyMatch(cf -> cf == bf.getBuffer() || cf == bf.getPacketBuffer());
                if (matches) {
                    Method method = ii.getMethods().get(0);
                    Signature signature = method.getDescriptor();
                    Type returnValue = signature.getReturnValue();
                    // buffer reference
                    assert ictx.getPops().size() == 1;
                    InstructionContext bufferCtx = ictx.getPops().get(0).getPushed();
                    if (bufferCtx.getInstruction().getType() != InstructionType.GETSTATIC) {
                        // sometimes buffer is passed to a function and then invoked.
                        return;
                    }
                    PacketRead packetRead = new PacketRead(returnValue, bufferCtx.getInstruction(), ictx);
                    if (!handler.reads.contains(packetRead)) {
                        handler.reads.add(packetRead);
                    }
                }
            }
            if (ictx.getInstruction().getType() == InstructionType.INVOKEVIRTUAL || ictx.getInstruction().getType() == InstructionType.INVOKESPECIAL || ictx.getInstruction().getType() == InstructionType.INVOKEINTERFACE) {
                InvokeInstruction ii = (InvokeInstruction) ictx.getInstruction();
                // read methods are scrambled so cant count them
                if (!handler.hasPacketRead(ictx.getInstruction())) {
                    handler.methodInvokes.addAll(ii.getMethods());
                }
            }
            if (ictx.getInstruction() instanceof SetFieldInstruction) {
                SetFieldInstruction sfi = (SetFieldInstruction) ictx.getInstruction();
                Field field = sfi.getMyField();
                if (field != null) {
                    handler.fieldWrite.add(field);
                }
            }
            if (ictx.getInstruction() instanceof GetFieldInstruction) {
                GetFieldInstruction gfi = (GetFieldInstruction) ictx.getInstruction();
                Field field = gfi.getMyField();
                if (field != null) {
                    handler.fieldRead.add(field);
                }
            }
            if (ictx.getInstruction() instanceof LVTInstruction) {
                LVTInstruction lvt = (LVTInstruction) ictx.getInstruction();
                if (!lvt.store()) {
                    // get lvt access order
                    Frame frame = ictx.getFrame();
                    int order = frame.getNextOrder();
                    if (!handler.lvtOrder.containsKey(lvt.getVariableIndex())) {
                        handler.lvtOrder.put(lvt.getVariableIndex(), order);
                    }
                }
            }
            if (ictx.getInstruction() instanceof PushConstantInstruction) {
                PushConstantInstruction pci = (PushConstantInstruction) ictx.getInstruction();
                handler.constants.add(pci.getConstant());
            }
        });
        logger.debug("Beginning execution of opcode {}", handler.getOpcode());
        e.run();
        logger.info("Executed opcode {}: {} mappable instructions", handler.getOpcode(), handler.mappable.size());
        handler.findReorderableReads();
    }
    List<PacketHandler> unsortedHandlers = new ArrayList<>(handlers.getHandlers());
    List<PacketHandler> sortedHandlers = new ArrayList<>(handlers.getHandlers()).stream().sorted((PacketHandler p1, PacketHandler p2) -> {
        int c = compareReads(p1.reads, p2.reads);
        if (c != 0) {
            return c;
        }
        if (p1.methodInvokes.size() != p2.methodInvokes.size()) {
            return Integer.compare(p1.methodInvokes.size(), p2.methodInvokes.size());
        }
        if (p1.fieldRead.size() != p2.fieldRead.size()) {
            return Integer.compare(p1.fieldRead.size(), p2.fieldRead.size());
        }
        if (p1.fieldWrite.size() != p2.fieldWrite.size()) {
            return Integer.compare(p1.fieldWrite.size(), p2.fieldWrite.size());
        }
        int i = Integer.compare(p1.mappable.size(), p2.mappable.size());
        if (i != 0) {
            return i;
        }
        int s1 = hashConstants(p1.constants), s2 = hashConstants(p2.constants);
        if (s1 != s2) {
            return Integer.compare(s1, s2);
        }
        logger.warn("Unable to differentiate {} from {}", p1, p2);
        return 0;
    }).map(s -> s.clone()).collect(Collectors.toList());
    assert sortedHandlers.size() == handlers.getHandlers().size();
    for (PacketHandler handler : sortedHandlers) {
        handler.sortedReads = new ArrayList<>(handler.reads);
        Collections.sort(handler.sortedReads, (PacketRead p1, PacketRead p2) -> {
            LVTInstruction l1 = (LVTInstruction) p1.getStore();
            LVTInstruction l2 = (LVTInstruction) p2.getStore();
            if (l1 == null && l2 == null) {
                return 0;
            }
            if (l1 == null) {
                return 1;
            }
            if (l2 == null) {
                return -1;
            }
            if (l1.getVariableIndex() == l2.getVariableIndex()) {
                return 0;
            }
            Integer i1 = handler.lvtOrder.get(l1.getVariableIndex());
            Integer i2 = handler.lvtOrder.get(l2.getVariableIndex());
            assert i1 != null;
            assert i2 != null;
            int i = Integer.compare(i1, i2);
            if (i == 0) {
                logger.warn("Cannot differentiate {} from {}", p1, p2);
            }
            return i;
        });
        Collections.reverse(handler.sortedReads);
    }
    ClassFile runeliteOpcodes = group.findClass(RUNELITE_OPCODES);
    assert runeliteOpcodes != null : "Opcodes class must exist";
    for (PacketHandler handler : sortedHandlers) {
        logger.info("Handler {} mappable {} reads {} invokes {} freads {} fwrites {}", handler.getOpcode(), handler.mappable.size(), handler.reads.size(), handler.methodInvokes.size(), handler.fieldRead.size(), handler.fieldWrite.size());
        final String fieldName = "PACKET_SERVER_" + handler.getOpcode();
        // Add opcode fields
        if (runeliteOpcodes.findField(fieldName) == null) {
            Field opField = new Field(runeliteOpcodes, fieldName, Type.INT);
            // ACC_FINAL causes javac to inline the fields, which prevents
            // the mapper from doing field mapping
            opField.setAccessFlags(ACC_PUBLIC | ACC_STATIC);
            // setting a non-final static field value
            // doesn't work with fernflower
            opField.setValue(handler.getOpcode());
            runeliteOpcodes.addField(opField);
            // add initialization
            Method clinit = runeliteOpcodes.findMethod("<clinit>");
            assert clinit != null;
            Instructions instructions = clinit.getCode().getInstructions();
            instructions.addInstruction(0, new LDC(instructions, handler.getOpcode()));
            instructions.addInstruction(1, new PutStatic(instructions, opField));
        }
    }
    // Find unique methods
    List<Method> methods = unsortedHandlers.stream().map(ph -> ph.getMethod()).distinct().collect(Collectors.toList());
    for (Method m : methods) {
        List<PacketHandler> unsortedMethodHandlers = unsortedHandlers.stream().filter(ph -> ph.getMethod() == m).collect(Collectors.toList());
        List<PacketHandler> sortedMethodHandlers = sortedHandlers.stream().filter(ph -> ph.getMethod() == m).collect(Collectors.toList());
        assert unsortedMethodHandlers.size() == sortedMethodHandlers.size();
        for (int i = 0; i < sortedMethodHandlers.size(); ++i) {
            PacketHandler unsorted = unsortedMethodHandlers.get(i);
            PacketHandler sortedh = sortedMethodHandlers.get(i);
            // Set opcode/jump from sorted -> unsorted
            If jump = (If) unsorted.getJump();
            PushConstantInstruction pci = (PushConstantInstruction) unsorted.getPush();
            assert unsorted.getOpcode() == ((Number) pci.getConstant()).intValue();
            Instructions instructions = unsorted.getMethod().getCode().getInstructions();
            final String fieldName = "PACKET_SERVER_" + sortedh.getOpcode();
            net.runelite.asm.pool.Field field = new net.runelite.asm.pool.Field(new net.runelite.asm.pool.Class(RUNELITE_OPCODES), fieldName, Type.INT);
            instructions.replace(unsorted.getPush(), new GetStatic(instructions, field));
            assert jump.getType() == InstructionType.IF_ICMPEQ || jump.getType() == InstructionType.IF_ICMPNE;
            Label startLabel = instructions.createLabelFor(sortedh.getStart());
            if (jump.getType() == InstructionType.IF_ICMPEQ) {
                instructions.replace(jump, new IfICmpEq(instructions, startLabel));
            } else if (jump.getType() == InstructionType.IF_ICMPNE) {
                // insert a jump after to go to sortedh start
                int idx = instructions.getInstructions().indexOf(jump);
                assert idx != -1;
                instructions.addInstruction(idx + 1, new Goto(instructions, startLabel));
            } else {
                throw new IllegalStateException();
            }
        }
    }
    insertSortedReads(group, sortedHandlers);
    insertPacketLength(group, ptf);
}
Also used : IfICmpEq(net.runelite.asm.attributes.code.instructions.IfICmpEq) LoggerFactory(org.slf4j.LoggerFactory) PacketHandler(net.runelite.deob.s2c.PacketHandler) Goto(net.runelite.asm.attributes.code.instructions.Goto) If(net.runelite.asm.attributes.code.instructions.If) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) InstructionType(net.runelite.asm.attributes.code.InstructionType) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) PacketTypeFinder(net.runelite.deob.deobfuscators.packethandler.PacketTypeFinder) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) Type(net.runelite.asm.Type) Deobfuscator(net.runelite.deob.Deobfuscator) BufferFinder(net.runelite.deob.deobfuscators.transformers.buffer.BufferFinder) Collectors(java.util.stream.Collectors) InstructionContext(net.runelite.asm.execution.InstructionContext) ComparisonInstruction(net.runelite.asm.attributes.code.instruction.types.ComparisonInstruction) List(java.util.List) ACC_PUBLIC(org.objectweb.asm.Opcodes.ACC_PUBLIC) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) PacketRead(net.runelite.deob.deobfuscators.packethandler.PacketRead) Signature(net.runelite.asm.signature.Signature) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) MessageDigest(java.security.MessageDigest) PutStatic(net.runelite.asm.attributes.code.instructions.PutStatic) ACC_STATIC(org.objectweb.asm.Opcodes.ACC_STATIC) ArrayList(java.util.ArrayList) ClassGroup(net.runelite.asm.ClassGroup) Method(net.runelite.asm.Method) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) JumpingInstruction(net.runelite.asm.attributes.code.instruction.types.JumpingInstruction) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) Frame(net.runelite.asm.execution.Frame) Logger(org.slf4j.Logger) RUNELITE_OPCODES(net.runelite.deob.deobfuscators.transformers.OpcodesTransformer.RUNELITE_OPCODES) Field(net.runelite.asm.Field) PacketLengthFinder(net.runelite.deob.deobfuscators.packethandler.PacketLengthFinder) Ints(com.google.common.primitives.Ints) InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) Execution(net.runelite.asm.execution.Execution) ClassFile(net.runelite.asm.ClassFile) Label(net.runelite.asm.attributes.code.Label) PacketHandlers(net.runelite.deob.s2c.PacketHandlers) HandlerFinder(net.runelite.deob.s2c.HandlerFinder) IfEq(net.runelite.asm.attributes.code.instructions.IfEq) LDC(net.runelite.asm.attributes.code.instructions.LDC) Instructions(net.runelite.asm.attributes.code.Instructions) Instruction(net.runelite.asm.attributes.code.Instruction) MappableInstruction(net.runelite.asm.attributes.code.instruction.types.MappableInstruction) Collections(java.util.Collections) Frame(net.runelite.asm.execution.Frame) BufferFinder(net.runelite.deob.deobfuscators.transformers.buffer.BufferFinder) PacketHandlers(net.runelite.deob.s2c.PacketHandlers) ArrayList(java.util.ArrayList) Label(net.runelite.asm.attributes.code.Label) LDC(net.runelite.asm.attributes.code.instructions.LDC) PacketRead(net.runelite.deob.deobfuscators.packethandler.PacketRead) Field(net.runelite.asm.Field) MappableInstruction(net.runelite.asm.attributes.code.instruction.types.MappableInstruction) Execution(net.runelite.asm.execution.Execution) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) IfICmpEq(net.runelite.asm.attributes.code.instructions.IfICmpEq) InstructionContext(net.runelite.asm.execution.InstructionContext) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) Goto(net.runelite.asm.attributes.code.instructions.Goto) ClassFile(net.runelite.asm.ClassFile) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) PutStatic(net.runelite.asm.attributes.code.instructions.PutStatic) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) PacketHandler(net.runelite.deob.s2c.PacketHandler) Signature(net.runelite.asm.signature.Signature) HandlerFinder(net.runelite.deob.s2c.HandlerFinder) PacketTypeFinder(net.runelite.deob.deobfuscators.packethandler.PacketTypeFinder) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) If(net.runelite.asm.attributes.code.instructions.If)

Aggregations

GetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)17 Field (net.runelite.asm.Field)13 InstructionContext (net.runelite.asm.execution.InstructionContext)13 StackContext (net.runelite.asm.execution.StackContext)11 ClassFile (net.runelite.asm.ClassFile)5 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)5 LDC (net.runelite.asm.attributes.code.instructions.LDC)5 Method (net.runelite.asm.pool.Method)5 Instruction (net.runelite.asm.attributes.code.Instruction)4 SetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction)4 Method (net.runelite.asm.Method)3 Instructions (net.runelite.asm.attributes.code.Instructions)3 FieldInstruction (net.runelite.asm.attributes.code.instruction.types.FieldInstruction)3 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Collectors (java.util.stream.Collectors)2 ClassGroup (net.runelite.asm.ClassGroup)2 Type (net.runelite.asm.Type)2 Code (net.runelite.asm.attributes.Code)2