1 19 20 package soot.javaToJimple; 21 import soot.*; 22 import java.util.*; 23 24 public class ClassResolver { 25 26 private ArrayList staticFieldInits; 27 private ArrayList fieldInits; 28 private ArrayList initializerBlocks; 29 private ArrayList staticInitializerBlocks; 30 31 34 protected void addSourceFileTag(soot.SootClass sc){ 35 soot.tagkit.SourceFileTag tag = null; 36 if (sc.hasTag("SourceFileTag")) { 37 tag = (soot.tagkit.SourceFileTag)sc.getTag("SourceFileTag"); 38 } 39 else { 40 tag = new soot.tagkit.SourceFileTag(); 41 sc.addTag(tag); 42 } 43 44 String name = Util.getSourceFileOfClass(sc); 45 46 47 if (InitialResolver.v().classToSourceMap() != null){ 48 if (InitialResolver.v().classToSourceMap().containsKey(name)){ 49 name = (String )InitialResolver.v().classToSourceMap().get(name); 50 } 51 } 52 53 int slashIndex = name.lastIndexOf("/"); 57 if (slashIndex != -1){ 58 name = name.substring(slashIndex+1); 59 } 60 tag.setSourceFile(name); 61 } 63 64 67 private void createClassDecl(polyglot.ast.ClassDecl cDecl){ 68 69 if (!cDecl.type().isTopLevel()){ 71 SootClass outerClass = ((soot.RefType)Util.getSootType(cDecl.type().outer())).getSootClass(); 72 73 if (InitialResolver.v().getInnerClassInfoMap() == null){ 74 InitialResolver.v().setInnerClassInfoMap(new HashMap()); 75 } 76 InitialResolver.v().getInnerClassInfoMap().put(sootClass, new InnerClassInfo(outerClass, cDecl.name(), InnerClassInfo.NESTED)); 77 sootClass.setOuterClass(outerClass); 78 } 79 80 polyglot.types.Flags flags = cDecl.flags(); 82 addModifiers(flags, cDecl); 83 84 if (cDecl.superClass() == null) { 86 soot.SootClass superClass = soot.Scene.v().getSootClass ("java.lang.Object"); 87 sootClass.setSuperclass(superClass); 88 } 89 else { 90 91 sootClass.setSuperclass(((soot.RefType)Util.getSootType(cDecl.superClass().type())).getSootClass()); 92 if (((polyglot.types.ClassType)cDecl.superClass().type()).isNested()){ 93 polyglot.types.ClassType superType = (polyglot.types.ClassType)cDecl.superClass().type(); 94 96 Util.addInnerClassTag(sootClass, sootClass.getName(), ((soot.RefType)Util.getSootType(superType.outer())).toString(), superType.name(), Util.getModifier(superType.flags())); 97 } 98 99 } 100 101 102 Iterator interfacesIt = cDecl.interfaces().iterator(); 104 while (interfacesIt.hasNext()) { 105 polyglot.ast.TypeNode next = (polyglot.ast.TypeNode)interfacesIt.next(); 106 sootClass.addInterface(((soot.RefType)Util.getSootType(next.type())).getSootClass()); 107 } 108 109 findReferences(cDecl); 110 createClassBody(cDecl.body()); 111 112 handleFieldInits(); 116 117 if ((staticFieldInits != null) || (staticInitializerBlocks != null)) { 118 soot.SootMethod clinitMethod; 119 if (!sootClass.declaresMethod("<clinit>", new ArrayList(), soot.VoidType.v())) { 120 clinitMethod = new soot.SootMethod("<clinit>", new ArrayList(), soot.VoidType.v(), soot.Modifier.STATIC, new ArrayList()); 121 122 sootClass.addMethod(clinitMethod); 123 PolyglotMethodSource mSource = new PolyglotMethodSource(); 124 mSource.setJBB(InitialResolver.v().getJBBFactory().createJimpleBodyBuilder()); 125 clinitMethod.setSource(mSource); 126 } 127 else { 128 clinitMethod = sootClass.getMethod("<clinit>", new ArrayList(), soot.VoidType.v()); 129 130 } 131 ((PolyglotMethodSource)clinitMethod.getSource()).setStaticFieldInits(staticFieldInits); 132 ((PolyglotMethodSource)clinitMethod.getSource()).setStaticInitializerBlocks(staticInitializerBlocks); 133 134 } 135 136 137 if (cDecl.type().isLocal()) { 139 AnonLocalClassInfo info = (AnonLocalClassInfo)InitialResolver.v().finalLocalInfo().get(new polyglot.util.IdentityKey(cDecl.type())); 140 ArrayList finalsList = addFinalLocals(cDecl.body(), info.finalLocalsAvail(), cDecl.type(), info); 141 Iterator it = sootClass.getMethods().iterator(); 142 while (it.hasNext()){ 143 soot.SootMethod meth = (soot.SootMethod)it.next(); 144 if (meth.getName().equals("<init>")){ 145 ((PolyglotMethodSource)meth.getSource()).setFinalsList(finalsList); 146 } 147 } 148 if (!info.inStaticMethod()){ 149 polyglot.types.ClassType outerType = cDecl.type().outer(); 150 addOuterClassThisRefToInit(outerType); 151 addOuterClassThisRefField(outerType); 152 } 153 } 154 155 else if (cDecl.type().isNested() && !cDecl.flags().isStatic()) { 158 polyglot.types.ClassType outerType = cDecl.type().outer(); 159 addOuterClassThisRefToInit(outerType); 160 addOuterClassThisRefField(outerType); 161 } 162 163 Util.addLnPosTags(sootClass, cDecl.position()); 164 } 165 166 167 private void findReferences(polyglot.ast.Node node) { 168 TypeListBuilder typeListBuilder = new TypeListBuilder(); 169 170 node.visit(typeListBuilder); 171 172 for( Iterator typeIt = typeListBuilder.getList().iterator(); typeIt.hasNext(); ) { 173 174 final polyglot.types.Type type = (polyglot.types.Type) typeIt.next(); 175 if (type.isPrimitive()) continue; 176 if (!type.isClass()) continue; 177 polyglot.types.ClassType classType = (polyglot.types.ClassType)type; 178 soot.Type sootClassType = Util.getSootType(classType); 179 references.add(sootClassType); 180 } 181 } 182 183 186 private void createClassBody(polyglot.ast.ClassBody classBody){ 187 188 189 staticFieldInits = null; 191 fieldInits = null; 192 initializerBlocks = null; 193 staticInitializerBlocks = null; 194 195 196 Iterator it = classBody.members().iterator(); 198 while (it.hasNext()){ 199 Object next = it.next(); 200 201 if (next instanceof polyglot.ast.MethodDecl) { 202 createMethodDecl((polyglot.ast.MethodDecl)next); 203 } 204 else if (next instanceof polyglot.ast.FieldDecl) { 205 createFieldDecl((polyglot.ast.FieldDecl)next); 206 } 207 else if (next instanceof polyglot.ast.ConstructorDecl){ 208 createConstructorDecl((polyglot.ast.ConstructorDecl)next); 209 } 210 else if (next instanceof polyglot.ast.ClassDecl){ 211 Util.addInnerClassTag(sootClass, Util.getSootType(((polyglot.ast.ClassDecl)next).type()).toString(), sootClass.getName(), ((polyglot.ast.ClassDecl)next).name().toString(), Util.getModifier(((polyglot.ast.ClassDecl)next).flags())); 214 } 215 else if (next instanceof polyglot.ast.Initializer) { 216 createInitializer((polyglot.ast.Initializer)next); 217 } 218 else { 219 throw new RuntimeException ("Class Body Member not implemented"); 220 } 221 } 222 handleInnerClassTags(classBody); 223 handleClassLiteral(classBody); 224 handleAssert(classBody); 225 } 226 227 private void addOuterClassThisRefField(polyglot.types.Type outerType){ 228 soot.Type outerSootType = Util.getSootType(outerType); 229 soot.SootField field = new soot.SootField("this$0", outerSootType, soot.Modifier.PRIVATE | soot.Modifier.FINAL); 230 sootClass.addField(field); 231 field.addTag(new soot.tagkit.SyntheticTag()); 232 } 233 234 private void addOuterClassThisRefToInit(polyglot.types.Type outerType){ 235 soot.Type outerSootType = Util.getSootType(outerType); 236 Iterator it = sootClass.getMethods().iterator(); 237 while (it.hasNext()){ 238 soot.SootMethod meth = (soot.SootMethod)it.next(); 239 if (meth.getName().equals("<init>")){ 240 List newParams = new ArrayList(); 241 newParams.add(outerSootType); 242 newParams.addAll(meth.getParameterTypes()); 243 meth.setParameterTypes(newParams); 244 meth.addTag(new soot.tagkit.EnclosingTag()); 245 if (InitialResolver.v().getHasOuterRefInInit() == null){ 246 InitialResolver.v().setHasOuterRefInInit(new ArrayList()); 247 } 248 InitialResolver.v().getHasOuterRefInInit().add(meth.getDeclaringClass().getType()); 249 } 250 } 251 } 252 private void addFinals(polyglot.types.LocalInstance li, ArrayList finalFields){ 253 Iterator it = sootClass.getMethods().iterator(); 255 while (it.hasNext()){ 256 soot.SootMethod meth = (soot.SootMethod)it.next(); 257 if (meth.getName().equals("<init>")){ 258 List newParams = new ArrayList(); 259 newParams.addAll(meth.getParameterTypes()); 260 newParams.add(Util.getSootType(li.type())); 261 meth.setParameterTypes(newParams); 262 } 263 } 264 265 soot.SootField sf = new soot.SootField("val$"+li.name(), Util.getSootType(li.type()), soot.Modifier.FINAL | soot.Modifier.PRIVATE); 267 sootClass.addField(sf); 268 finalFields.add(sf); 269 sf.addTag(new soot.tagkit.SyntheticTag()); 270 } 271 private ArrayList addFinalLocals(polyglot.ast.ClassBody cBody, ArrayList finalLocalsAvail, polyglot.types.ClassType nodeKeyType, AnonLocalClassInfo info){ 272 ArrayList finalFields = new ArrayList(); 273 274 LocalUsesChecker luc = new LocalUsesChecker(); 275 cBody.visit(luc); 276 277 ArrayList localsUsed = new ArrayList(); 278 291 Iterator fieldsNeededIt = finalLocalsAvail.iterator(); 292 while (fieldsNeededIt.hasNext()){ 293 294 polyglot.types.LocalInstance li = (polyglot.types.LocalInstance)((polyglot.util.IdentityKey)fieldsNeededIt.next()).object(); 295 if (!luc.getLocalDecls().contains(new polyglot.util.IdentityKey(li))){ 296 localsUsed.add(new polyglot.util.IdentityKey(li)); 297 addFinals(li, finalFields); 298 } 299 } 300 301 Iterator newsIt = luc.getNews().iterator(); 304 while (newsIt.hasNext()){ 305 polyglot.ast.New tempNew = (polyglot.ast.New)newsIt.next(); 306 polyglot.types.ClassType tempNewType = (polyglot.types.ClassType)tempNew.objectType().type(); 307 if (InitialResolver.v().finalLocalInfo().containsKey(new polyglot.util.IdentityKey(tempNewType))){ 308 AnonLocalClassInfo lInfo = (AnonLocalClassInfo)InitialResolver.v().finalLocalInfo().get(new polyglot.util.IdentityKey(tempNewType)); 309 Iterator it = lInfo.finalLocalsAvail().iterator(); 310 while (it.hasNext()){ 311 polyglot.types.LocalInstance li2 = (polyglot.types.LocalInstance)((polyglot.util.IdentityKey)it.next()).object(); 312 if (!sootClass.declaresField("val$"+li2.name(), Util.getSootType(li2.type()))){ 313 if (!luc.getLocalDecls().contains(new polyglot.util.IdentityKey(li2))){ 314 addFinals(li2, finalFields); 315 localsUsed.add(new polyglot.util.IdentityKey(li2)); 316 } 317 } 318 } 319 } 320 } 321 325 polyglot.types.ClassType superType = (polyglot.types.ClassType)nodeKeyType.superType(); 326 while (!Util.getSootType(superType).equals(soot.Scene.v().getSootClass("java.lang.Object").getType())){ 327 if (InitialResolver.v().finalLocalInfo().containsKey(new polyglot.util.IdentityKey(superType))){ 328 AnonLocalClassInfo lInfo = (AnonLocalClassInfo)InitialResolver.v().finalLocalInfo().get(new polyglot.util.IdentityKey(superType)); 329 Iterator it = lInfo.finalLocalsAvail().iterator(); 330 while (it.hasNext()){ 331 polyglot.types.LocalInstance li2 = (polyglot.types.LocalInstance)((polyglot.util.IdentityKey)it.next()).object(); 332 if (!sootClass.declaresField("val$"+li2.name(), Util.getSootType(li2.type()))){ 333 if (!luc.getLocalDecls().contains(new polyglot.util.IdentityKey(li2))){ 334 addFinals(li2, finalFields); 335 localsUsed.add(new polyglot.util.IdentityKey(li2)); 336 } 337 } 338 } 339 } 340 superType = (polyglot.types.ClassType)superType.superType(); 341 } 342 info.finalLocalsUsed(localsUsed); 343 InitialResolver.v().finalLocalInfo().put(new polyglot.util.IdentityKey(nodeKeyType), info); 344 return finalFields; 345 } 346 351 private void createAnonClassDecl(polyglot.ast.New aNew) { 352 353 SootClass outerClass = ((soot.RefType)Util.getSootType(aNew.anonType().outer())).getSootClass(); 354 if (InitialResolver.v().getInnerClassInfoMap() == null){ 355 InitialResolver.v().setInnerClassInfoMap(new HashMap()); 356 } 357 InitialResolver.v().getInnerClassInfoMap().put(sootClass, new InnerClassInfo(outerClass, "0", InnerClassInfo.ANON)); 358 sootClass.setOuterClass(outerClass); 359 360 soot.SootClass typeClass = ((soot.RefType)Util.getSootType(aNew.objectType().type())).getSootClass(); 361 362 if (((polyglot.types.ClassType)aNew.objectType().type()).flags().isInterface()){ 364 sootClass.addInterface(typeClass); 365 sootClass.setSuperclass(soot.Scene.v().getSootClass("java.lang.Object")); 366 } 367 else { 368 sootClass.setSuperclass(typeClass); 369 if (((polyglot.types.ClassType)aNew.objectType().type()).isNested()){ 370 polyglot.types.ClassType superType = (polyglot.types.ClassType)aNew.objectType().type(); 371 Util.addInnerClassTag(sootClass, typeClass.getName(), ((soot.RefType)Util.getSootType(superType.outer())).toString(), superType.name(), Util.getModifier(superType.flags())); 373 374 } 375 } 376 377 ArrayList params = new ArrayList(); 379 380 soot.SootMethod method; 381 if (((polyglot.types.ClassType)aNew.objectType().type()).flags().isInterface()){ 383 method = new soot.SootMethod("<init>", params, soot.VoidType.v()); 384 } 385 else { 386 if (!aNew.arguments().isEmpty()){ 387 388 polyglot.types.ConstructorInstance ci = InitialResolver.v().getConstructorForAnon(aNew); 389 Iterator aIt = ci.formalTypes().iterator(); 390 while (aIt.hasNext()){ 391 polyglot.types.Type pType = (polyglot.types.Type)aIt.next(); 392 params.add(Util.getSootType(pType)); 393 } 394 } 395 400 method = new soot.SootMethod("<init>", params, soot.VoidType.v()); 401 } 402 403 AnonClassInitMethodSource src = new AnonClassInitMethodSource(); 404 method.setSource(src); 405 sootClass.addMethod(method); 406 407 AnonLocalClassInfo info = (AnonLocalClassInfo)InitialResolver.v().finalLocalInfo().get(new polyglot.util.IdentityKey(aNew.anonType())); 408 409 if (aNew.qualifier() != null){ addQualifierRefToInit(aNew.qualifier().type()); 413 src.hasQualifier(true); 414 } 415 if (info != null && !info.inStaticMethod()){ 416 if (!InitialResolver.v().isAnonInCCall(aNew.anonType())){ 417 addOuterClassThisRefToInit(aNew.anonType().outer()); 418 addOuterClassThisRefField(aNew.anonType().outer()); 419 src.thisOuterType(Util.getSootType(aNew.anonType().outer())); 420 src.hasOuterRef(true); 421 } 422 } 423 src.polyglotType((polyglot.types.ClassType)aNew.anonType().superType()); 424 src.anonType((polyglot.types.ClassType)aNew.anonType()); 425 src.inStaticMethod(info.inStaticMethod()); 426 if (info != null){ 427 src.setFinalsList(addFinalLocals(aNew.body(), info.finalLocalsAvail(), (polyglot.types.ClassType)aNew.anonType(), info)); 428 } 429 src.outerClassType(Util.getSootType(aNew.anonType().outer())); 430 if (((polyglot.types.ClassType)aNew.objectType().type()).isNested()){ 431 src.superOuterType(Util.getSootType(((polyglot.types.ClassType)aNew.objectType().type()).outer())); 432 src.isSubType(Util.isSubType(aNew.anonType().outer(), ((polyglot.types.ClassType)aNew.objectType().type()).outer())); 433 } 434 435 Util.addLnPosTags(sootClass, aNew.position().line(), aNew.body().position().endLine(), aNew.position().column(), aNew.body().position().endColumn()); 436 } 437 438 public int getModifiers(polyglot.types.Flags flags){ 439 return Util.getModifier(flags); 440 } 441 442 445 private void addModifiers(polyglot.types.Flags flags, polyglot.ast.ClassDecl cDecl){ 446 int modifiers = 0; 447 if (cDecl.type().isNested()){ 448 if (flags.isPublic() || flags.isProtected() || flags.isPrivate()){ 449 modifiers = soot.Modifier.PUBLIC; 450 } 451 if (flags.isInterface()){ 452 modifiers = modifiers | soot.Modifier.INTERFACE; 453 } 454 if (flags.isAbstract()){ 455 modifiers = modifiers | soot.Modifier.ABSTRACT; 456 } 457 if (cDecl.type().outer().flags().isInterface()){ 462 modifiers = modifiers | soot.Modifier.PUBLIC; 463 } 464 } 465 else { 466 modifiers = getModifiers(flags); 467 } 468 sootClass.setModifiers(modifiers); 469 } 470 471 private soot.SootClass getSpecialInterfaceAnonClass(soot.SootClass addToClass){ 472 if ((InitialResolver.v().specialAnonMap() != null) && (InitialResolver.v().specialAnonMap().containsKey(addToClass))){ 475 return (soot.SootClass)InitialResolver.v().specialAnonMap().get(addToClass); 476 } 477 else { 478 String specialClassName = addToClass.getName()+"$"+InitialResolver.v().getNextAnonNum(); 479 soot.SootClass specialClass = new soot.SootClass(specialClassName); 481 soot.Scene.v().addClass(specialClass); 482 specialClass.setApplicationClass(); 483 specialClass.addTag(new soot.tagkit.SyntheticTag()); 484 specialClass.setSuperclass(soot.Scene.v().getSootClass("java.lang.Object")); 485 Util.addInnerClassTag(addToClass, specialClass.getName(), addToClass.getName(), null, soot.Modifier.STATIC); 486 Util.addInnerClassTag(specialClass, specialClass.getName(), addToClass.getName(), null, soot.Modifier.STATIC); 487 InitialResolver.v().addNameToAST(specialClassName); 488 references.add(specialClassName); 489 if (InitialResolver.v().specialAnonMap() == null){ 490 InitialResolver.v().setSpecialAnonMap(new HashMap()); 491 } 492 InitialResolver.v().specialAnonMap().put(addToClass, specialClass); 493 return specialClass; 494 } 495 } 496 497 501 private void handleAssert(polyglot.ast.ClassBody cBody){ 502 503 AssertStmtChecker asc = new AssertStmtChecker(); 505 cBody.visit(asc); 506 if (!asc.isHasAssert()) return; 507 508 510 String fieldName = "$assertionsDisabled"; 514 soot.Type fieldType = soot.BooleanType.v(); 515 if (!sootClass.declaresField(fieldName, fieldType)){ 516 soot.SootField assertionsDisabledField = new soot.SootField(fieldName, fieldType, soot.Modifier.STATIC | soot.Modifier.FINAL); 517 sootClass.addField(assertionsDisabledField); 518 assertionsDisabledField.addTag(new soot.tagkit.SyntheticTag()); 519 } 520 521 soot.SootClass addToClass = sootClass; 525 while ((InitialResolver.v().getInnerClassInfoMap() != null) && (InitialResolver.v().getInnerClassInfoMap().containsKey(addToClass))){ 526 addToClass = ((InnerClassInfo)InitialResolver.v().getInnerClassInfoMap().get(addToClass)).getOuterClass(); 527 } 528 529 fieldName = "class$"+soot.util.StringTools.replaceAll(addToClass.getName(), ".", "$"); 533 if ((InitialResolver.v().getInterfacesList() != null) && (InitialResolver.v().getInterfacesList().contains(addToClass.getName()))) { 534 addToClass = getSpecialInterfaceAnonClass(addToClass); 535 } 536 537 fieldType = soot.RefType.v("java.lang.Class"); 538 539 if (!addToClass.declaresField(fieldName, fieldType)){ 540 soot.SootField classField =new soot.SootField(fieldName, fieldType, soot.Modifier.STATIC); 541 addToClass.addField(classField); 542 classField.addTag(new soot.tagkit.SyntheticTag()); 543 } 544 545 547 String methodName = "class$"; 551 soot.Type methodRetType = soot.RefType.v("java.lang.Class"); 552 ArrayList paramTypes = new ArrayList(); 553 paramTypes.add(soot.RefType.v("java.lang.String")); 554 555 soot.SootMethod sootMethod = new soot.SootMethod(methodName, paramTypes, methodRetType, soot.Modifier.STATIC); 557 AssertClassMethodSource assertMSrc = new AssertClassMethodSource(); 558 sootMethod.setSource(assertMSrc); 559 560 if (!addToClass.declaresMethod(methodName, paramTypes, methodRetType)){ 561 addToClass.addMethod(sootMethod); 562 sootMethod.addTag(new soot.tagkit.SyntheticTag()); 563 } 564 565 methodName = "<clinit>"; 569 methodRetType = soot.VoidType.v(); 570 paramTypes = new ArrayList(); 571 572 sootMethod = new soot.SootMethod(methodName, paramTypes, methodRetType, soot.Modifier.STATIC); 574 PolyglotMethodSource mSrc = new PolyglotMethodSource(); 575 mSrc.setJBB(InitialResolver.v().getJBBFactory().createJimpleBodyBuilder()); 576 mSrc.hasAssert(true); 577 sootMethod.setSource(mSrc); 578 579 if (!sootClass.declaresMethod(methodName, paramTypes, methodRetType)){ 580 sootClass.addMethod(sootMethod); 581 } 582 else { 583 ((soot.javaToJimple.PolyglotMethodSource)sootClass.getMethod(methodName, paramTypes, methodRetType).getSource()).hasAssert(true); 584 } 585 } 586 589 private void createConstructorDecl(polyglot.ast.ConstructorDecl constructor){ 590 String name = "<init>"; 591 592 ArrayList parameters = createParameters(constructor); 593 594 ArrayList exceptions = createExceptions(constructor); 595 596 soot.SootMethod sootMethod = createSootConstructor(name, constructor.flags(), parameters, exceptions); 597 598 finishProcedure(constructor, sootMethod); 599 } 600 603 private void createMethodDecl(polyglot.ast.MethodDecl method) { 604 605 String name = createName(method); 606 607 ArrayList parameters = createParameters(method); 609 610 ArrayList exceptions = createExceptions(method); 612 613 soot.SootMethod sootMethod = createSootMethod(name, method.flags(), method.returnType().type(), parameters, exceptions); 614 615 finishProcedure(method, sootMethod); 616 } 617 620 private void finishProcedure(polyglot.ast.ProcedureDecl procedure, soot.SootMethod sootMethod){ 621 622 addProcedureToClass(sootMethod); 623 624 if (procedure.position() != null){ 625 if (procedure.body() != null) { 626 if (procedure.body().position() != null) { 627 Util.addLnPosTags(sootMethod, procedure.position().line(), procedure.body().position().endLine(), procedure.position().column(), procedure.body().position().endColumn()); 628 } 629 } 630 else { 631 Util.addLnPosTags(sootMethod, procedure.position()); 632 } 633 634 } 635 636 637 PolyglotMethodSource mSrc = new PolyglotMethodSource(procedure.body(), procedure.formals()); 638 mSrc.setJBB(InitialResolver.v().getJBBFactory().createJimpleBodyBuilder()); 639 640 sootMethod.setSource(mSrc); 641 642 } 643 644 private void handleFieldInits(){ 645 if ((fieldInits != null) || (initializerBlocks != null)) { 646 Iterator methodsIt = sootClass.getMethods().iterator(); 647 while (methodsIt.hasNext()) { 648 soot.SootMethod next = (soot.SootMethod)methodsIt.next(); 649 if (next.getName().equals("<init>")){ 650 651 soot.javaToJimple.PolyglotMethodSource src = (soot.javaToJimple.PolyglotMethodSource)next.getSource(); 652 src.setInitializerBlocks(initializerBlocks); 653 src.setFieldInits(fieldInits); 654 655 } 656 } 657 } 658 659 } 660 private void handleClassLiteral(polyglot.ast.ClassBody cBody){ 661 662 ClassLiteralChecker classLitChecker = new ClassLiteralChecker(); 664 cBody.visit(classLitChecker); 665 ArrayList classLitList = classLitChecker.getList(); 666 667 if (!classLitList.isEmpty()){ 668 669 soot.SootClass addToClass = sootClass; 670 if (addToClass.isInterface()) { 671 addToClass = getSpecialInterfaceAnonClass(addToClass); 672 } 673 674 String methodName = "class$"; 676 soot.Type methodRetType = soot.RefType.v("java.lang.Class"); 677 ArrayList paramTypes = new ArrayList(); 678 paramTypes.add(soot.RefType.v("java.lang.String")); 679 soot.SootMethod sootMethod = new soot.SootMethod(methodName, paramTypes, methodRetType, soot.Modifier.STATIC); 680 ClassLiteralMethodSource mSrc = new ClassLiteralMethodSource(); 681 sootMethod.setSource(mSrc); 682 683 if (!addToClass.declaresMethod(methodName, paramTypes, methodRetType)){ 684 addToClass.addMethod(sootMethod); 685 sootMethod.addTag(new soot.tagkit.SyntheticTag()); 686 } 687 688 689 Iterator classLitIt = classLitList.iterator(); 691 while (classLitIt.hasNext()) { 692 polyglot.ast.ClassLit classLit = (polyglot.ast.ClassLit)classLitIt.next(); 693 694 String fieldName = Util.getFieldNameForClassLit(classLit.typeNode().type()); 696 soot.Type fieldType = soot.RefType.v("java.lang.Class"); 697 698 soot.SootField sootField = new soot.SootField(fieldName, fieldType, soot.Modifier.STATIC); 699 if (!addToClass.declaresField(fieldName, fieldType)){ 700 addToClass.addField(sootField); 701 sootField.addTag(new soot.tagkit.SyntheticTag()); 702 } 703 } 704 } 705 } 706 709 private String getSimpleClassName(){ 710 String name = sootClass.getName(); 711 if (sootClass.getPackageName() != null){ 712 name = name.substring(name.lastIndexOf(".")+1, name.length()); 713 } 714 return name; 715 } 716 719 protected void createSource(polyglot.ast.SourceFile source){ 720 721 if (sootClass.hasTag("SourceFileTag")){ 723 soot.tagkit.SourceFileTag t = (soot.tagkit.SourceFileTag)sootClass.getTag("SourceFileTag"); 724 728 t.setAbsolutePath(source.source().path()); 729 } 730 else { 731 soot.tagkit.SourceFileTag t = new soot.tagkit.SourceFileTag(); 732 736 t.setAbsolutePath(source.source().path()); 737 sootClass.addTag(t); 738 } 739 740 String simpleName = sootClass.getName(); 741 742 Iterator declsIt = source.decls().iterator(); 743 boolean found = false; 744 745 while (declsIt.hasNext()){ 747 Object next = declsIt.next(); 748 if (next instanceof polyglot.ast.ClassDecl) { 749 polyglot.types.ClassType nextType = ((polyglot.ast.ClassDecl)next).type(); 750 if (Util.getSootType(nextType).equals(sootClass.getType())){ 751 createClassDecl((polyglot.ast.ClassDecl)next); 752 found = true; 753 } 754 } 755 } 756 757 if (!found) { 759 NestedClassListBuilder nestedClassBuilder = new NestedClassListBuilder(); 760 source.visit(nestedClassBuilder); 761 762 Iterator nestedDeclsIt = nestedClassBuilder.getClassDeclsList().iterator(); 763 while (nestedDeclsIt.hasNext() && !found){ 764 765 polyglot.ast.ClassDecl nextDecl = (polyglot.ast.ClassDecl)nestedDeclsIt.next(); 766 polyglot.types.ClassType type = (polyglot.types.ClassType)nextDecl.type(); 767 if (type.isLocal() && !type.isAnonymous()) { 768 769 if (InitialResolver.v().getLocalClassMap().containsVal(simpleName)){ 770 createClassDecl(((polyglot.ast.LocalClassDecl)InitialResolver.v().getLocalClassMap().getKey(simpleName)).decl()); 771 found = true; 772 } 773 } 774 else { 775 776 if (Util.getSootType(type).equals(sootClass.getType())){ 777 createClassDecl(nextDecl); 778 found = true; 779 } 780 } 781 } 782 783 if (!found) { 784 if ((InitialResolver.v().getAnonClassMap() != null) && InitialResolver.v().getAnonClassMap().containsVal(simpleName)){ 787 788 polyglot.ast.New aNew = (polyglot.ast.New)InitialResolver.v().getAnonClassMap().getKey(simpleName); 789 createAnonClassDecl(aNew); 790 findReferences(aNew.body()); 791 createClassBody(aNew.body()); 792 handleFieldInits(); 793 794 } 795 else { 796 } 801 } 802 } 803 804 805 } 806 807 private void handleInnerClassTags(polyglot.ast.ClassBody classBody){ 808 if ((InitialResolver.v().getInnerClassInfoMap() != null) && (InitialResolver.v().getInnerClassInfoMap().containsKey(sootClass))){ 810 812 InnerClassInfo tag = (InnerClassInfo)InitialResolver.v().getInnerClassInfoMap().get(sootClass); 813 Util.addInnerClassTag(sootClass, sootClass.getName(), tag.getInnerType() == InnerClassInfo.ANON ? null : tag.getOuterClass().getName(), tag.getInnerType() == InnerClassInfo.ANON ? null : tag.getSimpleName(), soot.Modifier.isInterface(tag.getOuterClass().getModifiers()) ? soot.Modifier.STATIC | soot.Modifier.PUBLIC : sootClass.getModifiers()); 814 SootClass outerClass = tag.getOuterClass(); 817 while (InitialResolver.v().getInnerClassInfoMap().containsKey(outerClass)){ 818 InnerClassInfo tag2 = (InnerClassInfo)InitialResolver.v().getInnerClassInfoMap().get(outerClass); 819 Util.addInnerClassTag(sootClass, outerClass.getName(), tag2.getInnerType() == InnerClassInfo.ANON ? null : tag2.getOuterClass().getName(), tag2.getInnerType() == InnerClassInfo.ANON ? null : tag2.getSimpleName(), tag2.getInnerType() == InnerClassInfo.ANON && soot.Modifier.isInterface(tag2.getOuterClass().getModifiers()) ? soot.Modifier.STATIC | soot.Modifier.PUBLIC : outerClass.getModifiers()); 820 outerClass = tag2.getOuterClass(); 821 } 822 } 823 824 } 825 private void addQualifierRefToInit(polyglot.types.Type type){ 826 soot.Type sootType = Util.getSootType(type); 827 Iterator it = sootClass.getMethods().iterator(); 828 while (it.hasNext()){ 829 soot.SootMethod meth = (soot.SootMethod)it.next(); 830 if (meth.getName().equals("<init>")){ 831 List newParams = new ArrayList(); 832 newParams.add(sootType); 833 newParams.addAll(meth.getParameterTypes()); 834 meth.setParameterTypes(newParams); 835 meth.addTag(new soot.tagkit.QualifyingTag()); 836 } 837 } 838 } 839 private void addProcedureToClass(soot.SootMethod method) { 840 sootClass.addMethod(method); 841 } 842 843 private void addConstValTag(polyglot.ast.FieldDecl field, soot.SootField sootField){ 844 if (field.fieldInstance().constantValue() instanceof Integer ){ 846 sootField.addTag(new soot.tagkit.IntegerConstantValueTag(((Integer )field.fieldInstance().constantValue()).intValue())); 847 } 848 else if (field.fieldInstance().constantValue() instanceof Character ){ 849 sootField.addTag(new soot.tagkit.IntegerConstantValueTag(((Character )field.fieldInstance().constantValue()).charValue())); 850 } 851 else if (field.fieldInstance().constantValue() instanceof Short ){ 852 sootField.addTag(new soot.tagkit.IntegerConstantValueTag(((Short )field.fieldInstance().constantValue()).shortValue())); 853 } 854 else if (field.fieldInstance().constantValue() instanceof Byte ){ 855 sootField.addTag(new soot.tagkit.IntegerConstantValueTag(((Byte )field.fieldInstance().constantValue()).byteValue())); 856 } 857 else if (field.fieldInstance().constantValue() instanceof Boolean ){ 858 boolean b = ((Boolean )field.fieldInstance().constantValue()).booleanValue(); 859 sootField.addTag(new soot.tagkit.IntegerConstantValueTag(b ? 1: 0)); 860 } 861 else if (field.fieldInstance().constantValue() instanceof Long ){ 862 sootField.addTag(new soot.tagkit.LongConstantValueTag(((Long )field.fieldInstance().constantValue()).longValue())); 863 } 864 else if (field.fieldInstance().constantValue() instanceof Double ){ 865 sootField.addTag(new soot.tagkit.DoubleConstantValueTag((long)((Double )field.fieldInstance().constantValue()).doubleValue())); 867 soot.tagkit.DoubleConstantValueTag tag = (soot.tagkit.DoubleConstantValueTag)sootField.getTag("DoubleConstantValueTag"); 869 } 871 else if (field.fieldInstance().constantValue() instanceof Float ){ 872 sootField.addTag(new soot.tagkit.FloatConstantValueTag(((Float )field.fieldInstance().constantValue()).floatValue())); 873 } 874 else if (field.fieldInstance().constantValue() instanceof String ){ 875 sootField.addTag(new soot.tagkit.StringConstantValueTag((String )field.fieldInstance().constantValue())); 876 } 877 else { 878 throw new RuntimeException ("Expecting static final field to have a constant value! For field: "+field+" of type: "+field.fieldInstance().constantValue().getClass()); 879 } 880 } 881 882 885 private void createFieldDecl(polyglot.ast.FieldDecl field){ 886 887 int modifiers = Util.getModifier(field.fieldInstance().flags()); 889 String name = field.fieldInstance().name(); 890 soot.Type sootType = Util.getSootType(field.fieldInstance().type()); 891 soot.SootField sootField = new soot.SootField(name, sootType, modifiers); 892 sootClass.addField(sootField); 893 894 895 if (field.fieldInstance().flags().isStatic()) { 896 if (field.init() != null) { 897 if (field.flags().isFinal() && (field.type().type().isPrimitive() || (field.type().type().toString().equals("java.lang.String"))) && field.fieldInstance().isConstant()){ 898 addConstValTag(field, sootField); 900 } 901 else { 902 if (staticFieldInits == null) { 903 staticFieldInits = new ArrayList(); 904 } 905 staticFieldInits.add(field); 906 } 907 } 908 } 909 else { 910 if (field.init() != null) { 911 if (fieldInits == null) { 912 fieldInits = new ArrayList(); 913 } 914 fieldInits.add(field); 915 } 916 } 917 918 919 Util.addLnPosTags(sootField, field.position()); 920 } 921 ClassResolver( SootClass sootClass, List references ) { 922 this.sootClass = sootClass; 923 this.references = references; 924 } 925 private final SootClass sootClass; 926 private final List references; 927 928 929 933 private String createName(polyglot.ast.ProcedureDecl procedure) { 934 return procedure.name(); 935 } 936 937 940 private ArrayList createParameters(polyglot.ast.ProcedureDecl procedure) { 941 ArrayList parameters = new ArrayList(); 942 Iterator formalsIt = procedure.formals().iterator(); 943 while (formalsIt.hasNext()){ 944 polyglot.ast.Formal next = (polyglot.ast.Formal)formalsIt.next(); 945 parameters.add(Util.getSootType(next.type().type())); 946 } 947 return parameters; 948 } 949 950 953 private ArrayList createExceptions(polyglot.ast.ProcedureDecl procedure) { 954 ArrayList exceptions = new ArrayList(); 955 Iterator throwsIt = procedure.throwTypes().iterator(); 956 while (throwsIt.hasNext()){ 957 polyglot.types.Type throwType = ((polyglot.ast.TypeNode)throwsIt.next()).type(); 958 exceptions.add(((soot.RefType)Util.getSootType(throwType)).getSootClass()); 959 } 960 return exceptions; 961 } 962 963 964 private soot.SootMethod createSootMethod(String name, polyglot.types.Flags flags , polyglot.types.Type returnType, ArrayList parameters, ArrayList exceptions){ 965 966 int modifier = Util.getModifier(flags); 967 soot.Type sootReturnType = Util.getSootType(returnType); 968 969 soot.SootMethod method = new soot.SootMethod(name, parameters, sootReturnType, modifier, exceptions); 970 return method; 971 } 972 973 976 private void createInitializer(polyglot.ast.Initializer initializer) { 977 if (initializer.flags().isStatic()) { 978 if (staticInitializerBlocks == null) { 979 staticInitializerBlocks = new ArrayList(); 980 } 981 staticInitializerBlocks.add(initializer.body()); 982 } 983 else { 984 if (initializerBlocks == null) { 985 initializerBlocks = new ArrayList(); 986 } 987 initializerBlocks.add(initializer.body()); 988 } 989 } 990 991 private soot.SootMethod createSootConstructor(String name, polyglot.types.Flags flags, ArrayList parameters, ArrayList exceptions) { 992 993 int modifier = Util.getModifier(flags); 994 995 soot.SootMethod method = new soot.SootMethod(name, parameters, soot.VoidType.v(), modifier, exceptions); 996 997 return method; 998 } 999 1000} 1001 1002 | Popular Tags |