1 19 20 package soot.javaToJimple; 21 import soot.*; 22 import java.util.*; 23 24 public class InitialResolver { 25 26 private polyglot.ast.Node astNode; private polyglot.frontend.Compiler compiler; 28 private polyglot.util.Position currentClassDeclPos; 29 private BiMap anonClassMap; private HashMap anonTypeMap; private BiMap localClassMap; private HashMap localTypeMap; private int privateAccessCounter = 0; private HashMap finalLocalInfo; private HashMap newToOuterMap; 37 38 private HashMap sootNameToAST = null; 39 private ArrayList hasOuterRefInInit; 41 private HashMap classToSourceMap; 42 private HashMap specialAnonMap; 43 private HashMap privateFieldGetAccessMap; 44 private HashMap privateFieldSetAccessMap; 45 private HashMap privateMethodGetAccessMap; 46 private ArrayList interfacesList; 47 private ArrayList cCallList; 48 49 private HashMap anonConstructorMap; 50 51 public void addToAnonConstructorMap(polyglot.ast.New anonNew, polyglot.types.ConstructorInstance ci){ 52 if (anonConstructorMap == null){ 53 anonConstructorMap = new HashMap(); 54 } 55 anonConstructorMap.put(anonNew, ci); 56 } 57 58 public polyglot.types.ConstructorInstance getConstructorForAnon(polyglot.ast.New anonNew){ 59 if (anonConstructorMap == null) return null; 60 return (polyglot.types.ConstructorInstance)anonConstructorMap.get(anonNew); 61 } 62 63 private FastHierarchy hierarchy; 64 65 private AbstractJBBFactory jbbFactory = new JimpleBodyBuilderFactory(); 66 67 public void setJBBFactory(AbstractJBBFactory jbbFactory){ 68 this.jbbFactory = jbbFactory; 69 } 70 71 public AbstractJBBFactory getJBBFactory(){ 72 return jbbFactory; 73 } 74 75 78 public boolean hasASTForSootName(String name){ 79 if (sootNameToAST == null) return false; 80 if (sootNameToAST.containsKey(name)) return true; 81 return false; 82 } 83 84 87 public void setASTForSootName(String name){ 88 if (!hasASTForSootName(name)) { 89 throw new RuntimeException ("Can only set AST for name if it exists. You should probably not be calling this method unless you know what you're doing!"); 90 } 91 setAst((polyglot.ast.Node)sootNameToAST.get(name)); 92 } 93 94 public InitialResolver(soot.Singletons.Global g){} 95 public static InitialResolver v() { 96 return soot.G.v().soot_javaToJimple_InitialResolver(); 97 } 98 99 100 101 104 public void formAst(String fullPath, List locations){ 105 106 JavaToJimple jtj = new JavaToJimple(); 107 polyglot.frontend.ExtensionInfo extInfo = jtj.initExtInfo(fullPath, locations); 108 compiler = new polyglot.frontend.Compiler(extInfo); 111 astNode = jtj.compile(compiler, fullPath, extInfo); 114 115 resolveAST(); 116 117 118 } 119 120 124 public void setAst(polyglot.ast.Node ast) { 125 astNode = ast; 126 } 127 128 132 public polyglot.ast.Node getAst(){ 133 return astNode; 134 } 135 136 private void makeASTMap() { 137 ClassDeclFinder finder = new ClassDeclFinder(); 138 astNode.visit(finder); 139 Iterator it = finder.declsFound().iterator(); 140 while (it.hasNext()){ 141 polyglot.ast.ClassDecl decl = (polyglot.ast.ClassDecl)it.next(); 142 polyglot.types.ClassType type = (polyglot.types.ClassType)decl.type(); 143 if (type.flags().isInterface()){ 144 if (interfacesList == null){ 145 interfacesList = new ArrayList(); 146 } 147 interfacesList.add(Util.getSootType(type).toString()); 148 } 149 addNameToAST(Util.getSootType(type).toString()); 150 } 151 } 152 153 157 protected void addNameToAST(String name){ 158 if (sootNameToAST == null){ 159 sootNameToAST = new HashMap(); 160 } 161 sootNameToAST.put(name, astNode); 162 } 163 164 public void resolveAST(){ 165 buildInnerClassInfo(); 166 if (astNode instanceof polyglot.ast.SourceFile) { 167 createClassToSourceMap((polyglot.ast.SourceFile)astNode); 168 } 169 } 170 171 public List resolveFromJavaFile(soot.SootClass sc) { 173 List references = new ArrayList(); 174 ClassResolver cr = new ClassResolver(sc, references); 175 176 if (astNode instanceof polyglot.ast.SourceFile) { 179 cr.createSource((polyglot.ast.SourceFile)astNode); 180 } 181 182 cr.addSourceFileTag(sc); 183 184 makeASTMap(); 185 186 return references; 187 } 188 189 190 private void createClassToSourceMap(polyglot.ast.SourceFile src){ 191 192 String srcName = src.source().path(); 193 String srcFileName = null; 194 if (src.package_() != null){ 195 String slashedPkg = soot.util.StringTools.replaceAll(src.package_().package_().fullName(), ".", System.getProperty("file.separator")); 196 srcFileName = srcName.substring(srcName.lastIndexOf(slashedPkg)); 197 } 198 else { 199 srcFileName = srcName.substring(srcName.lastIndexOf(System.getProperty("file.separator"))+1); 200 } 201 202 ArrayList list = new ArrayList(); 203 Iterator it = src.decls().iterator(); 204 while (it.hasNext()){ 205 polyglot.ast.ClassDecl nextDecl = (polyglot.ast.ClassDecl)it.next(); 206 addToClassToSourceMap(Util.getSootType(nextDecl.type()).toString(), srcFileName); 207 } 208 209 } 210 211 private void createLocalAndAnonClassNames(ArrayList anonBodyList, ArrayList localClassDeclList){ 212 Iterator anonBodyIt = anonBodyList.iterator(); 213 while (anonBodyIt.hasNext()){ 214 createAnonClassName((polyglot.ast.New)anonBodyIt.next()); 215 } 216 Iterator localClassDeclIt = localClassDeclList.iterator(); 217 while (localClassDeclIt.hasNext()){ 218 createLocalClassName((polyglot.ast.LocalClassDecl)localClassDeclIt.next()); 219 } 220 } 221 222 protected int getNextAnonNum(){ 223 if (anonTypeMap == null) return 1; 224 else return anonTypeMap.size()+1; 225 } 226 227 private void createAnonClassName(polyglot.ast.New nextNew){ 228 if (anonClassMap == null){ 230 anonClassMap = new BiMap(); 231 } 232 if (anonTypeMap == null){ 233 anonTypeMap = new HashMap(); 234 } 235 if (!anonClassMap.containsKey(nextNew)){ 236 int nextAvailNum = 1; 237 polyglot.types.ClassType outerToMatch = nextNew.anonType().outer(); 238 while (outerToMatch.isNested()){ 239 outerToMatch = outerToMatch.outer(); 240 } 241 242 if (!anonTypeMap.isEmpty()){ 243 Iterator matchIt = anonTypeMap.keySet().iterator(); 244 while (matchIt.hasNext()){ 245 polyglot.types.ClassType pType = (polyglot.types.ClassType)((polyglot.util.IdentityKey)matchIt.next()).object(); 246 polyglot.types.ClassType outerMatch = pType.outer(); 247 while (outerMatch.isNested()){ 248 outerMatch = outerMatch.outer(); 249 } 250 if (outerMatch.equals(outerToMatch)){ 251 int numFound = getAnonClassNum((String )anonTypeMap.get(new polyglot.util.IdentityKey(pType))); 252 if (numFound >= nextAvailNum){ 253 nextAvailNum = numFound+1; 254 } 255 } 256 } 257 } 258 259 String realName = outerToMatch.fullName()+"$"+nextAvailNum; 260 anonClassMap.put(nextNew, realName); 261 anonTypeMap.put(new polyglot.util.IdentityKey(nextNew.anonType()), realName); 262 addNameToAST(realName); 263 264 } 265 } 266 267 private void createLocalClassName(polyglot.ast.LocalClassDecl lcd){ 268 if (localClassMap == null){ 270 localClassMap = new BiMap(); 271 } 272 if (localTypeMap == null){ 273 localTypeMap = new HashMap(); 274 } 275 276 if (!localClassMap.containsKey(lcd)){ 277 int nextAvailNum = 1; 278 polyglot.types.ClassType outerToMatch = lcd.decl().type().outer(); 279 while (outerToMatch.isNested()){ 280 outerToMatch = outerToMatch.outer(); 281 } 282 283 if (!localTypeMap.isEmpty()){ 284 Iterator matchIt = localTypeMap.keySet().iterator(); 285 while (matchIt.hasNext()){ 286 polyglot.types.ClassType pType = (polyglot.types.ClassType)((polyglot.util.IdentityKey)matchIt.next()).object(); 287 polyglot.types.ClassType outerMatch = pType.outer(); 288 while (outerMatch.isNested()){ 289 outerMatch = outerMatch.outer(); 290 } 291 if (outerMatch.equals(outerToMatch)){ 292 int numFound = getLocalClassNum((String )localTypeMap.get(new polyglot.util.IdentityKey(pType)), lcd.decl().name()); 293 if (numFound >= nextAvailNum){ 294 nextAvailNum = numFound+1; 295 } 296 } 297 } 298 } 299 300 String realName = outerToMatch.fullName()+"$"+nextAvailNum+lcd.decl().name(); 301 localClassMap.put(lcd, realName); 302 localTypeMap.put(new polyglot.util.IdentityKey(lcd.decl().type()), realName); 303 addNameToAST(realName); 304 } 305 } 306 307 private static final int NO_MATCH = 0; 308 309 private int getLocalClassNum(String realName, String simpleName){ 310 int dIndex = realName.indexOf("$"); 313 int nIndex = realName.indexOf(simpleName, dIndex); 314 if (nIndex == -1) return NO_MATCH; 315 if (dIndex == -1) { 316 throw new RuntimeException ("Matching an incorrectly named local inner class: "+realName); 317 } 318 String numString = realName.substring(dIndex+1, nIndex); 319 for (int i = 0; i < numString.length(); i++){ 320 if (!Character.isDigit(numString.charAt(i))) return NO_MATCH; 321 } 322 return (new Integer (numString)).intValue(); 323 } 324 325 private int getAnonClassNum(String realName){ 326 int dIndex = realName.indexOf("$"); 329 if (dIndex == -1) { 330 throw new RuntimeException ("Matching an incorrectly named anon inner class: "+realName); 331 } 332 return (new Integer (realName.substring(dIndex+1))).intValue(); 333 } 334 335 336 340 private void addToClassToSourceMap(String className, String sourceName) { 341 342 if (classToSourceMap == null){ 343 classToSourceMap = new HashMap(); 344 } 345 classToSourceMap.put(className, sourceName); 346 } 347 348 349 public boolean hasClassInnerTag(soot.SootClass sc, String innerName){ 350 Iterator it = sc.getTags().iterator(); 351 while (it.hasNext()){ 352 soot.tagkit.Tag t = (soot.tagkit.Tag)it.next(); 353 if (t instanceof soot.tagkit.InnerClassTag) { 354 soot.tagkit.InnerClassTag tag = (soot.tagkit.InnerClassTag)t; 355 if (tag.getInnerClass().equals(innerName)) return true; 356 } 357 } 358 return false; 359 } 360 361 private void buildInnerClassInfo(){ 362 InnerClassInfoFinder icif = new InnerClassInfoFinder(); 363 astNode.visit(icif); 364 createLocalAndAnonClassNames(icif.anonBodyList(), icif.localClassDeclList()); 365 buildFinalLocalMap(icif.memberList()); 366 } 367 368 private void buildFinalLocalMap(ArrayList memberList){ 369 Iterator it = memberList.iterator(); 370 while (it.hasNext()){ 371 handleFinalLocals((polyglot.ast.ClassMember)it.next()); 372 } 373 } 374 375 private void handleFinalLocals(polyglot.ast.ClassMember member){ 376 MethodFinalsChecker mfc = new MethodFinalsChecker(); 377 member.visit(mfc); 378 if (cCallList == null){ 383 cCallList = new ArrayList(); 384 } 385 cCallList.addAll(mfc.ccallList()); 386 AnonLocalClassInfo alci = new AnonLocalClassInfo(); 388 if (member instanceof polyglot.ast.ProcedureDecl){ 389 polyglot.ast.ProcedureDecl procedure = (polyglot.ast.ProcedureDecl)member; 390 alci.finalLocalsAvail(mfc.finalLocals()); 392 if (procedure.flags().isStatic()){ 393 alci.inStaticMethod(true); 394 } 395 } 396 else if (member instanceof polyglot.ast.FieldDecl){ 397 alci.finalLocalsAvail(new ArrayList()); 398 if (((polyglot.ast.FieldDecl)member).flags().isStatic()){ 399 alci.inStaticMethod(true); 400 } 401 } 402 else if (member instanceof polyglot.ast.Initializer){ 403 alci.finalLocalsAvail(mfc.finalLocals()); 406 if (((polyglot.ast.Initializer)member).flags().isStatic()){ 407 alci.inStaticMethod(true); 408 } 409 } 410 if (finalLocalInfo == null){ 411 finalLocalInfo = new HashMap(); 412 } 413 Iterator it = mfc.inners().iterator(); 414 while (it.hasNext()){ 415 416 polyglot.types.ClassType cType = (polyglot.types.ClassType)((polyglot.util.IdentityKey)it.next()).object(); 417 HashMap typeToLocalUsed = mfc.typeToLocalsUsed(); 419 ArrayList localsUsed = new ArrayList(); 420 if (typeToLocalUsed.containsKey(new polyglot.util.IdentityKey(cType))){ 421 ArrayList localsNeeded = (ArrayList)typeToLocalUsed.get(new polyglot.util.IdentityKey(cType)); 422 Iterator usesIt = localsNeeded.iterator(); 423 while (usesIt.hasNext()){ 424 polyglot.types.LocalInstance li = (polyglot.types.LocalInstance)((polyglot.util.IdentityKey)usesIt.next()).object(); 425 if (alci.finalLocalsAvail().contains(new polyglot.util.IdentityKey(li))){ 426 localsUsed.add(new polyglot.util.IdentityKey(li)); 427 } 428 } 429 } 430 431 432 AnonLocalClassInfo info = new AnonLocalClassInfo(); 433 info.inStaticMethod(alci.inStaticMethod()); 434 info.finalLocalsAvail(localsUsed); 435 if (!finalLocalInfo.containsKey(new polyglot.util.IdentityKey(cType))){ 436 finalLocalInfo.put(new polyglot.util.IdentityKey(cType), info); 437 } 438 } 439 } 440 441 public boolean isAnonInCCall(polyglot.types.ClassType anonType){ 442 Iterator it = cCallList.iterator(); 444 while (it.hasNext()){ 445 polyglot.ast.ConstructorCall cCall = (polyglot.ast.ConstructorCall)it.next(); 446 Iterator argsIt = cCall.arguments().iterator(); 448 while (argsIt.hasNext()){ 449 Object next = argsIt.next(); 450 if (next instanceof polyglot.ast.New && ((polyglot.ast.New)next).anonType() != null){ 451 if (((polyglot.ast.New)next).anonType().equals(anonType)) return true; 453 } 454 } 455 } 456 return false; 457 } 458 459 public BiMap getAnonClassMap(){ 460 return anonClassMap; 461 } 462 463 public BiMap getLocalClassMap(){ 464 return localClassMap; 465 } 466 467 public HashMap getAnonTypeMap(){ 468 return anonTypeMap; 469 } 470 471 public HashMap getLocalTypeMap(){ 472 return localTypeMap; 473 } 474 475 public HashMap finalLocalInfo(){ 476 return finalLocalInfo; 477 } 478 479 public int getNextPrivateAccessCounter(){ 480 int res = privateAccessCounter; 481 privateAccessCounter++; 482 return res; 483 } 484 485 public ArrayList getHasOuterRefInInit(){ 486 return hasOuterRefInInit; 487 } 488 489 public void setHasOuterRefInInit(ArrayList list){ 490 hasOuterRefInInit = list; 491 } 492 493 public HashMap specialAnonMap(){ 494 return specialAnonMap; 495 } 496 497 public void setSpecialAnonMap(HashMap map){ 498 specialAnonMap = map; 499 } 500 501 public void hierarchy(soot.FastHierarchy fh){ 502 hierarchy = fh; 503 } 504 505 public soot.FastHierarchy hierarchy(){ 506 return hierarchy; 507 } 508 509 private HashMap innerClassInfoMap; 510 511 public HashMap getInnerClassInfoMap(){ 512 return innerClassInfoMap; 513 } 514 515 public void setInnerClassInfoMap(HashMap map){ 516 innerClassInfoMap = map; 517 } 518 519 protected HashMap classToSourceMap(){ 520 return classToSourceMap; 521 } 522 523 public void addToPrivateFieldGetAccessMap(polyglot.ast.Field field, soot.SootMethod meth){ 524 if (privateFieldGetAccessMap == null){ 525 privateFieldGetAccessMap = new HashMap(); 526 } 527 privateFieldGetAccessMap.put(new polyglot.util.IdentityKey(field.fieldInstance()), meth); 528 } 529 530 public HashMap getPrivateFieldGetAccessMap(){ 531 return privateFieldGetAccessMap; 532 } 533 534 public void addToPrivateFieldSetAccessMap(polyglot.ast.Field field, soot.SootMethod meth){ 535 if (privateFieldSetAccessMap == null){ 536 privateFieldSetAccessMap = new HashMap(); 537 } 538 privateFieldSetAccessMap.put(new polyglot.util.IdentityKey(field.fieldInstance()), meth); 539 } 540 541 public HashMap getPrivateFieldSetAccessMap(){ 542 return privateFieldSetAccessMap; 543 } 544 545 public void addToPrivateMethodGetAccessMap(polyglot.ast.Call call, soot.SootMethod meth){ 546 if (privateMethodGetAccessMap == null){ 547 privateMethodGetAccessMap = new HashMap(); 548 } 549 privateMethodGetAccessMap.put(new polyglot.util.IdentityKey(call.methodInstance()), meth); 550 } 551 552 public HashMap getPrivateMethodGetAccessMap(){ 553 return privateMethodGetAccessMap; 554 } 555 556 public ArrayList getInterfacesList() { 557 return interfacesList; 558 } 559 } 560 561 | Popular Tags |