Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
SVF::SlicedICFGView Class Reference

#include <SlicedGraphs.h>

Public Member Functions

 SlicedICFGView (ICFG *icfg, CallGraph *cg, const OrderedSet< const ICFGNode * > &keepNodes, const OrderedSet< const FunObjVar * > &keptFunctions, bool buildBridged=true)
 Build complete ICFG view from keepNodes and keptFunctions.
 
void getSuccNodes (const ICFGNode *node, std::vector< const ICFGNode * > &out) const
 Get successor nodes (including bridged edges)
 
void getPredNodes (const ICFGNode *node, std::vector< const ICFGNode * > &out) const
 Get predecessor nodes (including bridged edges)
 
bool isKeptNode (const ICFGNode *node) const
 Check if a node is in the sliced view.
 
const ICFGNodegetFunEntry (const FunObjVar *fun) const
 
void getFunICFGNodes (const FunObjVar *fun, std::vector< const ICFGNode * > &out) const
 Kept ICFG nodes of fun.
 
const OrderedSet< const ICFGNode * > & getKeptNodes () const
 Get all kept nodes.
 
const OrderedSet< const ICFGNode * > * bridgedSuccsOf (const ICFGNode *n) const
 
const OrderedSet< const ICFGNode * > * bridgedPredsOf (const ICFGNode *n) const
 
void dump (const std::string &filename) const
 Dump sliced ICFG to dot file.
 
ICFGgetOriginalICFG () const
 Get original ICFG.
 

Private Member Functions

void buildICFGSets (const OrderedSet< const ICFGNode * > &keepNodes, const OrderedSet< const FunObjVar * > &keptFunctions)
 
void buildBridgedEdges ()
 

Private Attributes

ICFGicfg
 
OrderedSet< const ICFGNode * > keptNodes
 
OrderedSet< const ICFGEdge * > keptEdges
 
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedEdges
 
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedPreds
 
Set< const ICFGNode * > keptNodesSet
 

Detailed Description

Definition at line 66 of file SlicedGraphs.h.

Constructor & Destructor Documentation

◆ SlicedICFGView()

SVF::SlicedICFGView::SlicedICFGView ( ICFG icfg,
CallGraph cg,
const OrderedSet< const ICFGNode * > &  keepNodes,
const OrderedSet< const FunObjVar * > &  keptFunctions,
bool  buildBridged = true 
)

Build complete ICFG view from keepNodes and keptFunctions.

Definition at line 252 of file SlicedGraphs.cpp.

257 : icfg(icfg)
258{
260 if (buildBridged)
262}
void buildICFGSets(const OrderedSet< const ICFGNode * > &keepNodes, const OrderedSet< const FunObjVar * > &keptFunctions)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

Member Function Documentation

◆ bridgedPredsOf()

const OrderedSet< const ICFGNode * > * SVF::SlicedICFGView::bridgedPredsOf ( const ICFGNode n) const
inline

Definition at line 107 of file SlicedGraphs.h.

108 {
109 auto it = bridgedPreds.find(n);
110 return it == bridgedPreds.end() ? nullptr : &it->second;
111 }
cJSON * n
Definition cJSON.cpp:2558
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedPreds

◆ bridgedSuccsOf()

const OrderedSet< const ICFGNode * > * SVF::SlicedICFGView::bridgedSuccsOf ( const ICFGNode n) const
inline

Bridged (synthetic) successors/predecessors of a kept node, or null if none. The traits iterators use these alongside the node's kept original edges.

Definition at line 102 of file SlicedGraphs.h.

103 {
104 auto it = bridgedEdges.find(n);
105 return it == bridgedEdges.end() ? nullptr : &it->second;
106 }
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedEdges

◆ buildBridgedEdges()

void SVF::SlicedICFGView::buildBridgedEdges ( )
private

Definition at line 334 of file SlicedGraphs.cpp.

