Skip to content

Commit

Permalink
better scfg construction
Browse files Browse the repository at this point in the history
  • Loading branch information
kadirayk committed Mar 13, 2023
1 parent adcf44c commit e30438f
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 339 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public Map<Unit, Set<DFF>> initialSeeds() {
if (m.getName().equals("entryPoint")) {
DirectedGraph<Unit> unitGraph = new BriefUnitGraph(m.getActiveBody());
SootMethod methodOf = icfg.getMethodOf(CFGUtil.getHead(unitGraph));
System.out.println(methodOf.getActiveBody());
//System.out.println(methodOf.getActiveBody());
return DefaultSeeds.make(Collections.singleton(CFGUtil.getHead(unitGraph)), zeroValue());
}
}
Expand Down
98 changes: 72 additions & 26 deletions src/main/java/sparse/CPAJimpleSparseCFGBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import analysis.data.DFF;
import com.google.common.graph.GraphBuilder;
import com.google.common.graph.MutableGraph;
import com.google.common.graph.Traverser;
import heros.sparse.SparseCFG;
import heros.sparse.SparseCFGBuilder;
import heros.sparse.SparseCFGQueryStat;
Expand All @@ -17,9 +18,7 @@
import util.CFGUtil;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;

Expand All @@ -46,30 +45,81 @@ public CPAJimpleSparseCFGBuilder(boolean enableExceptions) {
public SparseCFG<Unit, DFF> buildSparseCFG(SootMethod m, DFF d, SparseCFGQueryStat queryStat) {
log = m.getSignature().contains("com.google.common.base.Joiner$3");

DirectedGraph<Unit> graph = new BriefUnitGraph(m.getActiveBody());
int initialSize = graph.size();
JimpleSparseCFG cfg = new JimpleSparseCFG(d);
DirectedGraph<Unit> rawGraph = new BriefUnitGraph(m.getActiveBody());
List<Unit> heads = rawGraph.getHeads();
MutableGraph<Unit> mCFG = convertToMutableGraph(rawGraph);

Unit head = CFGUtil.getHead(graph);
queryStat.setInitialStmtCount(mCFG.nodes().size());
queryStat.setInitialEdgeCount(mCFG.edges().size());

Unit head = CFGUtil.getHead(rawGraph);
//handle Source
if (d.toString().equals("<<zero>>")) {
buildCompleteCFG(head, graph, cfg);
logCFG(LOGGER, cfg.getGraph(), "original", m.getActiveBody(), cfg.getD());
int finalSize = cfg.getGraph().nodes().size();
// we pick the non identity head
queryStat.setInitialStmtCount(initialSize);
queryStat.setFinalStmtCount(finalSize);
return cfg;
queryStat.setFinalStmtCount(mCFG.nodes().size());
queryStat.setFinalEdgeCount(mCFG.edges().size());
return new JimpleSparseCFG(d, mCFG);
}

buildCompleteCFG(head, graph, cfg);
//buildSparseCFG(head, null, graph, cfg, d, m);
int finalSize = cfg.getGraph().nodes().size();
queryStat.setInitialStmtCount(initialSize);
queryStat.setFinalStmtCount(finalSize);
sparsify(mCFG, heads, d, m, rawGraph);

//buildSparseCFG(head, null, rawGraph, cfg, d, m);
queryStat.setFinalStmtCount(mCFG.nodes().size());
queryStat.setFinalEdgeCount(mCFG.edges().size());
//logInfo(cfg);
logCFG(LOGGER, cfg.getGraph(), "sparse", m.getActiveBody(), cfg.getD());
return cfg;
return new JimpleSparseCFG(d, mCFG);
}

private void sparsify(MutableGraph<Unit> mCFG, List<Unit> heads, DFF d, SootMethod m, DirectedGraph<Unit> graph) {
Set<Unit> stmsToRemove = new HashSet<>();
for (Unit head : heads) {
Iterator<Unit> iter = getBFSIterator(mCFG, head);
while (iter.hasNext()) {
Unit unit = iter.next();
if (!stmsToRemove.contains(unit) && !shouldKeepStmt(unit, d, m, graph)) {
stmsToRemove.add(unit);
}
}
}
for (Unit unit : stmsToRemove) {
Set<Unit> preds = mCFG.predecessors(unit);
Set<Unit> succs = mCFG.successors(unit);
if (preds.size() == 1 && succs.size() == 1) {
// we do this to be safe, but one can investigate removing multiple edges
mCFG.removeNode(unit);
mCFG.putEdge(preds.iterator().next(), succs.iterator().next());
}
}
}

protected Iterator<Unit> getBFSIterator(MutableGraph<Unit> graph, Unit head) {
Traverser<Unit> traverser = Traverser.forGraph(graph);
return traverser.breadthFirst(head).iterator();
}


protected MutableGraph<Unit> convertToMutableGraph(DirectedGraph<Unit> rawGraph) {
int initialSize = rawGraph.size();
MutableGraph<Unit> mGraph = GraphBuilder.directed().build();
List<Unit> heads = rawGraph.getHeads();
for (Unit head : heads) {
addToMutableGraph(rawGraph, head, mGraph);
}
int finalSize = mGraph.nodes().size();
if (initialSize != finalSize) {
throw new RuntimeException("Graph size differs after conversion to mutable graph");
}
return mGraph;
}

protected void addToMutableGraph(
DirectedGraph<Unit> graph, Unit curr, MutableGraph<Unit> mutableGraph) {
List<Unit> succsOf = graph.getSuccsOf(curr);
for (Unit succ : succsOf) {
if (!mutableGraph.hasEdgeConnecting(curr, succ) && !curr.equals(succ)) {
mutableGraph.putEdge(curr, succ);
addToMutableGraph(graph, succ, mutableGraph);
}
}
}


Expand Down Expand Up @@ -130,7 +180,6 @@ private boolean shouldKeepStmt(Unit unit, DFF d, SootMethod m, DirectedGraph<Uni

//keep the stmt which generates the D
if (d.getGeneratedAt() != null && unit.toString().equals(d.getGeneratedAt().toString())) {
// TODO: would this be a problem?
return true;
}

Expand All @@ -139,9 +188,6 @@ private boolean shouldKeepStmt(Unit unit, DFF d, SootMethod m, DirectedGraph<Uni
return true;
}

// case 2: if stmt refers to v alone or v.f (instance field) handled in case 1
//handleCase2(stmt, sparseCFG);

// case 3: if stmt accesses T.f (static field) or is a callsite
if (keepForCase3(unit, d)) {
return true;
Expand Down Expand Up @@ -328,7 +374,7 @@ private boolean keepFieldLoad(Unit unit) {

private void logCFG(Logger logger, MutableGraph<Unit> graph, String cfgType, Body body, DFF d) {
if (log) {
logger.info(cfgType + "-" + d.toString() + ":\n" +
logger.info(cfgType + "-" + d.toString() + ":\n" +
graph.nodes().stream()
.map(Objects::toString)
.collect(Collectors.joining(System.lineSeparator())) + "\n" + body.toString());
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/sparse/JimpleSparseCFG.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public class JimpleSparseCFG implements SparseCFG<Unit, DFF> {
private MutableGraph<Unit> graph;
private DFF d; // which dff this SCFG belongs to

public JimpleSparseCFG(DFF d) {
public JimpleSparseCFG(DFF d, MutableGraph<Unit> graph) {
this.d = d;
this.graph = GraphBuilder.directed().build();
this.graph = graph;
}

public synchronized boolean addEdge(Unit node, Unit succ){
Expand Down
Loading

0 comments on commit e30438f

Please sign in to comment.