下面列出了怎么用org.objectweb.asm.tree.AbstractInsnNode的API类实例代码及写法,或者点击链接到github查看源代码。
private static SequenceQuery<AbstractInsnNode> arrayConditionalAtEnd() {
final Slot<LabelNode> loopStart = Slot.create(LabelNode.class);
final Slot<LabelNode> loopEnd = Slot.create(LabelNode.class);
final Slot<Integer> counter = Slot.create(Integer.class);
return QueryStart
.any(AbstractInsnNode.class)
.zeroOrMore(QueryStart.match(anyInstruction()))
.then(opCode(Opcodes.ARRAYLENGTH).and(mutationPoint()))
.then(opCode(Opcodes.ISTORE))
.then(opCode(Opcodes.ICONST_0).and(mutationPoint()))
.then(anIStore(counter.write()).and(debug("store")))
.then(gotoLabel(loopEnd.write()))
.then(aLabelNode(loopStart.write()))
.zeroOrMore(QueryStart.match(anyInstruction()))
.then(incrementsVariable(counter.read()).and(mutationPoint()))
.then(labelNode(loopEnd.read()))
.then(opCode(Opcodes.ILOAD))
.then(opCode(Opcodes.ILOAD))
.then(aConditionalJumpTo(loopStart).and(mutationPoint()))
.zeroOrMore(QueryStart.match(anyInstruction()));
}
public static InsnList getImportantList(InsnList list) {
if (list.size() == 0) {
return list;
}
HashMap<LabelNode, LabelNode> labels = new HashMap<LabelNode, LabelNode>();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof LabelNode) {
labels.put((LabelNode) insn, (LabelNode) insn);
}
}
InsnList importantNodeList = new InsnList();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof LabelNode || insn instanceof LineNumberNode) {
continue;
}
importantNodeList.add(insn.clone(labels));
}
return importantNodeList;
}
public static AbstractInsnNode getRandomValue(Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
return ASMUtils.getNumberInsn(RandomUtils.getRandomInt(0, 2));
case Type.CHAR:
return ASMUtils.getNumberInsn(RandomUtils.getRandomInt(Character.MIN_VALUE, Character.MAX_VALUE));
case Type.BYTE:
return ASMUtils.getNumberInsn(RandomUtils.getRandomInt(Byte.MIN_VALUE, Byte.MAX_VALUE));
case Type.SHORT:
return ASMUtils.getNumberInsn(RandomUtils.getRandomInt(Short.MIN_VALUE, Short.MAX_VALUE));
case Type.INT:
return ASMUtils.getNumberInsn(RandomUtils.getRandomInt());
case Type.FLOAT:
return ASMUtils.getNumberInsn(RandomUtils.getRandomFloat());
case Type.LONG:
return ASMUtils.getNumberInsn(RandomUtils.getRandomLong());
case Type.DOUBLE:
return ASMUtils.getNumberInsn(RandomUtils.getRandomDouble());
case Type.ARRAY:
case Type.OBJECT:
return new InsnNode(Opcodes.ACONST_NULL);
default:
throw new AssertionError();
}
}
@Inject(description = "Add hook to override returned value of isRowingBoat")
public void inject(MethodNode main) {
AbstractInsnNode preNode = main.instructions.getFirst();
Objects.requireNonNull(preNode, "Find pattern failed for pre node");
LabelNode jump = new LabelNode();
InsnList insnPre = new InsnList();
// insnPre.add(ASMHelper.call(GETSTATIC,
// TypesHook.Fields.ForgeHaxHooks_isNotRowingBoatActivated));
// insnPre.add(new JumpInsnNode(IFEQ, jump));
insnPre.add(new InsnNode(ICONST_0));
insnPre.add(new InsnNode(IRETURN)); // return false
// insnPre.add(jump);
main.instructions.insert(insnPre);
}
@SuppressWarnings("unchecked") // ASM API
public static void scanForAndCheckSetOnTouchListenerCalls(
ClassContext context,
ClassNode classNode) {
List<MethodNode> methods = classNode.methods;
for (MethodNode methodNode : methods) {
ListIterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode abstractInsnNode = iterator.next();
if (abstractInsnNode.getType() == AbstractInsnNode.METHOD_INSN) {
MethodInsnNode methodInsnNode = (MethodInsnNode) abstractInsnNode;
if (methodInsnNode.name.equals(SET_ON_TOUCH_LISTENER)
&& methodInsnNode.desc.equals(SET_ON_TOUCH_LISTENER_SIG)) {
checkSetOnTouchListenerCall(context, methodNode, methodInsnNode);
}
}
}
}
}
/**
* Returns the previous instruction prior to the given node, ignoring label
* and line number nodes.
*
* @param node the node to look up the previous instruction for
* @return the previous instruction, or null if no previous node was found
*/
@Nullable
public static AbstractInsnNode getPrevInstruction(@NonNull AbstractInsnNode node) {
AbstractInsnNode prev = node;
while (true) {
prev = prev.getPrevious();
if (prev == null) {
return null;
} else {
int type = prev.getType();
if (type != AbstractInsnNode.LINE && type != AbstractInsnNode.LABEL
&& type != AbstractInsnNode.FRAME) {
return prev;
}
}
}
}
@Override
public SourceValue newOperation(final AbstractInsnNode insn) {
int size;
switch (insn.getOpcode()) {
case LCONST_0:
case LCONST_1:
case DCONST_0:
case DCONST_1:
size = 2;
break;
case LDC:
Object value = ((LdcInsnNode) insn).cst;
size = value instanceof Long || value instanceof Double ? 2 : 1;
break;
case GETSTATIC:
size = Type.getType(((FieldInsnNode) insn).desc).getSize();
break;
default:
size = 1;
break;
}
return new SourceValue(size, insn);
}
/**
* <p>
* This method gets the end index for the provided Jump instruction
* </p>
*
* @param ain
* The given jump node
* @return int end index
*/
private int getEndIndexForBlock(AbstractInsnNode ain) {
int retIndex = 0;
if (ain instanceof JumpInsnNode) {
JumpInsnNode jin = (JumpInsnNode) ain;
LabelNode targetAIN = jin.label;
if (targetAIN.getPrevious() instanceof JumpInsnNode
&& Opcodes.GOTO == targetAIN.getPrevious().getOpcode()) {
retIndex = CollectionUtil.getObjectIndexInArray(this.insnArr, targetAIN
.getPrevious().getPrevious());
} else {
retIndex = CollectionUtil.getObjectIndexInArray(this.insnArr,
targetAIN.getPrevious());
}
}
return retIndex;
}
@Override
public boolean find(String desc, InsnList insns, Collection<AbstractInsnNode> nodes) {
boolean found = false;
int ordinal = 0;
ListIterator<AbstractInsnNode> iter = insns.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn instanceof JumpInsnNode && (this.opCode == -1 || insn.getOpcode() == this.opCode)) {
if (this.ordinal == -1 || this.ordinal == ordinal) {
nodes.add(insn);
found = true;
}
ordinal++;
}
}
return found;
}
private static InsnListSection insnListMatchesL(InsnList haystack, InsnList needle, int start, HashSet<LabelNode> controlFlowLabels) {
int h = start, n = 0;
for (; h < haystack.size() && n < needle.size(); h++) {
AbstractInsnNode insn = haystack.get(h);
if (insn.getType() == 15) {
continue;
}
if (insn.getType() == 8 && !controlFlowLabels.contains(insn)) {
continue;
}
if (!insnEqual(haystack.get(h), needle.get(n))) {
return null;
}
n++;
}
if (n != needle.size()) {
return null;
}
return new InsnListSection(haystack, start, h - 1);
}
@Override
public AbstractInsnNode tryMatch(InstructionMatcher matcher, AbstractInsnNode now) {
if (opcode != -1 && now.getOpcode() != opcode) {
return null;
}
if (!(now instanceof MethodInsnNode)) {
return null;
}
MethodInsnNode methodInsnNode = (MethodInsnNode) now;
boolean ownerMatches = owner == null || methodInsnNode.owner.equals(owner);
boolean nameMatches = name == null || methodInsnNode.name.equals(name);
boolean descMatches = desc == null || (basic ? TransformerHelper.basicType(methodInsnNode.desc) : methodInsnNode.desc).equals(desc);
if (!ownerMatches || !nameMatches || !descMatches) {
return null;
}
return now.getNext();
}
private boolean isVarBetweenBounds(AbstractInsnNode var, LabelNode lo, LabelNode hi) {
AbstractInsnNode x;
boolean loFound = false;
for (x = var; !(x == null || loFound); x = x.getPrevious()) {
loFound = x == lo;
}
if (!loFound)
return false;
boolean hiFound = false;
for (x = var; !(x == null || hiFound); x = x.getNext()) {
hiFound = x == hi;
}
return hiFound;
}
@Override
public void transform(JarArchive ja, ClassNode node) {
if (twoLongType) {
// init surroundings before decryption
Outer: for (ClassNode cn : ja.getClasses().values()) {
for (MethodNode mn : cn.methods) {
for (AbstractInsnNode ain : mn.instructions.toArray()) {
if (ain.getOpcode() == INVOKESPECIAL) {
MethodInsnNode min = (MethodInsnNode) ain;
if (min.owner.equals(node.name) && min.name.equals("<init>")) {
try {
Class.forName(cn.name.replace("/", "."), true, vm);
} catch (ClassNotFoundException e) {
}
continue Outer;
}
}
}
}
}
}
node.methods.forEach(mn -> removeDynamicCalls(node, mn));
}
@Override
public AbstractInsnNode tryMatch(InstructionMatcher matcher, AbstractInsnNode now) {
for (Step step : steps) {
AbstractInsnNode next = step.tryMatch(matcher, now);
if (next != null) {
return next;
}
}
return null;
}
public static long getLongFromInsn(AbstractInsnNode insn) {
int opcode = insn.getOpcode();
if (opcode >= Opcodes.LCONST_0 && opcode <= Opcodes.LCONST_1) {
return opcode - 9;
} else if (insn instanceof LdcInsnNode
&& ((LdcInsnNode) insn).cst instanceof Long) {
return (Long) ((LdcInsnNode) insn).cst;
}
throw new RadonException("Unexpected instruction");
}
public static void loadNode(ListIterator<AbstractInsnNode> iterator, Object paramType, int index) {
if (Opcodes.INTEGER.equals(paramType)) {
iterator.add(new VarInsnNode(Opcodes.ILOAD, index));
} else if (Opcodes.LONG.equals(paramType)) {
iterator.add(new VarInsnNode(Opcodes.LLOAD, index));
} else if (Opcodes.FLOAT.equals(paramType)) {
iterator.add(new VarInsnNode(Opcodes.FLOAD, index));
} else if (Opcodes.DOUBLE.equals(paramType)) {
iterator.add(new VarInsnNode(Opcodes.DLOAD, index));
} else {
iterator.add(new VarInsnNode(Opcodes.ALOAD, index));
}
}
public BlockVertex(MethodNode mn, Block block, ArrayList<AbstractInsnNode> nodes, LabelNode label, int listIndex) {
super();
this.mn = mn;
this.block = block;
this.nodes = nodes;
this.label = label;
this.listIndex = listIndex;
}
@Override
public AbstractInsnNode tryMatch(InstructionMatcher matcher, AbstractInsnNode now) {
if (now.getOpcode() == Opcodes.NEWARRAY && now instanceof IntInsnNode) {
if (this.sorts.contains(((IntInsnNode) now).operand)) {
return now.getNext();
}
}
return null;
}
/**
* Replaces class references in super constructor invocations.
* Must not replace references in this() constructor invocations.
*
* @param theClass the class being patched
* @param extenderClass the injected superclass
* @param mn method to process
*/
private static void replaceSuperCtorCalls(final ClassNode theClass, final ClassNode extenderClass, MethodNode mn) {
for (Iterator<AbstractInsnNode> it = mn.instructions.iterator(); it.hasNext(); ) {
AbstractInsnNode aIns = it.next();
if (aIns.getOpcode() == Opcodes.INVOKESPECIAL) {
MethodInsnNode mins = (MethodInsnNode)aIns;
if (CONSTRUCTOR_NAME.equals(mins.name) && mins.owner.equals(extenderClass.superName)) {
// replace with the extender class name
mins.owner = extenderClass.name;
}
break;
}
}
}
private static SequenceQuery<AbstractInsnNode> inifniteIteratorLoop() {
final Slot<LabelNode> loopStart = Slot.create(LabelNode.class);
return QueryStart
.any(AbstractInsnNode.class)
.then(methodCallThatReturns(ClassName.fromString("java/util/Iterator")))
.then(opCode(Opcodes.ASTORE))
.zeroOrMore(QueryStart.match(anyInstruction()))
.then(aJump())
.then(aLabelNode(loopStart.write()))
.oneOrMore(doesNotBreakIteratorLoop())
.then(jumpsTo(loopStart.read()))
// can't currently deal with loops with conditionals that cause additional jumps back
.zeroOrMore(QueryStart.match(jumpsTo(loopStart.read()).negate()));
}
private boolean isJumpBlock(Block b) {
for (AbstractInsnNode ain : b.getNodes()) {
int type = ain.getType();
if (type != AbstractInsnNode.LABEL && type != AbstractInsnNode.LINE && type != AbstractInsnNode.FRAME && type != AbstractInsnNode.JUMP_INSN) {
return false;
}
}
return true;
}
@Override
public boolean accept(AbstractInsnNode t) {
if (!(t instanceof VarInsnNode))
return false;
VarInsnNode vin = (VarInsnNode) t;
return opcodeFilter.accept(vin) && varFilter.accept(vin.var);
}
private List<AbstractInsnNode> createInstructionList() {
final List<AbstractInsnNode> list = new ArrayList<>();
for (AbstractInsnNode abstractInsnNode : this.rawNode.instructions) {
list.add(abstractInsnNode);
}
this.lazyInstructions = list;
return this.lazyInstructions;
}
public static Map<LabelNode, LabelNode> cloneLabels(InsnList insns) {
HashMap<LabelNode, LabelNode> labelMap = new HashMap<>();
for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) {
if (insn.getType() == 8) {
labelMap.put((LabelNode) insn, new LabelNode());
}
}
return labelMap;
}
public boolean isGetCurrentTask() {
AbstractInsnNode ain = getInstruction(startPos);
if (ain.getOpcode() == INVOKESTATIC) {
MethodInsnNode min = (MethodInsnNode)ain;
return min.owner.equals(TASK_CLASS) && min.name.equals("getCurrentTask");
}
return false;
}
private void record(ClassContext context, MethodNode method,
AbstractInsnNode instruction, String owner) {
if (owner.indexOf('$') != -1) {
// Don't report inner classes too; there will pretty much always be an outer class
// reference as well
return;
}
if (mCandidates == null) {
mCandidates = Lists.newArrayList();
}
mCandidates.add(new Candidate(owner, context.getClassNode().name, context.getJarFile()));
}
@Override
public boolean accept(AbstractInsnNode t) {
if (!(t instanceof IntInsnNode))
return false;
if (!opcodeFilter.accept(t))
return false;
IntInsnNode fin = (IntInsnNode) t;
if (!numberFilter.accept(fin.operand))
return false;
return true;
}
private Predicate<MutationDetails> mutatesIteratorLoopPlumbing() {
return a -> {
final int instruction = a.getInstructionIndex();
final MethodTree method = ForEachLoopFilter.this.currentClass.methods().stream()
.filter(MethodMatchers.forLocation(a.getId().getLocation()))
.findFirst()
.get();
final AbstractInsnNode mutatedInstruction = method.instruction(instruction);
final Context<AbstractInsnNode> context = Context.start(method.instructions(), DEBUG);
context.store(MUTATED_INSTRUCTION.write(), mutatedInstruction);
return ITERATOR_LOOP.matches(method.instructions(), context);
};
}
private String decodeInstruction(AbstractInsnNode insnNode) {
insnNode.accept(mp);
StringWriter sw = new StringWriter();
printer.print(new PrintWriter(sw));
printer.getText().clear();
return sw.toString();
}
public static AbstractInsnNode booleanValueOf() {
return new MethodInsnNode(
INVOKESTATIC,
Type.getInternalName(Conversions.class),
"booleanValueOf",
Type.getMethodDescriptor(
Type.BOOLEAN_TYPE,
Type.getType(Object.class)),
false);
}