335{
336 // bridgedEdges[u] (u kept) = kept nodes reachable from u through removed-only
337 // paths = U reachKept(s) over removed successors s of u, where reachKept(r) is
338 // computed by SCC-condensing the removed subgraph (cyclic) and propagating
339 // kept-reachability over the condensation -- linear, vs. node contraction whose
340 // cross-products blow up when the removed region is large (small slices).
341
342 // Index the removed nodes and their removed-only adjacency + kept successors.
343 std::vector<const ICFGNode*> removed;
345 for (ICFG::iterator it = icfg->begin(), eit = icfg->end(); it != eit; ++it)
346 {
347 const ICFGNode* n = it->second;
348 if (n == nullptr || keptNodesSet.count(n)) continue;
349 rid[n] = static_cast<int>(removed.size());
350 removed.push_back(n);
351 }
352 const int R = static_cast<int>(removed.size());
353
354 // call_i -> ret_i summary for call sites with an omitted callee (some resolved
355 // callee entry not retained), for every call site so paths can compose through
356 // removed ones. ret_i is in the same caller, so the seed stays intra-procedural.
358 for (ICFG::iterator it = icfg->begin(), eit = icfg->end(); it != eit; ++it)
359 {
360 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(it->second);
361 if (call == nullptr || call->getRetICFGNode() == nullptr) continue;
362 for (const ICFGEdge* e : call->getOutEdges())
363 if (e && SVFUtil::isa<CallCFGEdge>(e) && keptNodesSet.count(e->getDstNode()) == 0)
364 {
365 seedRet[call] = call->getRetICFGNode();
366 break;
367 }
368 }
369 // Local successors = intra edges + matched call->ret seeds; the only edges
370 // contraction may traverse. Original call/ret edges are excluded.
371 auto localSuccs = [&](const ICFGNode* n, std::vector<const ICFGNode*>& out)
372 {
373 out.clear();
374 for (const ICFGEdge* e : n->getOutEdges())
375 if (e && SVFUtil::isa<IntraCFGEdge>(e) && e->getDstNode())
376 out.push_back(e->getDstNode());
377 auto sit = seedRet.find(n);
378 if (sit != seedRet.end()) out.push_back(sit->second);
379 };
380
381 std::vector<std::vector<int>> radj(R); // removed -> removed succ ids
382 std::vector<std::vector<const ICFGNode*>> keptSucc(R); // removed -> kept succs
383 std::vector<const ICFGNode*> succs;
384 for (int i = 0; i < R; ++i)
385 {
387 for (const ICFGNode* d : succs)
388 {
389 if (keptNodesSet.count(d)) keptSucc[i].push_back(d);
390 else radj[i].push_back(rid[d]);
391 }
392 }
393
394 // Iterative Tarjan SCC over the removed subgraph. Components are produced in
395 // reverse-topological order, so comp ids of a node's successors are < its own.
396 std::vector<int> idx(R, -1), low(R, 0), comp(R, -1);
397 std::vector<char> onstk(R, 0);
398 std::vector<int> tstk;
399 int counter = 0, ncomp = 0;
400 for (int s0 = 0; s0 < R; ++s0)
401 {
402 if (idx[s0] != -1) continue;
403 std::vector<std::pair<int, size_t>> work;
404 work.emplace_back(s0, 0);
405 while (!work.empty())
406 {
407 int v = work.back().first;
408 size_t& pi = work.back().second;
409 if (pi == 0)
410 {
411 idx[v] = low[v] = counter++;
412 tstk.push_back(v);
413 onstk[v] = 1;
414 }
415 bool descend = false;
416 while (pi < radj[v].size())
417 {
418 int w = radj[v][pi++];
419 if (idx[w] == -1)
420 {
421 work.emplace_back(w, 0);
422 descend = true;
423 break;
424 }
425 else if (onstk[w] && idx[w] < low[v]) low[v] = idx[w];
426 }
427 if (descend) continue;
428 if (low[v] == idx[v])
429 {
430 while (true)
431 {
432 int w = tstk.back();
433 tstk.pop_back();
434 onstk[w] = 0;
435 comp[w] = ncomp;
436 if (w == v) break;
437 }
438 ++ncomp;
439 }
440 work.pop_back();
441 if (!work.empty())
442 {
443 int p = work.back().first;
444 if (low[v] < low[p]) low[p] = low[v];
445 }
446 }
447 }
448
449 // Condensation: base kept-successors and DAG successors per component.
450 std::vector<OrderedSet<const ICFGNode*>> baseKept(ncomp);
451 std::vector<OrderedSet<int>> dagSucc(ncomp);
452 for (int i = 0; i < R; ++i)
453 {
454 int ci = comp[i];
455 for (const ICFGNode* k : keptSucc[i]) baseKept[ci].insert(k);
456 for (int j : radj[i]) if (comp[j] != ci) dagSucc[ci].insert(comp[j]);
457 }
458
459 // Propagate reachKept in ascending comp order (successors have smaller ids).
460 std::vector<OrderedSet<const ICFGNode*>> reachKept(ncomp);
461 for (int c = 0; c < ncomp; ++c)
462 {
464 acc = baseKept[c];
465 for (int d : dagSucc[c]) acc.insert(reachKept[d].begin(), reachKept[d].end());
466 }
467
468 // bridgedEdges[u] = kept nodes reached from kept u through removed local paths,
469 // plus a matched call->ret summary when u is a seeded call site (kept ret).
470 for (const ICFGNode* u : keptNodesSet)
471 {
473 auto sit = seedRet.find(u);
474 for (const ICFGNode* s : succs)
475 {
476 if (keptNodesSet.count(s))
477 {
478 // Kept seed target: no real edge exists, so record the bridge; a
479 // kept intra target is a real edge handled by getSuccNodes.
480 if (sit != seedRet.end() && sit->second == s)
481 {
482 bridgedEdges[u].insert(s);
483 bridgedPreds[s].insert(u);
484 }
485 continue;
486 }
487 for (const ICFGNode* v : reachKept[comp[rid[s]]])
488 {
489 bridgedEdges[u].insert(v);
490 bridgedPreds[v].insert(u);
491 }
492 }
493 }
494
495 size_t totalBridgedEdges = 0;
496 for (const auto& pair : bridgedEdges) totalBridgedEdges += pair.second.size();
497 SVFUtil::outs() << "[SlicedICFGView] Built " << totalBridgedEdges
498 << " bridged edges across " << bridgedEdges.size() << " source nodes\n";
499}
cJSON * p
Definition cJSON.cpp:2559
if(prebuffer< 0)
Definition cJSON.cpp:1269
int count
Definition cJSON.h:216
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:440
iterator begin()
Iterators.
ICFGNodeIDToNodeMapTy::iterator iterator
Definition ICFG.h:58
Set< const ICFGNode * > keptNodesSet
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52

