protected boolean isClassLoaded(SootClass sc) { return sc.resolvingLevel() >= SootClass.SIGNATURES; }
protected void addToResolveWorklist(SootClass sc, int desiredLevel) { if (sc.resolvingLevel() >= desiredLevel) { return; } worklist[desiredLevel].add(sc); }
/** * Returns the list of SootClasses that have been resolved at least to the level specified. */ public List<SootClass> getClasses(int desiredLevel) { List<SootClass> ret = new ArrayList<SootClass>(); for (Iterator<SootClass> clIt = getClasses().iterator(); clIt.hasNext();) { final SootClass cl = clIt.next(); if (cl.resolvingLevel() >= desiredLevel) { ret.add(cl); } } return ret; }
/** 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>(); for (SootClass cls : classToDirSubclasses.get(c)) { if (cls.resolvingLevel() < SootClass.HIERARCHY) { continue; } l.addAll(getSubclassesOfIncluding(cls)); } l = Collections.unmodifiableList(l); classToSubclasses.put(c, l); return l; }
/** * Hierarchy - we know the hierarchy of the class and that's it requires at least Hierarchy for all supertypes and * enclosing types. */ protected void bringToHierarchy(SootClass sc) { if (sc.resolvingLevel() >= SootClass.HIERARCHY) { return; } if (Options.v().debug_resolver()) { logger.debug("bringing to HIERARCHY: " + sc); } sc.setResolvingLevel(SootClass.HIERARCHY); bringToHierarchyUnchecked(sc); }
public static boolean isUnresolved(Type type) { if (type instanceof ArrayType) { ArrayType at = (ArrayType) type; type = at.getArrayElementType(); } if (!(type instanceof RefType)) { return false; } RefType rt = (RefType) type; if (!rt.hasSootClass()) { return true; } SootClass cl = rt.getSootClass(); return cl.resolvingLevel() < SootClass.HIERARCHY; }
/** * Checks if the class has at lease the resolving level specified. This check ignores the resolution completeness. * * @param level * the resolution level, one of DANGLING, HIERARCHY, SIGNATURES, and BODIES * @throws java.lang.RuntimeException * if the resolution is at an insufficient level */ public void checkLevelIgnoreResolving(int level) { int currentLevel = resolvingLevel(); if (currentLevel < level) { String hint = "\nIf you are extending Soot, try to add the following call before calling soot.Main.main(..):\n" + "Scene.v().addBasicClass(" + getName() + "," + levelToString(level) + ");\n" + "Otherwise, try whole-program mode (-w)."; throw new RuntimeException("This operation requires resolving level " + levelToString(level) + " but " + name + " is at resolving level " + levelToString(currentLevel) + hint); } }
public void reResolve(SootClass cl, int newResolvingLevel) { int resolvingLevel = cl.resolvingLevel(); if (resolvingLevel >= newResolvingLevel) { return; } reResolveHierarchy(cl, SootClass.HIERARCHY); cl.setResolvingLevel(newResolvingLevel); addToResolveWorklist(cl, resolvingLevel); processResolveWorklist(); }
/** * Signatures - we know the signatures of all methods and fields requires at least Hierarchy for all referred to types in * these signatures. */ protected void bringToSignatures(SootClass sc) { if (sc.resolvingLevel() >= SootClass.SIGNATURES) { return; } bringToHierarchy(sc); if (Options.v().debug_resolver()) { logger.debug("bringing to SIGNATURES: " + sc); } sc.setResolvingLevel(SootClass.SIGNATURES); bringToSignaturesUnchecked(sc); }
/** * Bodies - we can now start loading the bodies of methods for all referred to methods and fields in the bodies, requires * signatures for the method receiver and field container, and hierarchy for all other classes referenced in method * references. Current implementation does not distinguish between the receiver and other references. Therefore, it is * conservative and brings all of them to signatures. But this could/should be improved. */ protected void bringToBodies(SootClass sc) { if (sc.resolvingLevel() >= SootClass.BODIES) { return; } bringToSignatures(sc); if (Options.v().debug_resolver()) { logger.debug("bringing to BODIES: " + sc); } sc.setResolvingLevel(SootClass.BODIES); bringToBodiesUnchecked(sc); }
@Override protected String getCommonSuperClass(String type1, String type2) { String typeName1 = type1.replace('/', '.'); String typeName2 = type2.replace('/', '.'); SootClass s1 = Scene.v().getSootClass(typeName1); SootClass s2 = Scene.v().getSootClass(typeName2); // If these two classes haven't been loaded yet or are phantom, we take // java.lang.Object as the common superclass final Type mergedType; if (s1.isPhantom() || s2.isPhantom() || s1.resolvingLevel() == SootClass.DANGLING || s2.resolvingLevel() == SootClass.DANGLING) { mergedType = Scene.v().getObjectType(); } else { Type t1 = s1.getType(); Type t2 = s2.getType(); mergedType = t1.merge(t2, Scene.v()); } if (mergedType instanceof RefType) { return slashify(((RefType) mergedType).getClassName()); } else { throw new RuntimeException("Could not find common super class"); } }
/** * Resolves the given class. Depending on the resolver settings, may decide to resolve other classes as well. If the class * has already been resolved, just returns the class that was already resolved. */ public SootClass resolveClass(String className, int desiredLevel) { SootClass resolvedClass = null; try { resolvedClass = makeClassRef(className); addToResolveWorklist(resolvedClass, desiredLevel); processResolveWorklist(); return resolvedClass; } catch (SootClassNotFoundException e) { // remove unresolved class and rethrow if (resolvedClass != null) { assert resolvedClass.resolvingLevel() == SootClass.DANGLING; Scene.v().removeClass(resolvedClass); } throw e; } }
/** * Checks if the class has at lease the resolving level specified. This check does nothing is the class resolution process * is not completed. * * @param level * the resolution level, one of DANGLING, HIERARCHY, SIGNATURES, and BODIES * @throws java.lang.RuntimeException * if the resolution is at an insufficient level */ public void checkLevel(int level) { // Fast check: e.g. FastHierarchy.canStoreClass calls this method quite // often int currentLevel = resolvingLevel(); if (currentLevel >= level) { return; } if (!Scene.v().doneResolving() || Options.v().ignore_resolving_levels()) { return; } checkLevelIgnoreResolving(level); }
private synchronized void ensureClassHasBodies(SootClass cl) { assert Scene.v().hasFastHierarchy(); if (cl.resolvingLevel() < SootClass.BODIES) { Scene.v().forceResolve(cl.getName(), SootClass.BODIES); Scene.v().getOrMakeFastHierarchy(); } assert Scene.v().hasFastHierarchy(); }
@Override public void visit(Node n) { if (n instanceof ClassConstantNode) { ClassConstantNode ccn = (ClassConstantNode) n; Type ccnType = ccn.getClassConstant().toSootType(); // If the referenced class has not been loaded, // we do this now SootClass targetClass = ((RefType) ccnType).getSootClass(); if (targetClass.resolvingLevel() == SootClass.DANGLING) { Scene.v().forceResolve(targetClass.getName(), SootClass.SIGNATURES); } // We can only create alloc nodes for types that // we know edgeTgt.makeP2Set().add(pag.makeAllocNode(edgeSrc.getValue(), ccnType, ccn.getMethod())); varNodeWorkList.add(edgeTgt); } }
if (sootClass.resolvingLevel() < SootClass.BODIES) { continue;
@Override public void visit(Node n) { if (n instanceof ClassConstantNode) { ClassConstantNode ccn = (ClassConstantNode) n; Type ccnType = ccn.getClassConstant().toSootType(); // If the referenced class has not been loaded, we do // this now SootClass targetClass = ((RefType) ccnType).getSootClass(); if (targetClass.resolvingLevel() == SootClass.DANGLING) { Scene.v().forceResolve(targetClass.getName(), SootClass.SIGNATURES); } instance.makeP2Set().add(pag.makeAllocNode(src.getValue(), ccnType, ccn.getMethod())); } }
@Override public void visit(Node n) { if (n instanceof ClassConstantNode) { ClassConstantNode ccn = (ClassConstantNode) n; Type ccnType = ccn.getClassConstant().toSootType(); // If the referenced class has not been loaded, // we do this now SootClass targetClass = ((RefType) ccnType).getSootClass(); if (targetClass.resolvingLevel() == SootClass.DANGLING) { Scene.v().forceResolve(targetClass.getName(), SootClass.SIGNATURES); } edgeTgt.makeP2Set().add(pag.makeAllocNode(edgeSrc.getValue(), ccnType, ccn.getMethod())); addToWorklist(edgeTgt); } }
if (cl.resolvingLevel() < SootClass.HIERARCHY) { continue;
/** * Retrieve the SootMethod equivalent of this method * * @return the SootMethod of this method */ public SootMethod makeSootMethod(final Method method) { int accessFlags = method.getAccessFlags(); // get the name of the method String name = method.getName(); List<SootClass> thrownExceptions = getThrownExceptions(method); List<Type> parameterTypes = getParameterTypes(method); // retrieve the return type of this method Type returnType = DexType.toSoot(method.getReturnType()); // Build soot method by all available parameters SootMethod sm = declaringClass.getMethodUnsafe(name, parameterTypes, returnType); if (sm == null) { sm = Scene.v().makeSootMethod(name, parameterTypes, returnType, accessFlags, thrownExceptions); } // if the method is abstract or native, no code needs to be transformed int flags = method.getAccessFlags(); if (Modifier.isAbstract(flags) || Modifier.isNative(flags)) { return sm; } if (Options.v().oaat() && declaringClass.resolvingLevel() <= SootClass.SIGNATURES) { return sm; } // sets the method source by adding its body as the active body sm.setSource(createMethodSource(method)); return sm; }