40using namespace SVFUtil;
78 assert(
false &&
"No preAbsTrace for this node");
95 return as[
var->getId()];
111 assert(
false &&
"Unknown SVFVar kind");
135 assert(
false &&
"Unknown SVFVar kind");
244 assert(
false &&
"No entry functions found for analysis");
295 std::vector<AbstractState>
workList;
315 else if (SVFUtil::isa<CallCFGEdge>(
edge))
319 else if (SVFUtil::isa<RetCFGEdge>(
edge))
379 if (!
loadVar0->getInEdges().empty())
389 if (!
loadVar0->getInEdges().empty())
401 if (!
loadVar1->getInEdges().empty())
411 if (!
loadVar1->getInEdges().empty())
478 for (
const auto &
addr: addrs)
500 for (
const auto &
addr: addrs)
518 for (
const auto &
addr: addrs)
537 for (
const auto &
addr: addrs)
556 for (
const auto &
addr: addrs)
572 assert(
false &&
"implement this part");
598 if (SVFUtil::isa<CopyStmt>(
stmt))
603 else if (
const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(
stmt))
605 if (
new_es.inVarToAddrsTable(load->getRHSVarID()))
608 for (
const auto &
addr: addrs)
627 if (
cmpVar->getInEdges().empty())
659 bool isFunEntry = SVFUtil::isa<FunEntryICFGNode>(node);
724 while (!worklist.
empty())
758 assert (
false &&
"it is not call node");
787 if (
retNode->getSVFStmts().size() > 0)
789 if (
const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*
retNode->getSVFStmts().begin()))
791 if (!retPE->getLHSVar()->isPointer() &&
792 !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
831 if (
Addrs.getAddrs().empty())
836 return SVFUtil::dyn_cast<FunObjVar>(
func_var);
869 assert(
false &&
"TOP mode should not reach narrowing phase for recursive functions");
876 assert(
false &&
"Unknown recursion handling mode");
915 if (
callee->isDeclaration())
1051 else if (SVFUtil::isa<UnaryOPStmt>(
stmt))
1054 else if (SVFUtil::isa<BranchStmt>(
stmt))
1058 else if (
const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(
stmt))
1062 else if (
const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(
stmt))
1087 else if (
const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(
stmt))
1092 assert(
false &&
"implement this part");
1103 if (
retNode->getSVFStmts().size() > 0)
1105 if (
const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*
retNode->getSVFStmts().begin()))
1108 if (!retPE->getLHSVar()->isPointer() && !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
1112 if (!
retNode->getOutEdges().empty())
1114 if (
retNode->getOutEdges().size() == 1)
1127 for (
const ICFGNode* node: bb->getICFGNodeList())
1131 if (
const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(
stmt))
1135 if (
as.inVarToAddrsTable(
lhs))
1137 if (!
rhsVar->isPointer() && !
rhsVar->isConstDataOrAggDataButNotNullPtr())
1175 if (
as[cond].getInterval().is_numeral())
1245 as.initObjVar(SVFUtil::cast<ObjVar>(
addr->getRHSVar()));
1266 switch (
binary->getOpcode())
1309 assert(
false &&
"undefined binary: ");
1320 if (
as.inVarToAddrsTable(
op0) &&
as.inVarToAddrsTable(
op1))
1349 if (!
as.inVarToValTable(
op0))
1351 if (!
as.inVarToValTable(
op1))
1354 if (
as.inVarToValTable(
op0) &&
as.inVarToValTable(
op1))
1357 if (
as[
op0].isInterval() &&
as[
op1].isInterval())
1362 auto predicate =
cmp->getPredicate();
1414 assert(
false &&
"undefined compare: ");
1418 else if (
as[
op0].isAddr() &&
as[
op1].isAddr())
1422 auto predicate =
cmp->getPredicate();
1429 if (
lhs.hasIntersect(
rhs))
1433 else if (
lhs.empty() &&
rhs.empty())
1447 if (
lhs.hasIntersect(
rhs))
1451 else if (
lhs.empty() &&
rhs.empty())
1466 if (
lhs.size() == 1 &&
rhs.size() == 1)
1481 if (
lhs.size() == 1 &&
rhs.size() == 1)
1496 if (
lhs.size() == 1 &&
rhs.size() == 1)
1511 if (
lhs.size() == 1 &&
rhs.size() == 1)
1535 assert(
false &&
"undefined compare: ");
1564 if (SVFUtil::isa<SVFIntegerType>(
type))
1567 if (
as[
var->getId()].getInterval().is_numeral())
1575 else if (
bits == 16)
1581 else if (
bits == 32)
1587 else if (
bits == 64)
1594 assert(
false &&
"cannot support int type other than u8/16/32/64");
1608 if(
itv.isBottom())
return itv;
1652 assert(
false &&
"cannot support dst int type other than u8/16/32");
1707 if (
as[
rhs].isAddr())
1717 assert(
false &&
"undefined copy kind");
void performStat() override
u32_t & getICFGNodeTrace()
Handles external API calls and manages abstract states.
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
void updateStateOnCall(const CallPE *callPE)
const FunObjVar * getCallee(const CallICFGNode *callNode)
Get callee function: directly for direct calls, via pointer analysis for indirect calls.
void updateStateOnStore(const StoreStmt *store)
virtual void handleFunCall(const CallICFGNode *callNode)
void analyzeFromAllProgEntries()
Analyze all entry points (functions without callers)
void updateStateOnGep(const GepStmt *gep)
void analyse()
Program entry.
virtual void handleGlobalNode()
Initialize abstract state for the global ICFG node and process global statements.
void handleFunction(const ICFGNode *funEntry, const CallICFGNode *caller=nullptr)
Handle a function body via worklist-driven WTO traversal starting from funEntry.
virtual bool isExtCall(const CallICFGNode *callNode)
void updateAbstractValue(const ValVar *var, const AbstractValue &val)
Set abstract value for a top-level variable at a given ICFG node.
AbstractState & getAbstractState(const ICFGNode *node)
Retrieve the abstract state from the trace for a given ICFG node; asserts if no trace exists.
AbstractInterpretation()
Constructor.
void updateStateOnPhi(const PhiStmt *phi)
bool handleICFGNode(const ICFGNode *node)
Handle an ICFG node: execute statements; return true if state changed.
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
Check if the branch on intraEdge is feasible under abstract state as.
std::vector< std::unique_ptr< AEDetector > > detectors
virtual void handleExtCall(const CallICFGNode *callNode)
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
Check if switch branch with case value succ is feasible; refine intervals in as accordingly.
Map< s32_t, s32_t > _reverse_predicate
PreAnalysis * preAnalysis
bool mergeStatesFromPredecessors(const ICFGNode *node)
void updateStateOnSelect(const SelectStmt *select)
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 skipRecursiveCall(const CallICFGNode *callNode)
Skip recursive callsites (within SCC); entry calls from outside SCC are not skipped.
bool hasAbstractState(const ICFGNode *node)
Check if an abstract state exists in the trace for a given ICFG node.
SVFIR * svfir
protected data members, also used in subclasses
virtual void runOnModule(ICFG *icfg)
virtual bool isRecursiveCallSite(const CallICFGNode *callNode, const FunObjVar *)
Check if caller and callee are in the same CallGraph SCC (i.e. a recursive callsite)
bool shouldApplyNarrowing(const FunObjVar *fun)
Check if narrowing should be applied: always for regular loops, mode-dependent for recursion.
virtual bool isRecursiveFun(const FunObjVar *fun)
Check if a function is recursive (part of a call graph SCC)
void updateStateOnAddr(const AddrStmt *addr)
virtual ~AbstractInterpretation()
Destructor.
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
Check if cmpStmt with successor value succ is feasible; refine intervals in as accordingly.
virtual void handleCallSite(const ICFGNode *node)
Handle a call site node: dispatch to ext-call, direct-call, or indirect-call handling.
void updateStateOnRet(const RetPE *retPE)
void updateStateOnCopy(const CopyStmt *copy)
void propagateObjVarAbsVal(const ObjVar *var, const ICFGNode *defSite)
Propagate an ObjVar's abstract value from defSite to all its use-site ICFGNodes via SVFG.
std::deque< const FunObjVar * > collectProgEntryFuns()
Get all entry point functions (functions without callers)
void updateStateOnLoad(const LoadStmt *load)
void updateStateOnBinary(const BinaryOPStmt *binary)
Map< const ICFGNode *, AbstractState > abstractTrace
Set< const ICFGNode * > allAnalyzedNodes
virtual void setTopToObjInRecursion(const CallICFGNode *callnode)
Set all store targets and return value to TOP for a recursive call node.
virtual void handleRecursiveCall(const CallICFGNode *callNode)
Handle recursive call in TOP mode: set all stores and return value to TOP.
virtual void handleLoopOrRecursion(const ICFGCycleWTO *cycle, const CallICFGNode *caller=nullptr)
Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration.
Map< s32_t, s32_t > _switch_lhsrhs_predicate
const SVFVar * getSVFVar(NodeID varId) const
Retrieve SVFVar given its ID; asserts if no such variable exists.
void updateStateOnCmp(const CmpStmt *cmp)
const AbstractValue & getAbstractValue(const ValVar *var)
Retrieve abstract value for a top-level variable at a given ICFG node.
static u32_t getVirtualMemAddress(u32_t idx)
The physical address starts with 0x7f...... + idx.
AbstractState narrowing(const AbstractState &other)
domain narrow with other, and return the narrowed domain
AbstractState widening(const AbstractState &other)
domain widen with other, and return the widened domain
AddressValue & getAddrs()
bool meet_with(const AddressValue &other)
Return a intersected AddressValue.
AddrSet::const_iterator begin() const
NodeID getRHSVarID() const
NodeID getLHSVarID() const
s64_t getIntNumeral() const
const FunObjVar * getFunction() const
Get function of this call node.
bool hasIndCSCallees(const CallICFGNode *cs) const
const FunctionSet & getIndCSCallees(const CallICFGNode *cs) const
@ ICMP_SGT
signed greater than
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_UGE
unsigned greater or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ ICMP_ULE
unsigned less or equal
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_ULT
unsigned less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ ICMP_SLT
signed less than
@ ICMP_UGT
unsigned greater than
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_SLE
signed less or equal
bool isDeclaration() const
iterator begin()
Iterators.
const GEdgeSetTy & getInEdges() const
const SVFStmtList & getSVFStmts() const
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
void updateCallGraph(CallGraph *callgraph)
update ICFG for indirect calls
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
GlobalICFGNode * getGlobalICFGNode() const
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
static BoundedInt minus_infinity()
Get minus infinity -inf.
static BoundedInt plus_infinity()
Get plus infinity +inf.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
static const OptionMap< u32_t > HandleRecur
recursion handling mode, Default: TOP
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
static const Option< u32_t > WidenDelay
static const Option< bool > PStat
bool inSameCallGraphSCC(const FunObjVar *fun1, const FunObjVar *fun2)
Return TRUE if this edge is inside a PTACallGraph SCC, i.e., src node and dst node are in the same SC...
bool isInRecursion(const FunObjVar *fun) const
const Map< const FunObjVar *, const ICFGWTO * > & getFuncToWTO() const
Accessors for WTO data.
const Set< const ICFGNode * > getUseSitesOfObjVar(const ObjVar *obj, const ICFGNode *node) const
Given an ObjVar and its def-site ICFGNode, find all use-site ICFGNodes.
AndersenWaveDiff * getPointerAnalysis() const
Accessors for Andersen's results.
void initWTO()
Build WTO for each function using call graph SCC.
CallGraph * getCallGraph() const
const CallSiteToFunPtrMap & getIndirectCallsites() const
Add/get indirect callsites.
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
ICFGNode * getICFGNode() const
u32_t getByteSize() const
virtual const std::string & getName() const
bool isExtCall(const FunObjVar *fun)
WTONode< ICFG > ICFGSingletonWTO
llvm::IRBuilder IRBuilder
WTOComponent< ICFG > ICFGWTOComp