◆ buildICFGSets()

void SVF::SlicedICFGView::buildICFGSets ( const OrderedSet< const ICFGNode * > &  keepNodes,
const OrderedSet< const FunObjVar * > &  keptFunctions 
)
private

Definition at line 306 of file SlicedGraphs.cpp.

308{
309 // keepNodes already includes all necessary nodes (call/ret nodes and entry/exit nodes)
310 // so we just need to copy them and build edges.
311
312 // Copy keepNodes to keptNodes
313 keptNodes.clear();
314 keptNodes.insert(keepNodes.begin(), keepNodes.end());
315
316 // Build keptNodesSet for fast lookup
317 keptNodesSet.clear();
318 keptNodesSet.insert(keptNodes.begin(), keptNodes.end());
319
320 // Build edges: only when both src and dst are in keptNodes
321 keptEdges.clear();
322 for (const ICFGNode* node : keptNodes)
323 {
324 for (const ICFGEdge* edge : node->getOutEdges())
325 {
326 if (edge && keptNodesSet.count(edge->getDstNode()))
327 {
328 keptEdges.insert(edge);
329 }
330 }
331 }
332}
OrderedSet< const ICFGEdge * > keptEdges
OrderedSet< const ICFGNode * > keptNodes

◆ dump()

void SVF::SlicedICFGView::dump ( const std::string &  filename) const

Dump sliced ICFG to dot file.

Definition at line 298 of file SlicedGraphs.cpp.

299{
300 // Kept nodes + kept original edges + bridged edges are all produced by the
301 // GenericGraphTraits<const SlicedICFGView*> iterators; GraphWriter styles
302 // bridged edges dashed via DOTGraphTraits::getEdgeAttributes.
304}
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)

◆ getFunEntry()

const ICFGNode * SVF::SlicedICFGView::getFunEntry ( const FunObjVar fun) const

First kept node of fun's entry (the kept FunEntryICFGNode, else the first kept node of the entry block, else the original entry).

Definition at line 788 of file SlicedGraphs.cpp.

