/** * Given an abstract dispatch to an object of type c and a method m, gives a list of possible * receiver methods. */ public List resolveAbstractDispatch(SootClass c, SootMethod m) { c.checkLevel(SootClass.HIERARCHY); m.getDeclaringClass().checkLevel(SootClass.HIERARCHY); checkState(); Iterator<SootClass> classesIt = null; if (c.isInterface()) { classesIt = getImplementersOf(c).iterator(); HashSet<SootClass> classes = new HashSet<SootClass>(); while (classesIt.hasNext()) classes.addAll(getSubclassesOfIncluding(classesIt.next())); classesIt = classes.iterator(); } else classesIt = getSubclassesOfIncluding(c).iterator(); ArraySet s = new ArraySet(); while (classesIt.hasNext()) { SootClass cl = classesIt.next(); if (Modifier.isAbstract(cl.getModifiers())) continue; s.add(resolveConcreteDispatch(cl, m)); } List l = new ArrayList(); l.addAll(s); return Collections.unmodifiableList(l); }
public void staticBlockInlining(SootClass sootClass) { this.sootClass = sootClass; // retrieve the clinit method if any for sootClass if (!sootClass.declaresMethod("void <clinit>()")) { System.out.println("no clinit"); return; } SootMethod clinit = sootClass.getMethod("void <clinit>()"); // System.out.println(clinit); // retireve the active body if (!clinit.hasActiveBody()) throw new RuntimeException("method " + clinit.getName() + " has no active body!"); Body clinitBody = clinit.getActiveBody(); Chain units = ((DavaBody) clinitBody).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode AST = (ASTNode) units.getFirst(); if (!(AST instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); AST.apply(new MethodCallFinder(this)); }
/** Returns a list of direct subinterfaces of c. */ public List getDirectSubinterfacesOf(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (!c.isInterface()) throw new RuntimeException("interface needed!"); checkState(); return interfaceToDirSubinterfaces.get(c); }
/** Returns a list of direct implementers of c, excluding itself. */ public List getDirectImplementersOf(SootClass i) { i.checkLevel(SootClass.HIERARCHY); if (!i.isInterface()) throw new RuntimeException("interface needed; got " + i); checkState(); return Collections.unmodifiableList(interfaceToDirImplementers.get(i)); }
/** Returns a list of direct subclasses of c, excluding c. */ public List getDirectSubclassesOf(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (c.isInterface()) throw new RuntimeException("class needed!"); checkState(); return Collections.unmodifiableList(classToDirSubclasses.get(c)); }
/** Returns a list of subinterfaces of c, including itself. */ public List<SootClass> getSubinterfacesOfIncluding(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (!c.isInterface()) throw new RuntimeException("interface needed!"); List<SootClass> l = new ArrayList<SootClass>(); l.addAll(getSubinterfacesOf(c)); l.add(c); return Collections.unmodifiableList(l); }
/** Returns a list of direct subclasses of c, including c. */ public List<SootClass> getDirectSubclassesOfIncluding(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (c.isInterface()) throw new RuntimeException("class needed!"); checkState(); List<SootClass> l = new ArrayList<SootClass>(); l.addAll(classToDirSubclasses.get(c)); l.add(c); return Collections.unmodifiableList(l); }
/** Returns true if the method m is visible from code in the class from. */ public boolean isVisible(SootClass from, SootMethod m) { from.checkLevel(SootClass.HIERARCHY); m.getDeclaringClass().checkLevel(SootClass.HIERARCHY); if (m.isPublic()) return true; if (m.isPrivate()) { return from.equals(m.getDeclaringClass()); } if (m.isProtected()) { return isClassSubclassOfIncluding(from, m.getDeclaringClass()); } // m is package return from.getJavaPackageName().equals(m.getDeclaringClass().getJavaPackageName()); // || isClassSubclassOfIncluding( from, m.getDeclaringClass() ); }
/** Returns a list of superclasses of c, including itself. */ public List<SootClass> getSuperclassesOfIncluding(SootClass c) { c.checkLevel(SootClass.HIERARCHY); List<SootClass> l = getSuperclassesOf(c); ArrayList<SootClass> al = new ArrayList<SootClass>(); al.add(c); al.addAll(l); return Collections.unmodifiableList(al); }
// This method is deprecated. Use soot.util.JasminOutputStream instead. public void writeXXXDeprecated(SootClass cl, String outputDir) { String outputDirWithSep = ""; if (!outputDir.equals("")) outputDirWithSep = outputDir + fileSeparator; try { File tempFile = new File(outputDirWithSep + cl.getName() + ".jasmin"); FileOutputStream streamOut = new FileOutputStream(tempFile); PrintWriter writerOut = new PrintWriter(new EscapedWriter(new OutputStreamWriter(streamOut))); if (cl.containsBafBody()) new soot.baf.JasminClass(cl).print(writerOut); else new soot.jimple.JasminClass(cl).print(writerOut); writerOut.close(); if (Options.v().time()) Timers.v().assembleJasminTimer.start(); // Invoke jasmin { String[] args; if (outputDir.equals("")) { args = new String[1]; args[0] = cl.getName() + ".jasmin"; } else { args = new String[3]; args[0] = "-d"; args[1] = outputDir; args[2] = outputDirWithSep + cl.getName() + ".jasmin"; } jasmin.Main.main(args); } tempFile.delete(); if (Options.v().time()) Timers.v().assembleJasminTimer.end(); } catch (IOException e) { throw new RuntimeException("Could not produce new classfile! (" + e + ")"); } }
public static void main(String args[]) { // Set classPath String exemplePath = "/Users/gamyot/Documents/workspace/Soot_Exemples/src/"; String objectPath = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar"; String tracePath = "/Users/gamyot/Documents/workspace/SootInstrumenter/src/"; Scene.v().setSootClassPath(".:" + objectPath + ":" + exemplePath + ":" + tracePath); Scene.v().loadClassAndSupport("java.lang.Object"); Scene.v().loadClassAndSupport("java.lang.System"); // Set up the class we’re working with SootClass c = Scene.v().loadClassAndSupport("MyExemples.ExempleBasic"); c.setApplicationClass(); // Get methods Iterator<SootMethod> methodIterator = c.methodIterator(); while (methodIterator.hasNext()) methodList.add(methodIterator.next()); // Iterate through the method list for (SootMethod m : methodList) { Body body = m.retrieveActiveBody(); PatchingChain<Unit> unitList = body.getUnits(); // get the all the "if statements" Units List<Unit> ifStmtList = searchIfStmts(body); // for each "if statement" unit, instrument and add the instrumentation code right after for (Unit ifStmtUnit : ifStmtList) { // Chain<Unit> instrumentedChain = generateInstrumentationUnits(ifStmtUnit, body); // unitList.insertAfter(instrumentedChain, ifStmtUnit); Chain<Unit> testChain = generateInstrumentationUnits(ifStmtUnit, body); unitList.insertAfter(testChain, ifStmtUnit); } // Output all the units for this method on terminal String methodName = m.getName(); System.out.println( "____Method: \"" + methodName + "\"__________________________________________________"); LoadAndGenerate.printAllUnits(body); } try { LoadAndGenerate.outputClassToBinary(c); } catch (IOException e) { e.printStackTrace(); } }
/** * Given an object of actual type C (o = new C()), returns the method which will be called on an * o.f() invocation. */ public SootMethod resolveConcreteDispatch(SootClass concreteType, SootMethod m) { concreteType.checkLevel(SootClass.HIERARCHY); m.getDeclaringClass().checkLevel(SootClass.HIERARCHY); checkState(); if (concreteType.isInterface()) throw new RuntimeException("class needed!"); Iterator<SootClass> it = getSuperclassesOfIncluding(concreteType).iterator(); String methodSig = m.getSubSignature(); while (it.hasNext()) { SootClass c = it.next(); if (c.declaresMethod(methodSig) && isVisible(c, m)) { return c.getMethod(methodSig); } } throw new RuntimeException( "could not resolve concrete dispatch!\nType: " + concreteType + "\nMethod: " + m); }
/** Returns a list of implementers of c, excluding itself. */ public List<SootClass> getImplementersOf(SootClass i) { i.checkLevel(SootClass.HIERARCHY); if (!i.isInterface()) throw new RuntimeException("interface needed; got " + i); checkState(); Iterator<SootClass> it = getSubinterfacesOfIncluding(i).iterator(); ArraySet set = new ArraySet(); while (it.hasNext()) { SootClass c = it.next(); set.addAll(getDirectImplementersOf(c)); } ArrayList l = new ArrayList(); l.addAll(set); return Collections.unmodifiableList(l); }
public void caseAFile(AFile node) { inAFile(node); { Object temp[] = node.getModifier().toArray(); for (int i = 0; i < temp.length; i++) { ((PModifier) temp[i]).apply(this); } } if (node.getFileType() != null) { node.getFileType().apply(this); } if (node.getClassName() != null) { node.getClassName().apply(this); } String className = (String) mProductions.removeLast(); if (mSootClass == null) { mSootClass = new SootClass(className); mSootClass.setResolvingLevel(SootClass.BODIES); } else { if (!mSootClass.getName().equals(className)) throw new RuntimeException( "Invalid SootClass for this JimpleAST. The SootClass provided is of type: >" + mSootClass.getName() + "< whereas this parse tree is for type: >" + className + "<"); } if (node.getExtendsClause() != null) { node.getExtendsClause().apply(this); } if (node.getImplementsClause() != null) { node.getImplementsClause().apply(this); } if (node.getFileBody() != null) { node.getFileBody().apply(this); } outAFile(node); }
/** Returns a list of subinterfaces of c, excluding itself. */ public List<SootClass> getSubinterfacesOf(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (!c.isInterface()) throw new RuntimeException("interface needed!"); checkState(); // If already cached, return the value. if (interfaceToSubinterfaces.get(c) != null) return interfaceToSubinterfaces.get(c); // Otherwise, build up the hashmap. List<SootClass> l = new ArrayList<SootClass>(); ListIterator it = interfaceToDirSubinterfaces.get(c).listIterator(); while (it.hasNext()) { l.addAll(getSubinterfacesOfIncluding((SootClass) it.next())); } interfaceToSubinterfaces.put(c, Collections.unmodifiableList(l)); return Collections.unmodifiableList(l); }
/* member = {field} modifier* type name semicolon | {method} modifier* type name l_paren parameter_list? r_paren throws_clause? method_body; */ public void outAFieldMember(AFieldMember node) { int modifier = 0; Type type = null; String name = null; name = (String) mProductions.removeLast(); type = (Type) mProductions.removeLast(); modifier = processModifiers(node.getModifier()); SootField f = new SootField(name, type, modifier); mSootClass.addField(f); }
public void outAFile(AFile node) { // not not pop members; they have been taken care of. List implementsList = null; String superClass = null; String classType = null; if (node.getImplementsClause() != null) { implementsList = (List) mProductions.removeLast(); } if (node.getExtendsClause() != null) { superClass = (String) mProductions.removeLast(); } classType = (String) mProductions.removeLast(); int modifierCount = node.getModifier().size(); int modifierFlags = processModifiers(node.getModifier()); if (classType.equals("interface")) modifierFlags |= Modifier.INTERFACE; mSootClass.setModifiers(modifierFlags); if (superClass != null) { mSootClass.setSuperclass(mResolver.makeClassRef(superClass)); } if (implementsList != null) { Iterator implIt = implementsList.iterator(); while (implIt.hasNext()) { SootClass interfaceClass = mResolver.makeClassRef((String) implIt.next()); mSootClass.addInterface(interfaceClass); } } mProductions.addLast(mSootClass); }
/** Returns a list of subclasses of c, excluding itself. */ public List<SootClass> getSubclassesOf(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (c.isInterface()) throw new RuntimeException("class needed!"); checkState(); // If already cached, return the value. if (classToSubclasses.get(c) != null) return classToSubclasses.get(c); // Otherwise, build up the hashmap. List<SootClass> l = new ArrayList<SootClass>(); ListIterator it = classToDirSubclasses.get(c).listIterator(); while (it.hasNext()) { SootClass cls = (SootClass) it.next(); if (cls.resolvingLevel() < SootClass.HIERARCHY) continue; l.addAll(getSubclassesOfIncluding(cls)); } l = Collections.unmodifiableList(l); classToSubclasses.put(c, l); return l; }
public ASTMethodNode inline(SootMethod maybeInline) { // check if this method should be inlined if (sootClass != null) { // 1, method should belong to the same class as the clinit method if (sootClass.declaresMethod(maybeInline.getSubSignature())) { // System.out.println("The method invoked is from the same class"); // 2, method should be static if (Modifier.isStatic(maybeInline.getModifiers())) { // decided to inline // send the ASTMethod node of the TO BE INLINED METHOD // retireve the active body if (!maybeInline.hasActiveBody()) throw new RuntimeException("method " + maybeInline.getName() + " has no active body!"); Body bod = maybeInline.getActiveBody(); Chain units = ((DavaBody) bod).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode ASTtemp = (ASTNode) units.getFirst(); if (!(ASTtemp instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); // restricting to methods which do not have any variables declared ASTMethodNode toReturn = (ASTMethodNode) ASTtemp; ASTStatementSequenceNode declarations = toReturn.getDeclarations(); if (declarations.getStatements().size() == 0) { // inline only if there are no declarations in the method inlined System.out.println("No declarations in the method. we can inline this method"); return toReturn; } } } } return null; // meaning dont inline }
public void outAMethodMember(AMethodMember node) { int modifier = 0; Type type; String name; List parameterList = null; List throwsClause = null; JimpleBody methodBody = null; if (node.getMethodBody() instanceof AFullMethodBody) methodBody = (JimpleBody) mProductions.removeLast(); if (node.getThrowsClause() != null) throwsClause = (List) mProductions.removeLast(); if (node.getParameterList() != null) { parameterList = (List) mProductions.removeLast(); } else { parameterList = new ArrayList(); } Object o = mProductions.removeLast(); name = (String) o; type = (Type) mProductions.removeLast(); modifier = processModifiers(node.getModifier()); SootMethod method; if (throwsClause != null) method = new SootMethod(name, parameterList, type, modifier, throwsClause); else method = new SootMethod(name, parameterList, type, modifier); mSootClass.addMethod(method); if (method.isConcrete()) { methodBody.setMethod(method); method.setActiveBody(methodBody); } else if (node.getMethodBody() instanceof AFullMethodBody) throw new RuntimeException("Impossible: !concrete => ! instanceof"); }
/** Returns a list of strict superclasses of c, starting with c's parent. */ public List<SootClass> getSuperclassesOf(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (c.isInterface()) throw new RuntimeException("class needed!"); checkState(); ArrayList<SootClass> l = new ArrayList<SootClass>(); SootClass cl = c; while (cl.hasSuperclass()) { l.add(cl.getSuperclass()); cl = cl.getSuperclass(); } return Collections.unmodifiableList(l); }
/** Constructs a hierarchy from the current scene. */ public Hierarchy() { this.sc = Scene.v(); state = sc.getState(); // Well, this used to be describable by 'Duh'. // Construct the subclasses hierarchy and the subinterfaces hierarchy. { Chain allClasses = sc.getClasses(); classToSubclasses = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f); interfaceToSubinterfaces = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f); classToDirSubclasses = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); interfaceToDirSubinterfaces = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); interfaceToDirImplementers = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); Iterator classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { interfaceToDirSubinterfaces.put(c, new ArrayList()); interfaceToDirImplementers.put(c, new ArrayList()); } else classToDirSubclasses.put(c, new ArrayList()); } classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.hasSuperclass()) { if (c.isInterface()) { Iterator subIt = c.getInterfaces().iterator(); while (subIt.hasNext()) { SootClass i = (SootClass) subIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; List<SootClass> l = interfaceToDirSubinterfaces.get(i); l.add(c); } } else { List<SootClass> l = classToDirSubclasses.get(c.getSuperclass()); l.add(c); Iterator subIt = c.getInterfaces().iterator(); while (subIt.hasNext()) { SootClass i = (SootClass) subIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; l = interfaceToDirImplementers.get(i); l.add(c); } } } } // Fill the directImplementers lists with subclasses. { classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { List<SootClass> imp = interfaceToDirImplementers.get(c); Set<SootClass> s = new ArraySet(); Iterator<SootClass> impIt = imp.iterator(); while (impIt.hasNext()) { SootClass c0 = impIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; s.addAll(getSubclassesOfIncluding(c0)); } imp.clear(); imp.addAll(s); } } } classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { interfaceToDirSubinterfaces.put( c, Collections.unmodifiableList(interfaceToDirSubinterfaces.get(c))); interfaceToDirImplementers.put( c, Collections.unmodifiableList(interfaceToDirImplementers.get(c))); } else classToDirSubclasses.put(c, Collections.unmodifiableList(classToDirSubclasses.get(c))); } } }
/** Returns the most specific type which is an ancestor of both c1 and c2. */ public SootClass getLeastCommonSuperclassOf(SootClass c1, SootClass c2) { c1.checkLevel(SootClass.HIERARCHY); c2.checkLevel(SootClass.HIERARCHY); throw new RuntimeException("Not implemented yet!"); }
/** Returns true if child is a direct subinterface of possibleParent. */ public boolean isInterfaceDirectSubinterfaceOf(SootClass child, SootClass possibleParent) { child.checkLevel(SootClass.HIERARCHY); possibleParent.checkLevel(SootClass.HIERARCHY); return getDirectSubinterfacesOf(possibleParent).contains(child); }
/** Returns true if parent is, or is a superclass of, possibleChild. */ public boolean isClassSuperclassOfIncluding(SootClass parent, SootClass possibleChild) { parent.checkLevel(SootClass.HIERARCHY); possibleChild.checkLevel(SootClass.HIERARCHY); return getSubclassesOfIncluding(parent).contains(possibleChild); }
/** Returns true if child is a subclass of possibleParent. */ public boolean isClassSubclassOf(SootClass child, SootClass possibleParent) { child.checkLevel(SootClass.HIERARCHY); possibleParent.checkLevel(SootClass.HIERARCHY); return getSuperclassesOf(child).contains(possibleParent); }
public void printTo(SootClass cl, PrintWriter out) { // add jimple line number tags setJimpleLnNum(1); // Print class name + modifiers { StringTokenizer st = new StringTokenizer(Modifier.toString(cl.getModifiers())); while (st.hasMoreTokens()) { String tok = (String) st.nextToken(); if (cl.isInterface() && tok.equals("abstract")) continue; out.print(tok + " "); } String classPrefix = ""; if (!cl.isInterface()) { classPrefix = classPrefix + " class"; classPrefix = classPrefix.trim(); } out.print(classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + ""); } // Print extension { if (cl.hasSuperclass()) out.print(" extends " + Scene.v().quotedNameOf(cl.getSuperclass().getName()) + ""); } // Print interfaces { Iterator interfaceIt = cl.getInterfaces().iterator(); if (interfaceIt.hasNext()) { out.print(" implements "); out.print("" + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); while (interfaceIt.hasNext()) { out.print(","); out.print(" " + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); } } } out.println(); incJimpleLnNum(); /* if (!addJimpleLn()) { Iterator clTagsIt = cl.getTags().iterator(); while (clTagsIt.hasNext()) { final Tag t = (Tag)clTagsIt.next(); out.println(t); } }*/ out.println("{"); incJimpleLnNum(); if (Options.v().print_tags_in_output()) { Iterator cTagIterator = cl.getTags().iterator(); while (cTagIterator.hasNext()) { Tag t = (Tag) cTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } // Print fields { Iterator fieldIt = cl.getFields().iterator(); if (fieldIt.hasNext()) { while (fieldIt.hasNext()) { SootField f = (SootField) fieldIt.next(); if (f.isPhantom()) continue; if (Options.v().print_tags_in_output()) { Iterator fTagIterator = f.getTags().iterator(); while (fTagIterator.hasNext()) { Tag t = (Tag) fTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.println(" " + f.getDeclaration() + ";"); if (addJimpleLn()) { setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f)); } // incJimpleLnNum(); } } } // Print methods { Iterator methodIt = cl.methodIterator(); if (methodIt.hasNext()) { if (cl.getMethodCount() != 0) { out.println(); incJimpleLnNum(); } while (methodIt.hasNext()) { SootMethod method = (SootMethod) methodIt.next(); if (method.isPhantom()) continue; if (!Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers())) { if (!method.hasActiveBody()) throw new RuntimeException("method " + method.getName() + " has no active body!"); else if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } printTo(method.getActiveBody(), out); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } else { if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.print(" "); out.print(method.getDeclaration()); out.println(";"); incJimpleLnNum(); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } } } } out.println("}"); incJimpleLnNum(); }