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);
}
}
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());
}
}
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);
}
}
}
Aggregations