789{
790 // Prefer the kept FunEntryICFGNode: MultiStageSlicer::expandCallDependence keeps it
791 // for every kept function and buildBridgedEdges links it to the kept body, so
792 // the MHP interleaving fixpoint can flow from it to every kept statement.
793 // The entry basic block's first instruction, by contrast, may be sliced out;
794 // returning it (a removed node) would strand the root/thread seed there --
795 // getSuccNodes() yields nothing for a non-kept node -- so the function body
796 // would never receive the thread's interleaving (a soundness bug).
797 if (const ICFGNode* fe = icfg->getFunEntryICFGNode(fun))
798 {
799 if (isKeptNode(fe))
800 return fe;
801 }
802 // Otherwise: first kept node in the entry block, or the original entry.
803 const ICFGNode* entry = fun->getEntryBlock()->front();
804 if (isKeptNode(entry))
805 return entry;
806 for (const ICFGNode* node : fun->getEntryBlock()->getICFGNodeList())
807 {
808 if (isKeptNode(node))
809 return node;
810 }
811 return entry;
812}
const SVFBasicBlock * getEntryBlock() const
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:243
const ICFGNode * front() const
bool isKeptNode(const ICFGNode *node) const
Check if a node is in the sliced view.

◆ getFunICFGNodes()

void SVF::SlicedICFGView::getFunICFGNodes ( const FunObjVar fun,
std::vector< const ICFGNode * > &  out 
) const

Kept ICFG nodes of fun.

Definition at line 814 of file SlicedGraphs.cpp.

816{
817 out.clear();
818 for (auto it : *fun)
819 {
820 const SVFBasicBlock* svfbb = it.second;
821 for (const ICFGNode* node : svfbb->getICFGNodeList())
822 if (isKeptNode(node))
823 out.push_back(node);
824 }
825}

◆ getKeptNodes()

const OrderedSet< const ICFGNode * > & SVF::SlicedICFGView::getKeptNodes ( ) const
inline

Get all kept nodes.

Definition at line 95 of file SlicedGraphs.h.

96 {
97 return keptNodes;
98 }

◆ getOriginalICFG()

ICFG * SVF::SlicedICFGView::getOriginalICFG ( ) const
inline

Get original ICFG.

Definition at line 117 of file SlicedGraphs.h.

118 {
119 return icfg;
120 }

◆ getPredNodes()

void SVF::SlicedICFGView::getPredNodes ( const ICFGNode node,
std::vector< const ICFGNode * > &  out 
) const

Get predecessor nodes (including bridged edges)

Definition at line 280 of file SlicedGraphs.cpp.

281{
282 out.clear();
283 if (!isKeptNode(node))
284 {
285 return;
286 }
288 const SlicedICFGNodeRef n{this, node};
289 for (auto it = GT::child_begin(n), e = GT::child_end(n); it != e; ++it)
290 out.push_back((*it).raw);
291}

◆ getSuccNodes()

void SVF::SlicedICFGView::getSuccNodes ( const ICFGNode node,
std::vector< const ICFGNode * > &  out 
) const

Get successor nodes (including bridged edges)

Definition at line 267 of file SlicedGraphs.cpp.

268{
269 out.clear();
270 if (!isKeptNode(node))
271 {
272 return;
273 }
275 const SlicedICFGNodeRef n{this, node};
276 for (auto it = GT::child_begin(n), e = GT::child_end(n); it != e; ++it)
277 out.push_back((*it).raw);
278}

◆ isKeptNode()

bool SVF::SlicedICFGView::isKeptNode ( const ICFGNode node) const

Check if a node is in the sliced view.

Definition at line 293 of file SlicedGraphs.cpp.

294{
295 return keptNodesSet.count(node) > 0;
296}

Member Data Documentation

◆ bridgedEdges

Map<const ICFGNode*, OrderedSet<const ICFGNode*> > SVF::SlicedICFGView::bridgedEdges
private

Definition at line 126 of file SlicedGraphs.h.

◆ bridgedPreds

Map<const ICFGNode*, OrderedSet<const ICFGNode*> > SVF::SlicedICFGView::bridgedPreds
private

Definition at line 129 of file SlicedGraphs.h.

◆ icfg

ICFG* SVF::SlicedICFGView::icfg
private

Definition at line 123 of file SlicedGraphs.h.

◆ keptEdges

OrderedSet<const ICFGEdge*> SVF::SlicedICFGView::keptEdges
private

Definition at line 125 of file SlicedGraphs.h.

◆ keptNodes

OrderedSet<const ICFGNode*> SVF::SlicedICFGView::keptNodes
private

Definition at line 124 of file SlicedGraphs.h.

◆ keptNodesSet

Set<const ICFGNode*> SVF::SlicedICFGView::keptNodesSet
private

Definition at line 130 of file SlicedGraphs.h.


The documentation for this class was generated from the following files: