1 19 20 package soot.util.cfgcmd; 21 22 import java.util.*; 23 24 import soot.*; 25 import soot.toolkits.exceptions.ThrowableSet; 26 import soot.toolkits.graph.DirectedGraph; 27 import soot.toolkits.graph.BlockGraph; 28 import soot.toolkits.graph.ExceptionalGraph; 29 import soot.toolkits.graph.Block; 30 import soot.toolkits.graph.UnitGraph; 31 import soot.util.dot.DotGraph; 32 import soot.util.dot.DotGraphAttribute; 33 import soot.util.dot.DotGraphConstants; 34 import soot.util.dot.DotGraphEdge; 35 import soot.util.dot.DotGraphNode; 36 37 38 42 public class CFGToDotGraph { 43 44 private boolean onePage; private boolean isBrief; 46 private boolean showExceptions; 47 private DotGraphAttribute unexceptionalControlFlowAttr; 48 private DotGraphAttribute exceptionalControlFlowAttr; 49 private DotGraphAttribute exceptionEdgeAttr; 50 private DotGraphAttribute headAttr; 51 private DotGraphAttribute tailAttr; 52 53 64 public CFGToDotGraph() { 65 setOnePage(true); 66 setBriefLabels(false); 67 setShowExceptions(true); 68 setUnexceptionalControlFlowAttr("color", "black"); 69 setExceptionalControlFlowAttr("color", "red"); 70 setExceptionEdgeAttr("color", "lightgray"); 71 setHeadAttr("fillcolor", "gray"); 72 setTailAttr("fillcolor", "lightgray"); 73 } 74 75 76 84 public void setOnePage(boolean onePage) { 85 this.onePage = onePage; 86 } 87 88 89 98 public void setBriefLabels(boolean useBrief) { 99 this.isBrief = useBrief; 100 } 101 102 103 113 public void setShowExceptions(boolean showExceptions) { 114 this.showExceptions = showExceptions; 115 } 116 117 118 129 public void setUnexceptionalControlFlowAttr(String id, String value) { 130 unexceptionalControlFlowAttr = new DotGraphAttribute(id, value); 131 } 132 133 134 145 public void setExceptionalControlFlowAttr(String id, String value) { 146 exceptionalControlFlowAttr = new DotGraphAttribute(id, value); 147 } 148 149 150 162 public void setExceptionEdgeAttr(String id, String value) { 163 exceptionEdgeAttr = new DotGraphAttribute(id, value); 164 } 165 166 167 177 public void setHeadAttr(String id, String value) { 178 headAttr = new DotGraphAttribute(id, value); 179 } 180 181 182 192 public void setTailAttr(String id, String value) { 193 tailAttr = new DotGraphAttribute(id, value); 194 } 195 196 197 212 private static Iterator sortedIterator(Collection coll, Comparator comp) { 213 if (coll.size() <= 1) { 214 return coll.iterator(); 215 } else { 216 Object array[] = coll.toArray(); 217 Arrays.sort(array, comp); 218 return Arrays.asList(array).iterator(); 219 } 220 } 221 222 226 private static class NodeComparator implements java.util.Comparator { 227 private DotNamer namer; 228 229 NodeComparator(DotNamer namer) { 230 this.namer = namer; 231 } 232 233 public int compare(Object o1, Object o2) { 234 return (namer.getNumber(o1) - namer.getNumber(o2)); 235 } 236 237 public boolean equal(Object o1, Object o2) { 238 return (namer.getNumber(o1) == namer.getNumber(o2)); 239 } 240 } 241 242 243 247 private static class ExceptionDestComparator implements java.util.Comparator { 248 private DotNamer namer; 249 250 ExceptionDestComparator(DotNamer namer) { 251 this.namer = namer; 252 } 253 254 private int getValue(Object o) { 255 Object handler = ((ExceptionalGraph.ExceptionDest) o).getHandlerNode(); 256 if (handler == null) { 257 return Integer.MAX_VALUE; 258 } else { 259 return namer.getNumber(handler); 260 } 261 } 262 263 public int compare(Object o1, Object o2) { 264 return (getValue(o1) - getValue(o2)); 265 } 266 267 public boolean equal(Object o1, Object o2) { 268 return (getValue(o1) == getValue(o2)); 269 } 270 } 271 272 273 288 public DotGraph drawCFG(DirectedGraph graph, Body body) { 289 DotGraph canvas = initDotGraph(body); 290 DotNamer namer = new DotNamer((int)(graph.size()/0.7f), 0.7f); 291 NodeComparator comparator = new NodeComparator(namer); 292 293 for (Iterator nodesIt = graph.iterator(); nodesIt.hasNext(); ) { 299 String junk = namer.getName(nodesIt.next()); 300 } 301 302 for (Iterator nodesIt = graph.iterator(); nodesIt.hasNext(); ) { 303 Object node = nodesIt.next(); 304 canvas.drawNode(namer.getName(node)); 305 for (Iterator succsIt = sortedIterator(graph.getSuccsOf(node), comparator); 306 succsIt.hasNext(); ) { 307 Object succ = succsIt.next(); 308 canvas.drawEdge(namer.getName(node), namer.getName(succ)); 309 } 310 } 311 setStyle(graph.getHeads(), canvas, namer, 312 DotGraphConstants.NODE_STYLE_FILLED, headAttr); 313 setStyle(graph.getTails(), canvas, namer, 314 DotGraphConstants.NODE_STYLE_FILLED, tailAttr); 315 if (! isBrief) { 316 formatNodeText(body, canvas, namer); 317 } 318 319 return canvas; 320 } 321 322 323 332 public DotGraph drawCFG(ExceptionalGraph graph) { 333 Body body = graph.getBody(); 334 DotGraph canvas = initDotGraph(body); 335 DotNamer namer = new DotNamer((int)(graph.size()/0.7f), 0.7f); 336 NodeComparator nodeComparator = new NodeComparator(namer); 337 338 for (Iterator nodesIt = graph.iterator(); nodesIt.hasNext(); ) { 341 String junk = namer.getName(nodesIt.next()); 342 } 343 344 for (Iterator nodesIt = graph.iterator(); nodesIt.hasNext(); ) { 345 Object node = nodesIt.next(); 346 347 canvas.drawNode(namer.getName(node)); 348 349 for (Iterator succsIt = sortedIterator(graph.getUnexceptionalSuccsOf(node), 350 nodeComparator); 351 succsIt.hasNext(); ) { 352 Object succ = succsIt.next(); 353 DotGraphEdge edge = canvas.drawEdge(namer.getName(node), 354 namer.getName(succ)); 355 edge.setAttribute(unexceptionalControlFlowAttr); 356 } 357 358 for (Iterator succsIt = sortedIterator(graph.getExceptionalSuccsOf(node), 359 nodeComparator); 360 succsIt.hasNext(); ) { 361 Object succ = succsIt.next(); 362 DotGraphEdge edge = canvas.drawEdge(namer.getName(node), 363 namer.getName(succ)); 364 edge.setAttribute(exceptionalControlFlowAttr); 365 } 366 367 if (showExceptions) { 368 for (Iterator destsIt = sortedIterator(graph.getExceptionDests(node), 369 new ExceptionDestComparator(namer)); 370 destsIt.hasNext(); ) { 371 ExceptionalGraph.ExceptionDest dest 372 = (ExceptionalGraph.ExceptionDest) destsIt.next(); 373 Object handlerStart = dest.getHandlerNode(); 374 if (handlerStart == null) { 375 handlerStart = new Object () { 379 public String toString() { 380 return "Esc"; 381 } 382 }; 383 DotGraphNode escapeNode = 384 canvas.drawNode(namer.getName(handlerStart)); 385 escapeNode.setStyle(DotGraphConstants.NODE_STYLE_INVISIBLE); 386 } 387 DotGraphEdge edge = canvas.drawEdge(namer.getName(node), 388 namer.getName(handlerStart)); 389 edge.setAttribute(exceptionEdgeAttr); 390 edge.setLabel(formatThrowableSet(dest.getThrowables())); 391 } 392 } 393 } 394 setStyle(graph.getHeads(), canvas, namer, 395 DotGraphConstants.NODE_STYLE_FILLED, headAttr); 396 setStyle(graph.getTails(), canvas, namer, 397 DotGraphConstants.NODE_STYLE_FILLED, tailAttr); 398 if (! isBrief) { 399 formatNodeText(graph.getBody(), canvas, namer); 400 } 401 return canvas; 402 } 403 404 405 415 private DotGraph initDotGraph(Body body) { 416 String graphname = "cfg"; 417 if (body != null) { 418 graphname = body.getMethod().getSubSignature(); 419 } 420 DotGraph canvas = new DotGraph(graphname); 421 canvas.setGraphLabel(graphname); 422 if (!onePage) { 423 canvas.setPageSize(8.5, 11.0); 424 } 425 if (isBrief) { 426 canvas.setNodeShape(DotGraphConstants.NODE_SHAPE_CIRCLE); 427 } else { 428 canvas.setNodeShape(DotGraphConstants.NODE_SHAPE_BOX); 429 } 430 return canvas; 431 } 432 433 434 440 private static class DotNamer extends HashMap { 441 private int nodecount = 0; 442 443 DotNamer(int initialCapacity, float loadFactor) { 444 super(initialCapacity, loadFactor); 445 } 446 447 DotNamer() { 448 super(); 449 } 450 451 String getName(Object node) { 452 Integer index = (Integer )this.get(node); 453 if (index == null) { 454 index = new Integer (nodecount++); 455 this.put(node, index); 456 } 457 return index.toString(); 458 } 459 460 int getNumber(Object node) { 461 Integer index = (Integer )this.get(node); 462 if (index == null) { 463 index = new Integer (nodecount++); 464 this.put(node, index); 465 } 466 return index.intValue(); 467 } 468 } 469 470 471 472 484 private void formatNodeText(Body body, DotGraph canvas, DotNamer namer) { 485 486 LabeledUnitPrinter printer = null; 487 if (body != null) { 488 printer = new BriefUnitPrinter(body); 489 printer.noIndent(); 490 } 491 492 for (Iterator nodesIt = namer.keySet().iterator(); 493 nodesIt.hasNext(); ) { 494 Object node = nodesIt.next(); 495 DotGraphNode dotnode = canvas.getNode(namer.getName(node)); 496 String nodeLabel = null; 497 498 if (printer == null) { 499 nodeLabel = node.toString(); 500 } else { 501 if (node instanceof Unit) { 502 ((Unit) node).toString(printer); 503 String targetLabel = (String ) printer.labels().get(node); 504 if (targetLabel == null) { 505 nodeLabel = printer.toString(); 506 } else { 507 nodeLabel = targetLabel + ": " + printer.toString(); 508 } 509 510 } else if (node instanceof Block) { 511 Iterator units = ((Block) node).iterator(); 512 StringBuffer buffer = new StringBuffer (); 513 while (units.hasNext()) { 514 Unit unit = (Unit) units.next(); 515 String targetLabel = (String ) printer.labels().get(unit); 516 if (targetLabel != null) { 517 buffer.append(targetLabel) 518 .append(":\\n"); 519 } 520 unit.toString(printer); 521 buffer.append(printer.toString()) 522 .append("\\l"); 523 } 524 nodeLabel = buffer.toString(); 525 } else { 526 nodeLabel = node.toString(); 527 } 528 } 529 dotnode.setLabel(nodeLabel); 530 } 531 } 532 533 534 548 private void setStyle(Collection objects, DotGraph canvas, 549 DotNamer namer, String style, 550 DotGraphAttribute attrib) { 551 for (Iterator it = objects.iterator(); it.hasNext(); ) { 553 Object object = it.next(); 554 DotGraphNode objectNode = canvas.getNode(namer.getName(object)); 555 objectNode.setStyle(style); 556 objectNode.setAttribute(attrib); 557 } 558 } 559 560 565 private String formatThrowableSet(ThrowableSet set) { 566 String input = set.toAbbreviatedString(); 567 568 int inputLength = input.length(); 571 StringBuffer result = new StringBuffer (inputLength+5); 572 for (int i = 0; i < inputLength; i++) { 573 char c = input.charAt(i); 574 if (c == '+' || c == '-') { 575 result.append("\\l"); 576 } 577 result.append(c); 578 } 579 return result.toString(); 580 } 581 } 582 583 584 | Popular Tags |