Search in sources :

Example 1 with Exception

use of net.runelite.asm.attributes.code.Exception in project runelite by runelite.

the class ControlFlowDeobfuscator method split.

/**
 * Add gotos at the end of blocks without terminal instructions
 *
 * @param code
 */
private void split(Code code) {
    Instructions ins = code.getInstructions();
    Exceptions exceptions = code.getExceptions();
    ControlFlowGraph graph = new ControlFlowGraph.Builder().build(code);
    List<Exception> exc = new ArrayList<>(exceptions.getExceptions());
    // Must clear this before ins.clear() runs
    exceptions.clear();
    ins.clear();
    // insert jumps where blocks flow into others
    for (Block block : graph.getBlocks()) {
        if (block.getFlowsInto() == null) {
            continue;
        }
        Block into = block.getFlowsInto();
        assert into.getFlowsFrom() == block;
        Instruction first = into.getInstructions().get(0);
        Label label;
        if (!(first instanceof Label)) {
            label = new Label(null);
            into.addInstruction(0, label);
        } else {
            label = (Label) first;
        }
        Goto g = new Goto(null, label);
        block.addInstruction(g);
        block.setFlowsInto(null);
        into.setFlowsFrom(null);
        ++insertedJump;
    }
    // Readd instructions from modified blocks
    for (Block block : graph.getBlocks()) {
        for (Instruction i : block.getInstructions()) {
            assert i.getInstructions() == null;
            // I shouldn't have to do this here
            i.setInstructions(ins);
            ins.addInstruction(i);
        }
    }
    // Readd exceptions
    for (Exception ex : exc) {
        exceptions.add(ex);
    }
}
Also used : Goto(net.runelite.asm.attributes.code.instructions.Goto) Exceptions(net.runelite.asm.attributes.code.Exceptions) ArrayList(java.util.ArrayList) Label(net.runelite.asm.attributes.code.Label) Instructions(net.runelite.asm.attributes.code.Instructions) Instruction(net.runelite.asm.attributes.code.Instruction) Exception(net.runelite.asm.attributes.code.Exception)

Example 2 with Exception

use of net.runelite.asm.attributes.code.Exception in project runelite by runelite.

the class Frame method processExceptions.

private void processExceptions(InstructionContext ictx) {
    if (this.execution.step) {
        // no frame.other
        return;
    }
    if (this.execution.noExceptions) {
        return;
    }
    for (Exception e : exceptions.get(ictx.getInstruction())) {
        Frame f = dup();
        Stack stack = f.getStack();
        while (stack.getSize() > 0) {
            stack.pop();
        }
        InstructionContext ins = new InstructionContext(ictx.getInstruction(), f);
        StackContext ctx = new StackContext(ins, Type.EXCEPTION, Value.UNKNOWN);
        stack.push(ctx);
        ins.push(ctx);
        f.jump(ictx, e.getHandler());
    }
}
Also used : Exception(net.runelite.asm.attributes.code.Exception)

Example 3 with Exception

use of net.runelite.asm.attributes.code.Exception in project runelite by runelite.

the class ControlFlowDeobfuscator method run.

private void run(Code code) {
    Instructions ins = code.getInstructions();
    Exceptions exceptions = code.getExceptions();
    ControlFlowGraph graph = new ControlFlowGraph.Builder().build(code);
    for (Block block : graph.getBlocks()) {
        assert block.getFlowsFrom() == null;
        assert block.getFlowsInto() == null;
    }
    if (// graph.toString() is expensive
    logger.isDebugEnabled()) {
        logger.debug(graph.toString());
    }
    List<Exception> originalExceptions = new ArrayList<>(exceptions.getExceptions());
    // Clear existing exceptions and instructions as we are going to
    // rebuild them
    exceptions.clear();
    ins.clear();
    List<Block> done = new ArrayList<>();
    Queue<Block> queue = new PriorityQueue<>(this::compareBlock);
    // add initial code block
    queue.add(graph.getHead());
    while (!queue.isEmpty()) {
        Block block = queue.remove();
        if (done.contains(block)) {
            continue;
        }
        done.add(block);
        ++placedBlocks;
        logger.debug("Placed block {}", block.getId());
        List<Block> next = block.getNext();
        if (next.isEmpty() == false) {
            // jumps are added in order their instructions are reached by ControlFlowGraph,
            // so the last jump is the goto.
            // 
            // removing this line causes the priority queue (due to implementation detail on how
            // it handles objects with equal priority) to try to optimize for block closeness
            // (how close blocks which are neighbors are to each other in bytecode).
            // I get a jump delta of ~+14k with this on 143, vs ~-47k when priotiziing optimizing
            // out jumps. I can't tell which is better.
            next.get(next.size() - 1).setJumptarget(true);
        }
        // add next reachable blocks
        for (Block bl : next) {
            queue.add(bl);
        }
        for (Instruction i : block.getInstructions()) {
            assert i.getInstructions() == null;
            // I shouldn't have to do this here
            i.setInstructions(ins);
            ins.addInstruction(i);
        }
    }
}
Also used : Exceptions(net.runelite.asm.attributes.code.Exceptions) ArrayList(java.util.ArrayList) Instructions(net.runelite.asm.attributes.code.Instructions) PriorityQueue(java.util.PriorityQueue) Instruction(net.runelite.asm.attributes.code.Instruction) Exception(net.runelite.asm.attributes.code.Exception)

Aggregations

Exception (net.runelite.asm.attributes.code.Exception)3 ArrayList (java.util.ArrayList)2 Exceptions (net.runelite.asm.attributes.code.Exceptions)2 Instruction (net.runelite.asm.attributes.code.Instruction)2 Instructions (net.runelite.asm.attributes.code.Instructions)2 PriorityQueue (java.util.PriorityQueue)1 Label (net.runelite.asm.attributes.code.Label)1 Goto (net.runelite.asm.attributes.code.instructions.Goto)1