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

#include <SlicedGraphs.h>

Public Member Functions

 SlicedICFGView (ICFG *icfg, const OrderedSet< const ICFGNode * > &keepNodes)
 Build an ICFG view from its explicit node membership.
 
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
 First kept node of fun's entry, or null when fun is outside the view.
 
const ICFGNodegetFunExit (const FunObjVar *fun) const
 Kept synthetic exit node of fun, or null when fun is outside the view.
 
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)
 
void buildBridgedEdges ()
 

Static Private Member Functions

static void getLocalSuccessors (const ICFGNode *node, const Map< const ICFGNode *, const ICFGNode * > &callsiteReturnNodes, std::vector< const ICFGNode * > &successors)
 

Private Attributes

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

Detailed Description

Definition at line 58 of file SlicedGraphs.h.

Constructor & Destructor Documentation

◆ SlicedICFGView()

SVF::SlicedICFGView::SlicedICFGView ( ICFG icfg,
const OrderedSet< const ICFGNode * > &  keepNodes 
)

Build an ICFG view from its explicit node membership.

Definition at line 267 of file SlicedGraphs.cpp.

269 : icfg(icfg)
270{
273}
void buildICFGSets(const OrderedSet< const ICFGNode * > &keepNodes)
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 96 of file SlicedGraphs.h.

97 {
98 auto it = bridgedPreds.find(n);
99 return it == bridgedPreds.end() ? nullptr : &it->second;
100 }
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 91 of file SlicedGraphs.h.

92 {
93 auto it = bridgedEdges.find(n);
94 return it == bridgedEdges.end() ? nullptr : &it->second;
95 }
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedEdges

◆ buildBridgedEdges()

void SVF::SlicedICFGView::buildBridgedEdges ( )
private

Definition at line 330 of file SlicedGraphs.cpp.

