/** * 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); }
/** 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 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); }
/** * 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); }
/** 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); }
/** 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; }
/** 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))); } } }
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(); }