List of usage examples for org.objectweb.asm.tree.analysis SourceInterpreter SourceInterpreter
public SourceInterpreter()
From source file:com.android.tools.lint.checks.JavaScriptInterfaceDetector.java
License:Apache License
@Nullable private String findFirstArgType(ClassContext context, ClassNode classNode, MethodNode method, MethodInsnNode call) {/* w w w .j a v a 2 s .co m*/ // Find object being passed in as the first argument Analyzer analyzer = new Analyzer(new SourceInterpreter() { @Override public SourceValue newOperation(AbstractInsnNode insn) { if (insn.getOpcode() == Opcodes.NEW) { String desc = ((TypeInsnNode) insn).desc; return new TypeValue(1, desc); } return super.newOperation(insn); } @Override public SourceValue newValue(Type type) { if (type != null && type.getSort() == Type.VOID) { return null; } else if (type != null) { return new TypeValue(1, type.getInternalName()); } return super.newValue(type); } @Override public SourceValue copyOperation(AbstractInsnNode insn, SourceValue value) { return value; } }); try { Frame[] frames = analyzer.analyze(classNode.name, method); InsnList instructions = method.instructions; Frame frame = frames[instructions.indexOf(call)]; if (frame.getStackSize() <= 1) { return null; } SourceValue stackValue = (SourceValue) frame.getStack(1); if (stackValue instanceof TypeValue) { return ((TypeValue) stackValue).getFqcn(); } } catch (AnalyzerException e) { context.log(e, null); } return null; }
From source file:com.android.tools.lint.checks.LocaleDetector.java
License:Apache License
@Override public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method, @NonNull MethodInsnNode call) {// ww w .j av a 2 s .c o m String owner = call.owner; String desc = call.desc; String name = call.name; if (owner.equals(DATE_FORMAT_OWNER)) { if (!name.equals(CONSTRUCTOR_NAME)) { return; } if (desc.equals("(Ljava/lang/String;Ljava/text/DateFormatSymbols;)V") //$NON-NLS-1$ || desc.equals("()V") //$NON-NLS-1$ || desc.equals("(Ljava/lang/String;)V")) { //$NON-NLS-1$ Location location = context.getLocation(call); String message = "To get local formatting use getDateInstance(), getDateTimeInstance(), " + "or getTimeInstance(), or use new SimpleDateFormat(String template, " + "Locale locale) with for example Locale.US for ASCII dates."; context.report(DATE_FORMAT, method, call, location, message, null); } return; } else if (!owner.equals(STRING_OWNER)) { return; } if (name.equals(FORMAT_METHOD)) { // Only check the non-locale version of String.format if (!desc.equals("(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;")) { //$NON-NLS-1$ return; } // Find the formatting string Analyzer analyzer = new Analyzer(new SourceInterpreter() { @Override public SourceValue newOperation(AbstractInsnNode insn) { if (insn.getOpcode() == Opcodes.LDC) { Object cst = ((LdcInsnNode) insn).cst; if (cst instanceof String) { return new StringValue(1, (String) cst); } } return super.newOperation(insn); } }); try { Frame[] frames = analyzer.analyze(classNode.name, method); InsnList instructions = method.instructions; Frame frame = frames[instructions.indexOf(call)]; if (frame.getStackSize() == 0) { return; } SourceValue stackValue = (SourceValue) frame.getStack(0); if (stackValue instanceof StringValue) { String format = ((StringValue) stackValue).getString(); if (format != null && StringFormatDetector.isLocaleSpecific(format)) { Location location = context.getLocation(call); String message = "Implicitly using the default locale is a common source of bugs: " + "Use String.format(Locale, ...) instead"; context.report(STRING_LOCALE, method, call, location, message, null); } } } catch (AnalyzerException e) { context.log(e, null); } } else { if (desc.equals("()Ljava/lang/String;")) { //$NON-NLS-1$ Location location = context.getLocation(call); String message = String.format("Implicitly using the default locale is a common source of bugs: " + "Use %1$s(Locale) instead", name); context.report(STRING_LOCALE, method, call, location, message, null); } } }
From source file:com.dragome.callbackevictor.serverside.bytecode.transformation.asm.ContinuationMethodAnalyzer.java
License:Apache License
@SuppressWarnings("unchecked") void moveNew() throws AnalyzerException { SourceInterpreter i = new SourceInterpreter(); Analyzer a = new Analyzer(i); a.analyze(className, this); final HashMap<AbstractInsnNode, MethodInsnNode> movable = new HashMap<AbstractInsnNode, MethodInsnNode>(); Frame[] frames = a.getFrames(); for (int j = 0; j < methods.size(); j++) { MethodInsnNode mnode = methods.get(j); // require to move NEW instruction int n = instructions.indexOf(mnode); Frame f = frames[n];// ww w .j av a 2s.com Type[] args = Type.getArgumentTypes(mnode.desc); SourceValue v = (SourceValue) f.getStack(f.getStackSize() - args.length - 1); Set<AbstractInsnNode> insns = v.insns; for (final AbstractInsnNode ins : insns) { if (ins.getOpcode() == NEW) { movable.put(ins, mnode); } else { // other known patterns int n1 = instructions.indexOf(ins); if (ins.getOpcode() == DUP) { // <init> with params AbstractInsnNode ins1 = instructions.get(n1 - 1); if (ins1.getOpcode() == NEW) { movable.put(ins1, mnode); } } else if (ins.getOpcode() == SWAP) { // in exception handler AbstractInsnNode ins1 = instructions.get(n1 - 1); AbstractInsnNode ins2 = instructions.get(n1 - 2); if (ins1.getOpcode() == DUP_X1 && ins2.getOpcode() == NEW) { movable.put(ins2, mnode); } } } } } int updateMaxStack = 0; for (final Map.Entry<AbstractInsnNode, MethodInsnNode> e : movable.entrySet()) { AbstractInsnNode node1 = e.getKey(); int n1 = instructions.indexOf(node1); AbstractInsnNode node2 = instructions.get(n1 + 1); AbstractInsnNode node3 = instructions.get(n1 + 2); int producer = node2.getOpcode(); instructions.remove(node1); // NEW boolean requireDup = false; if (producer == DUP) { instructions.remove(node2); // DUP requireDup = true; } else if (producer == DUP_X1) { instructions.remove(node2); // DUP_X1 instructions.remove(node3); // SWAP requireDup = true; } MethodInsnNode mnode = (MethodInsnNode) e.getValue(); AbstractInsnNode nm = mnode; int varOffset = stackRecorderVar + 1; Type[] args = Type.getArgumentTypes(mnode.desc); // optimizations for some common cases if (args.length == 0) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) doNew.add(new InsnNode(DUP)); instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } if (args.length == 1 && args[0].getSize() == 1) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) { doNew.add(new InsnNode(DUP)); doNew.add(new InsnNode(DUP2_X1)); doNew.add(new InsnNode(POP2)); updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values } else doNew.add(new InsnNode(SWAP)); instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } // TODO this one untested! if ((args.length == 1 && args[0].getSize() == 2) || (args.length == 2 && args[0].getSize() == 1 && args[1].getSize() == 1)) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) { doNew.add(new InsnNode(DUP)); doNew.add(new InsnNode(DUP2_X2)); doNew.add(new InsnNode(POP2)); updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values } else { doNew.add(new InsnNode(DUP_X2)); doNew.add(new InsnNode(POP)); updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for temp value } instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } final InsnList doNew = new InsnList(); // generic code using temporary locals // save stack for (int j = args.length - 1; j >= 0; j--) { Type type = args[j]; doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset)); varOffset += type.getSize(); } if (varOffset > maxLocals) { maxLocals = varOffset; } doNew.add(node1); // NEW if (requireDup) doNew.add(new InsnNode(DUP)); // restore stack for (int j = 0; j < args.length; j++) { Type type = args[j]; varOffset -= type.getSize(); doNew.add(new VarInsnNode(type.getOpcode(ILOAD), varOffset)); // clean up store to avoid memory leak? if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for ACONST_NULL doNew.add(new InsnNode(ACONST_NULL)); doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset)); } } instructions.insertBefore(nm, doNew); nm = doNew.getLast(); } maxStack += updateMaxStack; }
From source file:org.apache.commons.javaflow.providers.asm3.ContinuableMethodNode.java
License:Apache License
void moveNew() throws AnalyzerException { final SourceInterpreter i = new SourceInterpreter(); final Analyzer a = new Analyzer(i); a.analyze(className, this); final HashMap<AbstractInsnNode, MethodInsnNode> movable = new HashMap<AbstractInsnNode, MethodInsnNode>(); final Frame[] frames = a.getFrames(); for (int j = 0; j < methods.size(); j++) { final MethodInsnNode mnode = (MethodInsnNode) methods.get(j); // require to move NEW instruction int n = instructions.indexOf(mnode); Frame f = frames[n];//w w w .j a v a 2s . c o m Type[] args = Type.getArgumentTypes(mnode.desc); SourceValue v = (SourceValue) f.getStack(f.getStackSize() - args.length - 1); @SuppressWarnings("unchecked") Set<AbstractInsnNode> insns = v.insns; for (final AbstractInsnNode ins : insns) { if (ins.getOpcode() == NEW) { movable.put(ins, mnode); } else { // other known patterns int n1 = instructions.indexOf(ins); if (ins.getOpcode() == DUP) { // <init> with params AbstractInsnNode ins1 = instructions.get(n1 - 1); if (ins1.getOpcode() == NEW) { movable.put(ins1, mnode); } } else if (ins.getOpcode() == SWAP) { // in exception handler AbstractInsnNode ins1 = instructions.get(n1 - 1); AbstractInsnNode ins2 = instructions.get(n1 - 2); if (ins1.getOpcode() == DUP_X1 && ins2.getOpcode() == NEW) { movable.put(ins2, mnode); } } } } } int updateMaxStack = 0; for (final Map.Entry<AbstractInsnNode, MethodInsnNode> e : movable.entrySet()) { AbstractInsnNode node1 = e.getKey(); int n1 = instructions.indexOf(node1); AbstractInsnNode node2 = instructions.get(n1 + 1); AbstractInsnNode node3 = instructions.get(n1 + 2); int producer = node2.getOpcode(); instructions.remove(node1); // NEW boolean requireDup = false; if (producer == DUP) { instructions.remove(node2); // DUP requireDup = true; } else if (producer == DUP_X1) { instructions.remove(node2); // DUP_X1 instructions.remove(node3); // SWAP requireDup = true; } MethodInsnNode mnode = (MethodInsnNode) e.getValue(); AbstractInsnNode nm = mnode; int varOffset = stackRecorderVar + 1; Type[] args = Type.getArgumentTypes(mnode.desc); // optimizations for some common cases if (args.length == 0) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) doNew.add(new InsnNode(DUP)); instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } if (args.length == 1 && args[0].getSize() == 1) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) { doNew.add(new InsnNode(DUP)); doNew.add(new InsnNode(DUP2_X1)); doNew.add(new InsnNode(POP2)); updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values } else doNew.add(new InsnNode(SWAP)); instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } // TODO this one untested! if ((args.length == 1 && args[0].getSize() == 2) || (args.length == 2 && args[0].getSize() == 1 && args[1].getSize() == 1)) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) { doNew.add(new InsnNode(DUP)); doNew.add(new InsnNode(DUP2_X2)); doNew.add(new InsnNode(POP2)); updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values } else { doNew.add(new InsnNode(DUP_X2)); doNew.add(new InsnNode(POP)); updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for temp value } instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } final InsnList doNew = new InsnList(); // generic code using temporary locals // save stack for (int j = args.length - 1; j >= 0; j--) { Type type = args[j]; doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset)); varOffset += type.getSize(); } if (varOffset > maxLocals) { maxLocals = varOffset; } doNew.add(node1); // NEW if (requireDup) doNew.add(new InsnNode(DUP)); // restore stack for (int j = 0; j < args.length; j++) { Type type = args[j]; varOffset -= type.getSize(); doNew.add(new VarInsnNode(type.getOpcode(ILOAD), varOffset)); // clean up store to avoid memory leak? if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for ACONST_NULL doNew.add(new InsnNode(ACONST_NULL)); doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset)); } } instructions.insertBefore(nm, doNew); nm = doNew.getLast(); } maxStack += updateMaxStack; }
From source file:org.evosuite.graphs.cfg.BytecodeAnalyzer.java
License:Open Source License
/** * <p> * Constructor for BytecodeAnalyzer. * </p> */ public BytecodeAnalyzer() { super(new SourceInterpreter()); }
From source file:rubah.bytecode.transformers.RedirectFieldManipulation.java
License:Open Source License
@Override public MethodVisitor visitMethod(int access, String name, final String desc, String signature, String[] exceptions) {/* w ww . j a v a 2 s .co m*/ final MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); if (this.namespace.isBootstrap(this.thisClass)) return methodVisitor; if (this.thisClass.getFqn().startsWith("java.io") || this.thisClass.getFqn().startsWith("sun.reflect") || this.thisClass.getFqn().startsWith("sun.misc") || this.thisClass.getFqn().startsWith("java.security") || this.thisClass.getFqn().startsWith("java.util.concurrent.locks") || this.thisClass.getFqn().startsWith("java.util.concurrent.atomic") || (this.thisClass.getFqn().startsWith("java.lang") && !this.thisClass.getFqn().equals(Class.class.getName()))) return methodVisitor; if (this.objectsMap != null) { Method m = (Method) objectsMap.get(name); if (m == null) return methodVisitor; if (m.getName().startsWith(AddGettersAndSetters.GETTER_PREFFIX) || m.getName().startsWith(AddGettersAndSetters.SETTER_PREFFIX)) return methodVisitor; } MethodVisitor ret = new MethodNode(ASM5, access, name, desc, signature, exceptions) { private Frame<SourceValue>[] sourcesFrames; private boolean isStatic = Modifier.isStatic(access); @Override public void visitEnd() { Analyzer<SourceValue> sourceAnalyzer = new Analyzer<SourceValue>(new SourceInterpreter()); try { sourceAnalyzer.analyze(thisClass.getASMType().getInternalName(), this); } catch (AnalyzerException e) { System.out.println(namespace.isBootstrap(thisClass)); System.out.println(e.getMessage()); this.sourcesFrames = sourceAnalyzer.getFrames(); this.printAnalyzerResult(); throw new Error(e); } this.sourcesFrames = sourceAnalyzer.getFrames(); ListIterator<AbstractInsnNode> iter = this.instructions.iterator(); HashMap<AbstractInsnNode, InsnList> instructionsToAddBefore = new HashMap<AbstractInsnNode, InsnList>(); HashMap<AbstractInsnNode, InsnList> instructionsToAddAfter = new HashMap<AbstractInsnNode, InsnList>(); HashMap<AbstractInsnNode, AbstractInsnNode> instructionsToReplace = new HashMap<AbstractInsnNode, AbstractInsnNode>(); while (iter.hasNext()) { AbstractInsnNode insnNode = iter.next(); int opcode; switch ((opcode = insnNode.getOpcode())) { case INVOKESPECIAL: { MethodInsnNode methodNode = (MethodInsnNode) insnNode; int receiverDepth = Type.getArgumentTypes(methodNode.desc).length; if (!this.needsRedirect(insnNode, receiverDepth)) continue; for (AbstractInsnNode source : this.getSources(insnNode, receiverDepth)) { if (source.getOpcode() == AALOAD) // Already instrumented, skip it continue; instructionsToAddAfter.put(source, this.ensureNotProxy(methodNode.owner)); } break; } case INVOKEVIRTUAL: { MethodInsnNode methodNode = (MethodInsnNode) insnNode; MethodInvocationInfo m = new MethodInvocationInfo(methodNode.name, methodNode.owner, methodNode.desc); if (ensureNotProxyMethods.contains(m)) { int receiverDepth = 0; for (Type arg : Type.getArgumentTypes(methodNode.desc)) receiverDepth += arg.getSize(); if (!this.needsRedirect(insnNode, receiverDepth)) continue; for (AbstractInsnNode source : this.getSources(insnNode, receiverDepth)) instructionsToAddAfter.put(source, this.ensureNotProxy()); } break; } case GETFIELD: { if (!this.needsRedirect(insnNode, 0)) continue; FieldInsnNode fieldNode = (FieldInsnNode) insnNode; Type fieldOwner = findActualFieldOwner(Type.getObjectType(fieldNode.owner), fieldNode.name); opcode = (opcode == GETFIELD ? INVOKEVIRTUAL : INVOKESTATIC); String methodName = AddGettersAndSetters.generateGetterName(version, fieldOwner, fieldNode.name); String methodDesc = Type.getMethodDescriptor(Type.getType(fieldNode.desc)); instructionsToReplace.put(insnNode, new MethodInsnNode(opcode, fieldNode.owner, methodName, methodDesc, false)); break; } case PUTFIELD: { if (!this.needsRedirect(insnNode, 1)) continue; FieldInsnNode fieldNode = (FieldInsnNode) insnNode; Type fieldOwner = findActualFieldOwner(Type.getObjectType(fieldNode.owner), fieldNode.name); opcode = (opcode == PUTFIELD ? INVOKEVIRTUAL : INVOKESTATIC); String methodName = AddGettersAndSetters.generateSetterName(version, fieldOwner, fieldNode.name); String methodDesc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(fieldNode.desc)); instructionsToReplace.put(insnNode, new MethodInsnNode(opcode, fieldNode.owner, methodName, methodDesc, false)); break; } } } for (Entry<AbstractInsnNode, InsnList> entry : instructionsToAddBefore.entrySet()) this.instructions.insertBefore(entry.getKey(), entry.getValue()); for (Entry<AbstractInsnNode, InsnList> entry : instructionsToAddAfter.entrySet()) this.instructions.insert(entry.getKey(), entry.getValue()); // Destructive changes take place after constructive changes // so that the location nodes do not get destroyed too soon for (Entry<AbstractInsnNode, AbstractInsnNode> entry : instructionsToReplace.entrySet()) this.instructions.set(entry.getKey(), entry.getValue()); accept(methodVisitor); } private InsnList ensureNotProxy() { return this.ensureNotProxy(null); } private InsnList ensureNotProxy(String owner) { InsnList list = new InsnList(); LabelNode label = new LabelNode(); list.add(new InsnNode(DUP)); list.add(new TypeInsnNode(INSTANCEOF, Type.getType(RubahProxy.class).getInternalName())); list.add(new JumpInsnNode(IFEQ, label)); list.add(new TypeInsnNode(CHECKCAST, Type.getType(RubahProxy.class).getInternalName())); list.add(new MethodInsnNode(INVOKESTATIC, Type.getType(Rubah.class).getInternalName(), "getConverted", Type.getMethodDescriptor(Type.getType(Object.class), Type.getType(Object.class)), false)); if (owner != null) list.add(new TypeInsnNode(CHECKCAST, owner)); list.add(label); return list; } /** * * @param idx * @return True if local var, false if argument */ private boolean isLocalVar(int idx) { int lastVar = (this.isStatic ? 0 : 1); for (Type arg : Type.getArgumentTypes(desc)) lastVar += arg.getSize(); return idx >= lastVar; } private Set<AbstractInsnNode> getSources(AbstractInsnNode insnNode, int depth) { return this.getSources(insnNode, depth, new HashSet<AbstractInsnNode>(), new HashSet<AbstractInsnNode>()); } private Set<AbstractInsnNode> getSources(AbstractInsnNode insnNode, int depth, HashSet<AbstractInsnNode> allSources, HashSet<AbstractInsnNode> alreadySeen) { int idx = this.instructions.indexOf(insnNode); Frame<SourceValue> sourcesFrame = this.sourcesFrames[idx]; if (sourcesFrame == null) { // Bug in the analyzer or unreachable code return new HashSet<AbstractInsnNode>(); } Set<AbstractInsnNode> sources = sourcesFrame .getStack(sourcesFrame.getStackSize() - 1 - depth).insns; for (AbstractInsnNode source : sources) { if (alreadySeen.contains(source)) continue; alreadySeen.add(source); switch (source.getOpcode()) { case CHECKCAST: case DUP: allSources.addAll(this.getSources(source, 0, allSources, alreadySeen)); break; case ALOAD: // Is this an argument? VarInsnNode n = (VarInsnNode) source; if (isLocalVar(n.var)) { // Only ASTORE can save to local variables for (AbstractInsnNode astore : sourcesFrame.getLocal(n.var).insns) { allSources.addAll(this.getSources(astore, 0, allSources, alreadySeen)); } continue; } // Explicit fall-through default: allSources.add(source); break; } } return allSources; } private void printAnalyzerResult() { Textifier t = new Textifier(); TraceMethodVisitor mv = new TraceMethodVisitor(t); PrintWriter pw = new PrintWriter(System.out); pw.println(this.name + this.desc); for (int j = 0; j < this.instructions.size(); ++j) { this.instructions.get(j).accept(mv); StringBuffer s = new StringBuffer(); Frame<SourceValue> f = this.sourcesFrames[j]; if (f == null) { s.append('?'); } else { for (int k = 0; k < f.getLocals(); ++k) { for (AbstractInsnNode insn : f.getLocal(k).insns) { s.append(this.instructions.indexOf(insn)).append(' '); } } s.append(" : "); for (int k = 0; k < f.getStackSize(); ++k) { for (AbstractInsnNode insn : f.getStack(k).insns) { s.append(this.instructions.indexOf(insn)).append(' '); } } } while (s.length() < this.maxStack + this.maxLocals + 1) { s.append(' '); } pw.print(Integer.toString(j + 100000).substring(1)); pw.print(" " + s + " : " + t.text.get(t.text.size() - 1)); } for (int j = 0; j < this.tryCatchBlocks.size(); ++j) { this.tryCatchBlocks.get(j).accept(mv); pw.print(" " + t.text.get(t.text.size() - 1)); } pw.println(); pw.flush(); } private boolean needsRedirect(AbstractInsnNode insnNode, int stackDepth) { boolean ret = false; for (AbstractInsnNode insn : this.getSources(insnNode, stackDepth)) { switch (insn.getOpcode()) { case NEW: continue; case ALOAD: if (((VarInsnNode) insn).var != 0 || this.isStatic) ret = true; break; default: ret = true; break; } } return ret; } }; return ret; }