1 19 20 25 26 package soot.xml; 27 import soot.*; 28 import java.util.*; 29 import soot.util.*; 30 import soot.toolkits.graph.*; 31 import soot.toolkits.scalar.*; 32 import soot.jimple.InvokeExpr; 33 import soot.jimple.SpecialInvokeExpr; 34 import soot.jimple.StaticInvokeExpr; 35 import soot.jimple.Stmt; 36 import soot.jimple.toolkits.invoke.*; 37 import java.io.*; 38 39 40 public class XMLPrinter { 41 public static final String xmlHeader = "<?xml version=\"1.0\" ?>\n"; 43 public static final String dtdHeader = 44 "<!DOCTYPE jil SYSTEM \"http://www.sable.mcgill.ca/~flynn/jil/jil10.dtd\">\n"; 45 46 public XMLRoot root; 48 49 public String toString() { 51 if (root != null) 52 return root.toString(); 53 else 54 throw new RuntimeException ("Error generating XML!"); 55 } 56 57 public XMLNode addElement(String name) { 59 return addElement(name, "", "", ""); 60 } 61 public XMLNode addElement(String name, String value) { 62 return addElement(name, value, "", ""); 63 } 64 public XMLNode addElement(String name, String value, String [] attributes) { 65 return addElement(name, value, attributes, null); 66 } 67 public XMLNode addElement( 68 String name, 69 String value, 70 String attribute, 71 String attributeValue) { 72 return addElement( 73 name, 74 value, 75 new String [] { attribute }, 76 new String [] { attributeValue }); 77 } 78 public XMLNode addElement( 79 String name, 80 String value, 81 String [] attributes, 82 String [] values) { 83 return root.addElement(name, value, attributes, values); 84 } 85 86 public XMLPrinter(Singletons.Global g) { 87 } 88 public static XMLPrinter v() { 89 return G.v().soot_xml_XMLPrinter(); 90 } 91 92 private XMLNode xmlNode = null; 93 public XMLNode setXMLNode(XMLNode node) { 94 return (this.xmlNode = node); 95 } 96 97 98 private void printStatementsInBody(Body body, java.io.PrintWriter out) { 99 LabeledUnitPrinter up = new NormalUnitPrinter(body); 100 Map stmtToName = up.labels(); 101 102 Chain units = body.getUnits(); 103 104 ExceptionalUnitGraph exceptionalUnitGraph = 106 new soot.toolkits.graph.ExceptionalUnitGraph(body); 107 108 LiveLocals sll = new SimpleLiveLocals(exceptionalUnitGraph); 110 111 String cleanMethodName = cleanMethod(body.getMethod().getName()); 113 Iterator unitIt = units.iterator(); 114 Unit currentStmt = null; 115 Unit previousStmt; 116 String indent = " "; 117 String currentLabel = "default"; 118 long statementCount = 0; 119 long labelCount = 0; 120 long labelID = 0; 121 int index = 0; 122 123 Vector useList = new Vector(); 125 Vector useDataList = new Vector(); 126 Vector defList = new Vector(); 127 Vector defDataList = new Vector(); 128 Vector paramData = new Vector(); 129 Vector xmlLabelsList = new Vector(); 130 long maxStmtCount = 0; 131 132 158 159 XMLNode methodNode = 161 xmlNode.addChild( 162 "method", 163 new String [] { "name", "returntype", "class" }, 164 new String [] { 165 cleanMethodName, 166 body.getMethod().getReturnType().toString(), 167 body.getMethod().getDeclaringClass().getName().toString()}); 168 String declarationStr = 169 body.getMethod().getDeclaration().toString().trim(); 170 methodNode.addChild( 171 "declaration", 172 toCDATA(declarationStr), 173 new String [] { "length" }, 174 new String [] { declarationStr.length() + "" }); 175 176 XMLNode parametersNode = 178 methodNode.addChild( 179 "parameters", 180 new String [] { "method" }, 181 new String [] { cleanMethodName }); 182 XMLNode localsNode = methodNode.addChild("locals"); 183 XMLNode labelsNode = methodNode.addChild("labels"); 184 XMLNode stmtsNode = methodNode.addChild("statements"); 185 186 XMLLabel xmlLabel = 188 new XMLLabel(labelCount, cleanMethodName, currentLabel); 189 labelsNode.addChild( 190 "label", 191 new String [] { "id", "name", "method" }, 192 new String [] {(labelCount++) + "", currentLabel, cleanMethodName }); 193 194 while (unitIt.hasNext()) { 196 previousStmt = currentStmt; 197 currentStmt = (Unit) unitIt.next(); 198 Stmt stmtCurrentStmt = (Stmt) currentStmt; 199 200 if (stmtToName.containsKey(currentStmt)) { 202 currentLabel = stmtToName.get(currentStmt).toString(); 203 204 212 xmlLabel.stmtCount = labelID; 213 xmlLabel.stmtPercentage = 214 new Float ( 215 (new Float (labelID).floatValue() 216 / new Float (units.size()).intValue()) 217 * 100.0) 218 .longValue(); 219 if (xmlLabel.stmtPercentage > maxStmtCount) 220 maxStmtCount = xmlLabel.stmtPercentage; 221 222 xmlLabelsList.addElement(xmlLabel); 223 225 xmlLabel = 226 new XMLLabel(labelCount, cleanMethodName, currentLabel); 227 labelsNode.addChild( 228 "label", 229 new String [] { "id", "name", "method" }, 230 new String [] { 231 labelCount + "", 232 currentLabel, 233 cleanMethodName }); 234 labelCount++; 235 labelID = 0; 236 } 237 238 XMLNode stmtNode = 240 stmtsNode.addChild( 241 "statement", 242 new String [] { "id", "label", "method", "labelid" }, 243 new String [] { 244 statementCount + "", 245 currentLabel, 246 cleanMethodName, 247 labelID + "" }); 248 XMLNode sootstmtNode = 249 stmtNode.addChild( 250 "soot_statement", 251 new String [] { "branches", "fallsthrough" }, 252 new String [] { 253 boolToString(currentStmt.branches()), 254 boolToString(currentStmt.fallsThrough())}); 255 256 int j = 0; 258 Iterator boxIt = currentStmt.getUseBoxes().iterator(); 259 while (boxIt.hasNext()) { 260 ValueBox box = (ValueBox) boxIt.next(); 261 if (box.getValue() instanceof Local) { 262 String local = 263 cleanLocal(((Local) box.getValue()).toString()); 264 sootstmtNode.addChild( 265 "uses", 266 new String [] { "id", "local", "method" }, 267 new String [] { j + "", local, cleanMethodName }); 268 j++; 269 270 Vector tempVector = null; 271 int useIndex = useList.indexOf(local); 272 if (useIndex == -1) { 273 useDataList.addElement(tempVector); 274 useList.addElement(local); 275 useIndex = useList.indexOf(local); 276 } 277 278 if (useDataList.size() > useIndex) { 279 tempVector = (Vector) useDataList.elementAt(useIndex); 280 if (tempVector == null) { 281 tempVector = new Vector(); 282 } 283 tempVector.addElement(new Long (statementCount)); 284 useDataList.setElementAt(tempVector, useIndex); 285 } 286 } 287 } 288 289 j = 0; 291 boxIt = currentStmt.getDefBoxes().iterator(); 292 while (boxIt.hasNext()) { 293 ValueBox box = (ValueBox) boxIt.next(); 294 if (box.getValue() instanceof Local) { 295 String local = 296 cleanLocal(((Local) box.getValue()).toString()); 297 sootstmtNode.addChild( 298 "defines", 299 new String [] { "id", "local", "method" }, 300 new String [] { j + "", local, cleanMethodName }); 301 j++; 302 303 Vector tempVector = null; 304 int defIndex = defList.indexOf(local); 305 if (defIndex == -1) { 306 defDataList.addElement(tempVector); 307 defList.addElement(local); 308 defIndex = defList.indexOf(local); 309 } 310 311 if (defDataList.size() > defIndex) { 312 tempVector = (Vector) defDataList.elementAt(defIndex); 313 if (tempVector == null) { 314 tempVector = new Vector(); 315 } 316 tempVector.addElement(new Long (statementCount)); 317 defDataList.setElementAt(tempVector, defIndex); 318 } 319 } 320 } 321 322 381 382 List liveLocalsIn = sll.getLiveLocalsBefore(currentStmt); 384 List liveLocalsOut = sll.getLiveLocalsAfter(currentStmt); 385 XMLNode livevarsNode = 386 sootstmtNode.addChild( 387 "livevariables", 388 new String [] { "incount", "outcount" }, 389 new String [] { 390 liveLocalsIn.size() + "", 391 liveLocalsOut.size() + "" }); 392 for (int i = 0; i < liveLocalsIn.size(); i++) { 393 livevarsNode.addChild( 394 "in", 395 new String [] { "id", "local", "method" }, 396 new String [] { 397 i + "", 398 cleanLocal(liveLocalsIn.get(i).toString()), 399 cleanMethodName }); 400 } 401 for (int i = 0; i < liveLocalsOut.size(); i++) { 402 livevarsNode.addChild( 403 "out", 404 new String [] { "id", "local", "method" }, 405 new String [] { 406 i + "", 407 cleanLocal(liveLocalsOut.get(i).toString()), 408 cleanMethodName }); 409 } 410 411 for (int i = 0; 413 i < body.getMethod().getParameterTypes().size(); 414 i++) { 415 Vector tempVec = new Vector(); 416 paramData.addElement(tempVec); 417 } 418 419 currentStmt.toString(up); 421 String jimpleStr = up.toString().trim(); 422 if (currentStmt instanceof soot.jimple.IdentityStmt && 423 jimpleStr.indexOf("@parameter") != -1) { 424 String tempStr = 426 jimpleStr.substring(jimpleStr.indexOf("@parameter") + 10); 427 if (tempStr.indexOf(":") != -1) 428 tempStr = tempStr.substring(0, tempStr.indexOf(":")).trim(); 429 if (tempStr.indexOf(" ") != -1) 430 tempStr = tempStr.substring(0, tempStr.indexOf(" ")).trim(); 431 int paramIndex = new Integer (tempStr).intValue(); 432 Vector tempVec = (Vector) paramData.elementAt(paramIndex); 433 if (tempVec != null) 434 tempVec.addElement(Long.toString(statementCount)); 435 paramData.setElementAt(tempVec, paramIndex); 436 } 437 438 sootstmtNode.addChild( 440 "jimple", 441 toCDATA(jimpleStr), 442 new String [] { "length" }, 443 new String [] {(jimpleStr.length() + 1) + "" }); 444 445 labelID++; 447 statementCount++; 448 } 449 450 stmtsNode.addAttribute("count", statementCount + ""); 452 453 parametersNode.addAttribute( 455 "count", 456 body.getMethod().getParameterCount() + ""); 457 for (int i = 0; i < body.getMethod().getParameterTypes().size(); i++) { 458 XMLNode paramNode = 459 parametersNode.addChild( 460 "parameter", 461 new String [] { "id", "type", "method", "name" }, 462 new String [] { 463 i + "", 464 body.getMethod().getParameterTypes().get(i).toString(), 465 cleanMethodName, 466 "_parameter" + i }); 467 XMLNode sootparamNode = paramNode.addChild("soot_parameter"); 468 469 Vector tempVec = (Vector) paramData.elementAt(i); 470 for (int k = 0; k < tempVec.size(); k++) { 471 sootparamNode.addChild( 472 "use", 473 new String [] { "id", "line", "method" }, 474 new String [] { 475 k + "", 476 String.valueOf(tempVec.elementAt(k)) + "", 477 cleanMethodName }); 478 } 479 sootparamNode.addAttribute("uses", tempVec.size() + ""); 480 } 481 482 490 491 xmlLabel.stmtCount = labelID; 492 xmlLabel.stmtPercentage = 493 new Float ( 494 (new Float (labelID).floatValue() 495 / new Float (units.size()).floatValue()) 496 * 100.0) 497 .longValue(); 498 if (xmlLabel.stmtPercentage > maxStmtCount) 499 maxStmtCount = xmlLabel.stmtPercentage; 500 xmlLabelsList.addElement(xmlLabel); 501 502 Chain locals = body.getLocals(); 504 Iterator localsIterator = locals.iterator(); 505 Vector localTypes = new Vector(); 506 Vector typedLocals = new Vector(); 507 Vector typeCounts = new Vector(); 508 String xmlLongLocals = ""; 509 int j = 0; 510 int currentType = 0; 511 512 while (localsIterator.hasNext()) { 513 int useCount = 0; 514 int defineCount = 0; 515 Local localData = (Local) localsIterator.next(); 516 String local = cleanLocal((String ) localData.toString()); 517 String localType = localData.getType().toString(); 518 519 if (!localTypes.contains(localType)) { 521 localTypes.addElement(localType); 522 typedLocals.addElement(new Vector()); 523 typeCounts.addElement(new Integer (0)); 524 } 525 526 XMLNode localNode = 528 new XMLNode( 529 "local", 530 "", 531 new String [] { "id", "method", "name", "type" }, 532 new String [] { j + "", cleanMethodName, local, localType }); 533 XMLNode sootlocalNode = localNode.addChild("soot_local"); 534 currentType = 0; 535 536 for (int k = 0; k < localTypes.size(); k++) { 537 if (localType 538 .equalsIgnoreCase((String ) localTypes.elementAt(k))) { 539 currentType = k; 540 Integer tempInt = 541 new Integer ( 542 ((Integer ) typeCounts.elementAt(k)).intValue() + 1); 543 typeCounts.setElementAt(tempInt, k); 544 break; 545 } 546 } 547 548 for (int k = 0; k < useList.size(); k++) { 550 String query = (String ) useList.elementAt(k); 551 if (query.equalsIgnoreCase(local)) { 552 Vector tempVector = 553 (Vector) useDataList.elementAt(useList.indexOf(local)); 554 555 for (int i = 0; i < tempVector.size(); i++) { 556 sootlocalNode.addChild( 557 "use", 558 new String [] { "id", "line", "method" }, 559 new String [] { 560 i + "", 561 ((Long ) tempVector.elementAt(i)).toString(), 562 cleanMethodName }); 563 } 564 useCount = tempVector.size(); 565 break; 566 } 567 } 568 569 for (int k = 0; k < defList.size(); k++) { 571 String query = (String ) (defList.elementAt(k)); 572 if (query.equalsIgnoreCase(local)) { 573 Vector tempVector = 574 (Vector) defDataList.elementAt(defList.indexOf(local)); 575 576 for (int i = 0; i < tempVector.size(); i++) { 577 sootlocalNode.addChild( 578 "definition", 579 new String [] { "id", "line", "method" }, 580 new String [] { 581 i + "", 582 ((Long ) tempVector.elementAt(i)).toString(), 583 cleanMethodName }); 584 } 585 defineCount = tempVector.size(); 586 break; 587 } 588 } 589 590 sootlocalNode.addAttribute("uses", useCount + ""); 592 sootlocalNode.addAttribute("defines", defineCount + ""); 593 594 Vector list = (Vector) typedLocals.elementAt(currentType); 596 list.addElement(localNode); 597 typedLocals.setElementAt(list, currentType); 598 599 localsNode.addChild((XMLNode) localNode.clone()); 601 j++; 602 603 } 604 605 localsNode.addAttribute("count", locals.size() + ""); 607 608 XMLNode typesNode = 610 localsNode.addChild( 611 "types", 612 new String [] { "count" }, 613 new String [] { localTypes.size() + "" }); 614 615 for (int i = 0; i < localTypes.size(); i++) { 616 String type = (String ) localTypes.elementAt(i); 617 XMLNode typeNode = 618 typesNode.addChild( 619 "type", 620 new String [] { "id", "type", "count" }, 621 new String [] { 622 i + "", 623 type, 624 (Integer ) typeCounts.elementAt(i) + "" }); 625 626 Vector list = (Vector) typedLocals.elementAt(i); 627 for (j = 0; j < list.size(); j++) { 628 typeNode.addChild((XMLNode) list.elementAt(j)); 629 } 630 } 631 632 labelsNode.addAttribute("count", labelCount + ""); 634 XMLNode current = labelsNode.child; 635 for (int i = 0; i < xmlLabelsList.size(); i++) { 636 XMLLabel tempLabel = (XMLLabel) xmlLabelsList.elementAt(i); 637 tempLabel.stmtPercentage = 638 new Float ( 639 (new Float (tempLabel.stmtPercentage).floatValue() 640 / new Float (maxStmtCount).floatValue()) 641 * 100.0) 642 .longValue(); 643 644 if (current != null) { 645 current.addAttribute("stmtcount", tempLabel.stmtCount + ""); 646 current.addAttribute( 647 "stmtpercentage", 648 tempLabel.stmtPercentage + ""); 649 current = current.next; 650 } 651 } 652 653 statementCount = 0; 655 XMLNode exceptionsNode = methodNode.addChild("exceptions"); 656 Iterator trapIt = body.getTraps().iterator(); 657 if (trapIt.hasNext()) { 658 while (trapIt.hasNext()) { 659 Trap trap = (Trap) trapIt.next(); 660 661 XMLNode catchNode = 663 exceptionsNode.addChild( 664 "exception", 665 new String [] { "id", "method", "type" }, 666 new String [] { 667 (statementCount++) + "", 668 cleanMethodName, 669 Scene.v().quotedNameOf( 670 trap.getException().getName())}); 671 catchNode.addChild( 672 "begin", 673 new String [] { "label" }, 674 new String [] { 675 stmtToName.get(trap.getBeginUnit()).toString()}); 676 catchNode.addChild( 677 "end", 678 new String [] { "label" }, 679 new String [] { 680 stmtToName.get(trap.getEndUnit()).toString()}); 681 catchNode.addChild( 682 "handler", 683 new String [] { "label" }, 684 new String [] { 685 stmtToName.get(trap.getHandlerUnit()).toString()}); 686 } 687 } 688 689 exceptionsNode.addAttribute( 690 "count", 691 exceptionsNode.getNumberOfChildren() + ""); 692 693 695 return; 696 } 697 698 private String cleanMethod(String str) { 699 return str.trim().replace('<', '_').replace('>', '_'); 701 } 702 703 private String cleanLocal(String str) { 704 return str.trim(); } 707 708 private String toCDATA(String str) { 709 str = StringTools.replaceAll(str, "]]>", "]]>"); 711 return "<![CDATA[" + str + "]]>"; 712 } 713 714 private String boolToString(boolean bool) { 715 if (bool) 716 return "true"; 717 return "false"; 718 } 719 720 class XMLLabel { 721 public long id; 722 public String methodName; 723 public String label; 724 public long stmtCount; 725 public long stmtPercentage; 726 727 public XMLLabel(long in_id, String in_methodName, String in_label) { 728 id = in_id; 729 methodName = in_methodName; 730 label = in_label; 731 } 732 } 733 734 private void printXMLTo(SootClass cl, PrintWriter out) { 735 root = new XMLRoot(); 736 XMLNode xmlRootNode = null; 737 XMLNode xmlHistoryNode = null; 738 XMLNode xmlClassNode = null; 739 XMLNode xmlTempNode = null; 740 741 { 743 xmlRootNode = root.addElement("jil"); 745 746 String cmdlineStr = ""; 749 for (int i = 0; i < Main.v().cmdLineArgs.length; i++) { 750 cmdlineStr += Main.v().cmdLineArgs[i] + " "; 751 } 752 String dateStr = new Date().toString(); 753 xmlHistoryNode = xmlRootNode.addChild("history"); 754 xmlHistoryNode.addAttribute("created", dateStr); 755 xmlHistoryNode.addChild( 756 "soot", 757 new String [] { "version", "command", "timestamp" }, 758 new String [] { 759 Main.v().versionString, 760 cmdlineStr.trim(), 761 dateStr }); 762 763 xmlClassNode = 765 xmlRootNode.addChild( 766 "class", 767 new String [] { "name" }, 768 new String [] { 769 Scene.v().quotedNameOf(cl.getName()).toString()}); 770 if (cl.getPackageName().length() > 0) 771 xmlClassNode.addAttribute("package", cl.getPackageName()); 772 if (cl.hasSuperclass()) 773 xmlClassNode.addAttribute( 774 "extends", 775 Scene 776 .v() 777 .quotedNameOf(cl.getSuperclass().getName()) 778 .toString()); 779 780 xmlTempNode = xmlClassNode.addChild("modifiers"); 782 StringTokenizer st = 783 new StringTokenizer(Modifier.toString(cl.getModifiers())); 784 while (st.hasMoreTokens()) 785 xmlTempNode.addChild( 786 "modifier", 787 new String [] { "name" }, 788 new String [] { st.nextToken() + "" }); 789 xmlTempNode.addAttribute( 790 "count", 791 xmlTempNode.getNumberOfChildren() + ""); 792 } 793 794 { 796 xmlTempNode = 797 xmlClassNode.addChild( 798 "interfaces", 799 "", 800 new String [] { "count" }, 801 new String [] { cl.getInterfaceCount() + "" }); 802 803 Iterator interfaceIt = cl.getInterfaces().iterator(); 804 if (interfaceIt.hasNext()) { 805 while (interfaceIt.hasNext()) 806 xmlTempNode.addChild( 807 "implements", 808 "", 809 new String [] { "class" }, 810 new String [] { 811 Scene 812 .v() 813 .quotedNameOf( 814 ((SootClass) interfaceIt.next()).getName()) 815 .toString()}); 816 } 817 } 818 819 { 821 xmlTempNode = 822 xmlClassNode.addChild( 823 "fields", 824 "", 825 new String [] { "count" }, 826 new String [] { cl.getFieldCount() + "" }); 827 828 Iterator fieldIt = cl.getFields().iterator(); 829 if (fieldIt.hasNext()) { 830 int i = 0; 831 while (fieldIt.hasNext()) { 832 SootField f = (SootField) fieldIt.next(); 833 834 if (f.isPhantom()) 835 continue; 836 837 String type = f.getType().toString(); 838 String name = f.getName().toString(); 839 840 XMLNode xmlFieldNode = 842 xmlTempNode.addChild( 843 "field", 844 "", 845 new String [] { "id", "name", "type" }, 846 new String [] {(i++) + "", name, type }); 847 XMLNode xmlModifiersNode = 848 xmlFieldNode.addChild("modifiers"); 849 850 StringTokenizer st = 851 new StringTokenizer( 852 Modifier.toString(f.getModifiers())); 853 while (st.hasMoreTokens()) 854 xmlModifiersNode.addChild( 855 "modifier", 856 new String [] { "name" }, 857 new String [] { st.nextToken() + "" }); 858 859 xmlModifiersNode.addAttribute( 860 "count", 861 xmlModifiersNode.getNumberOfChildren() + ""); 862 } 863 } 864 } 865 866 { 868 Iterator methodIt = cl.methodIterator(); 869 870 setXMLNode( 871 xmlClassNode.addChild( 872 "methods", 873 new String [] { "count" }, 874 new String [] { cl.getMethodCount() + "" })); 875 876 while (methodIt.hasNext()) { 877 SootMethod method = (SootMethod) methodIt.next(); 878 879 if (method.isPhantom()) 880 continue; 881 882 if (!Modifier.isAbstract(method.getModifiers()) 883 && !Modifier.isNative(method.getModifiers())) { 884 if (!method.hasActiveBody()) 885 throw new RuntimeException ( 886 "method " 887 + method.getName() 888 + " has no active body!"); 889 else 890 printTo(method.getActiveBody(), out); 891 } 892 } 893 } 894 out.println(toString()); 895 } 896 897 public void printJimpleStyleTo(SootClass cl, PrintWriter out) { 898 printXMLTo(cl, out); 900 return; 901 } 902 903 909 private void printTo(Body b, PrintWriter out) { 910 b.validate(); 911 912 printStatementsInBody(b, out); 913 914 } 915 } 916 | Popular Tags |