int startIndex = 0; AbstractInsnNode[] insns = ctor.instructions.toArray(); for (int i = 0; i < insns.length; i++) { AbstractInsnNode node = insns[i];
@Override public int previousIndex() { if (previousInsn == null) { return -1; } if (cache == null) { cache = toArray(); } return previousInsn.index; }
public int previousIndex() { if (prev == null) { return -1; } if (cache == null) { cache = toArray(); } return prev.index; }
/** * Returns the index of the given instruction in this list. This method builds a cache of the * instruction indexes to avoid scanning the whole list each time it is called. Once the cache is * built, this method run in constant time. The cache is invalidated by all the methods that * modify the list. * * @param insnNode an instruction <i>of this list</i>. * @return the index of the given instruction in this list. <i>The result of this method is * undefined if the given instruction does not belong to this list</i>. Use {@link #contains } * to test if an instruction belongs to an instruction list or not. */ public int indexOf(final AbstractInsnNode insnNode) { if (cache == null) { cache = toArray(); } return insnNode.index; }
/** * Returns the index of the given instruction in this list. This method * builds a cache of the instruction indexes to avoid scanning the whole * list each time it is called. Once the cache is built, this method run in * constant time. The cache is invalidated by all the methods that modify * the list. * * @param insn * an instruction <i>of this list</i>. * @return the index of the given instruction in this list. <i>The result of * this method is undefined if the given instruction does not belong * to this list</i>. Use {@link #contains contains} to test if an * instruction belongs to an instruction list or not. */ public int indexOf(final AbstractInsnNode insn) { if (cache == null) { cache = toArray(); } return insn.index; }
public static <T extends AbstractInsnNode> void forEach(InsnList instructions, Class<T> type, Consumer<T> consumer) { AbstractInsnNode[] array = instructions.toArray(); for (AbstractInsnNode node : array) { if (node.getClass() == type) { //noinspection unchecked consumer.accept((T) node); } } }
/** * Returns the instruction whose index is given. This method builds a cache of the instructions in * this list to avoid scanning the whole list each time it is called. Once the cache is built, * this method runs in constant time. This cache is invalidated by all the methods that modify the * list. * * @param index the index of the instruction that must be returned. * @return the instruction whose index is given. * @throws IndexOutOfBoundsException if (index < 0 || index >= size()). */ public AbstractInsnNode get(final int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(); } if (cache == null) { cache = toArray(); } return cache[index]; }
/** * Returns the instruction whose index is given. This method builds a cache * of the instructions in this list to avoid scanning the whole list each * time it is called. Once the cache is built, this method run in constant * time. This cache is invalidated by all the methods that modify the list. * * @param index * the index of the instruction that must be returned. * @return the instruction whose index is given. * @throws IndexOutOfBoundsException * if (index < 0 || index >= size()). */ public AbstractInsnNode get(final int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(); } if (cache == null) { cache = toArray(); } return cache[index]; }
@Override public int nextIndex() { if (nextInsn == null) { return size(); } if (cache == null) { cache = toArray(); } return nextInsn.index; }
public int nextIndex() { if (next == null) { return size(); } if (cache == null) { cache = toArray(); } return next.index; }
private List<AbstractInsnNode> getRealInstructions(MethodNode method) { List<AbstractInsnNode> instructions = new LinkedList<>(); for (AbstractInsnNode node : method.instructions.toArray()) { if (node.getOpcode() != -1) instructions.add(node); } return instructions; }
public static List<MethodInsnNode> matchMethodInsnNodes(MethodNode methodNode, int opcode, String owner, String[] names, String desc) { ArrayList<MethodInsnNode> matches = Lists.newArrayList(); ArrayList<String> validMethodNames = Lists.newArrayList(names); for (AbstractInsnNode insnNode : methodNode.instructions.toArray()) { if (insnNode instanceof MethodInsnNode && insnNode.getOpcode() == opcode) { MethodInsnNode methodInsnNode = (MethodInsnNode)insnNode; if (methodInsnNode.owner.equals(owner) & validMethodNames.contains(methodInsnNode.name) && methodInsnNode.desc.equals(desc)) { matches.add(methodInsnNode); } } } return matches; }
public static SpecificMethodNodeTransformer instructionsInserter(String target, int priority, Function<AbstractInsnNode, Pair<InsnList, Boolean>> inserter) { return instructionsTransformer(priority, target, instructions -> { for (AbstractInsnNode node : instructions.toArray()) { Pair<InsnList, Boolean> pair = inserter.apply(node); if (pair != null) if (pair.getRight()) instructions.insertBefore(node, pair.getLeft()); else instructions.insert(node, pair.getLeft()); } }); }
void handlePatches(MethodNode methodNode) { FMLRelaunchLog.info(" Patching method " + this.method); this.patches.stream().filter(patch -> patch.predicate == null).forEach(patch -> { Method method = new Method(this.patcher, null); patch.consumer.accept(method); patch.at.apply(patch, methodNode, null, method); }); for (AbstractInsnNode insnNode : methodNode.instructions.toArray()) { this.patches.stream().filter(patch -> patch.predicate != null && patch.predicate.test(new PredicateData(this.patcher, this.cls, insnNode))).forEach(patch -> { Method method = new Method(this.patcher, insnNode); patch.consumer.accept(method); patch.at.apply(patch, methodNode, insnNode, method); }); } }
public static SpecificMethodNodeTransformer instructionsNodesTransformer(String target, int priority, Function<AbstractInsnNode, AbstractInsnNode> insnOld2new) { return instructionsTransformer(priority, target, instructions -> { for (AbstractInsnNode node : instructions.toArray()) { AbstractInsnNode res = insnOld2new.apply(node); if (res != null) instructions.set(node, res); else instructions.remove(node); } }); }
@Override public void transform() { AtomicInteger counter = new AtomicInteger(); this.getClassWrappers().parallelStream().filter(classWrapper -> !excluded(classWrapper)).forEach(classWrapper -> classWrapper.classNode.methods.parallelStream().filter(this::hasInstructions).forEach(methodNode -> { for (AbstractInsnNode insn : methodNode.instructions.toArray()) { if (insn instanceof LineNumberNode) { if (remove) { methodNode.instructions.remove(insn); } else { ((LineNumberNode) insn).line = RandomUtils.getRandomInt(); } counter.incrementAndGet(); } } }) ); LoggerUtils.stdOut(String.format("%s %d line numbers.", (remove) ? "Removed" : "Obfuscated", counter.get())); }
private void replace(int opcode, ClassNode owner, FieldNode field, MethodNode m) { if (Modifier.isStatic(field.access)) opcode -= 2; for (ClassNode cn : classMap.values()) { for (MethodNode mn : cn.methods) { AbstractInsnNode[] instructions = mn.instructions.toArray(); for (AbstractInsnNode node : instructions) { if (node.getType() != AbstractInsnNode.METHOD_INSN) { continue; } MethodInsnNode min = (MethodInsnNode) node; List<String> owners = getChildNames(owner); if (owners.contains(min.owner) && min.name.equals(m.name) && min.desc.equals(m.desc)) { FieldInsnNode fin = new FieldInsnNode(opcode, min.owner, field.name, field.desc); log.debug(" replace {}.{}.{}, insn: {}", cn.name, mn.name, mn.desc, QueryUtil.query(fin, "index")); mn.instructions.set(min, fin); } } } } }
@Override public void transform() { AtomicInteger count = new AtomicInteger(); long current = System.currentTimeMillis(); getClassWrappers().parallelStream().filter(classWrapper -> !excluded(classWrapper)).forEach(classWrapper -> classWrapper.methods.parallelStream().filter(methodWrapper -> !excluded(methodWrapper) && hasInstructions(methodWrapper.methodNode)).forEach(methodWrapper -> { MethodNode methodNode = methodWrapper.methodNode; for (AbstractInsnNode insn : methodNode.instructions.toArray()) { if (insn.getOpcode() == NOP) { methodNode.instructions.remove(insn); } } }) ); LoggerUtils.stdOut(String.format("Removed %d NOP instructions. [%dms]", count.get(), tookThisLong(current))); }
@Override public void transform() { AtomicInteger count = new AtomicInteger(); long current = System.currentTimeMillis(); getClassWrappers().parallelStream().filter(classWrapper -> !excluded(classWrapper)).forEach(classWrapper -> classWrapper.methods.parallelStream().filter(methodWrapper -> !excluded(methodWrapper) && hasInstructions(methodWrapper.methodNode)).forEach(methodWrapper -> { MethodNode methodNode = methodWrapper.methodNode; for (AbstractInsnNode insn : methodNode.instructions.toArray()) { if (insn.getOpcode() == GOTO) { JumpInsnNode gotoJump = (JumpInsnNode) insn; AbstractInsnNode insnAfterTarget = gotoJump.label.getNext(); if (insnAfterTarget != null && insnAfterTarget.getOpcode() == GOTO) { JumpInsnNode secGoto = (JumpInsnNode) insnAfterTarget; gotoJump.label = secGoto.label; count.incrementAndGet(); } } } })); LoggerUtils.stdOut(String.format("Normalized %d GOTO->GOTO sequences. [%dms]", count.get(), tookThisLong(current))); }
@Override public void transform() { AtomicInteger count = new AtomicInteger(); long current = System.currentTimeMillis(); getClassWrappers().parallelStream().filter(classWrapper -> !excluded(classWrapper)).forEach(classWrapper -> classWrapper.methods.parallelStream().filter(methodWrapper -> !excluded(methodWrapper) && hasInstructions(methodWrapper.methodNode)).forEach(methodWrapper -> { MethodNode methodNode = methodWrapper.methodNode; for (AbstractInsnNode insn : methodNode.instructions.toArray()) { if (insn.getOpcode() == GOTO) { JumpInsnNode gotoJump = (JumpInsnNode) insn; AbstractInsnNode insnAfterTarget = gotoJump.label.getNext(); if (insnAfterTarget != null && BytecodeUtils.isReturn(insnAfterTarget.getOpcode())) { methodNode.instructions.set(insn, new InsnNode(insnAfterTarget.getOpcode())); count.incrementAndGet(); } } } })); LoggerUtils.stdOut(String.format("Normalized %d GOTO->RETURN sequences. [%dms]", count.get(), tookThisLong(current))); }