1 19 20 24 25 package soot.dava; 26 27 import java.util.ArrayList ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 import soot.RefType; 33 import soot.Scene; 34 import soot.SootClass; 35 import soot.SootMethod; 36 import soot.SootMethodRef; 37 import soot.dava.internal.AST.ASTDoWhileNode; 38 import soot.dava.internal.AST.ASTForLoopNode; 39 import soot.dava.internal.AST.ASTIfElseNode; 40 import soot.dava.internal.AST.ASTIfNode; 41 import soot.dava.internal.AST.ASTLabeledBlockNode; 42 import soot.dava.internal.AST.ASTMethodNode; 43 import soot.dava.internal.AST.ASTNode; 44 import soot.dava.internal.AST.ASTStatementSequenceNode; 45 import soot.dava.internal.AST.ASTSwitchNode; 46 import soot.dava.internal.AST.ASTSynchronizedBlockNode; 47 import soot.dava.internal.AST.ASTTryNode; 48 import soot.dava.internal.AST.ASTUnconditionalLoopNode; 49 import soot.dava.internal.AST.ASTWhileNode; 50 import soot.dava.internal.asg.AugmentedStmt; 51 import soot.dava.toolkits.base.AST.analysis.DepthFirstAdapter; 52 import soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder; 53 import soot.grimp.internal.GNewInvokeExpr; 54 import soot.grimp.internal.GThrowStmt; 55 import soot.jimple.InvokeExpr; 56 import soot.jimple.InvokeStmt; 57 import soot.jimple.Stmt; 58 import soot.jimple.StringConstant; 59 60 public class MethodCallFinder extends DepthFirstAdapter{ 61 ASTMethodNode underAnalysis; 62 63 DavaStaticBlockCleaner cleaner; 64 65 public MethodCallFinder(DavaStaticBlockCleaner cleaner){ 66 this.cleaner=cleaner; 67 underAnalysis=null; 68 } 69 70 public MethodCallFinder(boolean verbose,DavaStaticBlockCleaner cleaner){ 71 super(verbose); 72 this.cleaner=cleaner; 73 underAnalysis=null; 74 } 75 76 public void inASTMethodNode(ASTMethodNode node){ 77 underAnalysis=node; 78 } 79 80 90 91 92 96 public void inInvokeStmt(InvokeStmt s){ 97 InvokeExpr invokeExpr = s.getInvokeExpr(); 98 SootMethod maybeInline = invokeExpr.getMethod(); 99 100 ASTMethodNode toInlineASTMethod = cleaner.inline(maybeInline); 102 if(toInlineASTMethod ==null){ 103 return; 105 } 106 else{ List subBodies = toInlineASTMethod.get_SubBodies(); 109 if(subBodies.size() != 1){ 110 throw new RuntimeException ("Found ASTMEthod node with more than one subBodies"); 111 } 112 List body = (List )subBodies.get(0); 113 114 115 ASTParentNodeFinder finder = new ASTParentNodeFinder(); 116 underAnalysis.apply(finder); 117 118 List newChangedBodyPart = createChangedBodyPart(s,body,finder); 119 120 121 boolean replaced = replaceSubBody(s,newChangedBodyPart,finder); 122 123 124 if(replaced){ 125 127 131 StaticDefinitionFinder defFinder = new StaticDefinitionFinder(maybeInline); 132 toInlineASTMethod.apply(defFinder); 133 134 if(defFinder.anyFinalFieldDefined()){ 135 137 SootClass runtime = Scene.v().loadClassAndSupport("java.lang.RuntimeException"); 139 if(runtime.declaresMethod("void <init>(java.lang.String)")){ 140 SootMethod sootMethod = runtime.getMethod("void <init>(java.lang.String)"); 141 SootMethodRef methodRef = sootMethod.makeRef(); 142 RefType myRefType = RefType.v(runtime); 143 StringConstant tempString = StringConstant.v("This method used to have a definition of a final variable. "+ 144 "Dava inlined the definition into the static initializer"); 145 List list = new ArrayList (); 146 list.add(tempString); 147 148 GNewInvokeExpr newInvokeExpr = new GNewInvokeExpr(myRefType,methodRef,list); 149 150 GThrowStmt throwStmt = new GThrowStmt(newInvokeExpr); 151 152 AugmentedStmt augStmt = new AugmentedStmt(throwStmt); 153 List sequence = new ArrayList (); 154 sequence.add(augStmt); 155 ASTStatementSequenceNode seqNode = new ASTStatementSequenceNode(sequence); 156 List subBody = new ArrayList (); 157 subBody.add(seqNode); 158 159 toInlineASTMethod.replaceBody(subBody); 160 } 161 } 162 } 163 164 } 165 } 166 167 public List getSubBodyFromSingleSubBodyNode(ASTNode node){ 168 List subBodies = node.get_SubBodies(); 169 if(subBodies.size() != 1) 170 throw new RuntimeException ("Found a single subBody node with more than 1 subBodies"); 171 172 return (List )subBodies.get(0); 173 } 174 175 176 public List createNewSubBody(List orignalBody, List partNewBody,Object stmtSeqNode){ 177 178 List newBody = new ArrayList (); 179 180 Iterator it = orignalBody.iterator(); 181 while(it.hasNext()){ 182 Object temp = it.next(); 183 if(temp != stmtSeqNode) 184 newBody.add(temp); 185 else{ 186 break; 188 } 189 } 190 newBody.addAll(partNewBody); 192 193 while(it.hasNext()){ 195 newBody.add(it.next()); 196 } 197 198 return newBody; 199 } 200 201 202 public boolean replaceSubBody(InvokeStmt s, List newChangedBodyPart,ASTParentNodeFinder finder){ 203 204 Object stmtSeqNode = finder.getParentOf(s); 206 207 Object ParentOfStmtSeq = finder.getParentOf(stmtSeqNode); 209 210 if(ParentOfStmtSeq ==null){ 211 throw new RuntimeException ("MethodCall FInder: parent of stmt seq node not found"); 212 } 213 214 ASTNode node = (ASTNode)ParentOfStmtSeq; 215 216 218 if(node instanceof ASTMethodNode){ 219 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 221 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 222 ((ASTMethodNode)node).replaceBody(newBody); 223 return true; 224 } 225 else if(node instanceof ASTSynchronizedBlockNode){ 226 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 228 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 229 ((ASTSynchronizedBlockNode)node).replaceBody(newBody); 230 return true; 231 } 232 else if(node instanceof ASTLabeledBlockNode){ 233 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 235 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 236 ((ASTLabeledBlockNode)node).replaceBody(newBody); 237 return true; 238 } 239 else if(node instanceof ASTUnconditionalLoopNode){ 240 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 242 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 243 ((ASTUnconditionalLoopNode)node).replaceBody(newBody); 244 return true; 245 } 246 else if(node instanceof ASTIfNode){ 247 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 249 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 250 ((ASTIfNode)node).replaceBody(newBody); 251 return true; 252 } 253 else if(node instanceof ASTWhileNode){ 254 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 256 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 257 ((ASTWhileNode)node).replaceBody(newBody); 258 return true; 259 } 260 else if(node instanceof ASTDoWhileNode){ 261 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 263 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 264 ((ASTDoWhileNode)node).replaceBody(newBody); 265 return true; 266 } 267 else if(node instanceof ASTForLoopNode){ 268 List subBodyToReplace = getSubBodyFromSingleSubBodyNode(node); 270 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 271 ((ASTForLoopNode)node).replaceBody(newBody); 272 return true; 273 } 274 else if(node instanceof ASTIfElseNode){ 275 List subBodies = node.get_SubBodies(); 276 if(subBodies.size() != 2) 277 throw new RuntimeException ("Found an ifelse ASTNode which does not have two bodies"); 278 List ifBody = (List )subBodies.get(0); 279 List elseBody = (List )subBodies.get(1); 280 281 int subBodyNumber=-1; 283 Iterator it = ifBody.iterator(); 284 while(it.hasNext()){ 285 Object temp = it.next(); 286 if(temp == stmtSeqNode){ 287 subBodyNumber=0; 288 break; 289 } 290 } 291 if(subBodyNumber!= 0){ 292 it = elseBody.iterator(); 293 while(it.hasNext()){ 294 Object temp = it.next(); 295 if(temp == stmtSeqNode){ 296 subBodyNumber=1; 297 break; 298 } 299 } 300 } 301 302 List subBodyToReplace = null; 303 if(subBodyNumber==0) 304 subBodyToReplace=ifBody; 305 else if (subBodyNumber==1) 306 subBodyToReplace=elseBody; 307 else 308 throw new RuntimeException ("Could not find the related ASTNode in the method"); 309 310 List newBody = createNewSubBody(subBodyToReplace,newChangedBodyPart,stmtSeqNode); 311 312 if(subBodyNumber==0){ 313 ((ASTIfElseNode)node).replaceBody(newBody,elseBody); 314 return true; 315 } 316 else if(subBodyNumber==1){ 317 ((ASTIfElseNode)node).replaceBody(ifBody,newBody); 318 return true; 319 } 320 } 321 else if(node instanceof ASTTryNode){ 322 323 326 List tryBody = ((ASTTryNode)node).get_TryBody(); 328 Iterator it = tryBody.iterator(); 329 330 boolean inTryBody = false; 332 while (it.hasNext()){ 333 ASTNode temp = (ASTNode) it.next(); 334 if(temp == stmtSeqNode){ 335 inTryBody=true; 336 break; 337 } 338 } 339 if(!inTryBody){ 340 return false; 342 } 343 344 345 List newBody = createNewSubBody(tryBody,newChangedBodyPart,stmtSeqNode); 346 ((ASTTryNode)node).replaceTryBody(newBody); 347 return true; 348 } 349 else if (node instanceof ASTSwitchNode){ 350 351 List indexList = ((ASTSwitchNode)node).getIndexList(); 352 Map index2BodyList = ((ASTSwitchNode)node).getIndex2BodyList(); 353 354 Iterator it = indexList.iterator(); 355 while (it.hasNext()) { Object currentIndex = it.next(); 357 List body = (List ) index2BodyList.get( currentIndex); 358 359 if (body != null){ 360 362 boolean found=false; 364 Iterator itBody = body.iterator(); 365 while (itBody.hasNext()){ 366 ASTNode temp = (ASTNode) itBody.next(); 367 if(temp == stmtSeqNode){ 368 found=true; 369 break; 370 } 371 } 372 if(found){ 373 List newBody = createNewSubBody(body,newChangedBodyPart,stmtSeqNode); 375 376 index2BodyList.put(currentIndex,newBody); 378 ((ASTSwitchNode)node).replaceIndex2BodyList(index2BodyList); 380 return true; 381 } 382 } } } 385 return false; 386 } 387 388 389 390 396 397 public List createChangedBodyPart(InvokeStmt s, List body, ASTParentNodeFinder finder){ 398 Object parent = finder.getParentOf(s); 400 if(parent == null){ 401 throw new RuntimeException ("MethodCall FInder: parent of invoke stmt not found"); 402 } 403 404 ASTNode parentNode = (ASTNode)parent; 405 if(!(parentNode instanceof ASTStatementSequenceNode)){ 406 throw new RuntimeException ("MethodCall FInder: parent node not a stmt seq node"); 407 } 408 409 ASTStatementSequenceNode orignal = (ASTStatementSequenceNode)parentNode; 410 411 412 List newInitialNode = new ArrayList (); 414 Iterator it = orignal.getStatements().iterator(); 415 while(it.hasNext()){ 416 AugmentedStmt as = (AugmentedStmt)it.next(); 417 Stmt tempStmt = as.get_Stmt(); 418 if(tempStmt != s){ 419 newInitialNode.add(as); 420 } 421 else{ 422 break; 424 } 425 } 426 427 List newSecondNode = new ArrayList (); 429 while(it.hasNext()){ 430 newSecondNode.add(it.next()); 431 } 432 433 List toReturn = new ArrayList (); 434 435 if(newInitialNode.size()!=0) 436 toReturn.add(new ASTStatementSequenceNode(newInitialNode)); 437 438 toReturn.addAll(body); 440 441 if(newSecondNode.size()!=0) 442 toReturn.add(new ASTStatementSequenceNode(newSecondNode)); 443 444 return toReturn; 445 } 446 447 448 449 } | Popular Tags |