public void defaultCase(Node node) { if (node instanceof TQuotedName || node instanceof TFullIdentifier || node instanceof TIdentifier || node instanceof TStringConstant || node instanceof TIntegerConstant || node instanceof TFloatConstant || node instanceof TAtIdentifier) { if (debug) G.v().out.println("Default case -pushing token:" + ((Token) node).getText()); String tokenString = ((Token) node).getText(); if (node instanceof TStringConstant || node instanceof TQuotedName) { tokenString = tokenString.substring(1, tokenString.length() - 1); } if (node instanceof TIdentifier || node instanceof TFullIdentifier || node instanceof TQuotedName || node instanceof TStringConstant) { try { tokenString = StringTools.getUnEscapedStringOf(tokenString); } catch (RuntimeException e) { G.v().out.println(tokenString); throw e; } } mProductions.addLast(tokenString); } }
public void setMainClassFromOptions() { if (mainClass != null) return; if (Options.v().main_class() != null && Options.v().main_class().length() > 0) { setMainClass(getSootClass(Options.v().main_class())); } else { // try to infer a main class from the command line if none is given for (Iterator<String> classIter = Options.v().classes().iterator(); classIter.hasNext(); ) { SootClass c = getSootClass(classIter.next()); if (c.declaresMethod( "main", Collections.<Type>singletonList(ArrayType.v(RefType.v("java.lang.String"), 1)), VoidType.v())) { G.v().out.println("No main class given. Inferred '" + c.getName() + "' as main class."); setMainClass(c); return; } } // try to infer a main class from the usual classpath if none is given for (Iterator<SootClass> classIter = getApplicationClasses().iterator(); classIter.hasNext(); ) { SootClass c = (SootClass) classIter.next(); if (c.declaresMethod( "main", Collections.<Type>singletonList(ArrayType.v(RefType.v("java.lang.String"), 1)), VoidType.v())) { G.v().out.println("No main class given. Inferred '" + c.getName() + "' as main class."); setMainClass(c); return; } } } }
private void analyzeLocal(SootMethod method, Value value) { Local l = (Local) value; boolean objIsThreadLocal = tloa.isObjectThreadLocal(l, method); if (objIsThreadLocal) { G.v().out.println("[lg.tlo] LOCAL " + l.toString() + " is thread-local in method " + method); } else { G.v().out.println("[lg.tlo] LOCAL " + l.toString() + " is thread-shared in method " + method); } }
private void analyzeField(SootMethod method, Value value) { FieldRef fr = (FieldRef) value; boolean fieldIsThreadLocal = tloa.isObjectThreadLocal(fr, method); if (fieldIsThreadLocal) { G.v().out.println("[lg.tlo] FIELD " + fr.toString() + " is thread-local in method " + method); } else { G.v() .out .println("[lg.tlo] FIELD " + fr.toString() + " is thread-shared in method " + method); } }
public StronglyConnectedComponentsBV(BitVector typeVariableList, TypeResolverBV resolver) throws TypeException { this.resolver = resolver; variables = typeVariableList; black = new TreeSet(); finished = new LinkedList(); for (BitSetIterator i = variables.iterator(); i.hasNext(); ) { TypeVariableBV var = resolver.typeVariableForId(i.next()); if (!black.contains(var)) { black.add(var); dfsg_visit(var); } } black = new TreeSet(); for (Iterator i = finished.iterator(); i.hasNext(); ) { TypeVariableBV var = (TypeVariableBV) i.next(); if (!black.contains(var)) { current_tree = new LinkedList(); forest.add(current_tree); black.add(var); dfsgt_visit(var); } } for (Iterator i = forest.iterator(); i.hasNext(); ) { LinkedList list = (LinkedList) i.next(); TypeVariableBV previous = null; StringBuffer s = null; if (DEBUG) { s = new StringBuffer("scc:\n"); } for (Iterator j = list.iterator(); j.hasNext(); ) { TypeVariableBV current = (TypeVariableBV) j.next(); if (DEBUG) { s.append(" " + current + "\n"); } if (previous == null) { previous = current; } else { try { previous = previous.union(current); } catch (TypeException e) { if (DEBUG) { G.v().out.println(s); } throw e; } } } } }
public TypeNode(int id, Type type) { this.id = id; this.type = type; if (DEBUG) { G.v().out.println("creating node " + this); } }
/** * Performs the work that is required to construct any sort of <tt>UnitGraph</tt>. * * @param body The body of the method for which to construct a control flow graph. */ protected UnitGraph(Body body) { this.body = body; unitChain = body.getUnits(); method = body.getMethod(); if (Options.v().verbose()) G.v() .out .println( "[" + method.getName() + "] Constructing " + this.getClass().getName() + "..."); }
/** * Traverse the statements in the given body, looking for aggregation possibilities; that is, * given a def d and a use u, d has no other uses, u has no other defs, collapse d and u. * * <p>option: only-stack-locals; if this is true, only aggregate variables starting with $ */ protected void internalTransform(Body b, String phaseName, Map<String, String> options) { StmtBody body = (StmtBody) b; boolean onlyStackVars = PhaseOptions.getBoolean(options, "only-stack-locals"); int aggregateCount = 1; if (Options.v().time()) Timers.v().aggregationTimer.start(); boolean changed = false; Map<ValueBox, Zone> boxToZone = new HashMap<ValueBox, Zone>(body.getUnits().size() * 2 + 1, 0.7f); // Determine the zone of every box { Zonation zonation = new Zonation(body); for (Unit u : body.getUnits()) { Zone zone = zonation.getZoneOf(u); for (ValueBox box : u.getUseBoxes()) { boxToZone.put(box, zone); } for (ValueBox box : u.getDefBoxes()) { boxToZone.put(box, zone); } } } do { if (Options.v().verbose()) G.v() .out .println( "[" + body.getMethod().getName() + "] Aggregating iteration " + aggregateCount + "..."); // body.printTo(new java.io.PrintWriter(G.v().out, true)); changed = internalAggregate(body, boxToZone, onlyStackVars); aggregateCount++; } while (changed); if (Options.v().time()) Timers.v().aggregationTimer.end(); }
protected void print_cfg(Body body) { DirectedGraph<Unit> graph = graphtype.buildGraph(body); DotGraph canvas = graphtype.drawGraph(drawer, graph, body); String methodname = body.getMethod().getSubSignature(); String filename = soot.SourceLocator.v().getOutputDir(); if (filename.length() > 0) { filename = filename + java.io.File.separator; } filename = filename + methodname.replace(java.io.File.separatorChar, '.') + DotGraph.DOT_EXTENSION; G.v().out.println("Generate dot file in " + filename); canvas.plot(filename); }
private static void usage() { G.v() .out .println( "Usage:\n" + " java soot.util.CFGViewer [soot options] [CFGViewer options] [class[:method]]...\n\n" + " CFGViewer options:\n" + " (When specifying the value for an '=' option, you only\n" + " need to type enough characters to specify the choice\n" + " unambiguously, and case is ignored.)\n" + "\n" + " --alt-classpath PATH :\n" + " specifies the classpath from which to load classes\n" + " that implement graph types whose names begin with 'Alt'.\n" + " --graph={" + CFGGraphType.help(0, 70, " ".length()) + "} :\n" + " show the specified type of graph.\n" + " Defaults to " + defaultGraph + ".\n" + " --ir={" + CFGIntermediateRep.help(0, 70, " ".length()) + "} :\n" + " create the CFG from the specified intermediate\n" + " representation. Defaults to " + defaultIR + ".\n" + " --brief :\n" + " label nodes with the unit or block index,\n" + " instead of the text of their statements.\n" + " --multipages :\n" + " produce dot file output for multiple 8.5x11\" pages.\n" + " By default, a single page is produced.\n" + " --help :\n" + " print this message.\n" + "\n" + " Particularly relevant soot options (see \"soot --help\" for details):\n" + " --soot-class-path PATH\n" + " --show-exception-dests\n" + " --throw-analysis {pedantic|unit}\n" + " --omit-excepting-unit-edges\n" + " --trim-cfgs\n"); }
public void loadDynamicClasses() { dynamicClasses = new ArrayList<SootClass>(); HashSet<String> dynClasses = new HashSet<String>(); dynClasses.addAll(Options.v().dynamic_class()); for (Iterator<String> pathIt = Options.v().dynamic_dir().iterator(); pathIt.hasNext(); ) { final String path = (String) pathIt.next(); dynClasses.addAll(SourceLocator.v().getClassesUnder(path)); } for (Iterator<String> pkgIt = Options.v().dynamic_package().iterator(); pkgIt.hasNext(); ) { final String pkg = (String) pkgIt.next(); dynClasses.addAll(SourceLocator.v().classesInDynamicPackage(pkg)); } for (String className : dynClasses) { dynamicClasses.add(loadClassAndSupport(className)); } // remove non-concrete classes that may accidentally have been loaded for (Iterator<SootClass> iterator = dynamicClasses.iterator(); iterator.hasNext(); ) { SootClass c = iterator.next(); if (!c.isConcrete()) { if (Options.v().verbose()) { G.v() .out .println( "Warning: dynamic class " + c.getName() + " is abstract or an interface, and it will not be considered."); } iterator.remove(); } } }
/** * Computes the analysis given a UnitGraph computed from a method body. It is recommended that a * ExceptionalUnitGraph (or similar) be provided for correct results in the case of exceptional * control flow. * * @param g a graph on which to compute the analysis. * @see ExceptionalUnitGraph */ public SimpleLiveLocals(UnitGraph graph) { if (Options.v().time()) Timers.v().liveTimer.start(); if (Options.v().verbose()) G.v() .out .println( "[" + graph.getBody().getMethod().getName() + "] Constructing SimpleLiveLocals..."); SimpleLiveLocalsAnalysis analysis = new SimpleLiveLocalsAnalysis(graph); if (Options.v().time()) Timers.v().livePostTimer.start(); // Build unitToLocals map { unitToLocalsAfter = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f); unitToLocalsBefore = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f); Iterator unitIt = graph.iterator(); while (unitIt.hasNext()) { Unit s = (Unit) unitIt.next(); FlowSet set = (FlowSet) analysis.getFlowBefore(s); unitToLocalsBefore.put(s, Collections.unmodifiableList(set.toList())); set = (FlowSet) analysis.getFlowAfter(s); unitToLocalsAfter.put(s, Collections.unmodifiableList(set.toList())); } } if (Options.v().time()) Timers.v().livePostTimer.end(); if (Options.v().time()) Timers.v().liveTimer.end(); }
protected void internalTransform(String phaseName, Map options) { if (Options.v().verbose()) G.v().out.println("Transforming all classes in the Scene to Shimple..."); // *** FIXME: Add debug output to indicate which class/method is being shimplified. // *** FIXME: Is ShimpleTransformer the right solution? The call graph may deem // some classes unreachable. Iterator classesIt = Scene.v().getClasses().iterator(); while (classesIt.hasNext()) { SootClass sClass = (SootClass) classesIt.next(); if (sClass.isPhantom()) continue; Iterator methodsIt = sClass.getMethods().iterator(); while (methodsIt.hasNext()) { SootMethod method = (SootMethod) methodsIt.next(); if (!method.isConcrete()) continue; if (method.hasActiveBody()) { Body body = method.getActiveBody(); ShimpleBody sBody = null; if (body instanceof ShimpleBody) { sBody = (ShimpleBody) body; if (!sBody.isSSA()) sBody.rebuild(); } else { sBody = Shimple.v().newBody(body); } method.setActiveBody(sBody); } else { MethodSource ms = new ShimpleMethodSource(method.getSource()); method.setSource(ms); } } } }
public static LineNumberAdder v() { return G.v().soot_jimple_toolkits_annotation_LineNumberAdder(); }
public static NullType v() { return G.v().soot_NullType(); }
public static ShimpleTransformer v() { return G.v().soot_shimple_ShimpleTransformer(); }
public String defaultClassPath() { StringBuffer sb = new StringBuffer(); if (System.getProperty("os.name").equals("Mac OS X")) { // in older Mac OS X versions, rt.jar was split into classes.jar and ui.jar sb.append(System.getProperty("java.home")); sb.append(File.separator); sb.append(".."); sb.append(File.separator); sb.append("Classes"); sb.append(File.separator); sb.append("classes.jar"); sb.append(File.pathSeparator); sb.append(System.getProperty("java.home")); sb.append(File.separator); sb.append(".."); sb.append(File.separator); sb.append("Classes"); sb.append(File.separator); sb.append("ui.jar"); sb.append(File.pathSeparator); } sb.append(System.getProperty("java.home")); sb.append(File.separator); sb.append("lib"); sb.append(File.separator); sb.append("rt.jar"); if (Options.v().whole_program() || Options.v().output_format() == Options.output_format_dava) { // add jce.jar, which is necessary for whole program mode // (java.security.Signature from rt.jar import javax.crypto.Cipher from jce.jar sb.append( File.pathSeparator + System.getProperty("java.home") + File.separator + "lib" + File.separator + "jce.jar"); } String defaultClassPath = sb.toString(); if (Options.v().src_prec() == Options.src_prec_apk) { // check that android.jar is not in classpath if (!defaultClassPath.contains("android.jar")) { String androidJars = Options.v().android_jars(); String forceAndroidJar = Options.v().force_android_jar(); if ((androidJars == null || androidJars.equals("")) && (forceAndroidJar == null || forceAndroidJar.equals(""))) { throw new RuntimeException( "You are analyzing an Android application but did not define android.jar. Options -android-jars or -force-android-jar should be used."); } String jarPath = ""; if (forceAndroidJar != null && !forceAndroidJar.equals("")) { jarPath = forceAndroidJar; } else if (androidJars != null && !androidJars.equals("")) { List<String> classPathEntries = new LinkedList<String>( Arrays.asList(Options.v().soot_classpath().split(File.pathSeparator))); classPathEntries.addAll(Options.v().process_dir()); Set<String> targetApks = new HashSet<String>(); for (String entry : classPathEntries) { if (entry.toLowerCase().endsWith(".apk") || entry .toLowerCase() .endsWith(".dex")) // on Windows, file names are case-insensitive targetApks.add(entry); } if (targetApks.size() == 0) throw new RuntimeException("no apk file given"); else if (targetApks.size() > 1) throw new RuntimeException( "only one Android application can be analyzed when using option -android-jars."); jarPath = getAndroidJarPath(androidJars, (String) targetApks.toArray()[0]); } if (jarPath.equals("")) throw new RuntimeException("android.jar not found."); File f = new File(jarPath); if (!f.exists()) throw new RuntimeException("file '" + jarPath + "' does not exist!"); else G.v().out.println("Using '" + jarPath + "' as android.jar"); defaultClassPath = jarPath + File.pathSeparator + defaultClassPath; } else { G.v() .out .println( "warning: defaultClassPath contains android.jar! Options -android-jars and -force-android-jar are ignored!"); } } return defaultClassPath; }
protected ReferenceVariable tempVariableImpl() { return pag.makeGlobalVarNode( new Pair("TempVar", new Integer(++G.v().SparkNativeHelper_tempVar)), RefType.v("java.lang.Object")); }
public static Scene v() { return G.v().soot_Scene(); }
/** * This method pushes all newExpr down to be the stmt directly before every invoke of the init * only if they are in the types list */ public void internalTransform(Body b, String phaseName, Map options) { JimpleBody body = (JimpleBody) b; if (Options.v().verbose()) G.v().out.println("[" + body.getMethod().getName() + "] Folding Jimple constructors..."); Chain units = body.getUnits(); List<Unit> stmtList = new ArrayList<Unit>(); stmtList.addAll(units); Iterator<Unit> it = stmtList.iterator(); Iterator<Unit> nextStmtIt = stmtList.iterator(); // start ahead one nextStmtIt.next(); SmartLocalDefs localDefs = SmartLocalDefsPool.v().getSmartLocalDefsFor(body); UnitGraph graph = localDefs.getGraph(); LocalUses localUses = new SimpleLocalUses(graph, localDefs); /* fold in NewExpr's with specialinvoke's */ while (it.hasNext()) { Stmt s = (Stmt) it.next(); if (!(s instanceof AssignStmt)) continue; /* this should be generalized to ArrayRefs */ // only deal with stmts that are an local = newExpr Value lhs = ((AssignStmt) s).getLeftOp(); if (!(lhs instanceof Local)) continue; Value rhs = ((AssignStmt) s).getRightOp(); if (!(rhs instanceof NewExpr)) continue; // check if very next statement is invoke --> // this indicates there is no control flow between // new and invoke and should do nothing if (nextStmtIt.hasNext()) { Stmt next = (Stmt) nextStmtIt.next(); if (next instanceof InvokeStmt) { InvokeStmt invoke = (InvokeStmt) next; if (invoke.getInvokeExpr() instanceof SpecialInvokeExpr) { SpecialInvokeExpr invokeExpr = (SpecialInvokeExpr) invoke.getInvokeExpr(); if (invokeExpr.getBase() == lhs) { break; } } } } // check if new is in the types list - only process these if (!types.contains(((NewExpr) rhs).getType())) continue; List lu = localUses.getUsesOf(s); Iterator luIter = lu.iterator(); boolean MadeNewInvokeExpr = false; while (luIter.hasNext()) { Unit use = ((UnitValueBoxPair) (luIter.next())).unit; if (!(use instanceof InvokeStmt)) continue; InvokeStmt is = (InvokeStmt) use; if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr) || lhs != ((SpecialInvokeExpr) is.getInvokeExpr()).getBase()) continue; // make a new one here AssignStmt constructStmt = Jimple.v() .newAssignStmt(((DefinitionStmt) s).getLeftOp(), ((DefinitionStmt) s).getRightOp()); constructStmt.setRightOp(Jimple.v().newNewExpr(((NewExpr) rhs).getBaseType())); MadeNewInvokeExpr = true; // redirect jumps use.redirectJumpsToThisTo(constructStmt); // insert new one here units.insertBefore(constructStmt, use); constructStmt.addTag(s.getTag("SourceLnPosTag")); } if (MadeNewInvokeExpr) { units.remove(s); } } }
public static Printer v() { return G.v().soot_Printer(); }
public static Integer1Type v() { return G.v().soot_jimple_toolkits_typing_fast_Integer1Type(); }
public static Aggregator v() { return G.v().soot_jimple_toolkits_base_Aggregator(); }
public static DumbPointerAnalysis v() { return G.v().soot_jimple_toolkits_pointer_DumbPointerAnalysis(); }
/** * Returns the single instance of <code>ThrowableSet.Manager</code>. * * @return Soot's <code>ThrowableSet.Manager</code>. */ public static Manager v() { return G.v().soot_toolkits_exceptions_ThrowableSet_Manager(); }
protected ReferenceVariable tempLocalVariableImpl(SootMethod method) { return pag.makeLocalVarNode( new Pair("TempVar", new Integer(++G.v().SparkNativeHelper_tempVar)), RefType.v("java.lang.Object"), method); }
/* file = modifier* file_type class_name extends_clause? implements_clause? file_body; */ public void inAFile(AFile node) { if (debug) G.v().out.println("reading class " + node.getClassName()); }
public static DavaStaticBlockCleaner v() { return G.v().soot_dava_DavaStaticBlockCleaner(); }
private int getTargetSDKVersion(String apkFile, String platformJARs) { // get AndroidManifest InputStream manifestIS = null; ZipFile archive = null; try { try { archive = new ZipFile(apkFile); for (Enumeration<? extends ZipEntry> entries = archive.entries(); entries.hasMoreElements(); ) { ZipEntry entry = entries.nextElement(); String entryName = entry.getName(); // We are dealing with the Android manifest if (entryName.equals("AndroidManifest.xml")) { manifestIS = archive.getInputStream(entry); break; } } } catch (Exception e) { throw new RuntimeException("Error when looking for manifest in apk: " + e); } if (manifestIS == null) { G.v() .out .println( "Could not find sdk version in Android manifest! Using default: " + defaultSdkVersion); return defaultSdkVersion; } // process AndroidManifest.xml int maxAPI = getMaxAPIAvailable(platformJARs); int sdkTargetVersion = -1; int minSdkVersion = -1; try { AXmlResourceParser parser = new AXmlResourceParser(); parser.open(manifestIS); int depth = 0; loop: while (true) { int type = parser.next(); switch (type) { case XmlPullParser.START_DOCUMENT: { break; } case XmlPullParser.END_DOCUMENT: break loop; case XmlPullParser.START_TAG: { depth++; String tagName = parser.getName(); if (depth == 2 && tagName.equals("uses-sdk")) { for (int i = 0; i != parser.getAttributeCount(); ++i) { String attributeName = parser.getAttributeName(i); String attributeValue = AXMLPrinter.getAttributeValue(parser, i); if (attributeName.equals("targetSdkVersion")) { sdkTargetVersion = Integer.parseInt(attributeValue); } else if (attributeName.equals("minSdkVersion")) { minSdkVersion = Integer.parseInt(attributeValue); } } } break; } case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.TEXT: break; } } } catch (Exception e) { e.printStackTrace(); } int APIVersion = -1; if (sdkTargetVersion != -1) { if (sdkTargetVersion > maxAPI && minSdkVersion != -1 && minSdkVersion <= maxAPI) { G.v() .out .println( "warning: Android API version '" + sdkTargetVersion + "' not available, using minApkVersion '" + minSdkVersion + "' instead"); APIVersion = minSdkVersion; } else { APIVersion = sdkTargetVersion; } } else if (minSdkVersion != -1) { APIVersion = minSdkVersion; } else { G.v() .out .println( "Could not find sdk version in Android manifest! Using default: " + defaultSdkVersion); APIVersion = defaultSdkVersion; } if (APIVersion <= 2) APIVersion = 3; return APIVersion; } finally { if (archive != null) try { archive.close(); } catch (IOException e) { throw new RuntimeException("Error when looking for manifest in apk: " + e); } } }