1 20 21 26 27 package soot; 28 import soot.tagkit.*; 29 import soot.util.*; 30 import java.util.*; 31 32 import soot.dava.*; 33 34 39 public class SootMethod 40 extends AbstractHost 41 implements ClassMember, Numberable, MethodOrMethodContext { 42 public static final String constructorName = "<init>"; 43 public static final String staticInitializerName = "<clinit>"; 44 45 46 String name; 47 48 50 List parameterTypes; 51 52 53 Type returnType; 54 55 56 boolean isDeclared; 57 58 59 SootClass declaringClass; 60 61 62 int modifiers; 63 64 65 boolean isPhantom = false; 66 67 68 List exceptions = null; 69 70 71 Body activeBody; 72 73 74 protected MethodSource ms; 75 76 80 private Body getBodyFromMethodSource(String phaseName) { 81 return ms.getBody(this, phaseName); 82 } 83 84 85 public void setSource(MethodSource ms) { 86 this.ms = ms; 87 } 88 89 90 public MethodSource getSource() { 91 return ms; 92 } 93 94 95 public int equivHashCode() { 96 return returnType.hashCode() * 101 + modifiers * 17 + name.hashCode(); 97 } 98 99 100 public SootMethod(String name, List parameterTypes, Type returnType) { 101 this.name = name; 102 this.parameterTypes = new ArrayList(); 103 this.parameterTypes.addAll(parameterTypes); 104 this.parameterTypes = Collections.unmodifiableList(this.parameterTypes); 105 this.returnType = returnType; 106 Scene.v().getMethodNumberer().add(this); 107 subsignature = 108 Scene.v().getSubSigNumberer().findOrAdd(getSubSignature()); 109 } 110 111 112 public SootMethod( 113 String name, 114 List parameterTypes, 115 Type returnType, 116 int modifiers) { 117 this.name = name; 118 this.parameterTypes = new ArrayList(); 119 this.parameterTypes.addAll(parameterTypes); 120 121 this.returnType = returnType; 122 this.modifiers = modifiers; 123 Scene.v().getMethodNumberer().add(this); 124 subsignature = 125 Scene.v().getSubSigNumberer().findOrAdd(getSubSignature()); 126 } 127 128 130 public SootMethod( 131 String name, 132 List parameterTypes, 133 Type returnType, 134 int modifiers, 135 List thrownExceptions) { 136 this.name = name; 137 this.parameterTypes = new ArrayList(); 138 this.parameterTypes.addAll(parameterTypes); 139 140 this.returnType = returnType; 141 this.modifiers = modifiers; 142 143 if (exceptions == null && !thrownExceptions.isEmpty()) { 144 exceptions = new ArrayList(); 145 this.exceptions.addAll(thrownExceptions); 146 } 147 Scene.v().getMethodNumberer().add(this); 148 subsignature = 149 Scene.v().getSubSigNumberer().findOrAdd(getSubSignature()); 150 } 151 152 153 public String getName() { 154 return name; 155 } 156 157 165 public void setDeclaringClass(SootClass declClass){ 166 if(declClass != null){ 167 declaringClass=declClass; 168 } 170 } 171 172 173 public SootClass getDeclaringClass() { 174 if (!isDeclared) 175 throw new RuntimeException ("not declared: " + getName()); 176 177 return declaringClass; 178 } 179 180 public void setDeclared(boolean isDeclared) { 181 this.isDeclared = isDeclared; 182 } 183 184 185 public boolean isDeclared() { 186 return isDeclared; 187 } 188 189 190 public boolean isPhantom() { 191 return isPhantom; 192 } 193 194 197 198 public boolean isConcrete() { 199 return !isPhantom() && !isAbstract() && !isNative(); 200 } 201 202 203 public void setPhantom(boolean value) { 204 if (value) { 205 if (!Scene.v().allowsPhantomRefs()) 206 throw new RuntimeException ("Phantom refs not allowed"); 207 if (declaringClass != null && !declaringClass.isPhantom()) 208 throw new RuntimeException ("Declaring class would have to be phantom"); 209 } 210 isPhantom = value; 211 } 212 213 214 public void setName(String name) { 215 boolean wasDeclared = isDeclared; 216 SootClass oldDeclaringClass = declaringClass; 217 if( wasDeclared ) oldDeclaringClass.removeMethod(this); 218 this.name = name; 219 subsignature = 220 Scene.v().getSubSigNumberer().findOrAdd(getSubSignature()); 221 if( wasDeclared) oldDeclaringClass.addMethod(this); 222 } 223 224 226 public int getModifiers() { 227 return modifiers; 228 } 229 230 232 public void setModifiers(int modifiers) { 233 if ((declaringClass != null) && (!declaringClass.isApplicationClass())) 234 throw new RuntimeException ("Cannot set modifiers of a method from a non-app class!"); 235 this.modifiers = modifiers; 236 } 237 238 239 public Type getReturnType() { 240 return returnType; 241 } 242 243 244 public void setReturnType(Type t) { 245 boolean wasDeclared = isDeclared; 246 SootClass oldDeclaringClass = declaringClass; 247 if( wasDeclared ) oldDeclaringClass.removeMethod(this); 248 returnType = t; 249 subsignature = 250 Scene.v().getSubSigNumberer().findOrAdd(getSubSignature()); 251 if( wasDeclared) oldDeclaringClass.addMethod(this); 252 } 253 254 255 public int getParameterCount() { 256 return parameterTypes.size(); 257 } 258 259 260 public Type getParameterType(int n) { 261 return (Type) parameterTypes.get(n); 262 } 263 264 267 public List getParameterTypes() { 268 return parameterTypes; 269 } 270 271 274 public void setParameterTypes( List l ) { 275 boolean wasDeclared = isDeclared; 276 SootClass oldDeclaringClass = declaringClass; 277 if( wasDeclared ) oldDeclaringClass.removeMethod(this); 278 List al = new ArrayList(); 279 al.addAll(l); 280 this.parameterTypes = Collections.unmodifiableList(al); 281 subsignature = 282 Scene.v().getSubSigNumberer().findOrAdd(getSubSignature()); 283 if( wasDeclared) oldDeclaringClass.addMethod(this); 284 } 285 286 289 public Body getActiveBody() { 290 if (declaringClass!=null && declaringClass.isPhantomClass()) 291 throw new RuntimeException ( 292 "cannot get active body for phantom class: " + getSignature()); 293 294 if (!hasActiveBody()) 295 throw new RuntimeException ( 296 "no active body present for method " + getSignature()); 297 298 return activeBody; 299 } 300 301 308 309 public Body retrieveActiveBody() { 310 declaringClass.checkLevel(SootClass.BODIES); 311 if (declaringClass.isPhantomClass()) 312 throw new RuntimeException ( 313 "cannot get resident body for phantom class : " 314 + getSignature() 315 + "; maybe you want to call c.setApplicationClass() on this class!"); 316 317 if (!hasActiveBody()) { 318 320 setActiveBody(this.getBodyFromMethodSource("jb")); 321 ms = null; 322 } 323 return getActiveBody(); 324 } 325 326 329 public void setActiveBody(Body body) { 330 if ((declaringClass != null) 331 && declaringClass.isPhantomClass()) 332 throw new RuntimeException ( 333 "cannot set active body for phantom class! " + this); 334 335 if (!isConcrete()) 336 throw new RuntimeException ( 337 "cannot set body for non-concrete method! " + this); 338 339 if (body.getMethod() != this) 340 body.setMethod(this); 341 342 activeBody = body; 343 } 344 345 346 public boolean hasActiveBody() { 347 return activeBody != null; 348 } 349 350 351 public void releaseActiveBody() { 352 activeBody = null; 353 } 354 355 357 public void addExceptionIfAbsent(SootClass e) { 358 if( !throwsException(e) ) addException(e); 359 } 360 361 public void addException(SootClass e) { 362 if (exceptions == null) 363 exceptions = new ArrayList(); 364 else if (exceptions.contains(e)) 365 throw new RuntimeException ( 366 "already throws exception " + e.getName()); 367 368 exceptions.add(e); 369 } 370 371 372 public void removeException(SootClass e) { 373 if (exceptions == null) 374 exceptions = new ArrayList(); 375 376 if (!exceptions.contains(e)) 377 throw new RuntimeException ( 378 "does not throw exception " + e.getName()); 379 380 exceptions.remove(e); 381 } 382 383 384 public boolean throwsException(SootClass e) { 385 return exceptions != null && exceptions.contains(e); 386 } 387 388 public void setExceptions(List exceptions) { 389 this.exceptions = new ArrayList(); 390 this.exceptions.addAll(exceptions); 391 } 392 393 396 397 public List getExceptions() { 398 if (exceptions == null) 399 exceptions = new ArrayList(); 400 401 return exceptions; 402 } 403 404 407 public boolean isStatic() { 408 return Modifier.isStatic(this.getModifiers()); 409 } 410 411 414 public boolean isPrivate() { 415 return Modifier.isPrivate(this.getModifiers()); 416 } 417 418 421 public boolean isPublic() { 422 return Modifier.isPublic(this.getModifiers()); 423 } 424 425 428 public boolean isProtected() { 429 return Modifier.isProtected(this.getModifiers()); 430 } 431 432 435 public boolean isAbstract() { 436 return Modifier.isAbstract(this.getModifiers()); 437 } 438 439 442 public boolean isNative() { 443 return Modifier.isNative(this.getModifiers()); 444 } 445 446 449 public boolean isSynchronized() { 450 return Modifier.isSynchronized(this.getModifiers()); 451 } 452 453 455 public String getBytecodeParms() { 456 StringBuffer buffer = new StringBuffer (); 457 for( Iterator typeIt = getParameterTypes().iterator(); typeIt.hasNext(); ) { 458 final Type type = (Type) typeIt.next(); 459 buffer.append(soot.jimple.JasminClass.jasminDescriptorOf(type)); 460 } 461 return buffer.toString().intern(); 462 } 463 464 468 public String getBytecodeSignature() { 469 String name = getName(); 470 471 StringBuffer buffer = new StringBuffer (); 472 buffer.append( 473 "<" + Scene.v().quotedNameOf(getDeclaringClass().getName()) + ": "); 474 buffer.append(name); 475 buffer.append(soot.jimple.JasminClass.jasminDescriptorOf(makeRef())); 476 buffer.append(">"); 477 478 return buffer.toString().intern(); 479 } 480 481 484 public String getSignature() { 485 return getSignature(getDeclaringClass(), getName(), getParameterTypes(), getReturnType()); 486 } 487 public static String getSignature(SootClass cl, String name, List params, Type returnType) { 488 StringBuffer buffer = new StringBuffer (); 489 buffer.append( 490 "<" + Scene.v().quotedNameOf(cl.getName()) + ": "); 491 buffer.append(getSubSignatureImpl(name, params, returnType)); 492 buffer.append(">"); 493 494 return buffer.toString().intern(); 497 } 498 499 502 public String getSubSignature() { 503 String name = getName(); 504 List params = getParameterTypes(); 505 Type returnType = getReturnType(); 506 507 return getSubSignatureImpl(name, params, returnType); 508 } 509 510 public static String getSubSignature( 511 String name, 512 List params, 513 Type returnType) { 514 return getSubSignatureImpl(name, params, returnType); 515 } 516 517 private static String getSubSignatureImpl( 518 String name, 519 List params, 520 Type returnType) { 521 StringBuffer buffer = new StringBuffer (); 522 Type t = returnType; 523 524 buffer.append(t.toString() + " " + Scene.v().quotedNameOf(name) + "("); 525 526 Iterator typeIt = params.iterator(); 527 528 if (typeIt.hasNext()) { 529 t = (Type) typeIt.next(); 530 531 buffer.append(t); 532 533 while (typeIt.hasNext()) { 534 buffer.append(","); 535 536 t = (Type) typeIt.next(); 537 buffer.append(t); 538 } 539 } 540 buffer.append(")"); 541 542 return buffer.toString().intern(); 543 } 544 545 private NumberedString subsignature; 546 public NumberedString getNumberedSubSignature() { 547 return subsignature; 548 } 549 550 551 public String toString() { 552 return getSignature(); 553 } 554 555 562 public String getDavaDeclaration() { 563 if (getName().equals(staticInitializerName)) 564 return "static"; 565 566 StringBuffer buffer = new StringBuffer (); 567 568 StringTokenizer st = 570 new StringTokenizer(Modifier.toString(this.getModifiers())); 571 if (st.hasMoreTokens()) 572 buffer.append(st.nextToken()); 573 574 while (st.hasMoreTokens()) 575 buffer.append(" " + st.nextToken()); 576 577 if (buffer.length() != 0) 578 buffer.append(" "); 579 580 582 if (getName().equals(constructorName)) 583 buffer.append(getDeclaringClass().getShortJavaStyleName()); 584 else { 585 Type t = this.getReturnType(); 586 587 String tempString = t.toString(); 588 589 Map options = PhaseOptions.v().getPhaseOptions("db.renamer"); 590 boolean force = PhaseOptions.getBoolean(options, "remove-fully-qualified"); 591 if (force) { 592 DavaBody body = (DavaBody) getActiveBody(); 593 IterableSet set = body.get_PackagesUsed(); 594 595 String packageName = null; 597 if (tempString.lastIndexOf('.') > 0) { packageName = tempString.substring(0, tempString 599 .lastIndexOf('.')); 600 } 601 if (packageName != null) { 602 if (!set.contains(packageName)) { 606 body.addPackage(packageName); 608 } else { 610 } 612 613 tempString = tempString.substring(tempString 615 .lastIndexOf('.') + 1); 616 } 617 } 618 619 buffer.append(tempString + " "); 620 621 622 623 buffer.append(Scene.v().quotedNameOf(this.getName())); 625 } 626 627 buffer.append("("); 628 629 Iterator typeIt = this.getParameterTypes().iterator(); 631 int count = 0; 632 while (typeIt.hasNext()) { 633 Type t = (Type) typeIt.next(); 634 String tempString = t.toString(); 635 636 643 644 Map options = PhaseOptions.v().getPhaseOptions("db.renamer"); 645 boolean force = PhaseOptions.getBoolean(options, "remove-fully-qualified"); 646 if (force) { 647 DavaBody body = (DavaBody) getActiveBody(); 648 IterableSet set = body.get_PackagesUsed(); 649 650 String packageName = null; 652 if (tempString.lastIndexOf('.') > 0) { packageName = tempString.substring(0, tempString 654 .lastIndexOf('.')); 655 } 656 if (packageName != null) { 657 if (!set.contains(packageName)) { 661 body.addPackage(packageName); 663 } else { 665 } 667 668 tempString = tempString.substring(tempString 670 .lastIndexOf('.') + 1); 671 } 672 } 673 674 buffer.append(tempString); 675 676 buffer.append(" "); 677 if (hasActiveBody()){ 678 buffer.append(((DavaBody) getActiveBody()).get_ParamMap().get(new Integer (count++))); 679 } 680 else { 681 if (t == BooleanType.v()) 682 buffer.append("z" + count++); 683 else if (t == ByteType.v()) 684 buffer.append("b" + count++); 685 else if (t == ShortType.v()) 686 buffer.append("s" + count++); 687 else if (t == CharType.v()) 688 buffer.append("c" + count++); 689 else if (t == IntType.v()) 690 buffer.append("i" + count++); 691 else if (t == LongType.v()) 692 buffer.append("l" + count++); 693 else if (t == DoubleType.v()) 694 buffer.append("d" + count++); 695 else if (t == FloatType.v()) 696 buffer.append("f" + count++); 697 else if (t == StmtAddressType.v()) 698 buffer.append("a" + count++); 699 else if (t == ErroneousType.v()) 700 buffer.append("e" + count++); 701 else if (t == NullType.v()) 702 buffer.append("n" + count++); 703 else 704 buffer.append("r" + count++); 705 } 706 707 if (typeIt.hasNext()) 708 buffer.append(", "); 709 710 } 711 712 buffer.append(")"); 713 714 if (exceptions != null) { 716 Iterator exceptionIt = this.getExceptions().iterator(); 717 718 if (exceptionIt.hasNext()) { 719 buffer.append( 720 " throws " + ((SootClass) exceptionIt.next()).getName()); 721 722 while (exceptionIt.hasNext()) { 723 buffer.append( 724 ", " + ((SootClass) exceptionIt.next()).getName()); 725 } 726 } 727 } 728 729 return buffer.toString().intern(); 730 } 731 732 736 public String getDeclaration() { 737 StringBuffer buffer = new StringBuffer (); 738 739 StringTokenizer st = 741 new StringTokenizer(Modifier.toString(this.getModifiers())); 742 if (st.hasMoreTokens()) 743 buffer.append(st.nextToken()); 744 745 while (st.hasMoreTokens()) 746 buffer.append(" " + st.nextToken()); 747 748 if (buffer.length() != 0) 749 buffer.append(" "); 750 751 753 buffer.append(this.getReturnType() + " "); 754 buffer.append(Scene.v().quotedNameOf(this.getName())); 755 756 buffer.append("("); 757 758 Iterator typeIt = this.getParameterTypes().iterator(); 760 while (typeIt.hasNext()) { 762 Type t = (Type) typeIt.next(); 763 764 buffer.append(t); 765 766 if (typeIt.hasNext()) 767 buffer.append(", "); 768 769 } 770 771 buffer.append(")"); 772 773 if (exceptions != null) { 775 Iterator exceptionIt = this.getExceptions().iterator(); 776 777 if (exceptionIt.hasNext()) { 778 buffer.append( 779 " throws " + ((SootClass) exceptionIt.next()).getName()); 780 781 while (exceptionIt.hasNext()) { 782 buffer.append( 783 ", " + ((SootClass) exceptionIt.next()).getName()); 784 } 785 } 786 } 787 788 return buffer.toString().intern(); 789 } 790 public final int getNumber() { 791 return number; 792 } 793 public final void setNumber(int number) { 794 this.number = number; 795 } 796 private int number = 0; 797 public SootMethod method() { return this; } 798 public Context context() { return null; } 799 public SootMethodRef makeRef() { 800 return Scene.v().makeMethodRef( declaringClass, name, parameterTypes, returnType, isStatic() ); 801 } 802 } 803 | Popular Tags |