|
Static Value-Flow Analysis
|
#include <AbstractInterpretation.h>
Public Types | |
| enum | AESparsity { Dense , SemiSparse , Sparse } |
| enum | HandleRecur { TOP , WIDEN_ONLY , WIDEN_NARROW } |
Static Public Member Functions | |
| static AbstractInterpretation & | getAEInstance () |
Protected Member Functions | |
| AbstractInterpretation () | |
| virtual AbstractState | getFullCycleHeadState (const ICFGCycleWTO *cycle) |
| virtual bool | widenCycleState (const AbstractState &prev, const AbstractState &cur, const ICFGCycleWTO *cycle) |
| virtual bool | narrowCycleState (const AbstractState &prev, const AbstractState &cur, const ICFGCycleWTO *cycle) |
| bool | shouldApplyNarrowing (const FunObjVar *fun) |
| Check if narrowing should be applied: always for regular loops, mode-dependent for recursion. | |
Protected Attributes | |
| SVFIR * | svfir {nullptr} |
| Data and helpers reachable from SparseAbstractInterpretation. | |
| AEWTO * | preAnalysis {nullptr} |
| Map< const ICFGNode *, AbstractState > | abstractTrace |
| per-node trace; owned here | |
Private Member Functions | |
| virtual void | handleGlobalNode () |
| Initialize abstract state for the global ICFG node and process global statements. | |
| bool | mergeStatesFromPredecessors (const ICFGNode *node) |
| bool | isBranchFeasible (const IntraCFGEdge *edge, AbstractState &as) |
| Returns true if the branch is reachable; narrows as in-place. | |
| virtual void | handleCallSite (const ICFGNode *node) |
| Handle a call site node: dispatch to ext-call, direct-call, or indirect-call handling. | |
| virtual void | handleLoopOrRecursion (const ICFGCycleWTO *cycle, const CallICFGNode *caller=nullptr) |
| Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration. | |
| void | handleFunction (const ICFGNode *funEntry, const CallICFGNode *caller=nullptr) |
| Handle a function body via worklist-driven WTO traversal starting from funEntry. | |
| bool | handleICFGNode (const ICFGNode *node) |
| Handle an ICFG node: execute statements; return true if state changed. | |
| virtual void | handleSVFStatement (const SVFStmt *stmt) |
| Dispatch an SVF statement (Addr/Binary/Cmp/Load/Store/Copy/Gep/Select/Phi/Call/Ret) to its handler. | |
| bool | isCmpBranchFeasible (const IntraCFGEdge *edge, AbstractState &as) |
| Returns true if the cmp-conditional branch is feasible; narrows as in-place. | |
| bool | isSwitchBranchFeasible (const IntraCFGEdge *edge, AbstractState &as) |
| Returns true if the switch branch is feasible; narrows as in-place. | |
| void | updateStateOnAddr (const AddrStmt *addr) |
| void | updateStateOnBinary (const BinaryOPStmt *binary) |
| void | updateStateOnCmp (const CmpStmt *cmp) |
| void | updateStateOnLoad (const LoadStmt *load) |
| void | updateStateOnStore (const StoreStmt *store) |
| void | updateStateOnCopy (const CopyStmt *copy) |
| void | updateStateOnCall (const CallPE *callPE) |
| void | updateStateOnRet (const RetPE *retPE) |
| void | updateStateOnGep (const GepStmt *gep) |
| void | updateStateOnSelect (const SelectStmt *select) |
| void | updateStateOnPhi (const PhiStmt *phi) |
| AbsExtAPI * | getUtils () |
| virtual bool | isExtCall (const CallICFGNode *callNode) |
| virtual void | handleExtCall (const CallICFGNode *callNode) |
| virtual bool | isRecursiveFun (const FunObjVar *fun) |
| Check if a function is recursive (part of a call graph SCC) | |
| virtual void | skipRecursionWithTop (const CallICFGNode *callNode) |
| virtual bool | isRecursiveCallSite (const CallICFGNode *callNode, const FunObjVar *) |
| Check if caller and callee are in the same CallGraph SCC (i.e. a recursive callsite) | |
| virtual void | handleFunCall (const CallICFGNode *callNode) |
| bool | skipRecursiveCall (const CallICFGNode *callNode) |
| Skip recursive callsites (within SCC); entry calls from outside SCC are not skipped. | |
| const FunObjVar * | getCallee (const CallICFGNode *callNode) |
| Get callee function: directly for direct calls, via pointer analysis for indirect calls. | |
Private Attributes | |
| AEAPI * | api {nullptr} |
| Execution State, used to store the Interval Value of every SVF variable. | |
| ICFG * | icfg |
| CallGraph * | callGraph |
| AEStat * | stat |
| Map< std::string, std::function< void(const CallICFGNode *)> > | func_map |
| Set< const ICFGNode * > | allAnalyzedNodes |
| std::string | moduleName |
| std::vector< std::unique_ptr< AEDetector > > | detectors |
| AbsExtAPI * | utils |
Friends | |
| class | AEStat |
| class | AEAPI |
| class | BufOverflowDetector |
| class | NullptrDerefDetector |
AbstractInterpretation is same as Abstract Execution.
Owns the per-node abstract trace and exposes the read/write API directly (no separate state-manager indirection). Sparse modes are implemented as subclasses that override the virtual hooks below (cycle helpers, ValVar accessors, joinStates, def/use queries).
Definition at line 60 of file AbstractInterpretation.h.
| Enumerator | |
|---|---|
| Dense | |
| SemiSparse | |
| Sparse | |
Definition at line 83 of file AbstractInterpretation.h.
| Enumerator | |
|---|---|
| TOP | |
| WIDEN_ONLY | |
| WIDEN_NARROW | |
Definition at line 90 of file AbstractInterpretation.h.
|
virtual |
|
protected |
Factory-only construction. External callers must use getAEInstance(); SparseAbstractInterpretation reaches this via its own ctor.
Definition at line 62 of file AbstractInterpretation.cpp.
|
inline |
Definition at line 118 of file AbstractInterpretation.h.
| void AbstractInterpretation::analyse | ( | ) |
Program entry.
Program entry - analyze from all entry points (multi-entry analysis is the default)
Definition at line 144 of file AbstractInterpretation.cpp.
| void AbstractInterpretation::analyzeFromAllProgEntries | ( | ) |
Analyze all entry points (functions without callers)
Analyze all entry points (functions without callers) - for whole-program analysis. Abstract state is shared across entry points so that functions analyzed from earlier entries are not re-analyzed from scratch.
Definition at line 153 of file AbstractInterpretation.cpp.
Get all entry point functions (functions without callers)
Collect entry point functions for analysis. Entry points are functions without callers (no incoming edges in CallGraph). Uses a deque to allow efficient insertion at front for prioritizing main()
Definition at line 111 of file AbstractInterpretation.cpp.
| AbstractState & AbstractInterpretation::getAbsState | ( | const ICFGNode * | node | ) |
Definition at line 44 of file AbstractStateManager.cpp.
| void AbstractInterpretation::getAbsState | ( | const Set< const ObjVar * > & | vars, |
| AbstractState & | result, | ||
| const ICFGNode * | node | ||
| ) |
Definition at line 168 of file AbstractStateManager.cpp.
| void AbstractInterpretation::getAbsState | ( | const Set< const SVFVar * > & | vars, |
| AbstractState & | result, | ||
| const ICFGNode * | node | ||
| ) |
Definition at line 178 of file AbstractStateManager.cpp.
| void AbstractInterpretation::getAbsState | ( | const Set< const ValVar * > & | vars, |
| AbstractState & | result, | ||
| const ICFGNode * | node | ||
| ) |
Definition at line 158 of file AbstractStateManager.cpp.
|
virtual |
Reimplemented in SVF::SemiSparseAbstractInterpretation, and SVF::FullSparseAbstractInterpretation.
Definition at line 90 of file AbstractStateManager.cpp.
|
virtual |
Reimplemented in SVF::SemiSparseAbstractInterpretation, and SVF::FullSparseAbstractInterpretation.
Definition at line 97 of file AbstractStateManager.cpp.
|
virtual |
Read a top-level variable's abstract value. Dense base does a direct trace lookup; sparse subclasses override with their own resolution chain (def-site walk, call-result fallback, etc.). All three overloads are virtual so full-sparse can route ObjVar reads through the SVFG.
Dense base: direct trace lookup, with a top sentinel for genuinely missing entries (e.g. function parameters like argc, never written before first read). Sparse subclasses override with a def-site resolution chain.
The "in map" check is a raw map.count — NOT inVarToValTable / inVarToAddrsTable, which gate on isInterval / isAddr. SVF canonically represents uninit and null-pointer shapes as (interval=bottom ∧ addrs=∅); those predicates would falsely report such an entry as "not present", and the top fallback below would then clobber the very signal NullptrDerefDetector::isUninit keys off.
Reimplemented in SVF::SemiSparseAbstractInterpretation, SVF::FullSparseAbstractInterpretation, SVF::SemiSparseAbstractInterpretation, SVF::FullSparseAbstractInterpretation, and SVF::FullSparseAbstractInterpretation.
Definition at line 80 of file AbstractStateManager.cpp.
|
static |
Factory: returns the singleton instance. The concrete class is chosen once, on first call, from Options::AESparsity(): SemiSparseAbstractInterpretation for SemiSparse, FullSparseAbstractInterpretation for Sparse, otherwise the dense base. Must be called only after the option parser has run.
Factory: first call allocates the concrete subclass based on Options::AESparsity(); all subsequent calls return the same instance. Must only be called after the option parser has populated AESparsity.
Definition at line 77 of file AbstractInterpretation.cpp.
Definition at line 370 of file AbstractStateManager.cpp.
|
private |
Get callee function: directly for direct calls, via pointer analysis for indirect calls.
Definition at line 672 of file AbstractInterpretation.cpp.
|
protectedvirtual |
Build a full cycle-head AbstractState. Dense default: trace[cycle_head] as-is. Semi-sparse subclass: also pull cycle ValVars from def-sites.
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 162 of file AELoopRecursion.cpp.
| IntervalValue AbstractInterpretation::getGepByteOffset | ( | const GepStmt * | gep | ) |
Definition at line 253 of file AbstractStateManager.cpp.
| IntervalValue AbstractInterpretation::getGepElementIndex | ( | const GepStmt * | gep | ) |
Definition at line 196 of file AbstractStateManager.cpp.
| AddressValue AbstractInterpretation::getGepObjAddrs | ( | const ValVar * | pointer, |
| IntervalValue | offset | ||
| ) |
Definition at line 313 of file AbstractStateManager.cpp.
| const SVFType * AbstractInterpretation::getPointeeElement | ( | const ObjVar * | var, |
| const ICFGNode * | node | ||
| ) |
Definition at line 355 of file AbstractStateManager.cpp.
|
inline |
Definition at line 183 of file AbstractInterpretation.h.
|
inlineprivate |
Definition at line 279 of file AbstractInterpretation.h.
Handle a call site node: dispatch to ext-call, direct-call, or indirect-call handling.
Definition at line 639 of file AbstractInterpretation.cpp.
|
privatevirtual |
Definition at line 662 of file AbstractInterpretation.cpp.
|
privatevirtual |
Handle direct or indirect call: get callee(s), process function body, set return state.
For direct calls, the callee is known statically. For indirect calls, the previous implementation resolved callees from the abstract state's address domain, which only picked the first address and missed other targets. Since the abstract state's address domain is not an over-approximation for function pointers (it may be uninitialized or incomplete), we now use Andersen's pointer analysis results from the pre-computed call graph, which soundly resolves all possible indirect call targets.
Definition at line 706 of file AbstractInterpretation.cpp.
|
private |
Handle a function body via worklist-driven WTO traversal starting from funEntry.
Handle a function using worklist algorithm guided by WTO order. All top-level WTO components are pushed into the worklist upfront, so the traversal order is exactly the WTO order — each node is visited once, and cycles are handled as whole components.
Definition at line 611 of file AbstractInterpretation.cpp.
|
privatevirtual |
Initialize abstract state for the global ICFG node and process global statements.
handle global node Initializes the abstract state for the global ICFG node and processes all global statements. This includes setting up the null pointer and black hole pointer (blkPtr). BlkPtr is initialized to point to the BlackHole object, representing an unknown memory location that cannot be statically resolved.
Definition at line 177 of file AbstractInterpretation.cpp.
Handle an ICFG node: execute statements; return true if state changed.
Handle an ICFG node: execute statements on the current abstract state. The node's pre-state must already be in getAbsState(node) (set by mergeStatesFromPredecessors, or by handleGlobalNode for the global node). Returns true if the abstract state has changed, false if fixpoint reached or unreachable.
Definition at line 552 of file AbstractInterpretation.cpp.
|
privatevirtual |
Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration.
Definition at line 235 of file AELoopRecursion.cpp.
Dispatch an SVF statement (Addr/Binary/Cmp/Load/Store/Copy/Gep/Select/Phi/Call/Ret) to its handler.
Definition at line 741 of file AbstractInterpretation.cpp.
Definition at line 64 of file AbstractStateManager.cpp.
|
virtual |
Reimplemented in SVF::SemiSparseAbstractInterpretation, and SVF::FullSparseAbstractInterpretation.
Definition at line 119 of file AbstractStateManager.cpp.
|
virtual |
Reimplemented in SVF::SemiSparseAbstractInterpretation, and SVF::FullSparseAbstractInterpretation.
Definition at line 127 of file AbstractStateManager.cpp.
|
virtual |
Side-effect-free existence check.
Dense base: direct existence check at node. Mirrors the simplified getAbsValue lookup — uses raw map.contains rather than inVar*Table predicates, which would falsely report neutral (interval=bottom ∧ addrs=∅) entries as "not present".
Reimplemented in SVF::SemiSparseAbstractInterpretation, SVF::FullSparseAbstractInterpretation, SVF::SemiSparseAbstractInterpretation, SVF::FullSparseAbstractInterpretation, and SVF::FullSparseAbstractInterpretation.
Definition at line 111 of file AbstractStateManager.cpp.
|
private |
Returns true if the branch is reachable; narrows as in-place.
Definition at line 536 of file AbstractInterpretation.cpp.
|
private |
Returns true if the cmp-conditional branch is feasible; narrows as in-place.
Definition at line 440 of file AbstractInterpretation.cpp.
|
privatevirtual |
Definition at line 657 of file AbstractInterpretation.cpp.
|
privatevirtual |
Check if caller and callee are in the same CallGraph SCC (i.e. a recursive callsite)
Definition at line 104 of file AELoopRecursion.cpp.
Check if a function is recursive (part of a call graph SCC)
Definition at line 47 of file AELoopRecursion.cpp.
|
private |
Returns true if the switch branch is feasible; narrows as in-place.
Definition at line 499 of file AbstractInterpretation.cpp.
|
virtual |
Join src into dst with sparsity-aware semantics. Dense merges everything; semi-sparse skips ValVars.
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 59 of file AbstractStateManager.cpp.
| AbstractValue AbstractInterpretation::loadValue | ( | const ValVar * | pointer, |
| const ICFGNode * | node | ||
| ) |
Definition at line 337 of file AbstractStateManager.cpp.
Pull-based state merge: read abstractTrace[pred] for each predecessor, apply branch refinement for conditional IntraCFGEdges, and join into abstractTrace[node]. Returns true if at least one predecessor had state.
Pull-based state merge: for each predecessor that has an abstract state, copy its state, apply branch refinement for conditional IntraCFGEdges, and join all feasible states into getAbsState(node). The join is dispatched through the manager so semi-sparse can skip ValVar merging. Returns true if at least one predecessor contributed state.
Definition at line 217 of file AbstractInterpretation.cpp.
|
protectedvirtual |
Narrow prev with cur; write the narrowed state back. Returns true when narrowing is disabled or the narrowed state equals prev. Semi-sparse subclass scatters the narrowed ValVars on non-fixpoint.
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 183 of file AELoopRecursion.cpp.
|
inline |
Definition at line 187 of file AbstractInterpretation.h.
|
virtual |
collect checkpoint
Definition at line 45 of file AbstractInterpretation.cpp.
Check if narrowing should be applied: always for regular loops, mode-dependent for recursion.
Definition at line 130 of file AELoopRecursion.cpp.
|
privatevirtual |
TOP mode for recursive calls: skip the function body entirely and conservatively set all reachable stores and the return value to TOP.
Definition at line 54 of file AELoopRecursion.cpp.
|
private |
Skip recursive callsites (within SCC); entry calls from outside SCC are not skipped.
Definition at line 112 of file AELoopRecursion.cpp.
| void AbstractInterpretation::storeValue | ( | const ValVar * | pointer, |
| const AbstractValue & | val, | ||
| const ICFGNode * | node | ||
| ) |
Definition at line 347 of file AbstractStateManager.cpp.
|
virtual |
Replace the state at node. Sparse subclasses replace only the ObjVar map (ValVars live at def-sites).
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 54 of file AbstractStateManager.cpp.
|
virtual |
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 141 of file AbstractStateManager.cpp.
|
virtual |
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 148 of file AbstractStateManager.cpp.
|
virtual |
Write a variable's abstract value. Sparse subclasses re-route ValVar writes to the def-site.
Reimplemented in SVF::SemiSparseAbstractInterpretation, and SVF::SemiSparseAbstractInterpretation.
Definition at line 136 of file AbstractStateManager.cpp.
Definition at line 895 of file AbstractInterpretation.cpp.
|
private |
Definition at line 913 of file AbstractInterpretation.cpp.
Handle CallPE: phi-like merging of actual parameters from all call sites into the formal parameter at FunEntryICFGNode (e.g., formal = join(actual1@cs1, actual2@cs2, ...))
Definition at line 870 of file AbstractInterpretation.cpp.
Definition at line 970 of file AbstractInterpretation.cpp.
Definition at line 1209 of file AbstractInterpretation.cpp.
Definition at line 808 of file AbstractInterpretation.cpp.
Definition at line 1195 of file AbstractInterpretation.cpp.
Definition at line 835 of file AbstractInterpretation.cpp.
Definition at line 887 of file AbstractInterpretation.cpp.
|
private |
Definition at line 816 of file AbstractInterpretation.cpp.
Definition at line 1202 of file AbstractInterpretation.cpp.
|
protectedvirtual |
Widen prev with cur; write the widened state to trace[cycle_head]. Returns true when next == prev (fixpoint). Semi-sparse subclass additionally scatters ValVars to their def-sites.
Reimplemented in SVF::SemiSparseAbstractInterpretation.
Definition at line 171 of file AELoopRecursion.cpp.
Definition at line 63 of file AbstractInterpretation.h.
Definition at line 62 of file AbstractInterpretation.h.
|
friend |
Definition at line 64 of file AbstractInterpretation.h.
|
friend |
Definition at line 65 of file AbstractInterpretation.h.
|
protected |
per-node trace; owned here
Definition at line 308 of file AbstractInterpretation.h.
Definition at line 298 of file AbstractInterpretation.h.
Execution State, used to store the Interval Value of every SVF variable.
Definition at line 273 of file AbstractInterpretation.h.
|
private |
Definition at line 276 of file AbstractInterpretation.h.
|
private |
Definition at line 301 of file AbstractInterpretation.h.
|
private |
Definition at line 296 of file AbstractInterpretation.h.
|
private |
Definition at line 275 of file AbstractInterpretation.h.
|
private |
Definition at line 299 of file AbstractInterpretation.h.
Definition at line 307 of file AbstractInterpretation.h.
|
private |
Definition at line 277 of file AbstractInterpretation.h.
Data and helpers reachable from SparseAbstractInterpretation.
Definition at line 306 of file AbstractInterpretation.h.
|
private |
Definition at line 302 of file AbstractInterpretation.h.