1 19 20 package soot.jimple.toolkits.annotation.callgraph; 21 22 import soot.*; 23 import java.util.*; 24 import soot.toolkits.graph.*; 25 import soot.toolkits.scalar.*; 26 import soot.tagkit.*; 27 import soot.jimple.*; 28 import soot.util.queue.*; 29 import soot.jimple.toolkits.callgraph.*; 30 import soot.toolkits.graph.interaction.*; 31 import soot.options.*; 32 33 34 public class CallGraphGrapher extends SceneTransformer 35 { 36 public CallGraphGrapher(Singletons.Global g){} 37 public static CallGraphGrapher v() { return G.v().soot_jimple_toolkits_annotation_callgraph_CallGraphGrapher();} 38 39 private MethodToContexts methodToContexts; 40 private CallGraph cg; 41 private boolean showLibMeths; 42 43 private ArrayList getTgtMethods(SootMethod method, boolean recurse){ 44 if (!method.hasActiveBody()){ 46 return new ArrayList(); 47 } 48 Body b = method.getActiveBody(); 49 ArrayList list = new ArrayList(); 50 Iterator sIt = b.getUnits().iterator(); 51 while (sIt.hasNext()){ 52 Stmt s = (Stmt) sIt.next(); 53 Iterator edges = cg.edgesOutOf(s); 54 while (edges.hasNext()){ 55 Edge e = (Edge)edges.next(); 56 SootMethod sm = e.tgt(); 57 59 if (sm.getDeclaringClass().isLibraryClass()){ 60 if (isShowLibMeths()){ 61 if (recurse){ 62 list.add(new MethInfo(sm, hasTgtMethods(sm) | hasSrcMethods(sm), e.kind())); 63 } 64 else { 65 list.add(new MethInfo(sm, true, e.kind())); 66 } 67 } 68 } 69 else { 70 if (recurse){ 71 list.add(new MethInfo(sm, hasTgtMethods(sm) | hasSrcMethods(sm), e.kind())); 72 } 73 else { 74 list.add(new MethInfo(sm, true, e.kind())); 75 } 76 } 77 } 78 } 79 return list; 80 } 81 82 private boolean hasTgtMethods(SootMethod meth){ 83 ArrayList list = getTgtMethods(meth, false); 84 if (!list.isEmpty()) return true; 85 else return false; 86 } 87 88 private boolean hasSrcMethods(SootMethod meth){ 89 ArrayList list = getSrcMethods(meth, false); 90 if (list.size() > 1) return true; 91 else return false; 92 } 93 94 private ArrayList getSrcMethods(SootMethod method, boolean recurse){ 95 ArrayList list = new ArrayList(); 97 98 for( Iterator momcIt = methodToContexts.get(method).iterator(); momcIt.hasNext(); ) { 99 final MethodOrMethodContext momc = (MethodOrMethodContext) momcIt.next(); 100 Iterator callerEdges = cg.edgesInto(momc); 101 while (callerEdges.hasNext()){ 102 Edge callEdge = (Edge)callerEdges.next(); 103 SootMethod methodCaller = callEdge.src(); 104 if (methodCaller.getDeclaringClass().isLibraryClass()){ 105 if (isShowLibMeths()){ 106 if (recurse){ 107 list.add(new MethInfo(methodCaller, hasTgtMethods(methodCaller) | hasSrcMethods(methodCaller), callEdge.kind())); 108 } 109 else { 110 list.add(new MethInfo(methodCaller, true, callEdge.kind())); 111 } 112 } 113 } 114 else { 115 if (recurse){ 116 list.add(new MethInfo(methodCaller, hasTgtMethods(methodCaller) | hasSrcMethods(methodCaller), callEdge.kind())); 117 } 118 else { 119 list.add(new MethInfo(methodCaller, true, callEdge.kind())); 120 } 121 } 122 } 123 } 124 return list; 125 } 126 127 protected void internalTransform(String phaseName, Map options){ 128 129 CGGOptions opts = new CGGOptions(options); 130 if (opts.show_lib_meths()){ 131 setShowLibMeths(true); 132 } 133 cg = Scene.v().getCallGraph(); 134 if (Options.v().interactive_mode()){ 135 reset(); 136 } 137 } 138 139 public void reset() { 140 if (methodToContexts == null){ 141 methodToContexts = new MethodToContexts(Scene.v().getReachableMethods().listener()); 142 } 143 144 SootClass sc = Scene.v().getMainClass(); 145 SootMethod sm = getFirstMethod(sc); 146 ArrayList tgts = getTgtMethods(sm, true); 148 ArrayList srcs = getSrcMethods(sm, true); 150 CallGraphInfo info = new CallGraphInfo(sm, tgts, srcs); 152 InteractionHandler.v().handleCallGraphStart(info, this); 154 } 155 156 private SootMethod getFirstMethod(SootClass sc){ 157 ArrayList paramTypes = new ArrayList(); 158 paramTypes.add(soot.ArrayType.v(soot.RefType.v("java.lang.String"), 1)); 159 if (sc.declaresMethod("main", paramTypes, soot.VoidType.v())){ 160 return sc.getMethod("main", paramTypes, soot.VoidType.v()); 161 } 162 else { 163 return (SootMethod)sc.getMethods().get(0); 164 } 165 } 166 167 public void handleNextMethod(){ 168 if (!getNextMethod().hasActiveBody()) return; 169 ArrayList tgts = getTgtMethods(getNextMethod(), true); 170 ArrayList srcs = getSrcMethods(getNextMethod(), true); 172 CallGraphInfo info = new CallGraphInfo(getNextMethod(), tgts, srcs); 174 InteractionHandler.v().handleCallGraphPart(info); 176 } 178 179 private SootMethod nextMethod; 180 181 public void setNextMethod(SootMethod m){ 182 nextMethod = m; 183 } 184 185 public SootMethod getNextMethod(){ 186 return nextMethod; 187 } 188 189 public void setShowLibMeths(boolean b){ 190 showLibMeths = b; 191 } 192 193 public boolean isShowLibMeths(){ 194 return showLibMeths; 195 } 196 197 } 198 199 200 | Popular Tags |