Skip to content

Commit d9017bd

Browse files
committed
Allow to debug the abstraction tree
1 parent 32fc811 commit d9017bd

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package soot.jimple.infoflow.util;
2+
3+
import java.util.ArrayDeque;
4+
import java.util.IdentityHashMap;
5+
import java.util.Set;
6+
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
10+
import com.google.common.html.HtmlEscapers;
11+
12+
import soot.jimple.infoflow.data.Abstraction;
13+
import soot.util.IdentityHashSet;
14+
15+
/**
16+
* Creates a Graphviz/dot graph of a {@link Abstraction} tree.
17+
* Contains the abstractions as well as its predecessors an neighbors
18+
*
19+
* @author Marc Miltenberger
20+
*/
21+
public final class DebugAbstractionTree {
22+
23+
private static final Logger logger = LoggerFactory.getLogger(DebugAbstractionTree.class);
24+
25+
private DebugAbstractionTree() {
26+
}
27+
28+
/**
29+
* Creates a dot graph with indices as labels for the abstractions (otherwise, it would be way too large).
30+
* The correspondence is printed to log.
31+
* @param absStart start abstraction of the tree (root)
32+
* @param printNeighbors whether to print neighbors
33+
* @return the dot graph
34+
*/
35+
public static String createDotGraph(Abstraction absStart, boolean printNeighbors) {
36+
IdentityHashMap<Abstraction, Integer> absToId = new IdentityHashMap<>();
37+
ArrayDeque<Abstraction> workQueue = new ArrayDeque<>();
38+
StringBuilder sbNodes = new StringBuilder();
39+
StringBuilder sbEdges = new StringBuilder();
40+
41+
int idCounter = 0;
42+
43+
workQueue.add(absStart);
44+
while (!workQueue.isEmpty()) {
45+
Abstraction p = workQueue.poll();
46+
Integer id = absToId.get(p);
47+
if (id == null) {
48+
idCounter++;
49+
absToId.put(p, idCounter);
50+
String absName = String.valueOf(idCounter); // escape(p.toString());
51+
logger.info(idCounter + ": " + p);
52+
StringBuilder neighbors = new StringBuilder();
53+
for (int i = 0; i < p.getNeighborCount(); i++) {
54+
neighbors.append(String.format("|<n%d> n%d", i, i));
55+
}
56+
if (p.getNeighborCount() > 0 && printNeighbors)
57+
workQueue.addAll(p.getNeighbors());
58+
if (p.getPredecessor() != null)
59+
workQueue.add(p.getPredecessor());
60+
else {
61+
if (p.getSourceContext() != null)
62+
absName += " [source]";
63+
}
64+
sbNodes.append(String.format(" abs%d[label=\"{%s|{<a> A%s}}\"];\n", idCounter, absName,
65+
neighbors.toString()));
66+
}
67+
}
68+
workQueue.add(absStart);
69+
Set<Abstraction> seen = new IdentityHashSet<>();
70+
while (!workQueue.isEmpty()) {
71+
Abstraction p = workQueue.poll();
72+
if (seen.add(p)) {
73+
Integer id = absToId.get(p);
74+
Abstraction pred = p.getPredecessor();
75+
if (pred != null) {
76+
int dest = absToId.get(pred);
77+
sbEdges.append(String.format(" abs%s:a -> abs%d;\n", id, dest));
78+
workQueue.add(pred);
79+
}
80+
if (p.getNeighborCount() > 0 && printNeighbors) {
81+
int i = 0;
82+
for (Abstraction n : p.getNeighbors()) {
83+
int dest = absToId.get(n);
84+
sbEdges.append(String.format(" abs%s:n%s -> abs%d;\n", id, i, dest));
85+
i++;
86+
}
87+
workQueue.addAll(p.getNeighbors());
88+
}
89+
}
90+
}
91+
92+
return "digraph Debug {\n" + " node [shape=record];\n" + sbNodes.toString() + sbEdges.toString() + "}";
93+
}
94+
95+
private static String escape(String string) {
96+
return HtmlEscapers.htmlEscaper().escape(string);
97+
}
98+
99+
}

0 commit comments

Comments
 (0)