use of net.runelite.asm.attributes.code.Exceptions 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.Exceptions in project runelite by runelite.
the class Renamer method renameClass.
private void renameClass(ClassGroup group, ClassFile cf, String name) {
for (ClassFile c : group.getClasses()) {
// rename on child interfaces and classes
renameClass(c, cf, name);
for (Method method : c.getMethods()) {
// rename on instructions. this includes method calls and field accesses.
if (method.getCode() != null) {
Code code = method.getCode();
// rename on instructions
for (Instruction i : code.getInstructions().getInstructions()) {
i.renameClass(cf.getName(), name);
}
// rename on exception handlers
Exceptions exceptions = code.getExceptions();
exceptions.renameClass(cf, name);
}
// rename on parameters
Signature.Builder builder = new Signature.Builder();
Signature signature = method.getDescriptor();
for (int i = 0; i < signature.size(); ++i) {
Type type = signature.getTypeOfArg(i);
if (type.getInternalName().equals(cf.getName())) {
builder.addArgument(Type.getType("L" + name + ";", type.getDimensions()));
} else {
builder.addArgument(type);
}
}
// rename return type
if (signature.getReturnValue().getInternalName().equals(cf.getName())) {
builder.setReturnType(Type.getType("L" + name + ";", signature.getReturnValue().getDimensions()));
} else {
builder.setReturnType(signature.getReturnValue());
}
Signature newSignature = builder.build();
if (!method.getDescriptor().equals(newSignature)) {
// Signature was updated. Annotate it
if (method.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE) == null) {
// Signature was not previously renamed
method.getAnnotations().addAnnotation(DeobAnnotations.OBFUSCATED_SIGNATURE, "signature", method.getDescriptor().toString());
}
}
method.setDescriptor(newSignature);
// rename on exceptions thrown
if (method.getExceptions() != null) {
method.getExceptions().renameClass(cf, name);
}
}
// rename on fields
for (Field field : c.getFields()) {
if (field.getType().getInternalName().equals(cf.getName())) {
if (field.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE) == null) {
// Signature was updated. Annotate it
field.getAnnotations().addAnnotation(DeobAnnotations.OBFUSCATED_SIGNATURE, "signature", field.getType().toString());
}
field.setType(Type.getType("L" + name + ";", field.getType().getDimensions()));
}
}
}
if (cf.getAnnotations().find(DeobAnnotations.OBFUSCATED_NAME) == null) {
cf.getAnnotations().addAnnotation(DeobAnnotations.OBFUSCATED_NAME, "value", cf.getName());
}
group.renameClass(cf, name);
}
use of net.runelite.asm.attributes.code.Exceptions in project runelite by runelite.
the class CodeVisitor method visitTryCatchBlock.
@Override
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
Exceptions exceptions = code.getExceptions();
net.runelite.asm.attributes.code.Exception e = new net.runelite.asm.attributes.code.Exception(exceptions);
Instructions ins = code.getInstructions();
net.runelite.asm.attributes.code.Label startL = ins.findOrCreateLabel(start);
net.runelite.asm.attributes.code.Label endL = ins.findOrCreateLabel(end);
net.runelite.asm.attributes.code.Label handlerL = ins.findOrCreateLabel(handler);
assert startL != null;
assert endL != null;
assert handlerL != null;
e.setStart(startL);
e.setEnd(endL);
e.setHandler(handlerL);
if (type != null) {
e.setCatchType(new net.runelite.asm.pool.Class(type));
}
exceptions.add(e);
}
use of net.runelite.asm.attributes.code.Exceptions 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