@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 cst = ((LdcInsnNode) insn).cst; size = cst instanceof Long || cst instanceof Double ? 2 : 1; break; case GETSTATIC: size = Type.getType(((FieldInsnNode) insn).desc).getSize(); break; default: size = 1; } return new SourceValue(size, insn); }
@Override public SourceValue unaryOperation(final AbstractInsnNode insn, final SourceValue value) { int size; switch (insn.getOpcode()) { case LNEG: case DNEG: case I2L: case I2D: case L2D: case F2L: case F2D: case D2L: size = 2; break; case GETFIELD: size = Type.getType(((FieldInsnNode) insn).desc).getSize(); break; default: size = 1; } return new SourceValue(size, insn); }
private void updateState(FieldInsnNode insn) { Type type = Type.getType(insn.desc); switch (insn.getOpcode()) { case Opcodes.GETSTATIC: state.push(type); break; case Opcodes.PUTSTATIC: state.pop(); break; case Opcodes.GETFIELD: { state.pop(JarState.OBJECT_TYPE); state.push(type); break; } case Opcodes.PUTFIELD: { state.pop(); state.pop(JarState.OBJECT_TYPE); break; } default: throw new Unreachable("Unexpected FieldInsn opcode: " + insn.getOpcode()); } }
public RunMethod.ClosureFieldInstance toClosureFieldInstance() { assert (this.isClosed()); FieldNode fieldNode = instanceFieldNode(); InsnList il = new InsnList(); il.add(new VarInsnNode(ALOAD, 0)); il.add(instantiationInsns()); il.add(new FieldInsnNode( PUTFIELD, context.thisClassType().getInternalName(), instanceFieldName(), instanceType().getDescriptor())); return new RunMethod.ClosureFieldInstance(instanceFieldNode(), il); }
private InsnList fetchInstanceInsns() { InsnList il = new InsnList(); if (this.isClosed()) { if (this.isPure()) { il.add(new FieldInsnNode( GETSTATIC, instanceType().getInternalName(), ASMBytecodeEmitter.instanceFieldName(), instanceType().getDescriptor())); } else { il.add(new VarInsnNode(ALOAD, 0)); il.add(new FieldInsnNode( GETFIELD, context.thisClassType().getInternalName(), instanceFieldName(), instanceType().getDescriptor())); } } else { il.add(instantiationInsns()); } return il; }
@Override public void transform(ClassNode clazz, MethodNode method, InsnMatcher matcher) { method.tryCatchBlocks.clear(); method.localVariables.clear(); method.instructions.clear(); /* this.loginHandlerList.put(SteamIdAsString, loginHandler); */ method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); method.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "com/wurmonline/server/steam/SteamHandler", "loginHandlerList", "Ljava/util/Map;")); method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); method.instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true)); method.instructions.add(new InsnNode(Opcodes.POP)); /* return true; */ method.instructions.add(new InsnNode(Opcodes.ICONST_1)); method.instructions.add(new InsnNode(Opcodes.IRETURN)); }
public static CallGraph build(Map<String, ClassFactory> classes, boolean includeFields) { CallGraph graph = new CallGraph(); ClassMethodVisitor callVisitor = new ClassMethodVisitor() { public void visitMethodInsn(MethodInsnNode min) { if (classes.containsKey(min.owner)) { graph.addClassCall(min.owner, method); graph.addMethodCall(min.owner + "." + min.name + min.desc, method); } } public void visitFieldInsn(FieldInsnNode fin) { if (includeFields && classes.containsKey(fin.owner)) { graph.addClassCall(fin.owner, method); } if (classes.containsKey(fin.owner)) { graph.addFieldCall(fin.owner + "." + fin.name, method); } } }; classes.values().forEach(factory -> factory.dispatch(callVisitor)); return graph; }
private static void collectAdvancedData(Map<String, ClassFactory> classes) { linearized.forEach((method, list) -> { list.stream().filter(ain -> ain instanceof FieldInsnNode).forEach(ain -> { int index = list.indexOf(ain); int dist = 3; if (index - dist >= 0 && index + dist < list.size()) { FieldInsnNode fin = (FieldInsnNode) ain; String key = (fin.owner + "." + fin.name); int sum = 0; for (int i = 0; i < dist; i++) { AbstractInsnNode p = list.get(index - i); AbstractInsnNode n = list.get(index + i); int extraP = extraWeight(classes, p); int extraN = extraWeight(classes, n); sum += (p.getOpcode() + extraP + n.getOpcode() + extraN); } boolean getter = (fin.getOpcode() == GETFIELD || fin.getOpcode() == GETSTATIC); Map<String, List<Integer>> map = (getter ? getsums : putsums); if (!map.containsKey(key)) { map.put(key, new ArrayList<>()); } map.get(key).add(sum); } }); }); }
@Override public void patchMethod(MethodNode methodNode, ClassNode classNode, boolean obfuscated) { AbstractInsnNode insert = ASMUtil.findFirstInstruction(methodNode, Opcodes.DSTORE, 5); if (insert == null) return; InsnList insnList = new InsnList(); insnList.add(new VarInsnNode(Opcodes.ALOAD, 0)); insnList.add(new FieldInsnNode(Opcodes.GETFIELD, obfuscated ? "nh" : "net/minecraft/network/NetHandlerPlayServer", obfuscated ? "b" : "playerEntity", obfuscated ? "Lmw;" : "Lnet/minecraft/entity/player/EntityPlayerMP;")); insnList.add(new VarInsnNode(Opcodes.DLOAD, 5)); insnList.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/techjar/vivecraftforge/util/ASMDelegator", "playerEntityReachDistance", obfuscated ? "(Lyz;D)D" : "(Lnet/minecraft/entity/player/EntityPlayer;D)D", false)); insnList.add(new VarInsnNode(Opcodes.DSTORE, 5)); methodNode.instructions.insert(insert, insnList); VivecraftForgeLog.debug("Inserted delegate method call."); AbstractInsnNode removeInsn = ASMUtil.findFirstInstruction(methodNode, Opcodes.LDC, 9.0D); if (removeInsn != null) { int remove = methodNode.instructions.indexOf(removeInsn); for (int i = 0; i < 2; i++) { methodNode.instructions.remove(methodNode.instructions.get(remove)); } VivecraftForgeLog.debug("Removed variable assignment."); } else { VivecraftForgeLog.debug("Variable assignment not found."); } }
private boolean isSmokeMethod(MethodNode method) { boolean containsArray = false; int putstatic = 0; int getstatic = 0; for(AbstractInsnNode ain : method.instructions.toArray()) if(ain.getOpcode() == Opcodes.ANEWARRAY) containsArray = true; else if(ain.getOpcode() == Opcodes.PUTSTATIC || ain.getOpcode() == Opcodes.GETSTATIC) if(((FieldInsnNode)ain).desc.equals("[Ljava/lang/String;")) { if(ain.getOpcode() == Opcodes.PUTSTATIC) putstatic++; else getstatic++; } return containsArray && putstatic == 2 && getstatic == 2; }
public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) { if (node1.getType() != node2.getType()) { return false; } else if (node1.getOpcode() != node2.getOpcode()) { return false; } switch (node2.getType()) { case VAR_INSN: return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); case TYPE_INSN: return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); case FIELD_INSN: return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); case METHOD_INSN: return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); case LDC_INSN: return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); case IINC_INSN: return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); case INT_INSN: return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2); default: return true; } }
public static boolean shouldMarkStack(MethodNode methodNode) { for (Iterator<AbstractInsnNode> iterator = methodNode.instructions.iterator(); iterator.hasNext();) { AbstractInsnNode insn = iterator.next(); if (insn instanceof FieldInsnNode) { FieldInsnNode field = (FieldInsnNode) insn; if (field.getOpcode() == PUTFIELD && field.name.equals("stackContext") && field.owner.equals(AlchemyTransformerManager.HOOK_RESULT_DESC)) return true; } if (insn instanceof MethodInsnNode) { MethodInsnNode method = (MethodInsnNode) insn; if (method.name.equals("operationStack") && method.owner.equals(AlchemyTransformerManager.HOOK_RESULT_DESC)) return true; } } return false; }
/** * TODO: Complete JavaDoc * * @param methodNode * @param owner The class of the variable to be hooked * @param var The variable to be hooked * @param desc * @param newClass The class the hooked variable will be stored in * @param newVar The variable name the hooked variable will be stored in * @param newDesc * @param canRead Specifies if the hooked variable should be readable * @param canWrite Specifies if the hooked variable should be writable */ private void hookClassVariable(MethodNode methodNode, String owner, String var, String desc, String newClass, String newVar, String newDesc, boolean canRead, boolean canWrite) { Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator(); while (insnNodeList.hasNext()) { AbstractInsnNode insnNode = insnNodeList.next(); int opcode = insnNode.getOpcode(); if (opcode == Opcodes.GETFIELD || opcode == Opcodes.PUTFIELD) { FieldInsnNode field = (FieldInsnNode)insnNode; if (field.owner.equals(owner) && field.name.equals(var) && field.desc.equals(desc)) { if (opcode == Opcodes.GETFIELD && canWrite) { methodNode.instructions.insert(insnNode, new FieldInsnNode(Opcodes.GETSTATIC, newClass, newVar, newDesc)); methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.POP)); } else if (opcode == Opcodes.PUTFIELD && canRead) { methodNode.instructions.insertBefore(insnNode, new InsnNode(Opcodes.DUP_X1)); methodNode.instructions.insert(insnNode, new FieldInsnNode(Opcodes.PUTSTATIC, newClass, newVar, newDesc)); } } } } }
/** * TODO: Complete JavaDoc * * @param methodNode * @param owner The class of the variable to be hooked * @param var The variable to be hooked * @param desc * @param newClass The class the hooked variable will be stored in * @param newVar The variable name the hooked variable will be stored in * @param newDesc */ private void hookStaticVariable(MethodNode methodNode, String owner, String var, String desc, String newClass, String newVar, String newDesc) { Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator(); while (insnNodeList.hasNext()) { AbstractInsnNode insnNode = insnNodeList.next(); int opcode = insnNode.getOpcode(); if (opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC) { FieldInsnNode field = (FieldInsnNode)insnNode; if (field.owner.equals(owner) && field.name.equals(var) && field.desc.equals(desc)) { field.owner = newClass; field.name = newVar; field.desc = newDesc; } } } }
public Value 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 cst = ((LdcInsnNode) insn).cst; size = cst instanceof Long || cst instanceof Double ? 2 : 1; break; case GETSTATIC: size = Type.getType(((FieldInsnNode) insn).desc).getSize(); break; default: size = 1; } return new DataflowValue(size, insn); }
public Value unaryOperation(final AbstractInsnNode insn, final Value value) { int size; switch (insn.getOpcode()) { case LNEG: case DNEG: case I2L: case I2D: case L2D: case F2L: case F2D: case D2L: size = 2; break; case GETFIELD: size = Type.getType(((FieldInsnNode) insn).desc).getSize(); break; default: size = 1; } return new DataflowValue(size, insn); }
@Override public ConstValue newOperation(AbstractInsnNode insn) { switch (insn.getOpcode()) { case LCONST_0: case LCONST_1: case DCONST_0: case DCONST_1: return ConstValue.TWO_SLOT; case LDC: Object cst = ((LdcInsnNode) insn).cst; if (cst instanceof Type) { // constant class return ConstValue.string(((Type)cst).getInternalName()); } return cst instanceof Long || cst instanceof Double ? ConstValue.TWO_SLOT: ConstValue.ONE_SLOT; case GETSTATIC: return ConstValue.slot(Type.getType(((FieldInsnNode) insn).desc).getSize()); default: return ConstValue.ONE_SLOT; } }
@Override public ConstValue unaryOperation(AbstractInsnNode insn, ConstValue value) { switch (insn.getOpcode()) { case LNEG: case DNEG: case I2L: case I2D: case L2D: case F2L: case F2D: case D2L: return ConstValue.TWO_SLOT; case GETFIELD: return ConstValue.slot(Type.getType(((FieldInsnNode) insn).desc).getSize()); default: return ConstValue.ONE_SLOT; } }
@Deprecated @Override public void run() { ListIterator<AbstractInsnNode> iterator; AbstractInsnNode next; iterator = mn.instructions.iterator(); while (iterator.hasNext()) { next = iterator.next(); if (next instanceof FieldInsnNode) { if (((FieldInsnNode) next).owner.startsWith("java/")) continue; } else continue; FieldInsnNode fn = (FieldInsnNode) next; if (next.getOpcode() == GETFIELD) { } if (next.getOpcode() == PUTFIELD) { } } }
private static MethodNode findEnumSwitchUsage(ClassNode classNode, String owner) { String target = ENUM_SWITCH_PREFIX + owner.replace('/', '$'); @SuppressWarnings("rawtypes") // ASM API List methodList = classNode.methods; for (Object f : methodList) { MethodNode method = (MethodNode) f; InsnList nodes = method.instructions; for (int i = 0, n = nodes.size(); i < n; i++) { AbstractInsnNode instruction = nodes.get(i); if (instruction.getOpcode() == Opcodes.GETSTATIC) { FieldInsnNode field = (FieldInsnNode) instruction; if (field.name.equals(target)) { return method; } } } } return null; }
@Override protected boolean matches(ClassNode cn) { Pattern p = new PatternBuilder() .add(new MethodElement(new MethodInsnNode(INVOKESPECIAL, null, null, null, false)), new MethodElement(new MethodInsnNode(INVOKESTATIC, null, null, null, false)), new AnyElement(), new AnyElement(), new FieldElement(new FieldInsnNode(GETSTATIC, null, null, null)), new MethodElement(new MethodInsnNode(INVOKEVIRTUAL, null, null, null, false)), new InstructionElement(IFEQ), new AnyElement(), new MethodElement(new MethodInsnNode(INVOKEVIRTUAL, null, null, null, false))) .build(); for (MethodNode mn : cn.methods) if (p.contains(mn.instructions)) return true; return false; }
@Override public InsnList build(MethodContext context) { Type returnType = context.getResultType(); InsnList insnList = new InsnList(); LabelNode continueLabel = new LabelNode(); insnList.add(new InsnNode(DUP)); insnList.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(clazz), field, Type.getDescriptor(Object.class))); insnList.add(new JumpInsnNode(IF_ACMPEQ, continueLabel)); if (returnType.getSize() == 0) { insnList.add(new InsnNode(POP)); insnList.add(new InsnNode(RETURN)); } else if (isPrimitive(returnType)) { insnList.add(new UnboxPrimitives(returnType).build(context)); insnList.add(new InsnNode(returnType.getOpcode(IRETURN))); } else { insnList.add(new TypeInsnNode(CHECKCAST, returnType.getInternalName())); insnList.add(new InsnNode(ARETURN)); } insnList.add(continueLabel); insnList.add(new InsnNode(POP)); return insnList; }
private void injectFieldsIn(MethodNode rootNode) { InsnList instructions = rootNode.instructions; if (instructions.size() == 0) { return; } AbstractInsnNode node = instructions.getFirst(); while (node != null) { while (! (node instanceof FieldInsnNode) || ! AsmUtils.isPutField(node.getOpcode())) { node = node.getNext(); if (node == null) { return; } } this.trackFieldToInject((FieldInsnNode) node, rootNode.instructions); node = node.getNext(); } }
public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) { if (node1.getOpcode() != node2.getOpcode()) { return false; } switch (node2.getType()) { case VAR_INSN: return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); case TYPE_INSN: return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); case FIELD_INSN: return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); case METHOD_INSN: return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); case LDC_INSN: return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); case IINC_INSN: return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); case INT_INSN: return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2); default: return true; } }
/*** * * * @param fn * @param inst * @param dsi */ private void writeValue(String owner, FieldNode fn, InsnList inst, PdxSItem dsi) { String desc = new StringBuffer("(Ljava/lang/String;").append(fn.desc) .append(")Lcom/gemstone/gemfire/pdx/PdxWriter;").toString(); inst.add(new VarInsnNode(ALOAD, 1)); inst.add(new LdcInsnNode(fn.name)); inst.add(new VarInsnNode(ALOAD, 0)); inst.add(new FieldInsnNode(GETFIELD, owner, fn.name, fn.desc)); // add INVOKEVIRTUAL method if (PdxConstants.TYPE_BYTECODE_BYTE_B.equals(fn.desc)) // data type ->byte inst.add(AsmHelper.newMethodInsnNode(INVOKEVIRTUAL, PdxConstants.TYPE_BYTECODE_BYTE, "byteValue", fn.desc, false)); else if (PdxConstants.TYPE_BYTECODE_BOOL_Z.equals(fn.desc)) // data type -> // boolean inst.add(AsmHelper.newMethodInsnNode(INVOKEVIRTUAL, PdxConstants.TYPE_BYTECODE_BOOL, "booleanValue", fn.desc, false)); inst.add(AsmHelper.newMethodInsnNode(INVOKEINTERFACE, PdxConstants.PDX_WRITER_VALUE, dsi.toMethod, desc, true)); inst.add(new InsnNode(POP)); }