private void build(InvokeDynamicInsnNode insn, IRBuilder builder) { // Bootstrap method Handle bsmHandle = insn.bsm; if (bsmHandle.getTag() != Opcodes.H_INVOKESTATIC && bsmHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) { throw new Unreachable( "Bootstrap handle is not yet supported: tag == " + bsmHandle.getTag()); } // Resolve the bootstrap method. DexMethodHandle bootstrapMethod = getMethodHandle(application, bsmHandle); // Decode static bootstrap arguments List<DexValue> bootstrapArgs = new ArrayList<>(); for (Object arg : insn.bsmArgs) { bootstrapArgs.add(decodeBootstrapArgument(arg)); } // Construct call site DexCallSite callSite = application .getCallSite(insn.name, insn.desc, bootstrapMethod, bootstrapArgs); buildInvoke(insn.desc, null /* Not needed */, false /* Receiver is passed explicitly */, builder, (types, registers) -> builder.addInvokeCustom(callSite, types, registers)); }
private int findInvokeDynamic() { AtomicInteger total = new AtomicInteger(); classNodes().forEach(classNode -> { classNode.methods.forEach(methodNode -> { for (int i = 0; i < methodNode.instructions.size(); i++) { AbstractInsnNode abstractInsnNode = methodNode.instructions.get(i); if (abstractInsnNode instanceof InvokeDynamicInsnNode) { InvokeDynamicInsnNode dyn = (InvokeDynamicInsnNode) abstractInsnNode; if (dyn.bsmArgs.length > 0 && dyn.bsmArgs[0] instanceof String) { total.incrementAndGet(); } } } }); }); return total.get(); }
@Override public ConstValue naryOperation(final AbstractInsnNode insn, final List<? extends ConstValue> values) { int opcode = insn.getOpcode(); if (opcode == Opcodes.MULTIANEWARRAY) { return new ConstValue(1); } else if (opcode == Opcodes.INVOKEDYNAMIC) { return new ConstValue(Type.getReturnType( ((InvokeDynamicInsnNode) insn).desc).getSize()); } else { int size = Type.getReturnType(((MethodInsnNode) insn).desc) .getSize(); Object cst = InvocationInterpreter.getInstance().execute( (MethodInsnNode) insn, values); return new ConstValue(size, cst); } }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC) { return newValue(Type .getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
@Override public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) { int size; int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { size = 1; } else { String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc : ((MethodInsnNode) insn).desc; size = Type.getReturnType(desc).getSize(); } return new SourceValue(size, insn); }
public void patchMethod(MethodNode methodNode, String patchName, String clazzName) { methodNode.desc = methodNode.desc.replace(patchName, clazzName); for (Iterator<AbstractInsnNode> iterator = methodNode.instructions.iterator(); iterator.hasNext();) { AbstractInsnNode insn = iterator.next(); if (insn instanceof TypeInsnNode) { TypeInsnNode type = (TypeInsnNode) insn; type.desc = replace(type.desc, patchName, clazzName); } else if (insn instanceof FieldInsnNode) { FieldInsnNode field = (FieldInsnNode) insn; field.owner = replace(field.owner, patchName, clazzName); } else if (insn instanceof MethodInsnNode) { MethodInsnNode method = (MethodInsnNode) insn; if (method.owner.equals(patchName) && method.getOpcode() == INVOKEVIRTUAL) method.setOpcode(INVOKESPECIAL); method.owner = replace(method.owner, patchName, clazzName); } else if (insn instanceof InvokeDynamicInsnNode) { InvokeDynamicInsnNode dynamic = (InvokeDynamicInsnNode) insn; String patchDesc = ASMHelper.getClassDesc(patchName), clazzDesc = ASMHelper.getClassDesc(clazzName); dynamic.desc = replace(dynamic.desc, patchDesc, clazzDesc); for (int i = 0; i < dynamic.bsmArgs.length; i++) if (dynamic.bsmArgs[i] instanceof Handle) { Handle handle = (Handle) dynamic.bsmArgs[i]; dynamic.bsmArgs[i] = new Handle(handle.getTag(), replace(handle.getOwner(), patchName, clazzName), handle.getName(), replace(handle.getDesc(), patchDesc, clazzDesc), handle.isInterface()); } } else if (insn instanceof FrameNode) { FrameNode frame = (FrameNode) insn; if (frame.local != null) frame.local.replaceAll((o -> o instanceof String ? replace((String) o, patchName, clazzName) : o)); if (frame.stack != null) frame.stack.replaceAll((o -> o instanceof String ? replace((String) o, patchName, clazzName) : o)); } } }
@Override public ConstValue naryOperation(AbstractInsnNode insn, List<? extends ConstValue> values) { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return ConstValue.ONE_SLOT; } else { String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc : ((MethodInsnNode) insn).desc; return ConstValue.slot(Type.getReturnType(desc).getSize()); } }
@Override public void handle(AbstractInsnNode node) throws IncorrectNodeException { super.handle(node); LOG.debug(logNode(node)); checkType(node, InvokeDynamicInsnNode.class); InvokeDynamicInsnNode invokeNode = (InvokeDynamicInsnNode) node; mState.getActiveStack().push(new LambdaExpression(invokeNode.name, invokeNode.desc, invokeNode.bsm, invokeNode.bsmArgs)); }
/** * Clones an invokevirtual/invokespecial/invokeinterface/invokedynamic node and returns it as an instruction list. * @param insnNode instruction to clone * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if node isn't of invoke type * @return instruction list with cloned instruction */ public static InsnList cloneInvokeNode(AbstractInsnNode insnNode) { Validate.notNull(insnNode); Validate.isTrue(insnNode instanceof MethodInsnNode || insnNode instanceof InvokeDynamicInsnNode); InsnList ret = new InsnList(); ret.add(insnNode.clone(new HashMap<>())); return ret; }
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { final InvokeDynamicInsnNode mnode = new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs); if (needsFrameGuard(INVOKEDYNAMIC, bsm.getOwner(), name, desc)) { Label label = new Label(); super.visitLabel(label); labels.add(label); nodes.add(mnode); } instructions.add(mnode); }
int findCallSiteInvocationInsertionIndex(final MethodInsnNode mnode) { int inSelected = -1; for (AbstractInsnNode otherIns = mnode; otherIns != null && inSelected < 0; ) { otherIns = otherIns.getNext(); if (otherIns instanceof MethodInsnNode || otherIns instanceof InvokeDynamicInsnNode) { inSelected = nodes.indexOf(otherIns); } } return inSelected; }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.opcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC) { return newValue(Type .getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
@Override public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) { int size; int opcode = insn.opcode(); if (opcode == MULTIANEWARRAY) { size = 1; } else { String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc : ((MethodInsnNode) insn).desc; size = Type.getReturnType(desc).getSize(); } return new SourceValue(size, insn); }
public CodeBlock invokedynamic(final String name, final String descriptor, final Handle bootstrapMethod, final Object... bootstrapArguments) { instructionList.add(new InvokeDynamicInsnNode(name, descriptor, bootstrapMethod, bootstrapArguments)); return this; }
public CodeBlock visitInvokeDynamicInsn(final String name, final String desc, final Handle bootstrapMethod, final Object... bootstrapArguments) { instructionList.add(new InvokeDynamicInsnNode(name, desc, bootstrapMethod, bootstrapArguments)); return this; }
private List<Lambda> pathOperator(ClassNode owner, List<MethodNode> methods, Insn<MethodInsnNode> it) { List<Lambda> result = new ArrayList<>(); Insn.ldcFor(it.node).stream() .map(e -> e.cst.toString()) .findFirst() .ifPresent(path -> { it.prev() .filter(is(InvokeDynamicInsnNode.class)) .findFirst() .map(InvokeDynamicInsnNode.class::cast) .ifPresent(n -> { Arrays.asList(n.bsmArgs).stream() .filter(Handle.class::isInstance) .findFirst() .map(Handle.class::cast) .ifPresent(handle -> { methods.stream() .filter(m -> m.name.equals(handle.getName())) .findFirst() .ifPresent(pathAction -> { log.debug("pathAction {}", path); lambdas(loader, owner, pathAction).stream() .filter(Lambda.class::isInstance) .map(Lambda.class::cast) .forEach(lambda -> { result.add(lambda.prefix(path)); }); }); }); }); }); log.debug("pathOperator: {}", result); return result; }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC){ return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
@Override public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) { int size; int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { size = 1; } else { String desc = (opcode == INVOKEDYNAMIC)? ((InvokeDynamicInsnNode) insn).desc: ((MethodInsnNode) insn).desc; size = Type.getReturnType(desc).getSize(); } return new SourceValue(size, insn); }
private void updateState(AbstractInsnNode insn) { switch (insn.getType()) { case AbstractInsnNode.INSN: updateState((InsnNode) insn); break; case AbstractInsnNode.INT_INSN: updateState((IntInsnNode) insn); break; case AbstractInsnNode.VAR_INSN: updateState((VarInsnNode) insn); break; case AbstractInsnNode.TYPE_INSN: updateState((TypeInsnNode) insn); break; case AbstractInsnNode.FIELD_INSN: updateState((FieldInsnNode) insn); break; case AbstractInsnNode.METHOD_INSN: updateState((MethodInsnNode) insn); break; case AbstractInsnNode.INVOKE_DYNAMIC_INSN: updateState((InvokeDynamicInsnNode) insn); break; case AbstractInsnNode.JUMP_INSN: updateState((JumpInsnNode) insn); break; case AbstractInsnNode.LABEL: updateState((LabelNode) insn); break; case AbstractInsnNode.LDC_INSN: updateState((LdcInsnNode) insn); break; case AbstractInsnNode.IINC_INSN: updateState((IincInsnNode) insn); break; case AbstractInsnNode.TABLESWITCH_INSN: updateState((TableSwitchInsnNode) insn); break; case AbstractInsnNode.LOOKUPSWITCH_INSN: updateState((LookupSwitchInsnNode) insn); break; case AbstractInsnNode.MULTIANEWARRAY_INSN: updateState((MultiANewArrayInsnNode) insn); break; case AbstractInsnNode.LINE: updateState((LineNumberNode) insn); break; default: throw new Unreachable("Unexpected instruction " + insn); } }