39using namespace SVFUtil;
121 if (
it->second->getInEdges().empty())
123 for (
auto inEdge:
it->second->getInEdges())
130 if (
inEdge->isDirectCallEdge())
132 else if (
inEdge->isIndirectCallEdge())
135 assert(
false &&
"CallGraphEdge must "
136 "be either direct or indirect!");
199 std::vector<AbstractState>
workList;
207 SVFUtil::dyn_cast<IntraCFGEdge>(
edge))
227 SVFUtil::dyn_cast<CallCFGEdge>(
edge))
235 SVFUtil::dyn_cast<RetCFGEdge>(
edge))
246 assert(
false &&
"Unhandled ICFGEdge type encountered!");
294 if (!
loadVar0->getInEdges().empty())
304 if (!
loadVar0->getInEdges().empty())
316 if (!
loadVar1->getInEdges().empty())
326 if (!
loadVar1->getInEdges().empty())
393 for (
const auto &
addr: addrs)
415 for (
const auto &
addr: addrs)
433 for (
const auto &
addr: addrs)
452 for (
const auto &
addr: addrs)
471 for (
const auto &
addr: addrs)
487 assert(
false &&
"implement this part");
513 if (SVFUtil::isa<CopyStmt>(
stmt))
518 else if (
const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(
stmt))
520 if (
new_es.inVarToAddrsTable(load->getRHSVarID()))
523 for (
const auto &
addr: addrs)
542 if (
cmpVar->getInEdges().empty())
571 std::deque<const ICFGNode*> worklist;
602 bool isFunEntry = SVFUtil::isa<FunEntryICFGNode>(node);
681 std::vector<const ICFGNode*>
outEdges;
721 std::vector<const ICFGNode*>
outEdges;
762 while (!worklist.
empty())
814 assert (
false &&
"it is not call node");
855 if (
retNode->getSVFStmts().size() > 0)
857 if (
const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*
retNode->getSVFStmts().begin()))
859 if (!retPE->getLHSVar()->isPointer() &&
860 !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
899 if (
Addrs.getAddrs().empty())
904 return SVFUtil::dyn_cast<FunObjVar>(
func_var);
937 assert(
false &&
"TOP mode should not reach narrowing phase for recursive functions");
944 assert(
false &&
"Unknown recursion handling mode");
1107 else if (SVFUtil::isa<UnaryOPStmt>(
stmt))
1110 else if (SVFUtil::isa<BranchStmt>(
stmt))
1114 else if (
const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(
stmt))
1118 else if (
const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(
stmt))
1143 else if (
const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(
stmt))
1148 assert(
false &&
"implement this part");
1159 if (
retNode->getSVFStmts().size() > 0)
1161 if (
const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*
retNode->getSVFStmts().begin()))
1164 if (!retPE->getLHSVar()->isPointer() && !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
1168 if (!
retNode->getOutEdges().empty())
1170 if (
retNode->getOutEdges().size() == 1)
1183 for (
const ICFGNode* node: bb->getICFGNodeList())
1187 if (
const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(
stmt))
1191 if (
as.inVarToAddrsTable(
lhs))
1193 if (!
rhsVar->isPointer() && !
rhsVar->isConstDataOrAggDataButNotNullPtr())
1238 if (
it.second->getFun())
1240 funs.insert(
it.second->getFun());
1266 if (
fullName.find(
'/') == std::string::npos)
1284 std::cout << std::setw(
field_width) <<
it->first <<
it->second <<
"\n";
1286 SVFUtil::outs() <<
"-------------------------------------------------------\n";
1294 SVFUtil::outs() <<
"#######################################################" << std::endl;
1308 if (
const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
1310 if (
const FunObjVar *fun = call->getCalledFunction())
1377 if (
as[cond].getInterval().is_numeral())
1447 as.initObjVar(SVFUtil::cast<ObjVar>(
addr->getRHSVar()));
1468 switch (
binary->getOpcode())
1511 assert(
false &&
"undefined binary: ");
1522 if (
as.inVarToAddrsTable(
op0) &&
as.inVarToAddrsTable(
op1))
1551 if (!
as.inVarToValTable(
op0))
1553 if (!
as.inVarToValTable(
op1))
1556 if (
as.inVarToValTable(
op0) &&
as.inVarToValTable(
op1))
1559 if (
as[
op0].isInterval() &&
as[
op1].isInterval())
1564 auto predicate =
cmp->getPredicate();
1609 assert(
false &&
"undefined compare: ");
1613 else if (
as[
op0].isAddr() &&
as[
op1].isAddr())
1617 auto predicate =
cmp->getPredicate();
1624 if (
lhs.hasIntersect(
rhs))
1628 else if (
lhs.empty() &&
rhs.empty())
1642 if (
lhs.hasIntersect(
rhs))
1646 else if (
lhs.empty() &&
rhs.empty())
1661 if (
lhs.size() == 1 &&
rhs.size() == 1)
1676 if (
lhs.size() == 1 &&
rhs.size() == 1)
1691 if (
lhs.size() == 1 &&
rhs.size() == 1)
1706 if (
lhs.size() == 1 &&
rhs.size() == 1)
1723 assert(
false &&
"undefined compare: ");
1752 if (SVFUtil::isa<SVFIntegerType>(
type))
1755 if (
as[
var->getId()].getInterval().is_numeral())
1763 else if (
bits == 16)
1769 else if (
bits == 32)
1775 else if (
bits == 64)
1782 assert(
false &&
"cannot support int type other than u8/16/32/64");
1796 if(
itv.isBottom())
return itv;
1840 assert(
false &&
"cannot support dst int type other than u8/16/32");
1895 if (
as[
rhs].isAddr())
1905 assert(
false &&
"undefined copy kind");
void performStat() override
u32_t & getICFGNodeTrace()
std::string getMemUsage()
AbstractInterpretation * _ae
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.
std::vector< const ICFGNode * > getNextNodesOfCycle(const ICFGCycleWTO *cycle) const
virtual bool isRecursiveCall(const CallICFGNode *callNode)
Check if a call node calls a recursive function.
virtual void recursiveCallPass(const CallICFGNode *callNode)
Handle recursive call in TOP mode: set all stores and return value to TOP.
void updateStateOnStore(const StoreStmt *store)
bool hasAbsStateFromTrace(const ICFGNode *node)
void collectCycleHeads(const std::list< const ICFGWTOComp * > &comps)
Recursively collect cycle heads from nested WTO components.
virtual void handleFunCall(const CallICFGNode *callNode)
Handle direct or indirect call: get callee, process function body, set return state.
Set< const FunObjVar * > recursiveFuns
void updateStateOnGep(const GepStmt *gep)
void analyse()
Program entry.
virtual void handleGlobalNode()
Global ICFGNode is handled at the entry of the program,.
bool mergeStatesFromPredecessors(const ICFGNode *icfgNode)
virtual bool isExtCall(const CallICFGNode *callNode)
void initWTO()
Compute IWTO for each function partition entry.
AbstractInterpretation()
Constructor.
void updateStateOnPhi(const PhiStmt *phi)
bool handleICFGNode(const ICFGNode *node)
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
std::vector< std::unique_ptr< AEDetector > > detectors
std::vector< const ICFGNode * > getNextNodes(const ICFGNode *node) const
virtual void handleExtCall(const CallICFGNode *callNode)
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
Set< const CallICFGNode * > checkpoints
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
Map< s32_t, s32_t > _reverse_predicate
void updateStateOnSelect(const SelectStmt *select)
virtual void handleSVFStatement(const SVFStmt *stmt)
bool skipRecursiveCall(const CallICFGNode *callNode)
Skip recursive callsites (within SCC); entry calls from outside SCC are not skipped.
SVFIR * svfir
protected data members, also used in subclasses
virtual void runOnModule(ICFG *icfg)
void handleFunction(const ICFGNode *funEntry)
virtual bool isRecursiveCallSite(const CallICFGNode *callNode, const FunObjVar *)
Check if a call is a recursive callsite (within same SCC, not entry call from outside)
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)
Map< const ICFGNode *, const ICFGCycleWTO * > cycleHeadToCycle
virtual void handleCallSite(const ICFGNode *node)
void updateStateOnRet(const RetPE *retPE)
void updateStateOnCopy(const CopyStmt *copy)
Set< std::pair< const CallICFGNode *, NodeID > > nonRecursiveCallSites
void updateStateOnLoad(const LoadStmt *load)
void updateStateOnBinary(const BinaryOPStmt *binary)
Map< const ICFGNode *, AbstractState > abstractTrace
std::vector< const CallICFGNode * > callSiteStack
virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto)
handle instructions in svf basic blocks
virtual void setTopToObjInRecursion(const CallICFGNode *callnode)
Set all store values in a recursive function to TOP (used in TOP mode)
Map< s32_t, s32_t > _switch_lhsrhs_predicate
void updateStateOnCmp(const CmpStmt *cmp)
virtual void handleLoopOrRecursion(const ICFGCycleWTO *cycle)
Map< const FunObjVar *, const ICFGWTO * > funcToWTO
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
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
NodeID getRHSVarID() const
NodeID getLHSVarID() const
s64_t getIntNumeral() const
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
@ 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_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_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 push(const Data &data)
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
bool isDeclaration() const
iterator begin()
Iterators.
u32_t nodeNum
total num of edge
NodeType * getGNode(NodeID id) const
Get a node.
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
virtual const std::string toString() 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.
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 > NullDerefCheck
nullptr dereference checker, Default: false
static const Option< bool > PStat
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
CallGraph * getCallGraph() const
Return call graph.
SCCDetection< CallGraph * > CallGraphSCC
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
const CallGraph * getCallGraph()
Get CG.
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
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
std::ostream & errs()
Overwrite llvm::errs()
bool isExtCall(const FunObjVar *fun)
std::ostream & outs()
Overwrite llvm::outs()
llvm::IRBuilder IRBuilder