private static void printDetails(CGNode method, ExplodedControlFlowGraph cfg, FlowGraph pruned) { int deletedEdges = 0; int originalEdges = 0; for (IExplodedBasicBlock node : cfg) { originalEdges += cfg.getSuccNodeCount(node); Iterator<IExplodedBasicBlock> it = cfg.getSuccNodes(node); int srcNum = node.getNumber(); while (it.hasNext()) { IExplodedBasicBlock dst = it.next(); int dstNum = dst.getNumber(); if (pruned.hasEdge(srcNum, dstNum)) { deletedEdges++; } } } DecimalFormat df = new DecimalFormat("00.00"); double percent = ((double) deletedEdges / (double) originalEdges) * 100.0; Log.info( "EXC: " + df.format(percent) + "% - edges: " + originalEdges + " deleted: " + deletedEdges + " - " + edu.kit.joana.deprecated.jsdg.util.Util.methodName(method.getMethod())); }
/** flow function for normal intraprocedural edges */ public IUnaryFlowFunction getNormalFlowFunction( final BasicBlockInContext<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> dest) { final IExplodedBasicBlock ebb = src.getDelegate(); SSAInstruction instruction = ebb.getInstruction(); if (instruction instanceof SSAPutInstruction) { final SSAPutInstruction putInstr = (SSAPutInstruction) instruction; if (putInstr.isStatic()) { return new IUnaryFlowFunction() { public IntSet getTargets(int d1) { // first, gen this statement int factNum = domain.getMappedIndex(Pair.make(src.getNode(), ebb.getFirstInstructionIndex())); assert factNum != -1; MutableSparseIntSet result = MutableSparseIntSet.makeEmpty(); result.add(factNum); // if incoming statement is some different statement that defs the same static field, // kill it; otherwise, keep it if (d1 != factNum) { IField staticField = cha.resolveField(putInstr.getDeclaredField()); assert staticField != null; Pair<CGNode, Integer> otherPutInstrAndNode = domain.getMappedObject(d1); SSAPutInstruction otherPutInstr = (SSAPutInstruction) otherPutInstrAndNode.fst.getIR() .getInstructions()[otherPutInstrAndNode.snd]; IField otherStaticField = cha.resolveField(otherPutInstr.getDeclaredField()); if (!staticField.equals(otherStaticField)) { result.add(d1); } } return result; } public String toString() { return "Reaching Defs Normal Flow"; } }; } } // identity function when src block isn't for a putstatic return IdentityFlowFunction.identity(); }
/** * collect the putstatic instructions in the call graph as {@link PathEdge} seeds for the * analysis */ private Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> collectInitialSeeds() { Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> result = HashSetFactory.make(); for (BasicBlockInContext<IExplodedBasicBlock> bb : supergraph) { IExplodedBasicBlock ebb = bb.getDelegate(); SSAInstruction instruction = ebb.getInstruction(); if (instruction instanceof SSAPutInstruction) { SSAPutInstruction putInstr = (SSAPutInstruction) instruction; if (putInstr.isStatic()) { final CGNode cgNode = bb.getNode(); Pair<CGNode, Integer> fact = Pair.make(cgNode, ebb.getFirstInstructionIndex()); int factNum = domain.add(fact); BasicBlockInContext<IExplodedBasicBlock> fakeEntry = getFakeEntry(cgNode); // note that the fact number used for the source of this path edge doesn't really matter result.add(PathEdge.createPathEdge(fakeEntry, factNum, bb, factNum)); } } } return result; }
public AbstractPDGNode getMainPDGNode(IExplodedBasicBlock bb) { AbstractPDGNode pdgnode = null; SSAInstruction instr = bb.getInstruction(); if (instr == null) { return null; } List<AbstractPDGNode> nodes = pdg.getNodesForInstruction(instr); if (nodes == null || nodes.isEmpty()) { return null; } // the first element of the node list is per convention always the // main node concerning the instruction pdgnode = nodes.get(0); return pdgnode; }
public boolean hasNormalEdge(IExplodedBasicBlock src, IExplodedBasicBlock dst) { return finalGraph.hasEdge(src.getNumber(), dst.getNumber()); }
private void createFirstAndLastNodes(IExplodedBasicBlock block) { final SSAInstruction instr = block.getInstruction(); if (block == ecfg.entry()) { assert (entry == null); CFGNode cfgNode = createNode(block); Set<CFGNode> first = HashSetFactory.make(1); first.add(cfgNode); firstNodes.put(block, first); entry = cfgNode; Set<? extends AbstractParameterNode> after = getAllHeapLocatedFormIns(); CFGNode current = cfgNode; for (AbstractParameterNode p : after) { CFGNode param = findOrCreateNode(block, p); cfg.addEdge(current, param); current = param; numberOfParameterNodes++; } if (instr != null) { AbstractPDGNode node = pdg.getMainNodeForInstruction(instr); if (node != null) { CFGNode artificialNode = createArtificialNode(block, node); cfg.addEdge(current, artificialNode); current = artificialNode; } } Set<CFGNode> last = HashSetFactory.make(1); last.add(current); lastNodes.put(block, last); } else if (block == ecfg.exit()) { assert (exit == null); CFGNode cfgNode = createNode(block); Set<AbstractParameterNode> before = getAllHeapLocatedFormOuts(); if (!pdg.isIgnoreExceptions() && pdg.getExceptionalExit() != null) { before.add(pdg.getExceptionalExit()); } if (before.isEmpty()) { Set<CFGNode> first = HashSetFactory.make(1); first.add(cfgNode); firstNodes.put(block, first); } else { CFGNode current = null; for (AbstractParameterNode p : before) { CFGNode param = findOrCreateNode(block, p); if (current == null) { Set<CFGNode> first = HashSetFactory.make(1); first.add(param); firstNodes.put(block, first); } else { cfg.addEdge(current, param); } current = param; numberOfParameterNodes++; } cfg.addEdge(current, cfgNode); } exit = cfgNode; Set<CFGNode> last = HashSetFactory.make(1); last.add(cfgNode); lastNodes.put(block, last); } else if (block.isCatchBlock() && instr != null) { // special case where a single cfg node corresponds to 2 statements... CFGNode cfgNode = createNode(block); Set<CFGNode> first = HashSetFactory.make(1); first.add(cfgNode); firstNodes.put(block, first); AbstractPDGNode pdgNode = pdg.getMainNodeForInstruction(instr); CFGNode lastNode = createArtificialNode(block, pdgNode); Set<CFGNode> last = HashSetFactory.make(1); last.add(lastNode); lastNodes.put(block, last); cfg.addEdge(cfgNode, lastNode); List<AbstractPDGNode> nodes = pdg.getNodesForInstruction(instr); for (AbstractPDGNode node : nodes) { if (node instanceof ExpressionNode) { sdg2cfg.put((ExpressionNode) node, lastNode); } } } else if (instr instanceof SSAInvokeInstruction) { // method call found - add actual in nodes before and actual-out // nodes after the call Set<CFGNode> first = HashSetFactory.make(); Set<CFGNode> last = HashSetFactory.make(); Set<CallNode> calls = getCallsForInstruction((SSAInvokeInstruction) instr); CFGNode compoundCallNode = null; if (calls.size() > 1) { compoundCallNode = createNode(block); first.add(compoundCallNode); } for (CallNode call : calls) { CFGNode cfgNode = createNode(block, call); Set<? extends AbstractParameterNode> actIns = getAllHeapLocatedActualIns(call); numberOfParameterNodes += actIns.size(); if (actIns.size() == 0) { if (compoundCallNode == null) { first.add(cfgNode); } else { cfg.addEdge(compoundCallNode, cfgNode); } } else { CFGNode current = null; for (AbstractParameterNode p : actIns) { CFGNode param = findOrCreateNode(block, p); if (current == null) { if (compoundCallNode == null) { first.add(param); } else { cfg.addEdge(compoundCallNode, param); } } else { cfg.addEdge(current, param); } current = param; } cfg.addEdge(current, cfgNode); } Set<? extends AbstractParameterNode> actOuts = getAllHeapLocatedActualOuts(call); numberOfParameterNodes += actOuts.size(); CFGNode current = cfgNode; for (AbstractParameterNode p : actOuts) { CFGNode param = findOrCreateNode(block, p); cfg.addEdge(current, param); current = param; } last.add(current); } firstNodes.put(block, first); lastNodes.put(block, last); } else { CFGNode cfgNode = createNode(block); AbstractPDGNode node = null; if (instr != null) { node = pdg.getMainNodeForInstruction(instr); } if (node instanceof ExpressionNode) { ExpressionNode expr = (ExpressionNode) node; sdg2cfg.put((ExpressionNode) node, cfgNode); if (expr.isFieldAccess() || expr.isArrayAccess()) { Set<CFGNode> first = HashSetFactory.make(1); Set<CFGNode> last = HashSetFactory.make(1); last.add(cfgNode); CFGNode pred = null; if (!expr.isStaticFieldAccess()) { CFGNode baseCfg = createArtificialNode(block, expr.getBaseValue()); first.add(baseCfg); pred = baseCfg; } if (expr.isArrayAccess()) { CFGNode indexCfg = createArtificialNode(block, expr.getIndexValue()); if (pred != null) { cfg.addEdge(pred, indexCfg); } else { first.add(indexCfg); } pred = indexCfg; } if (expr.isGet()) { CFGNode fieldCfg = createArtificialNode(block, expr.getFieldValue()); if (pred != null) { cfg.addEdge(pred, fieldCfg); } else { first.add(fieldCfg); } pred = fieldCfg; } if (expr.isSet()) { CFGNode valCfg = createArtificialNode(block, expr.getSetValue()); if (pred != null) { cfg.addEdge(pred, valCfg); } else { first.add(valCfg); } pred = valCfg; } if (pred != null) { cfg.addEdge(pred, cfgNode); } else { first.add(cfgNode); } firstNodes.put(block, first); lastNodes.put(block, last); } else { Set<CFGNode> firstAndLast = HashSetFactory.make(1); firstAndLast.add(cfgNode); firstNodes.put(block, firstAndLast); lastNodes.put(block, firstAndLast); } } else { Set<CFGNode> firstAndLast = HashSetFactory.make(1); firstAndLast.add(cfgNode); firstNodes.put(block, firstAndLast); lastNodes.put(block, firstAndLast); } } }