1 20 21 26 27 28 29 30 31 package soot; 32 import soot.options.*; 33 import soot.tagkit.*; 34 import soot.*; 35 import soot.jimple.*; 36 import soot.toolkits.graph.*; 37 import soot.util.*; 38 import java.util.*; 39 import java.io.*; 40 import soot.baf.*; 41 42 public abstract class AbstractJasminClass 43 { 44 protected Map unitToLabel; 45 protected Map localToSlot; 46 protected Map subroutineToReturnAddressSlot; 47 48 protected List code; 49 50 protected boolean isEmittingMethodCode; 51 protected int labelCount; 52 53 protected boolean isNextGotoAJsr; 54 protected int returnAddressSlot; 55 protected int currentStackHeight = 0; 56 protected int maxStackHeight = 0; 57 58 protected Map localToGroup; 59 protected Map groupToColorCount; 60 protected Map localToColor; 61 62 63 protected Map blockToStackHeight = new HashMap(); protected Map blockToLogicalStackHeight = new HashMap(); 66 67 public static String slashify(String s) 68 { 69 return s.replace('.', '/'); 70 } 71 72 public static int sizeOfType(Type t) 73 { 74 if(t instanceof DoubleWordType || t instanceof LongType || t instanceof DoubleType) 75 return 2; 76 else if(t instanceof VoidType) 77 return 0; 78 else 79 return 1; 80 } 81 82 public static int argCountOf(SootMethodRef m) 83 { 84 int argCount = 0; 85 Iterator typeIt = m.parameterTypes().iterator(); 86 87 while(typeIt.hasNext()) 88 { 89 Type t = (Type) typeIt.next(); 90 91 argCount += sizeOfType(t); 92 } 93 94 return argCount; 95 } 96 97 public static String jasminDescriptorOf(Type type) 98 { 99 TypeSwitch sw; 100 101 type.apply(sw = new TypeSwitch() 102 { 103 public void caseBooleanType(BooleanType t) 104 { 105 setResult("Z"); 106 } 107 108 public void caseByteType(ByteType t) 109 { 110 setResult("B"); 111 } 112 113 public void caseCharType(CharType t) 114 { 115 setResult("C"); 116 } 117 118 public void caseDoubleType(DoubleType t) 119 { 120 setResult("D"); 121 } 122 123 public void caseFloatType(FloatType t) 124 { 125 setResult("F"); 126 } 127 128 public void caseIntType(IntType t) 129 { 130 setResult("I"); 131 } 132 133 public void caseLongType(LongType t) 134 { 135 setResult("J"); 136 } 137 138 public void caseShortType(ShortType t) 139 { 140 setResult("S"); 141 } 142 143 public void defaultCase(Type t) 144 { 145 throw new RuntimeException ("Invalid type: " + t); 146 } 147 148 public void caseArrayType(ArrayType t) 149 { 150 StringBuffer buffer = new StringBuffer (); 151 152 for(int i = 0; i < t.numDimensions; i++) 153 buffer.append("["); 154 155 setResult(buffer.toString() + jasminDescriptorOf(t.baseType)); 156 } 157 158 public void caseRefType(RefType t) 159 { 160 setResult("L" + t.getClassName().replace('.', '/') + ";"); 161 } 162 163 public void caseVoidType(VoidType t) 164 { 165 setResult("V"); 166 } 167 }); 168 169 return (String ) sw.getResult(); 170 171 } 172 173 public static String jasminDescriptorOf(SootMethodRef m) 174 { 175 StringBuffer buffer = new StringBuffer (); 176 177 buffer.append("("); 178 179 { 181 Iterator typeIt = m.parameterTypes().iterator(); 182 183 while(typeIt.hasNext()) 184 { 185 Type t = (Type) typeIt.next(); 186 187 buffer.append(jasminDescriptorOf(t)); 188 } 189 } 190 191 buffer.append(")"); 192 193 buffer.append(jasminDescriptorOf(m.returnType())); 194 195 return buffer.toString(); 196 } 197 198 protected void emit(String s) 199 { 200 okayEmit(s); 201 } 202 203 protected void okayEmit(String s) 204 { 205 if(isEmittingMethodCode && !s.endsWith(":")) 206 code.add(" " + s); 207 else 208 code.add(s); 209 } 210 211 private String getVisibilityAnnotationAttr(VisibilityAnnotationTag tag){ 212 StringBuffer sb = new StringBuffer (); 213 if (tag.getVisibility() == AnnotationConstants.RUNTIME_VISIBLE){ 214 sb.append(".runtime_visible_annotation\n"); 215 } 216 else { 217 sb.append(".runtime_invisible_annotation\n"); 218 } 219 if (tag.hasAnnotations()){ 220 Iterator it = tag.getAnnotations().iterator(); 221 while (it.hasNext()){ 222 AnnotationTag annot = (AnnotationTag)it.next(); 223 sb.append(".annotation "); 224 sb.append(soot.util.StringTools.getQuotedStringOf(annot.getType())+"\n"); 225 for (int i = 0; i < annot.getNumElems(); i++){ 226 sb.append(getElemAttr(annot.getElemAt(i))); 227 } 228 sb.append(".end .annotation\n"); 229 } 230 } 231 sb.append(".end .annotation_attr\n"); 232 return sb.toString(); 233 } 234 235 236 private String getVisibilityParameterAnnotationAttr(VisibilityParameterAnnotationTag tag){ 237 StringBuffer sb = new StringBuffer (); 238 sb.append(".param "); 239 if (tag.getKind() == AnnotationConstants.RUNTIME_VISIBLE){ 240 sb.append(".runtime_visible_annotation\n"); 241 } 242 else { 243 sb.append(".runtime_invisible_annotation\n"); 244 } 245 ArrayList vis_list = tag.getVisibilityAnnotations(); 246 if (vis_list != null){ 247 Iterator it = vis_list.iterator(); 248 while (it.hasNext()){ 249 sb.append(getVisibilityAnnotationAttr((VisibilityAnnotationTag)it.next())); 250 } 251 } 252 sb.append(".end .param\n"); 253 return sb.toString(); 254 } 255 256 private String getElemAttr(AnnotationElem elem){ 257 StringBuffer result = new StringBuffer (".elem "); 258 switch (elem.getKind()){ 259 case 'Z': { 260 result.append(".bool_kind "); 261 result.append("\""+elem.getName()+"\" "); 262 result.append(((AnnotationIntElem)elem).getValue()); 263 result.append("\n"); 264 break; 265 } 266 case 'S': { 267 result.append(".short_kind "); 268 result.append("\""+elem.getName()+"\" "); 269 result.append(((AnnotationIntElem)elem).getValue()); 270 result.append("\n"); 271 break; 272 } 273 case 'B': { 274 result.append(".byte_kind "); 275 result.append("\""+elem.getName()+"\" "); 276 result.append(((AnnotationIntElem)elem).getValue()); 277 result.append("\n"); 278 break; 279 } 280 case 'C': { 281 result.append(".char_kind "); 282 result.append("\""+elem.getName()+"\" "); 283 result.append(((AnnotationIntElem)elem).getValue()); 284 result.append("\n"); 285 break; 286 } 287 case 'I': { 288 result.append(".int_kind "); 289 result.append("\""+elem.getName()+"\" "); 290 result.append(((AnnotationIntElem)elem).getValue()); 291 result.append("\n"); 292 break; 293 } 294 case 'J': { 295 result.append(".long_kind "); 296 result.append("\""+elem.getName()+"\" "); 297 result.append(((AnnotationLongElem)elem).getValue()); 298 result.append("\n"); 299 break; 300 } 301 case 'F': { 302 result.append(".float_kind "); 303 result.append("\""+elem.getName()+"\" "); 304 result.append(Float.floatToRawIntBits(((AnnotationFloatElem)elem).getValue())); 305 result.append("\n"); 306 break; 307 } 308 case 'D': { 309 result.append(".doub_kind "); 310 result.append("\""+elem.getName()+"\" "); 311 result.append(Double.doubleToRawLongBits(((AnnotationDoubleElem)elem).getValue())); 312 result.append("\n"); 313 break; 314 } 315 case 's': { 316 result.append(".str_kind "); 317 result.append("\""+elem.getName()+"\" "); 318 result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationStringElem)elem).getValue())); 319 result.append("\n"); 320 break; 321 } 322 case 'e': { 323 result.append(".enum_kind "); 324 result.append("\""+elem.getName()+"\" "); 325 result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationEnumElem)elem).getTypeName())); 326 result.append(" "); 327 result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationEnumElem)elem).getConstantName())); 328 result.append("\n"); 329 break; 330 } 331 case 'c': { 332 result.append(".cls_kind "); 333 result.append("\""+elem.getName()+"\" "); 334 result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationClassElem)elem).getDesc())); 335 result.append("\n"); 336 break; 337 } 338 case '[': { 339 result.append(".arr_kind "); 340 result.append("\""+elem.getName()+"\" "); 341 AnnotationArrayElem arrayElem = (AnnotationArrayElem)elem; 342 result.append("\n"); 343 for (int i = 0; i < arrayElem.getNumValues(); i++){ 344 result.append(getElemAttr(arrayElem.getValueAt(i))); 346 } 347 result.append(".end .arr_elem\n"); 348 break; 349 } 350 case '@': { 351 result.append(".ann_kind "); 352 result.append("\""+elem.getName()+"\"\n"); 353 AnnotationTag annot = ((AnnotationAnnotationElem)elem).getValue(); 354 result.append(".annotation "); 355 result.append(soot.util.StringTools.getQuotedStringOf(annot.getType())+"\n"); 356 for (int i = 0; i < annot.getNumElems(); i++){ 357 result.append(getElemAttr(annot.getElemAt(i))); 358 } 359 result.append(".end .annotation\n"); 360 result.append(".end .annot_elem\n"); 361 break; 362 } 363 default : { 364 throw new RuntimeException ("Unknown Elem Attr Kind: "+elem.getKind()); 365 } 366 } 367 return result.toString(); 368 } 369 370 public AbstractJasminClass(SootClass sootClass) 371 { 372 if(Options.v().time()) 373 Timers.v().buildJasminTimer.start(); 374 375 if(Options.v().verbose()) 376 G.v().out.println("[" + sootClass.getName() + "] Constructing baf.JasminClass..."); 377 378 code = new LinkedList(); 379 380 { 382 int modifiers = sootClass.getModifiers(); 383 384 385 if ((sootClass.getTag("SourceFileTag") != null) && (!Options.v().no_output_source_file_attribute())){ 386 String srcName = ((SourceFileTag)sootClass.getTag("SourceFileTag")).getSourceFile(); 387 emit(".source "+soot.util.StringTools.getEscapedStringOf(srcName)); 388 } 389 if(Modifier.isInterface(modifiers)) 390 { 391 modifiers -= Modifier.INTERFACE; 392 393 emit(".interface " + Modifier.toString(modifiers) + " " + slashify(sootClass.getName())); 394 } 395 else 396 emit(".class " + Modifier.toString(modifiers) + " " + slashify(sootClass.getName())); 397 398 if(sootClass.hasSuperclass()) 399 emit(".super " + slashify(sootClass.getSuperclass().getName())); 400 else 401 emit(".no_super"); 402 403 emit(""); 404 } 405 406 { 408 Iterator interfaceIt = sootClass.getInterfaces().iterator(); 409 410 while(interfaceIt.hasNext()) 411 { 412 SootClass inter = (SootClass) interfaceIt.next(); 413 414 emit(".implements " + slashify(inter.getName())); 415 } 416 417 420 } 421 422 423 424 425 426 427 Iterator it = sootClass.getTags().iterator(); 429 while(it.hasNext()) { 430 Tag tag = (Tag) it.next(); 431 if(tag instanceof Attribute) 432 emit(".class_attribute " + tag.getName() + " \"" + new String (Base64.encode(((Attribute)tag).getValue()))+"\""); 433 436 } 437 438 439 if (sootClass.hasTag("SyntheticTag")){ 441 emit(".synthetic\n"); 442 } 443 if (sootClass.hasTag("DeprecatedTag")){ 445 emit(".deprecated\n"); 446 } 447 if (sootClass.hasTag("InnerClassAttribute")){ 449 if (!Options.v().no_output_inner_classes_attribute()){ 450 emit(".inner_class_attr "); 451 Iterator innersIt = ((InnerClassAttribute)sootClass.getTag("InnerClassAttribute")).getSpecs().iterator(); 452 while (innersIt.hasNext()){ 453 InnerClassTag ict = (InnerClassTag)innersIt.next(); 454 emit(".inner_class_spec_attr "+ 456 "\""+ict.getInnerClass()+"\" "+ 457 458 "\""+ict.getOuterClass()+"\" "+ 459 460 "\""+ict.getShortName()+"\" "+ 461 Modifier.toString(ict.getAccessFlags())+" "+ 462 463 ".end .inner_class_spec_attr"); 464 } 465 emit(".end .inner_class_attr\n"); 466 } 467 } 468 if (sootClass.hasTag("EnclosingMethodTag")){ 469 String encMeth = ".enclosing_method_attr "; 470 EnclosingMethodTag eMethTag = (EnclosingMethodTag)sootClass.getTag("EnclosingMethodTag"); 471 encMeth += "\""+eMethTag.getEnclosingClass()+"\" "; 472 encMeth += "\""+eMethTag.getEnclosingMethod()+"\" "; 473 encMeth += "\""+eMethTag.getEnclosingMethodSig()+"\"\n"; 474 emit(encMeth); 475 } 476 if (sootClass.hasTag("SignatureTag")){ 477 String sigAttr = ".signature_attr "; 478 SignatureTag sigTag = (SignatureTag)sootClass.getTag("SignatureTag"); 479 sigAttr += "\""+sigTag.getSignature()+"\"\n"; 480 emit(sigAttr); 481 } 482 483 Iterator vit = sootClass.getTags().iterator(); 484 while (vit.hasNext()){ 485 Tag t = (Tag)vit.next(); 486 if (t.getName().equals("VisibilityAnnotationTag")){ 487 emit(getVisibilityAnnotationAttr((VisibilityAnnotationTag)t)); 488 } 489 } 490 491 { 493 Iterator fieldIt = sootClass.getFields().iterator(); 494 495 while(fieldIt.hasNext()) 496 { 497 SootField field = (SootField) fieldIt.next(); 498 499 String fieldString = ".field " + Modifier.toString(field.getModifiers()) + " " + "\"" + field.getName() + "\"" + " " + jasminDescriptorOf(field.getType()); 500 501 if (field.hasTag("StringConstantValueTag")){ 502 fieldString += " = "; 503 fieldString += soot.util.StringTools.getQuotedStringOf(((StringConstantValueTag)field.getTag("StringConstantValueTag")).getStringValue()); 504 } 505 else if (field.hasTag("IntegerConstantValueTag")){ 506 fieldString += " = "; 507 fieldString += ((IntegerConstantValueTag)field.getTag("IntegerConstantValueTag")).getIntValue(); 508 } 509 else if (field.hasTag("LongConstantValueTag")){ 510 fieldString += " = "; 511 fieldString += ((LongConstantValueTag)field.getTag("LongConstantValueTag")).getLongValue(); 512 } 513 else if (field.hasTag("FloatConstantValueTag")){ 514 fieldString += " = "; 515 float val = ((FloatConstantValueTag)field.getTag("FloatConstantValueTag")).getFloatValue(); 516 fieldString += Float.floatToRawIntBits(val); 517 } 518 else if (field.hasTag("DoubleConstantValueTag")){ 519 fieldString += " = "; 520 double val = ((DoubleConstantValueTag)field.getTag("DoubleConstantValueTag")).getDoubleValue(); 521 fieldString += Double.doubleToRawLongBits(val); 522 } 523 if (field.hasTag("SyntheticTag")){ 524 fieldString +=" .synthetic"; 525 } 526 527 fieldString +="\n"; 528 if (field.hasTag("DeprecatedTag")){ 529 fieldString +=".deprecated\n"; 530 } 531 if (field.hasTag("SignatureTag")){ 532 fieldString += ".signature_attr "; 533 SignatureTag sigTag = (SignatureTag)field.getTag("SignatureTag"); 534 fieldString += "\""+sigTag.getSignature()+"\"\n"; 535 } 536 Iterator vfit = field.getTags().iterator(); 537 while (vfit.hasNext()){ 538 Tag t = (Tag)vfit.next(); 539 if (t.getName().equals("VisibilityAnnotationTag")){ 540 fieldString += getVisibilityAnnotationAttr((VisibilityAnnotationTag)t); 541 } 542 } 543 544 emit(fieldString); 545 546 Iterator attributeIt = field.getTags().iterator(); 547 while(attributeIt.hasNext()) { 548 Tag tag = (Tag) attributeIt.next(); 549 if(tag instanceof Attribute) 550 emit(".field_attribute " + tag.getName() + " \"" + new String (Base64.encode(((Attribute)tag).getValue())) +"\""); 551 } 552 553 } 554 555 if(sootClass.getFieldCount() != 0) 556 emit(""); 557 } 558 559 { 561 Iterator methodIt = sootClass.methodIterator(); 562 563 while(methodIt.hasNext()) 564 { 565 emitMethod((SootMethod) methodIt.next()); 566 emit(""); 567 } 568 } 569 570 if(Options.v().time()) 571 Timers.v().buildJasminTimer.end(); 572 } 573 574 protected void assignColorsToLocals(Body body) 575 { 576 if(Options.v().verbose()) 577 G.v().out.println("[" + body.getMethod().getName() + 578 "] Assigning colors to locals..."); 579 580 if(Options.v().time()) 581 Timers.v().packTimer.start(); 582 583 localToGroup = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 584 groupToColorCount = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 585 localToColor = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 586 587 { 589 Iterator localIt = body.getLocals().iterator(); 590 591 while(localIt.hasNext()) 592 { 593 Local l = (Local) localIt.next(); 594 Object g; 595 596 if(sizeOfType(l.getType()) == 1) 597 g = IntType.v(); 598 else 599 g = LongType.v(); 600 601 localToGroup.put(l, g); 602 603 if(!groupToColorCount.containsKey(g)) 604 { 605 groupToColorCount.put(g, new Integer (0)); 606 } 607 } 608 } 609 610 { 612 Iterator codeIt = body.getUnits().iterator(); 613 614 while(codeIt.hasNext()) 615 { 616 Stmt s = (Stmt) codeIt.next(); 617 618 if(s instanceof IdentityStmt && 619 ((IdentityStmt) s).getLeftOp() instanceof Local) 620 { 621 Local l = (Local) ((IdentityStmt) s).getLeftOp(); 622 623 Object group = localToGroup.get(l); 624 int count = ((Integer ) groupToColorCount.get(group)).intValue(); 625 626 localToColor.put(l, new Integer (count)); 627 628 count++; 629 630 groupToColorCount.put(group, new Integer (count)); 631 } 632 } 633 } 634 635 } 636 637 protected void emitMethod(SootMethod method) 638 { 639 if (method.isPhantom()) 640 return; 641 642 emit(".method " + Modifier.toString(method.getModifiers()) + " " + 644 method.getName() + jasminDescriptorOf(method.makeRef())); 645 646 Iterator throwsIt = method.getExceptions().iterator(); 647 while (throwsIt.hasNext()){ 648 SootClass exceptClass = (SootClass)throwsIt.next(); 649 emit(".throws "+exceptClass.getName()); 650 } 651 if (method.hasTag("SyntheticTag")){ 652 emit(".synthetic"); 653 } 654 if (method.hasTag("DeprecatedTag")){ 655 emit(".deprecated"); 656 } 657 if (method.hasTag("SignatureTag")){ 658 String sigAttr = ".signature_attr "; 659 SignatureTag sigTag = (SignatureTag)method.getTag("SignatureTag"); 660 sigAttr += "\""+sigTag.getSignature()+"\""; 661 emit(sigAttr); 662 } 663 if (method.hasTag("AnnotationDefaultTag")){ 664 String annotDefAttr = ".annotation_default "; 665 AnnotationDefaultTag annotDefTag = (AnnotationDefaultTag)method.getTag("AnnotationDefaultTag"); 666 annotDefAttr += getElemAttr(annotDefTag.getDefaultVal()); 667 annotDefAttr += ".end .annotation_default"; 668 emit(annotDefAttr); 669 } 670 Iterator vit = method.getTags().iterator(); 671 while (vit.hasNext()){ 672 Tag t = (Tag)vit.next(); 673 if (t.getName().equals("VisibilityAnnotationTag")){ 674 emit(getVisibilityAnnotationAttr((VisibilityAnnotationTag)t)); 675 } 676 if (t.getName().equals("VisibilityParameterAnnotationTag")){ 677 emit(getVisibilityParameterAnnotationAttr((VisibilityParameterAnnotationTag)t)); 678 } 679 } 680 681 if(method.isConcrete()) 682 { 683 if(!method.hasActiveBody()) 684 throw new RuntimeException ("method: " + method.getName() + " has no active body!"); 685 else 686 emitMethodBody(method); 687 } 688 689 emit(".end method"); 691 692 Iterator it = method.getTags().iterator(); 693 while(it.hasNext()) { 694 Tag tag = (Tag) it.next(); 695 if(tag instanceof Attribute) 696 emit(".method_attribute " + tag.getName() + " \"" + new String (Base64.encode(tag.getValue())) +"\""); 697 } 698 } 699 700 protected abstract void emitMethodBody(SootMethod method); 701 702 public void print(PrintWriter out) 703 { 704 Iterator it = code.iterator(); 705 706 while(it.hasNext()) 707 out.println(it.next()); 708 } 709 710 } 711 712 | Popular Tags |