331{
332 // bridgedEdges[u] (u kept) = kept nodes reachable from u through removed-only
333 // paths = U reachKept(s) over removed successors s of u, where reachKept(r) is
334 // computed by SCC-condensing the removed subgraph (cyclic) and propagating
335 // kept-reachability over the condensation -- linear, vs. node contraction whose
336 // cross-products blow up when the removed region is large (small slices).
337
338 // Index the removed nodes and their removed-only adjacency + kept successors.
339 std::vector<const ICFGNode*> removed;
341 for (ICFG::iterator it = icfg->begin(), eit = icfg->end();
342 it != eit; ++it)
343 {
344 const ICFGNode* node = it->second;
345 if (node == nullptr || keptNodesSet.count(node))
346 continue;
347 removedNodeIndex[node] = static_cast<int>(removed.size());
348 removed.push_back(node);
349 }
350 const int removedNodeCount = static_cast<int>(removed.size());
351
352 // call_i -> ret_i summary for call sites with an omitted callee (some resolved
353 // callee entry not retained), for every call site so paths can compose through
354 // removed ones. ret_i is in the same caller, so the seed stays intra-procedural.
356 for (ICFG::iterator it = icfg->begin(), eit = icfg->end();
357 it != eit; ++it)
358 {
359 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(it->second);
360 if (call == nullptr || call->getRetICFGNode() == nullptr)
361 continue;
362 for (const ICFGEdge* edge : call->getOutEdges())
363 if (edge != nullptr && SVFUtil::isa<CallCFGEdge>(edge) &&
364 keptNodesSet.count(edge->getDstNode()) == 0)
365 {
366 seedRet[call] = call->getRetICFGNode();
367 break;
368 }
369 }
370 // Local successors = intra edges + matched call->ret seeds; the only edges
371 // contraction may traverse. Original call/ret edges are excluded.
372 std::vector<std::vector<int>> removedSuccessors(removedNodeCount);
373 std::vector<std::vector<const ICFGNode*>>
375 std::vector<const ICFGNode*> successors;
377 {
379 for (const ICFGNode* successor : successors)
380 {
381 if (keptNodesSet.count(successor))
383 else
384 {
385 const auto found = removedNodeIndex.find(successor);
386 if (found != removedNodeIndex.end())
387 removedSuccessors[nodeIndex].push_back(found->second);
388 }
389 }
390 }
391
392 // Iterative Tarjan SCC over the removed subgraph. Components are produced in
393 // reverse-topological order, so comp ids of a node's successors are < its own.
394 std::vector<int> discoveryIndex(removedNodeCount, -1);
395 std::vector<int> lowLink(removedNodeCount, 0);
396 std::vector<int> component(removedNodeCount, -1);
397 std::vector<char> onStack(removedNodeCount, 0);
398 std::vector<int> tarjanStack;
399 int nextDiscoveryIndex = 0;
400 int componentCount = 0;
401 for (int root = 0; root < removedNodeCount; ++root)
402 {
403 if (discoveryIndex[root] != -1)
404 continue;
405 std::vector<std::pair<int, size_t>> work;
406 work.emplace_back(root, 0);
407 while (!work.empty())
408 {
409 const int nodeIndex = work.back().first;
410 size_t& successorPosition = work.back().second;
411 if (successorPosition == 0)
412 {
415 tarjanStack.push_back(nodeIndex);
416 onStack[nodeIndex] = 1;
417 }
418 bool descend = false;
420 {
421 const int successorIndex =
424 {
425 work.emplace_back(successorIndex, 0);
426 descend = true;
427 break;
428 }
429 if (onStack[successorIndex] &&
432 }
433 if (descend)
434 continue;
436 {
437 while (true)
438 {
439 const int componentNode = tarjanStack.back();
440 tarjanStack.pop_back();
441 onStack[componentNode] = 0;
442 component[componentNode] = componentCount;
444 break;
445 }
447 }
448 work.pop_back();
449 if (!work.empty())
450 {
451 const int parentIndex = work.back().first;
454 }
455 }
456 }
457
458 // Condensation: base kept-successors and DAG successors per component.
459 std::vector<OrderedSet<const ICFGNode*>> baseKept(componentCount);
460 std::vector<OrderedSet<int>> componentSuccessors(componentCount);
462 {
463 const int componentIndex = component[nodeIndex];
467 if (component[successorIndex] != componentIndex)
469 component[successorIndex]);
470 }
471
472 // Propagate reachKept in ascending comp order (successors have smaller ids).
473 std::vector<OrderedSet<const ICFGNode*>>
477 {
482 reachable.insert(
485 }
486
487 // bridgedEdges[u] = kept nodes reached from kept u through removed local paths,
488 // plus a matched call->ret summary when u is a seeded call site (kept ret).
489 for (const ICFGNode* source : keptNodesSet)
490 {
491 getLocalSuccessors(source, seedRet, successors);
492 const auto seedReturn = seedRet.find(source);
493 for (const ICFGNode* successor : successors)
494 {
495 if (keptNodesSet.count(successor))
496 {
497 // Kept seed target: no real edge exists, so record the bridge; a
498 // kept intra target is a real edge handled by getSuccNodes.
499 if (seedReturn != seedRet.end() &&
500 seedReturn->second == successor)
501 {
504 }
505 continue;
506 }
507 const auto removedIndex = removedNodeIndex.find(successor);
508 if (removedIndex == removedNodeIndex.end())
509 {
511 << "[ERROR] Local ICFG successor is neither kept nor indexed\n";
512 std::abort();
513 }
514 for (const ICFGNode* target :
516 {
517 bridgedEdges[source].insert(target);
518 bridgedPreds[target].insert(source);
519 }
520 }
521 }
522
523 size_t totalBridgedEdges = 0;
524 for (const auto& pair : bridgedEdges)
525 totalBridgedEdges += pair.second.size();
526 SVFUtil::outs() << "[SlicedICFGView] Built " << totalBridgedEdges
527 << " bridged edges across " << bridgedEdges.size()
528 << " source nodes\n";
529}
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
static void getLocalSuccessors(const ICFGNode *node, const Map< const ICFGNode *, const ICFGNode * > &callsiteReturnNodes, std::vector< const ICFGNode * > &successors)
Set< const ICFGNode * > keptNodesSet
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52

◆ buildICFGSets()

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

Definition at line 319 of file SlicedGraphs.cpp.

321{
322 keptNodes.clear();
323 keptNodes.insert(keepNodes.begin(), keepNodes.end());
324
325 // Build keptNodesSet for fast lookup
326 keptNodesSet.clear();
327 keptNodesSet.insert(keptNodes.begin(), keptNodes.end());
328}
OrderedSet< const ICFGNode * > keptNodes

◆ dump()

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

Dump sliced ICFG to dot file.

Definition at line 311 of file SlicedGraphs.cpp.

312{
313 // Kept nodes + kept original edges + bridged edges are all produced by the
314 // GenericGraphTraits<const SlicedICFGView*> iterators; GraphWriter styles
315 // bridged edges dashed via DOTGraphTraits::getEdgeAttributes.
317}
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, or null when fun is outside the view.

Definition at line 883 of file SlicedGraphs.cpp.

884{
885 // Prefer the kept FunEntryICFGNode: MultiStageSlicer::expandCallDependence keeps it
886 // for every kept function and buildBridgedEdges links it to the kept body, so
887 // the MHP interleaving fixpoint can flow from it to every kept statement.
888 // The entry basic block's first instruction, by contrast, may be sliced out;
889 // returning it (a removed node) would strand the root/thread seed there --
890 // getSuccNodes() yields nothing for a non-kept node -- so the function body
891 // would never receive the thread's interleaving (a soundness bug).
892 if (const ICFGNode* fe = icfg->getFunEntryICFGNode(fun))
893 {
894 if (isKeptNode(fe))
895 return fe;
896 }
897 // A view constructor always retains the synthetic entry. Keep the fallback
898 // for defensive compatibility with directly constructed SlicedICFGViews,
899 // but never return a node outside this view.
900 const ICFGNode* entry = fun->getEntryBlock()->front();
901 if (isKeptNode(entry))
902 return entry;
903 for (const ICFGNode* node : fun->getEntryBlock()->getICFGNodeList())
904 {
905 if (isKeptNode(node))
906 return node;
907 }
908 return nullptr;
909}
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.

◆ getFunExit()

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

Kept synthetic exit node of fun, or null when fun is outside the view.

Definition at line 911 of file SlicedGraphs.cpp.

912{
913 const ICFGNode* exit = icfg->getFunExitICFGNode(fun);
914 return isKeptNode(exit) ? exit : nullptr;
915}
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:250

◆ getFunICFGNodes()

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

Kept ICFG nodes of fun.

Definition at line 917 of file SlicedGraphs.cpp.

919{
920 out.clear();
921 for (auto it : *fun)
922 {
923 const SVFBasicBlock* svfbb = it.second;
924 for (const ICFGNode* node : svfbb->getICFGNodeList())
925 if (isKeptNode(node))
926 out.push_back(node);
927 }
928}

◆ getKeptNodes()

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

Get all kept nodes.

Definition at line 84 of file SlicedGraphs.h.

85 {
86 return keptNodes;
87 }

◆ getLocalSuccessors()

void SVF::SlicedICFGView::getLocalSuccessors ( const ICFGNode node,
const Map< const ICFGNode *, const ICFGNode * > &  callsiteReturnNodes,
std::vector< const ICFGNode * > &  successors 
)
staticprivate

Definition at line 531 of file SlicedGraphs.cpp.

535{
536 successors.clear();
537 for (const ICFGEdge* edge : node->getOutEdges())
538 if (edge != nullptr && SVFUtil::isa<IntraCFGEdge>(edge) &&
539 edge->getDstNode() != nullptr)
540 successors.push_back(edge->getDstNode());
541
542 const auto returnNode = callsiteReturnNodes.find(node);
543 if (returnNode != callsiteReturnNodes.end())
544 successors.push_back(returnNode->second);
545}

◆ getOriginalICFG()

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

Get original ICFG.

Definition at line 106 of file SlicedGraphs.h.

107 {
108 return icfg;
109 }

◆ getPredNodes()

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

Get predecessor nodes (including bridged edges)

Definition at line 292 of file SlicedGraphs.cpp.

294{
295 out.clear();
296 if (!isKeptNode(node))
297 {
298 return;
299 }
301 const SlicedICFGNodeRef n{this, node};
302 for (auto it = GT::child_begin(n), e = GT::child_end(n); it != e; ++it)
303 out.push_back((*it).raw);
304}

◆ getSuccNodes()

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

Get successor nodes (including bridged edges)

Definition at line 278 of file SlicedGraphs.cpp.

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

◆ isKeptNode()

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

Check if a node is in the sliced view.

Definition at line 306 of file SlicedGraphs.cpp.

307{
308 return keptNodesSet.count(node) > 0;
309}

Member Data Documentation

◆ bridgedEdges

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

Definition at line 114 of file SlicedGraphs.h.

◆ bridgedPreds

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

Definition at line 117 of file SlicedGraphs.h.

◆ icfg

ICFG* SVF::SlicedICFGView::icfg
private

Definition at line 112 of file SlicedGraphs.h.

◆ keptNodes

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

Definition at line 113 of file SlicedGraphs.h.

◆ keptNodesSet

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

Definition at line 118 of file SlicedGraphs.h.


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