Static Value-Flow Analysis
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | Friends | List of all members
SVF::AbstractInterpretation Class Reference

AbstractInterpretation is same as Abstract Execution. More...

#include <AbstractInterpretation.h>

Public Types

typedef SCCDetection< PTACallGraph * > CallGraphSCC
 

Public Member Functions

 AbstractInterpretation ()
 Constructor. More...
 
virtual void runOnModule (ICFG *icfg)
 
virtual ~AbstractInterpretation ()
 Destructor. More...
 
void analyse ()
 Program entry. More...
 
void addDetector (std::unique_ptr< AEDetector > detector)
 

Static Public Member Functions

static AbstractInterpretationgetAEInstance ()
 

Public Attributes

Set< const CallICFGNode * > checkpoints
 

Private Member Functions

virtual void handleGlobalNode ()
 Global ICFGNode is handled at the entry of the program,. More...
 
void initWTO ()
 Mark recursive functions in the call graph. More...
 
bool mergeStatesFromPredecessors (const ICFGNode *icfgNode)
 
bool isBranchFeasible (const IntraCFGEdge *intraEdge, AbstractState &as)
 
virtual void handleSingletonWTO (const ICFGSingletonWTO *icfgSingletonWto)
 handle instructions in svf basic blocks More...
 
virtual void handleCallSite (const ICFGNode *node)
 
virtual void handleCycleWTO (const ICFGCycleWTO *cycle)
 handle wto cycle (loop) More...
 
void handleWTOComponents (const std::list< const ICFGWTOComp * > &wtoComps)
 Hanlde two types of WTO components (singleton and cycle) More...
 
void handleWTOComponent (const ICFGWTOComp *wtoComp)
 
virtual void handleSVFStatement (const SVFStmt *stmt)
 
virtual void SkipRecursiveCall (const CallICFGNode *callnode)
 
bool isCmpBranchFeasible (const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
 
bool isSwitchBranchFeasible (const SVFVar *var, s64_t succ, AbstractState &as)
 
void collectCheckPoint ()
 
void checkPointAllSet ()
 
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)
 
AbstractStategetAbsStateFromTrace (const ICFGNode *node)
 
bool hasAbsStateFromTrace (const ICFGNode *node)
 
AbsExtAPIgetUtils ()
 
virtual bool isExtCall (const CallICFGNode *callNode)
 
virtual void extCallPass (const CallICFGNode *callNode)
 
virtual bool isRecursiveCall (const CallICFGNode *callNode)
 
virtual void recursiveCallPass (const CallICFGNode *callNode)
 
virtual bool isDirectCall (const CallICFGNode *callNode)
 
virtual void directCallFunPass (const CallICFGNode *callNode)
 
virtual bool isIndirectCall (const CallICFGNode *callNode)
 
virtual void indirectCallFunPass (const CallICFGNode *callNode)
 

Private Attributes

SVFIRsvfir
 protected data members, also used in subclasses More...
 
AEAPIapi {nullptr}
 Execution State, used to store the Interval Value of every SVF variable. More...
 
ICFGicfg
 
AEStatstat
 
std::vector< const CallICFGNode * > callSiteStack
 
Map< const SVFFunction *, ICFGWTO * > funcToWTO
 
Set< const SVFFunction * > recursiveFuns
 
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
 
Map< const ICFGNode *, AbstractStateabstractTrace
 
std::string moduleName
 
std::vector< std::unique_ptr< AEDetector > > detectors
 
AbsExtAPIutils
 
Map< s32_t, s32_t_reverse_predicate
 
Map< s32_t, s32_t_switch_lhsrhs_predicate
 

Friends

class AEStat
 
class AEAPI
 
class BufOverflowDetector
 

Detailed Description

AbstractInterpretation is same as Abstract Execution.

Definition at line 102 of file AbstractInterpretation.h.

Member Typedef Documentation

◆ CallGraphSCC

Definition at line 109 of file AbstractInterpretation.h.

Constructor & Destructor Documentation

◆ AbstractInterpretation()

AbstractInterpretation::AbstractInterpretation ( )

Constructor.

Definition at line 60 of file AbstractInterpretation.cpp.

61 {
62  stat = new AEStat(this);
63 }

◆ ~AbstractInterpretation()

AbstractInterpretation::~AbstractInterpretation ( )
virtual

Destructor.

Definition at line 65 of file AbstractInterpretation.cpp.

66 {
67  delete stat;
68  for (auto it: funcToWTO)
69  delete it.second;
70 
71 }
Map< const SVFFunction *, ICFGWTO * > funcToWTO

Member Function Documentation

◆ addDetector()

void SVF::AbstractInterpretation::addDetector ( std::unique_ptr< AEDetector detector)
inline

Definition at line 127 of file AbstractInterpretation.h.

128  {
129  detectors.push_back(std::move(detector));
130  }
std::vector< std::unique_ptr< AEDetector > > detectors
constexpr std::remove_reference< T >::type && move(T &&t) noexcept
Definition: SVFUtil.h:447

◆ analyse()

void AbstractInterpretation::analyse ( )

Program entry.

Definition at line 107 of file AbstractInterpretation.cpp.

108 {
109  initWTO();
110  // handle Global ICFGNode of SVFModule
114  if (const SVFFunction* fun = svfir->getModule()->getSVFFunction("main"))
115  {
116  ICFGWTO* wto = funcToWTO[fun];
118  }
119 }
virtual void handleGlobalNode()
Global ICFGNode is handled at the entry of the program,.
void initWTO()
Mark recursive functions in the call graph.
SVFIR * svfir
protected data members, also used in subclasses
void handleWTOComponents(const std::list< const ICFGWTOComp * > &wtoComps)
Hanlde two types of WTO components (singleton and cycle)
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
GlobalICFGNode * getGlobalICFGNode() const
Definition: ICFG.h:236
NodeID getBlkPtr() const
Definition: IRGraph.h:169
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
Definition: IntervalValue.h:94
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
SVFModule * getModule()
Definition: SVFIR.h:161
const SVFFunction * getSVFFunction(const std::string &name)
Definition: SVFModule.cpp:48
const WTOComponentRefList & getWTOComponents() const
Get all wto components in WTO.
Definition: WTO.h:589

◆ checkPointAllSet()

void AbstractInterpretation::checkPointAllSet ( )
private

Definition at line 946 of file AbstractInterpretation.cpp.

947 {
948  if (checkpoints.size() == 0)
949  {
950  return;
951  }
952  else
953  {
954  SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
955  for (const CallICFGNode* call: checkpoints)
956  SVFUtil::errs() << call->toString() + "\n";
957  assert(false);
958  }
959 
960 }
Set< const CallICFGNode * > checkpoints
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition: SVFUtil.cpp:76
std::ostream & errs()
Overwrite llvm::errs()
Definition: SVFUtil.h:56

◆ collectCheckPoint()

void AbstractInterpretation::collectCheckPoint ( )
private

Definition at line 915 of file AbstractInterpretation.cpp.

916 {
917  // traverse every ICFGNode
918  Set<std::string> ae_checkpoint_names = {"svf_assert"};
919  Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
920 
921  for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
922  {
923  const ICFGNode* node = it->second;
924  if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
925  {
926  if (const SVFFunction *fun = call->getCalledFunction())
927  {
928  if (ae_checkpoint_names.find(fun->getName()) !=
929  ae_checkpoint_names.end())
930  {
931  checkpoints.insert(call);
932  }
934  {
935  if (buf_checkpoint_names.find(fun->getName()) !=
936  buf_checkpoint_names.end())
937  {
938  checkpoints.insert(call);
939  }
940  }
941  }
942  }
943  }
944 }
iterator begin()
Iterators.
Definition: GenericGraph.h:627
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition: Options.h:252
ICFG * getICFG() const
Definition: SVFIR.h:171
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96

◆ directCallFunPass()

void AbstractInterpretation::directCallFunPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 614 of file AbstractInterpretation.cpp.

615 {
616  AbstractState& as = getAbsStateFromTrace(callNode);
617  callSiteStack.push_back(callNode);
618 
619  abstractTrace[callNode] = as;
620 
621  ICFGWTO* wto = funcToWTO[callNode->getCalledFunction()];
623 
624  callSiteStack.pop_back();
625  // handle Ret node
626  const RetICFGNode *retNode = callNode->getRetICFGNode();
627  // resume ES to callnode
628  abstractTrace[retNode] = abstractTrace[callNode];
629 }
Map< const ICFGNode *, AbstractState > abstractTrace
std::vector< const CallICFGNode * > callSiteStack
const SVFFunction * getCalledFunction() const
Definition: ICFGNode.h:518
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition: ICFGNode.h:457

◆ extCallPass()

void AbstractInterpretation::extCallPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 575 of file AbstractInterpretation.cpp.

576 {
577  callSiteStack.push_back(callNode);
578  utils->handleExtAPI(callNode);
579  for (auto& detector : detectors)
580  {
581  detector->handleStubFunctions(callNode);
582  }
583  callSiteStack.pop_back();
584 }
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.
Definition: AbsExtAPI.cpp:387

◆ getAbsStateFromTrace()

AbstractState& SVF::AbstractInterpretation::getAbsStateFromTrace ( const ICFGNode node)
inlineprivate

Definition at line 258 of file AbstractInterpretation.h.

259  {
260  const ICFGNode* repNode = icfg->getRepNode(node);
261  if (abstractTrace.count(repNode) == 0)
262  {
263  assert(0 && "No preAbsTrace for this node");
264  }
265  else
266  {
267  return abstractTrace[repNode];
268  }
269  }
const ICFGNode * getRepNode(const ICFGNode *node) const
Definition: ICFG.h:246

◆ getAEInstance()

static AbstractInterpretation& SVF::AbstractInterpretation::getAEInstance ( )
inlinestatic

Definition at line 121 of file AbstractInterpretation.h.

122  {
123  static AbstractInterpretation instance;
124  return instance;
125  }

◆ getUtils()

AbsExtAPI* SVF::AbstractInterpretation::getUtils ( )
inlineprivate

Definition at line 277 of file AbstractInterpretation.h.

278  {
279  return utils;
280  }

◆ handleCallSite()

void AbstractInterpretation::handleCallSite ( const ICFGNode node)
privatevirtual

handle call node in ICFGNode

Parameters
nodeICFGNode which has a single CallICFGNode

Definition at line 539 of file AbstractInterpretation.cpp.

540 {
541  if (const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node))
542  {
543  if (isExtCall(callNode))
544  {
545  extCallPass(callNode);
546  }
547  else if (isRecursiveCall(callNode))
548  {
549  recursiveCallPass(callNode);
550  }
551  else if (isDirectCall(callNode))
552  {
553  directCallFunPass(callNode);
554  }
555  else if (isIndirectCall(callNode))
556  {
557  indirectCallFunPass(callNode);
558  }
559  else
560  {
561  assert(false && "implement this part");
562  }
563  }
564  else
565  {
566  assert (false && "it is not call node");
567  }
568 }
virtual bool isRecursiveCall(const CallICFGNode *callNode)
virtual void recursiveCallPass(const CallICFGNode *callNode)
virtual bool isDirectCall(const CallICFGNode *callNode)
virtual void extCallPass(const CallICFGNode *callNode)
virtual void directCallFunPass(const CallICFGNode *callNode)
virtual bool isExtCall(const CallICFGNode *callNode)
virtual bool isIndirectCall(const CallICFGNode *callNode)
virtual void indirectCallFunPass(const CallICFGNode *callNode)

◆ handleCycleWTO()

void AbstractInterpretation::handleCycleWTO ( const ICFGCycleWTO cycle)
privatevirtual

handle wto cycle (loop)

handle wto cycle (loop)

Parameters
cycleWTOCycle which has weak topo order of basic blocks and nested cycles

Definition at line 667 of file AbstractInterpretation.cpp.

668 {
669  const ICFGNode* cycle_head = cycle->head()->getICFGNode();
670  // Flag to indicate if we are in the increasing phase
671  bool increasing = true;
672  // Infinite loop until a fixpoint is reached,
673  for (u32_t cur_iter = 0;; cur_iter++)
674  {
675  // Start widening or narrowing if cur_iter >= widen threshold (widen delay)
676  if (cur_iter >= Options::WidenDelay())
677  {
678  // Widen or narrow after processing cycle head node
679  AbstractState prev_head_state = abstractTrace[cycle_head];
680  handleWTOComponent(cycle->head());
681  AbstractState cur_head_state = abstractTrace[cycle_head];
682  if (increasing)
683  {
684  // Widening phase
685  abstractTrace[cycle_head] = prev_head_state.widening(cur_head_state);
686  if (abstractTrace[cycle_head] == prev_head_state)
687  {
688  increasing = false;
689  continue;
690  }
691  }
692  else
693  {
694  // Widening's fixpoint reached in the widening phase, switch to narrowing
695  abstractTrace[cycle_head] = prev_head_state.narrowing(cur_head_state);
696  if (abstractTrace[cycle_head] == prev_head_state)
697  {
698  // Narrowing's fixpoint reached in the narrowing phase, exit loop
699  break;
700  }
701  }
702  }
703  else
704  {
705  // Handle the cycle head
706  handleSingletonWTO(cycle->head());
707  }
708  // Handle the cycle body
710  }
711 }
unsigned u32_t
Definition: CommandLine.h:18
void handleWTOComponent(const ICFGWTOComp *wtoComp)
virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto)
handle instructions in svf basic blocks
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
static const Option< u32_t > WidenDelay
Definition: Options.h:246
const WTONode< GraphT > * head() const
Return the head of the cycle.
Definition: WTO.h:412
const WTOComponentRefList & getWTOComponents() const
Get all wto components in WTO cycle.
Definition: WTO.h:418

◆ handleGlobalNode()

void AbstractInterpretation::handleGlobalNode ( )
privatevirtual

Global ICFGNode is handled at the entry of the program,.

handle global node

Definition at line 122 of file AbstractInterpretation.cpp.

123 {
124  const ICFGNode* node = icfg->getGlobalICFGNode();
125  abstractTrace[node] = AbstractState();
127  // Global Node, we just need to handle addr, load, store, copy and gep
128  for (const SVFStmt *stmt: node->getSVFStmts())
129  {
130  handleSVFStatement(stmt);
131  }
132 }
virtual void handleSVFStatement(const SVFStmt *stmt)
const SVFStmtList & getSVFStmts() const
Definition: ICFGNode.h:117

◆ handleSingletonWTO()

void AbstractInterpretation::handleSingletonWTO ( const ICFGSingletonWTO icfgSingletonWto)
privatevirtual

handle instructions in svf basic blocks

handle instructions in ICFGSingletonWTO

Parameters
blockbasic block that has one instruction or a series of instructions

Definition at line 480 of file AbstractInterpretation.cpp.

481 {
482  const ICFGNode* node = icfgSingletonWto->getICFGNode();
483  stat->getBlockTrace()++;
484 
485  std::deque<const ICFGNode*> worklist;
486 
487  const std::vector<const ICFGNode*>& worklist_vec = icfg->getSubNodes(node);
488  for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it)
489  {
490  const ICFGNode* curNode = *it;
491  stat->getICFGNodeTrace()++;
492  // handle SVF Stmt
493  for (const SVFStmt *stmt: curNode->getSVFStmts())
494  {
495  handleSVFStatement(stmt);
496  }
497  // inlining the callee by calling handleFunc for the callee function
498  if (const CallICFGNode* callnode = SVFUtil::dyn_cast<CallICFGNode>(curNode))
499  {
500  handleCallSite(callnode);
501  }
502  for (auto& detector: detectors)
503  detector->detect(getAbsStateFromTrace(node), node);
504  stat->countStateSize();
505  }
506 }
u32_t & getICFGNodeTrace()
virtual void handleCallSite(const ICFGNode *node)
const std::vector< const ICFGNode * > & getSubNodes(const ICFGNode *node) const
Definition: ICFG.h:241
const NodeT * getICFGNode() const
Return the graph node.
Definition: WTO.h:344

◆ handleSVFStatement()

void AbstractInterpretation::handleSVFStatement ( const SVFStmt stmt)
privatevirtual

handle SVF Statement like CmpStmt, CallStmt, GepStmt, LoadStmt, StoreStmt, etc.

Parameters
stmtSVFStatement which is a value flow of instruction

Definition at line 713 of file AbstractInterpretation.cpp.

714 {
715  if (const AddrStmt *addr = SVFUtil::dyn_cast<AddrStmt>(stmt))
716  {
717  updateStateOnAddr(addr);
718  }
719  else if (const BinaryOPStmt *binary = SVFUtil::dyn_cast<BinaryOPStmt>(stmt))
720  {
721  updateStateOnBinary(binary);
722  }
723  else if (const CmpStmt *cmp = SVFUtil::dyn_cast<CmpStmt>(stmt))
724  {
725  updateStateOnCmp(cmp);
726  }
727  else if (SVFUtil::isa<UnaryOPStmt>(stmt))
728  {
729  }
730  else if (SVFUtil::isa<BranchStmt>(stmt))
731  {
732  // branch stmt is handled in hasBranchES
733  }
734  else if (const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(stmt))
735  {
736  updateStateOnLoad(load);
737  }
738  else if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
739  {
740  updateStateOnStore(store);
741  }
742  else if (const CopyStmt *copy = SVFUtil::dyn_cast<CopyStmt>(stmt))
743  {
745  }
746  else if (const GepStmt *gep = SVFUtil::dyn_cast<GepStmt>(stmt))
747  {
748  updateStateOnGep(gep);
749  }
750  else if (const SelectStmt *select = SVFUtil::dyn_cast<SelectStmt>(stmt))
751  {
752  updateStateOnSelect(select);
753  }
754  else if (const PhiStmt *phi = SVFUtil::dyn_cast<PhiStmt>(stmt))
755  {
756  updateStateOnPhi(phi);
757  }
758  else if (const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
759  {
760  // To handle Call Edge
761  updateStateOnCall(callPE);
762  }
763  else if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
764  {
765  updateStateOnRet(retPE);
766  }
767  else
768  assert(false && "implement this part");
769 }
copy
Definition: cJSON.cpp:414
void updateStateOnCall(const CallPE *callPE)
void updateStateOnStore(const StoreStmt *store)
void updateStateOnGep(const GepStmt *gep)
void updateStateOnPhi(const PhiStmt *phi)
void updateStateOnSelect(const SelectStmt *select)
void updateStateOnAddr(const AddrStmt *addr)
void updateStateOnRet(const RetPE *retPE)
void updateStateOnCopy(const CopyStmt *copy)
void updateStateOnLoad(const LoadStmt *load)
void updateStateOnBinary(const BinaryOPStmt *binary)
void updateStateOnCmp(const CmpStmt *cmp)

◆ handleWTOComponent()

void AbstractInterpretation::handleWTOComponent ( const ICFGWTOComp wtoComp)
private

Definition at line 519 of file AbstractInterpretation.cpp.

520 {
521  if (const ICFGSingletonWTO* node = SVFUtil::dyn_cast<ICFGSingletonWTO>(wtoNode))
522  {
523  if (mergeStatesFromPredecessors(node->getICFGNode()))
524  handleSingletonWTO(node);
525  }
526  // Handle WTO cycles
527  else if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(wtoNode))
528  {
529  if (mergeStatesFromPredecessors(cycle->head()->getICFGNode()))
530  handleCycleWTO(cycle);
531  }
532  // Assert false for unknown WTO types
533  else
534  {
535  assert(false && "unknown WTO type!");
536  }
537 }
virtual void handleCycleWTO(const ICFGCycleWTO *cycle)
handle wto cycle (loop)
bool mergeStatesFromPredecessors(const ICFGNode *icfgNode)

◆ handleWTOComponents()

void AbstractInterpretation::handleWTOComponents ( const std::list< const ICFGWTOComp * > &  wtoComps)
private

Hanlde two types of WTO components (singleton and cycle)

Definition at line 511 of file AbstractInterpretation.cpp.

512 {
513  for (const ICFGWTOComp* wtoNode : wtoComps)
514  {
515  handleWTOComponent(wtoNode);
516  }
517 }

◆ hasAbsStateFromTrace()

bool SVF::AbstractInterpretation::hasAbsStateFromTrace ( const ICFGNode node)
inlineprivate

Definition at line 271 of file AbstractInterpretation.h.

272  {
273  const ICFGNode* repNode = icfg->getRepNode(node);
274  return abstractTrace.count(repNode) != 0;
275  }

◆ indirectCallFunPass()

void AbstractInterpretation::indirectCallFunPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 637 of file AbstractInterpretation.cpp.

638 {
639  AbstractState& as = getAbsStateFromTrace(callNode);
640  const auto callsiteMaps = svfir->getIndirectCallsites();
641  NodeID call_id = callsiteMaps.at(callNode);
642  if (!as.inVarToAddrsTable(call_id))
643  {
644  return;
645  }
646  AbstractValue Addrs = as[call_id];
647  NodeID addr = *Addrs.getAddrs().begin();
649  const SVFFunction *callfun = SVFUtil::dyn_cast<SVFFunction>(func_var->getValue());
650  if (callfun)
651  {
652  callSiteStack.push_back(callNode);
653  abstractTrace[callNode] = as;
654 
655  ICFGWTO* wto = funcToWTO[callfun];
657  callSiteStack.pop_back();
658  // handle Ret node
659  const RetICFGNode *retNode = callNode->getRetICFGNode();
660  abstractTrace[retNode] = abstractTrace[callNode];
661  }
662 }
bool inVarToAddrsTable(u32_t id) const
whether the variable is in varToAddrs table
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
AddressValue & getAddrs()
AddrSet::const_iterator begin() const
Definition: AddressValue.h:92
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
const CallSiteToFunPtrMap & getIndirectCallsites() const
Add/get indirect callsites.
Definition: SVFIR.h:350
const SVFValue * getValue() const
Get/has methods of the components.
Definition: SVFVariables.h:83
u32_t NodeID
Definition: GeneralType.h:55

◆ initWTO()

void AbstractInterpretation::initWTO ( )
private

Mark recursive functions in the call graph.

This function identifies and marks recursive functions in the call graph. It does this by detecting cycles in the call graph's strongly connected components (SCC). Any function found to be part of a cycle is marked as recursive.

Definition at line 80 of file AbstractInterpretation.cpp.

81 {
83  // Detect if the call graph has cycles by finding its strongly connected components (SCC)
84  Andersen::CallGraphSCC* callGraphScc = ander->getCallGraphSCC();
85  callGraphScc->find();
86  auto callGraph = ander->getCallGraph();
87 
88  // Iterate through the call graph
89  for (auto it = callGraph->begin(); it != callGraph->end(); it++)
90  {
91  // Check if the current function is part of a cycle
92  if (callGraphScc->isInCycle(it->second->getId()))
93  recursiveFuns.insert(it->second->getFunction()); // Mark the function as recursive
94  }
95 
96  // Initialize WTO for each function in the module
97  for (const SVFFunction* fun : svfir->getModule()->getFunctionSet())
98  {
99  if(fun->isDeclaration())
100  continue;
101  auto* wto = new ICFGWTO(icfg, icfg->getFunEntryICFGNode(fun));
102  wto->init();
103  funcToWTO[fun] = wto;
104  }
105 }
Set< const SVFFunction * > recursiveFuns
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition: Andersen.h:408
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition: ICFG.cpp:234
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
PTACallGraph * getCallGraph() const
Return call graph.
SCCDetection< PTACallGraph * > CallGraphSCC
void find(void)
Definition: SCC.h:308
const FunctionSetType & getFunctionSet() const
Definition: SVFModule.h:199

◆ isBranchFeasible()

bool AbstractInterpretation::isBranchFeasible ( const IntraCFGEdge intraEdge,
AbstractState as 
)
private

Check if execution state exist at the branch edge

Parameters
intraEdgethe edge from CmpStmt to the next node
Returns
if this edge is feasible

Definition at line 452 of file AbstractInterpretation.cpp.

454 {
455  const SVFVar *cmpVar = intraEdge->getCondition();
456  if (cmpVar->getInEdges().empty())
457  {
458  return isSwitchBranchFeasible(cmpVar,
459  intraEdge->getSuccessorCondValue(), as);
460  }
461  else
462  {
463  assert(!cmpVar->getInEdges().empty() &&
464  "no in edges?");
465  SVFStmt *cmpVarInStmt = *cmpVar->getInEdges().begin();
466  if (const CmpStmt *cmpStmt = SVFUtil::dyn_cast<CmpStmt>(cmpVarInStmt))
467  {
468  return isCmpBranchFeasible(cmpStmt,
469  intraEdge->getSuccessorCondValue(), as);
470  }
471  else
472  {
473  return isSwitchBranchFeasible(
474  cmpVar, intraEdge->getSuccessorCondValue(), as);
475  }
476  }
477  return true;
478 }
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
const GEdgeSetTy & getInEdges() const
Definition: GenericGraph.h:434
s64_t getSuccessorCondValue() const
Definition: ICFGEdge.h:147
const SVFVar * getCondition() const
Definition: ICFGEdge.h:142

◆ isCmpBranchFeasible()

bool AbstractInterpretation::isCmpBranchFeasible ( const CmpStmt cmpStmt,
s64_t  succ,
AbstractState as 
)
private

Check if this cmpStmt and succ are satisfiable to the execution state.

Parameters
cmpStmtCmpStmt is a conditional branch statement
succthe value of cmpStmt (True or False)
Returns
if this ICFGNode has preceding execution state

Definition at line 187 of file AbstractInterpretation.cpp.

189 {
190  AbstractState new_es = as;
191  // get cmp stmt's op0, op1, and predicate
192  NodeID op0 = cmpStmt->getOpVarID(0);
193  NodeID op1 = cmpStmt->getOpVarID(1);
194  NodeID res_id = cmpStmt->getResID();
195  s32_t predicate = cmpStmt->getPredicate();
196 
197  // if op0 or op1 is undefined, return;
198  // skip address compare
199  if (new_es.inVarToAddrsTable(op0) || new_es.inVarToAddrsTable(op1))
200  {
201  as = new_es;
202  return true;
203  }
204  const LoadStmt *load_op0 = nullptr;
205  const LoadStmt *load_op1 = nullptr;
206  // get '%1 = load i32 s', and load inst may not exist
207  SVFVar* loadVar0 = svfir->getGNode(op0);
208  if (!loadVar0->getInEdges().empty())
209  {
210  SVFStmt *loadVar0InStmt = *loadVar0->getInEdges().begin();
211  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt))
212  {
213  load_op0 = loadStmt;
214  }
215  else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar0InStmt))
216  {
217  loadVar0 = svfir->getGNode(copyStmt->getRHSVarID());
218  if (!loadVar0->getInEdges().empty())
219  {
220  SVFStmt *loadVar0InStmt2 = *loadVar0->getInEdges().begin();
221  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt2))
222  {
223  load_op0 = loadStmt;
224  }
225  }
226  }
227  }
228 
229  SVFVar* loadVar1 = svfir->getGNode(op1);
230  if (!loadVar1->getInEdges().empty())
231  {
232  SVFStmt *loadVar1InStmt = *loadVar1->getInEdges().begin();
233  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt))
234  {
235  load_op1 = loadStmt;
236  }
237  else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar1InStmt))
238  {
239  loadVar1 = svfir->getGNode(copyStmt->getRHSVarID());
240  if (!loadVar1->getInEdges().empty())
241  {
242  SVFStmt *loadVar1InStmt2 = *loadVar1->getInEdges().begin();
243  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt2))
244  {
245  load_op1 = loadStmt;
246  }
247  }
248  }
249  }
250  // for const X const, we may get concrete resVal instantly
251  // for var X const, we may get [0,1] if the intersection of var and const is not empty set
252  IntervalValue resVal = new_es[res_id].getInterval();
253  resVal.meet_with(IntervalValue((s64_t) succ, succ));
254  // If Var X const generates bottom value, it means this branch path is not feasible.
255  if (resVal.isBottom())
256  {
257  return false;
258  }
259 
260  bool b0 = new_es[op0].getInterval().is_numeral();
261  bool b1 = new_es[op1].getInterval().is_numeral();
262 
263  // if const X var, we should reverse op0 and op1.
264  if (b0 && !b1)
265  {
266  std::swap(op0, op1);
267  std::swap(load_op0, load_op1);
268  predicate = _switch_lhsrhs_predicate[predicate];
269  }
270  else
271  {
272  // if var X var, we cannot preset the branch condition to infer the intervals of var0,var1
273  if (!b0 && !b1)
274  {
275  as = new_es;
276  return true;
277  }
278  // if const X const, we can instantly get the resVal
279  else if (b0 && b1)
280  {
281  as = new_es;
282  return true;
283  }
284  }
285  // if cmp is 'var X const == false', we should reverse predicate 'var X' const == true'
286  // X' is reverse predicate of X
287  if (succ == 0)
288  {
289  predicate = _reverse_predicate[predicate];
290  }
291  else {}
292  // change interval range according to the compare predicate
293  AddressValue addrs;
294  if(load_op0 && new_es.inVarToAddrsTable(load_op0->getRHSVarID()))
295  addrs = new_es[load_op0->getRHSVarID()].getAddrs();
296 
297  IntervalValue &lhs = new_es[op0].getInterval(), &rhs = new_es[op1].getInterval();
298  switch (predicate)
299  {
300  case CmpStmt::Predicate::ICMP_EQ:
301  case CmpStmt::Predicate::FCMP_OEQ:
302  case CmpStmt::Predicate::FCMP_UEQ:
303  {
304  // Var == Const, so [var.lb, var.ub].meet_with(const)
305  lhs.meet_with(rhs);
306  // if lhs is register value, we should also change its mem obj
307  for (const auto &addr: addrs)
308  {
309  NodeID objId = new_es.getInternalID(addr);
310  if (new_es.inAddrToValTable(objId))
311  {
312  new_es.load(addr).meet_with(rhs);
313  }
314  }
315  break;
316  }
317  case CmpStmt::Predicate::ICMP_NE:
318  case CmpStmt::Predicate::FCMP_ONE:
319  case CmpStmt::Predicate::FCMP_UNE:
320  // Compliment set
321  break;
322  case CmpStmt::Predicate::ICMP_UGT:
323  case CmpStmt::Predicate::ICMP_SGT:
324  case CmpStmt::Predicate::FCMP_OGT:
325  case CmpStmt::Predicate::FCMP_UGT:
326  // Var > Const, so [var.lb, var.ub].meet_with([Const+1, +INF])
328  // if lhs is register value, we should also change its mem obj
329  for (const auto &addr: addrs)
330  {
331  NodeID objId = new_es.getInternalID(addr);
332  if (new_es.inAddrToValTable(objId))
333  {
334  new_es.load(addr).meet_with(
336  }
337  }
338  break;
339  case CmpStmt::Predicate::ICMP_UGE:
340  case CmpStmt::Predicate::ICMP_SGE:
341  case CmpStmt::Predicate::FCMP_OGE:
342  case CmpStmt::Predicate::FCMP_UGE:
343  {
344  // Var >= Const, so [var.lb, var.ub].meet_with([Const, +INF])
346  // if lhs is register value, we should also change its mem obj
347  for (const auto &addr: addrs)
348  {
349  NodeID objId = new_es.getInternalID(addr);
350  if (new_es.inAddrToValTable(objId))
351  {
352  new_es.load(addr).meet_with(
354  }
355  }
356  break;
357  }
358  case CmpStmt::Predicate::ICMP_ULT:
359  case CmpStmt::Predicate::ICMP_SLT:
360  case CmpStmt::Predicate::FCMP_OLT:
361  case CmpStmt::Predicate::FCMP_ULT:
362  {
363  // Var < Const, so [var.lb, var.ub].meet_with([-INF, const.ub-1])
365  // if lhs is register value, we should also change its mem obj
366  for (const auto &addr: addrs)
367  {
368  NodeID objId = new_es.getInternalID(addr);
369  if (new_es.inAddrToValTable(objId))
370  {
371  new_es.load(addr).meet_with(
373  }
374  }
375  break;
376  }
377  case CmpStmt::Predicate::ICMP_ULE:
378  case CmpStmt::Predicate::ICMP_SLE:
379  case CmpStmt::Predicate::FCMP_OLE:
380  case CmpStmt::Predicate::FCMP_ULE:
381  {
382  // Var <= Const, so [var.lb, var.ub].meet_with([-INF, const.ub])
384  // if lhs is register value, we should also change its mem obj
385  for (const auto &addr: addrs)
386  {
387  NodeID objId = new_es.getInternalID(addr);
388  if (new_es.inAddrToValTable(objId))
389  {
390  new_es.load(addr).meet_with(
392  }
393  }
394  break;
395  }
396  case CmpStmt::Predicate::FCMP_FALSE:
397  break;
398  case CmpStmt::Predicate::FCMP_TRUE:
399  break;
400  default:
401  assert(false && "implement this part");
402  abort();
403  }
404  as = new_es;
405  return true;
406 }
Map< s32_t, s32_t > _reverse_predicate
Map< s32_t, s32_t > _switch_lhsrhs_predicate
virtual bool inAddrToValTable(u32_t id) const
whether the memory address stores abstract value
virtual AbstractValue & load(u32_t addr)
void meet_with(const AbstractValue &other)
NodeID getRHSVarID() const
u32_t getPredicate() const
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
static BoundedInt minus_infinity()
Get minus infinity -inf.
Definition: IntervalValue.h:77
bool isBottom() const
Definition: IntervalValue.h:71
static BoundedInt plus_infinity()
Get plus infinity +inf.
Definition: IntervalValue.h:83
NodeID getOpVarID(u32_t pos) const
NodeID getResID() const
signed s32_t
Definition: GeneralType.h:47
signed long long s64_t
Definition: GeneralType.h:49

◆ isDirectCall()

bool AbstractInterpretation::isDirectCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 610 of file AbstractInterpretation.cpp.

611 {
612  return funcToWTO.find(callNode->getCalledFunction()) != funcToWTO.end();
613 }

◆ isExtCall()

bool AbstractInterpretation::isExtCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 570 of file AbstractInterpretation.cpp.

571 {
572  return SVFUtil::isExtCall(callNode->getCalledFunction());
573 }
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:278

◆ isIndirectCall()

bool AbstractInterpretation::isIndirectCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 631 of file AbstractInterpretation.cpp.

632 {
633  const auto callsiteMaps = svfir->getIndirectCallsites();
634  return callsiteMaps.find(callNode) != callsiteMaps.end();
635 }

◆ isRecursiveCall()

bool AbstractInterpretation::isRecursiveCall ( const CallICFGNode callNode)
privatevirtual

Definition at line 586 of file AbstractInterpretation.cpp.

587 {
588  return recursiveFuns.find(callNode->getCalledFunction()) != recursiveFuns.end();
589 }

◆ isSwitchBranchFeasible()

bool AbstractInterpretation::isSwitchBranchFeasible ( const SVFVar var,
s64_t  succ,
AbstractState as 
)
private

Check if this SwitchInst and succ are satisfiable to the execution state.

Parameters
varvar in switch inst
succthe case value of switch inst
Returns
if this ICFGNode has preceding execution state

Definition at line 408 of file AbstractInterpretation.cpp.

410 {
411  AbstractState new_es = as;
412  IntervalValue& switch_cond = new_es[var->getId()].getInterval();
413  s64_t value = succ;
415  for (SVFStmt *cmpVarInStmt: var->getInEdges())
416  {
417  workList.push(cmpVarInStmt);
418  }
419  switch_cond.meet_with(IntervalValue(value, value));
420  if (switch_cond.isBottom())
421  {
422  return false;
423  }
424  while(!workList.empty())
425  {
426  const SVFStmt* stmt = workList.pop();
427  if (SVFUtil::isa<CopyStmt>(stmt))
428  {
429  IntervalValue& copy_cond = new_es[var->getId()].getInterval();
430  copy_cond.meet_with(IntervalValue(value, value));
431  }
432  else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
433  {
434  if (new_es.inVarToAddrsTable(load->getRHSVarID()))
435  {
436  AddressValue &addrs = new_es[load->getRHSVarID()].getAddrs();
437  for (const auto &addr: addrs)
438  {
439  NodeID objId = new_es.getInternalID(addr);
440  if (new_es.inAddrToValTable(objId))
441  {
442  new_es.load(addr).meet_with(switch_cond);
443  }
444  }
445  }
446  }
447  }
448  as = new_es;
449  return true;
450 }
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260

◆ mergeStatesFromPredecessors()

bool AbstractInterpretation::mergeStatesFromPredecessors ( const ICFGNode icfgNode)
private

Check if execution state exist by merging states of predecessor nodes

Parameters
icfgNodeThe icfg node to analyse
Returns
if this node has preceding execution state

get execution state by merging states of predecessor blocks Scenario 1: preblock --—(intraEdge)-—> block, join the preES of inEdges Scenario 2: preblock --—(callEdge)-—> block

Definition at line 137 of file AbstractInterpretation.cpp.

138 {
139  std::vector<AbstractState> workList;
140  AbstractState preAs;
141  for (auto& edge: icfgNode->getInEdges())
142  {
143  if (abstractTrace.find(edge->getSrcNode()) != abstractTrace.end())
144  {
145  const IntraCFGEdge *intraCfgEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge);
146  if (intraCfgEdge && intraCfgEdge->getCondition())
147  {
148  AbstractState tmpEs = abstractTrace[edge->getSrcNode()];
149  if (isBranchFeasible(intraCfgEdge, tmpEs))
150  {
151  workList.push_back(tmpEs);
152  }
153  else
154  {
155  // do nothing
156  }
157  }
158  else
159  {
160  workList.push_back(abstractTrace[edge->getSrcNode()]);
161  }
162  }
163  else
164  {
165 
166  }
167  }
168  if (workList.size() == 0)
169  {
170  return false;
171  }
172  else
173  {
174  while (!workList.empty())
175  {
176  preAs.joinWith(workList.back());
177  workList.pop_back();
178  }
179  // Has ES on the in edges - Feasible block
180  // update post as
181  abstractTrace[icfgNode] = preAs;
182  return true;
183  }
184 }
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.

◆ recursiveCallPass()

void AbstractInterpretation::recursiveCallPass ( const CallICFGNode callNode)
privatevirtual

Definition at line 591 of file AbstractInterpretation.cpp.

592 {
593  AbstractState& as = getAbsStateFromTrace(callNode);
594  SkipRecursiveCall(callNode);
595  const RetICFGNode *retNode = callNode->getRetICFGNode();
596  if (retNode->getSVFStmts().size() > 0)
597  {
598  if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
599  {
600  if (!retPE->getLHSVar()->isPointer() &&
601  !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
602  {
603  as[retPE->getLHSVarID()] = IntervalValue::top();
604  }
605  }
606  }
607  abstractTrace[retNode] = as;
608 }
virtual void SkipRecursiveCall(const CallICFGNode *callnode)

◆ runOnModule()

void AbstractInterpretation::runOnModule ( ICFG icfg)
virtual

collect checkpoint

Definition at line 40 of file AbstractInterpretation.cpp.

41 {
42  stat->startClk();
43  icfg = _icfg;
44  svfir = PAG::getPAG();
46 
49 
50  analyse();
52  stat->endClk();
54  if (Options::PStat())
55  stat->performStat();
56  for (auto& detector: detectors)
57  detector->reportBug();
58 }
void performStat() override
Handles external API calls and manages abstract states.
Definition: AbsExtAPI.h:46
static const Option< bool > PStat
Definition: Options.h:119
virtual void endClk()
Definition: SVFStat.h:63
virtual void startClk()
Definition: SVFStat.h:58

◆ SkipRecursiveCall()

void AbstractInterpretation::SkipRecursiveCall ( const CallICFGNode callnode)
privatevirtual

Check if this callnode is recursive call and skip it.

Parameters
callnodeCallICFGNode which calls a recursive function

Definition at line 772 of file AbstractInterpretation.cpp.

773 {
774  AbstractState& as = getAbsStateFromTrace(callNode);
775  const RetICFGNode *retNode = callNode->getRetICFGNode();
776  if (retNode->getSVFStmts().size() > 0)
777  {
778  if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
779  {
780  AbstractState as;
781  if (!retPE->getLHSVar()->isPointer() && !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
782  as[retPE->getLHSVarID()] = IntervalValue::top();
783  }
784  }
785  if (!retNode->getOutEdges().empty())
786  {
787  if (retNode->getOutEdges().size() == 1)
788  {
789 
790  }
791  else
792  {
793  return;
794  }
795  }
797  FIFOWorkList<const ICFGNode *> instWorklist;
798  for (const SVFBasicBlock * bb: callNode->getCalledFunction()->getReachableBBs())
799  {
800  for (const ICFGNode* node: bb->getICFGNodeList())
801  {
802  for (const SVFStmt *stmt: node->getSVFStmts())
803  {
804  if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
805  {
806  const SVFVar *rhsVar = store->getRHSVar();
807  u32_t lhs = store->getLHSVarID();
808  if (as.inVarToAddrsTable(lhs))
809  {
810  if (!rhsVar->isPointer() && !rhsVar->isConstDataOrAggDataButNotNullPtr())
811  {
812  const AbstractValue &addrs = as[lhs];
813  for (const auto &addr: addrs.getAddrs())
814  {
815  as.store(addr, IntervalValue::top());
816  }
817  }
818  }
819  }
820  }
821  }
822  }
823 }
void store(u32_t addr, const AbstractValue &val)
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
bool isConstDataOrAggDataButNotNullPtr() const
virtual bool isPointer() const
Whether it is a pointer.
Definition: SVFVariables.h:106

◆ updateStateOnAddr()

void AbstractInterpretation::updateStateOnAddr ( const AddrStmt addr)
private

Definition at line 1052 of file AbstractInterpretation.cpp.

1053 {
1055  as.initObjVar(SVFUtil::cast<ObjVar>(addr->getRHSVar()));
1056  if (addr->getRHSVar()->getType()->getKind() == SVFType::SVFIntegerTy)
1057  as[addr->getRHSVarID()].getInterval().meet_with(utils->getRangeLimitFromType(addr->getRHSVar()->getType()));
1058  as[addr->getLHSVarID()] = as[addr->getRHSVarID()];
1059 }
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
Definition: AbsExtAPI.cpp:701
void initObjVar(ObjVar *objVar)
NodeID getLHSVarID() const
SVFVar * getRHSVar() const
ICFGNode * getICFGNode() const
@ SVFIntegerTy
Definition: SVFType.h:169
GNodeK getKind() const
Definition: SVFType.h:213
virtual const SVFType * getType() const
Return type of the value.
Definition: SVFVariables.h:96

◆ updateStateOnBinary()

void AbstractInterpretation::updateStateOnBinary ( const BinaryOPStmt binary)
private

Find the comparison predicates in "class BinaryOPStmt:OpCode" under SVF/svf/include/SVFIR/SVFStatements.h You are only required to handle integer predicates, including Add, FAdd, Sub, FSub, Mul, FMul, SDiv, FDiv, UDiv, SRem, FRem, URem, Xor, And, Or, AShr, Shl, LShr

Definition at line 1062 of file AbstractInterpretation.cpp.

1063 {
1067  const ICFGNode* node = binary->getICFGNode();
1068  AbstractState& as = getAbsStateFromTrace(node);
1069  u32_t op0 = binary->getOpVarID(0);
1070  u32_t op1 = binary->getOpVarID(1);
1071  u32_t res = binary->getResID();
1072  if (!as.inVarToValTable(op0)) as[op0] = IntervalValue::top();
1073  if (!as.inVarToValTable(op1)) as[op1] = IntervalValue::top();
1074  IntervalValue &lhs = as[op0].getInterval(), &rhs = as[op1].getInterval();
1075  IntervalValue resVal;
1076  switch (binary->getOpcode())
1077  {
1078  case BinaryOPStmt::Add:
1079  case BinaryOPStmt::FAdd:
1080  resVal = (lhs + rhs);
1081  break;
1082  case BinaryOPStmt::Sub:
1083  case BinaryOPStmt::FSub:
1084  resVal = (lhs - rhs);
1085  break;
1086  case BinaryOPStmt::Mul:
1087  case BinaryOPStmt::FMul:
1088  resVal = (lhs * rhs);
1089  break;
1090  case BinaryOPStmt::SDiv:
1091  case BinaryOPStmt::FDiv:
1092  case BinaryOPStmt::UDiv:
1093  resVal = (lhs / rhs);
1094  break;
1095  case BinaryOPStmt::SRem:
1096  case BinaryOPStmt::FRem:
1097  case BinaryOPStmt::URem:
1098  resVal = (lhs % rhs);
1099  break;
1100  case BinaryOPStmt::Xor:
1101  resVal = (lhs ^ rhs);
1102  break;
1103  case BinaryOPStmt::And:
1104  resVal = (lhs & rhs);
1105  break;
1106  case BinaryOPStmt::Or:
1107  resVal = (lhs | rhs);
1108  break;
1109  case BinaryOPStmt::AShr:
1110  resVal = (lhs >> rhs);
1111  break;
1112  case BinaryOPStmt::Shl:
1113  resVal = (lhs << rhs);
1114  break;
1115  case BinaryOPStmt::LShr:
1116  resVal = (lhs >> rhs);
1117  break;
1118  default:
1119  assert(false && "undefined binary: ");
1120  }
1121  as[res] = resVal;
1122 }
virtual bool inVarToValTable(u32_t id) const
whether the variable is in varToVal table
u32_t getOpcode() const

◆ updateStateOnCall()

void AbstractInterpretation::updateStateOnCall ( const CallPE callPE)
private

Definition at line 1035 of file AbstractInterpretation.cpp.

1036 {
1038  NodeID lhs = callPE->getLHSVarID();
1039  NodeID rhs = callPE->getRHSVarID();
1040  as[lhs] = as[rhs];
1041 }

◆ updateStateOnCmp()

void AbstractInterpretation::updateStateOnCmp ( const CmpStmt cmp)
private

Definition at line 1124 of file AbstractInterpretation.cpp.

1125 {
1127  u32_t op0 = cmp->getOpVarID(0);
1128  u32_t op1 = cmp->getOpVarID(1);
1129  // if it is address
1130  if (as.inVarToAddrsTable(op0) && as.inVarToAddrsTable(op1))
1131  {
1132  IntervalValue resVal;
1133  AddressValue addrOp0 = as[op0].getAddrs();
1134  AddressValue addrOp1 = as[op1].getAddrs();
1135  u32_t res = cmp->getResID();
1136  if (addrOp0.equals(addrOp1))
1137  {
1138  resVal = IntervalValue(1, 1);
1139  }
1140  else if (addrOp0.hasIntersect(addrOp1))
1141  {
1142  resVal = IntervalValue(0, 1);
1143  }
1144  else
1145  {
1146  resVal = IntervalValue(0, 0);
1147  }
1148  as[res] = resVal;
1149  }
1150  else
1151  {
1152  if (!as.inVarToValTable(op0))
1153  as[op0] = IntervalValue::top();
1154  if (!as.inVarToValTable(op1))
1155  as[op1] = IntervalValue::top();
1156  u32_t res = cmp->getResID();
1157  if (as.inVarToValTable(op0) && as.inVarToValTable(op1))
1158  {
1159  IntervalValue resVal;
1160  if (as[op0].isInterval() && as[op1].isInterval())
1161  {
1162  IntervalValue &lhs = as[op0].getInterval(),
1163  &rhs = as[op1].getInterval();
1164  // AbstractValue
1165  auto predicate = cmp->getPredicate();
1166  switch (predicate)
1167  {
1168  case CmpStmt::ICMP_EQ:
1169  case CmpStmt::FCMP_OEQ:
1170  case CmpStmt::FCMP_UEQ:
1171  resVal = (lhs == rhs);
1172  // resVal = (lhs.getInterval() == rhs.getInterval());
1173  break;
1174  case CmpStmt::ICMP_NE:
1175  case CmpStmt::FCMP_ONE:
1176  case CmpStmt::FCMP_UNE:
1177  resVal = (lhs != rhs);
1178  break;
1179  case CmpStmt::ICMP_UGT:
1180  case CmpStmt::ICMP_SGT:
1181  case CmpStmt::FCMP_OGT:
1182  case CmpStmt::FCMP_UGT:
1183  resVal = (lhs > rhs);
1184  break;
1185  case CmpStmt::ICMP_UGE:
1186  case CmpStmt::ICMP_SGE:
1187  case CmpStmt::FCMP_OGE:
1188  case CmpStmt::FCMP_UGE:
1189  resVal = (lhs >= rhs);
1190  break;
1191  case CmpStmt::ICMP_ULT:
1192  case CmpStmt::ICMP_SLT:
1193  case CmpStmt::FCMP_OLT:
1194  case CmpStmt::FCMP_ULT:
1195  resVal = (lhs < rhs);
1196  break;
1197  case CmpStmt::ICMP_ULE:
1198  case CmpStmt::ICMP_SLE:
1199  case CmpStmt::FCMP_OLE:
1200  case CmpStmt::FCMP_ULE:
1201  resVal = (lhs <= rhs);
1202  break;
1203  case CmpStmt::FCMP_FALSE:
1204  resVal = IntervalValue(0, 0);
1205  break;
1206  case CmpStmt::FCMP_TRUE:
1207  resVal = IntervalValue(1, 1);
1208  break;
1209  default:
1210  {
1211  assert(false && "undefined compare: ");
1212  }
1213  }
1214  as[res] = resVal;
1215  }
1216  else if (as[op0].isAddr() && as[op1].isAddr())
1217  {
1218  AddressValue &lhs = as[op0].getAddrs(),
1219  &rhs = as[op1].getAddrs();
1220  auto predicate = cmp->getPredicate();
1221  switch (predicate)
1222  {
1223  case CmpStmt::ICMP_EQ:
1224  case CmpStmt::FCMP_OEQ:
1225  case CmpStmt::FCMP_UEQ:
1226  {
1227  if (lhs.hasIntersect(rhs))
1228  {
1229  resVal = IntervalValue(0, 1);
1230  }
1231  else if (lhs.empty() && rhs.empty())
1232  {
1233  resVal = IntervalValue(1, 1);
1234  }
1235  else
1236  {
1237  resVal = IntervalValue(0, 0);
1238  }
1239  break;
1240  }
1241  case CmpStmt::ICMP_NE:
1242  case CmpStmt::FCMP_ONE:
1243  case CmpStmt::FCMP_UNE:
1244  {
1245  if (lhs.hasIntersect(rhs))
1246  {
1247  resVal = IntervalValue(0, 1);
1248  }
1249  else if (lhs.empty() && rhs.empty())
1250  {
1251  resVal = IntervalValue(0, 0);
1252  }
1253  else
1254  {
1255  resVal = IntervalValue(1, 1);
1256  }
1257  break;
1258  }
1259  case CmpStmt::ICMP_UGT:
1260  case CmpStmt::ICMP_SGT:
1261  case CmpStmt::FCMP_OGT:
1262  case CmpStmt::FCMP_UGT:
1263  {
1264  if (lhs.size() == 1 && rhs.size() == 1)
1265  {
1266  resVal = IntervalValue(*lhs.begin() > *rhs.begin());
1267  }
1268  else
1269  {
1270  resVal = IntervalValue(0, 1);
1271  }
1272  break;
1273  }
1274  case CmpStmt::ICMP_UGE:
1275  case CmpStmt::ICMP_SGE:
1276  case CmpStmt::FCMP_OGE:
1277  case CmpStmt::FCMP_UGE:
1278  {
1279  if (lhs.size() == 1 && rhs.size() == 1)
1280  {
1281  resVal = IntervalValue(*lhs.begin() >= *rhs.begin());
1282  }
1283  else
1284  {
1285  resVal = IntervalValue(0, 1);
1286  }
1287  break;
1288  }
1289  case CmpStmt::ICMP_ULT:
1290  case CmpStmt::ICMP_SLT:
1291  case CmpStmt::FCMP_OLT:
1292  case CmpStmt::FCMP_ULT:
1293  {
1294  if (lhs.size() == 1 && rhs.size() == 1)
1295  {
1296  resVal = IntervalValue(*lhs.begin() < *rhs.begin());
1297  }
1298  else
1299  {
1300  resVal = IntervalValue(0, 1);
1301  }
1302  break;
1303  }
1304  case CmpStmt::ICMP_ULE:
1305  case CmpStmt::ICMP_SLE:
1306  case CmpStmt::FCMP_OLE:
1307  case CmpStmt::FCMP_ULE:
1308  {
1309  if (lhs.size() == 1 && rhs.size() == 1)
1310  {
1311  resVal = IntervalValue(*lhs.begin() <= *rhs.begin());
1312  }
1313  else
1314  {
1315  resVal = IntervalValue(0, 1);
1316  }
1317  break;
1318  }
1319  case CmpStmt::FCMP_FALSE:
1320  resVal = IntervalValue(0, 0);
1321  break;
1322  case CmpStmt::FCMP_TRUE:
1323  resVal = IntervalValue(1, 1);
1324  break;
1325  default:
1326  {
1327  assert(false && "undefined compare: ");
1328  }
1329  }
1330  as[res] = resVal;
1331  }
1332  }
1333  }
1334 }
bool equals(const AddressValue &rhs) const
Definition: AddressValue.h:87
bool hasIntersect(const AddressValue &other)
Definition: AddressValue.h:164
bool empty() const
Definition: AddressValue.h:102
u32_t size() const
Definition: AddressValue.h:107
@ 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
@ ICMP_NE
not equal
@ 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

◆ updateStateOnCopy()

void AbstractInterpretation::updateStateOnCopy ( const CopyStmt copy)
private

Definition at line 1352 of file AbstractInterpretation.cpp.

1353 {
1354  auto getZExtValue = [](AbstractState& as, const SVFVar* var)
1355  {
1356  const SVFType* type = var->getType();
1357  if (SVFUtil::isa<SVFIntegerType>(type))
1358  {
1359  u32_t bits = type->getByteSize() * 8;
1360  if (as[var->getId()].getInterval().is_numeral())
1361  {
1362  if (bits == 8)
1363  {
1364  int8_t signed_i8_value = as[var->getId()].getInterval().getIntNumeral();
1365  u32_t unsigned_value = static_cast<uint8_t>(signed_i8_value);
1366  return IntervalValue(unsigned_value, unsigned_value);
1367  }
1368  else if (bits == 16)
1369  {
1370  s16_t signed_i16_value = as[var->getId()].getInterval().getIntNumeral();
1371  u32_t unsigned_value = static_cast<u16_t>(signed_i16_value);
1372  return IntervalValue(unsigned_value, unsigned_value);
1373  }
1374  else if (bits == 32)
1375  {
1376  s32_t signed_i32_value = as[var->getId()].getInterval().getIntNumeral();
1377  u32_t unsigned_value = static_cast<u32_t>(signed_i32_value);
1378  return IntervalValue(unsigned_value, unsigned_value);
1379  }
1380  else if (bits == 64)
1381  {
1382  s64_t signed_i64_value = as[var->getId()].getInterval().getIntNumeral();
1383  return IntervalValue((s64_t)signed_i64_value, (s64_t)signed_i64_value);
1384  // we only support i64 at most
1385  }
1386  else
1387  {
1388  assert(false && "cannot support int type other than u8/16/32/64");
1389  }
1390  }
1391  else
1392  {
1393  return IntervalValue::top(); // TODO: may have better solution
1394  }
1395  }
1396  return IntervalValue::top(); // TODO: may have better solution
1397  };
1398 
1399  auto getTruncValue = [&](const AbstractState& as, const SVF::SVFVar* var,
1400  const SVFType* dstType)
1401  {
1402  const IntervalValue& itv = as[var->getId()].getInterval();
1403  if(itv.isBottom()) return itv;
1404  // get the value of ub and lb
1405  s64_t int_lb = itv.lb().getIntNumeral();
1406  s64_t int_ub = itv.ub().getIntNumeral();
1407  // get dst type
1408  u32_t dst_bits = dstType->getByteSize() * 8;
1409  if (dst_bits == 8)
1410  {
1411  // get the signed value of ub and lb
1412  int8_t s8_lb = static_cast<int8_t>(int_lb);
1413  int8_t s8_ub = static_cast<int8_t>(int_ub);
1414  if (s8_lb > s8_ub)
1415  {
1416  // return range of s8
1417  return utils->getRangeLimitFromType(dstType);
1418  }
1419  return IntervalValue(s8_lb, s8_ub);
1420  }
1421  else if (dst_bits == 16)
1422  {
1423  // get the signed value of ub and lb
1424  s16_t s16_lb = static_cast<s16_t>(int_lb);
1425  s16_t s16_ub = static_cast<s16_t>(int_ub);
1426  if (s16_lb > s16_ub)
1427  {
1428  // return range of s16
1429  return utils->getRangeLimitFromType(dstType);
1430  }
1431  return IntervalValue(s16_lb, s16_ub);
1432  }
1433  else if (dst_bits == 32)
1434  {
1435  // get the signed value of ub and lb
1436  s32_t s32_lb = static_cast<s32_t>(int_lb);
1437  s32_t s32_ub = static_cast<s32_t>(int_ub);
1438  if (s32_lb > s32_ub)
1439  {
1440  // return range of s32
1441  return utils->getRangeLimitFromType(dstType);
1442  }
1443  return IntervalValue(s32_lb, s32_ub);
1444  }
1445  else
1446  {
1447  assert(false && "cannot support dst int type other than u8/16/32");
1448  }
1449  };
1450 
1451  AbstractState& as = getAbsStateFromTrace(copy->getICFGNode());
1452  u32_t lhs = copy->getLHSVarID();
1453  u32_t rhs = copy->getRHSVarID();
1454 
1455  if (copy->getCopyKind() == CopyStmt::COPYVAL)
1456  {
1457  as[lhs] = as[rhs];
1458  }
1459  else if (copy->getCopyKind() == CopyStmt::ZEXT)
1460  {
1461  as[lhs] = getZExtValue(as, copy->getRHSVar());
1462  }
1463  else if (copy->getCopyKind() == CopyStmt::SEXT)
1464  {
1465  as[lhs] = as[rhs].getInterval();
1466  }
1467  else if (copy->getCopyKind() == CopyStmt::FPTOSI)
1468  {
1469  as[lhs] = as[rhs].getInterval();
1470  }
1471  else if (copy->getCopyKind() == CopyStmt::FPTOUI)
1472  {
1473  as[lhs] = as[rhs].getInterval();
1474  }
1475  else if (copy->getCopyKind() == CopyStmt::SITOFP)
1476  {
1477  as[lhs] = as[rhs].getInterval();
1478  }
1479  else if (copy->getCopyKind() == CopyStmt::UITOFP)
1480  {
1481  as[lhs] = as[rhs].getInterval();
1482  }
1483  else if (copy->getCopyKind() == CopyStmt::TRUNC)
1484  {
1485  as[lhs] = getTruncValue(as, copy->getRHSVar(), copy->getLHSVar()->getType());
1486  }
1487  else if (copy->getCopyKind() == CopyStmt::FPTRUNC)
1488  {
1489  as[lhs] = as[rhs].getInterval();
1490  }
1491  else if (copy->getCopyKind() == CopyStmt::INTTOPTR)
1492  {
1493  //insert nullptr
1494  }
1495  else if (copy->getCopyKind() == CopyStmt::PTRTOINT)
1496  {
1497  as[lhs] = IntervalValue::top();
1498  }
1499  else if (copy->getCopyKind() == CopyStmt::BITCAST)
1500  {
1501  if (as[rhs].isAddr())
1502  {
1503  as[lhs] = as[rhs];
1504  }
1505  else
1506  {
1507  // do nothing
1508  }
1509  }
1510  else
1511  {
1512  assert(false && "undefined copy kind");
1513  abort();
1514  }
1515 }
newitem type
Definition: cJSON.cpp:2739
s64_t getIntNumeral() const
Definition: NumericValue.h:703
const BoundedInt & lb() const
Return the lower bound.
const BoundedInt & ub() const
Return the upper bound.
signed short s16_t
Definition: GeneralType.h:53
unsigned short u16_t
Definition: GeneralType.h:52

◆ updateStateOnGep()

void AbstractInterpretation::updateStateOnGep ( const GepStmt gep)
private

Definition at line 962 of file AbstractInterpretation.cpp.

963 {
965  u32_t rhs = gep->getRHSVarID();
966  u32_t lhs = gep->getLHSVarID();
967  IntervalValue offsetPair = as.getElementIndex(gep);
968  AbstractValue gepAddrs;
969  APOffset lb = offsetPair.lb().getIntNumeral() < Options::MaxFieldLimit()?
970  offsetPair.lb().getIntNumeral(): Options::MaxFieldLimit();
971  APOffset ub = offsetPair.ub().getIntNumeral() < Options::MaxFieldLimit()?
972  offsetPair.ub().getIntNumeral(): Options::MaxFieldLimit();
973  for (APOffset i = lb; i <= ub; i++)
974  gepAddrs.join_with(as.getGepObjAddrs(rhs,IntervalValue(i)));
975  as[lhs] = gepAddrs;
976 }
IntervalValue getElementIndex(const GepStmt *gep)
AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset)
void join_with(const AbstractValue &other)
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition: Options.h:38
s64_t APOffset
Definition: GeneralType.h:60

◆ updateStateOnLoad()

void AbstractInterpretation::updateStateOnLoad ( const LoadStmt load)
private

Definition at line 1336 of file AbstractInterpretation.cpp.

1337 {
1339  u32_t rhs = load->getRHSVarID();
1340  u32_t lhs = load->getLHSVarID();
1341  as[lhs] = as.loadValue(rhs);
1342 }
AbstractValue loadValue(NodeID varId)

◆ updateStateOnPhi()

void AbstractInterpretation::updateStateOnPhi ( const PhiStmt phi)
private

Definition at line 996 of file AbstractInterpretation.cpp.

997 {
998  const ICFGNode* icfgNode = phi->getICFGNode();
999  AbstractState& as = getAbsStateFromTrace(icfgNode);
1000  u32_t res = phi->getResID();
1001  AbstractValue rhs;
1002  for (u32_t i = 0; i < phi->getOpVarNum(); i++)
1003  {
1004  NodeID curId = phi->getOpVarID(i);
1005  const ICFGNode* opICFGNode = phi->getOpICFGNode(i);
1006  if (hasAbsStateFromTrace(opICFGNode))
1007  {
1008  AbstractState tmpEs = abstractTrace[opICFGNode];
1009  AbstractState& opAs = getAbsStateFromTrace(opICFGNode);
1010  const ICFGEdge* edge = icfg->getICFGEdge(opICFGNode, icfgNode, ICFGEdge::IntraCF);
1011  // if IntraEdge, check the condition, if it is feasible, join the value
1012  // if IntraEdge but not conditional edge, join the value
1013  // if not IntraEdge, join the value
1014  if (edge)
1015  {
1016  const IntraCFGEdge* intraEdge = SVFUtil::cast<IntraCFGEdge>(edge);
1017  if (intraEdge->getCondition())
1018  {
1019  if (isBranchFeasible(intraEdge, tmpEs))
1020  rhs.join_with(opAs[curId]);
1021  }
1022  else
1023  rhs.join_with(opAs[curId]);
1024  }
1025  else
1026  {
1027  rhs.join_with(opAs[curId]);
1028  }
1029  }
1030  }
1031  as[res] = rhs;
1032 }
bool hasAbsStateFromTrace(const ICFGNode *node)
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition: ICFG.cpp:303
u32_t getOpVarNum() const
const ICFGNode * getOpICFGNode(u32_t op_idx) const
Return the corresponding ICFGNode of this operand.

◆ updateStateOnRet()

void AbstractInterpretation::updateStateOnRet ( const RetPE retPE)
private

Definition at line 1043 of file AbstractInterpretation.cpp.

1044 {
1046  NodeID lhs = retPE->getLHSVarID();
1047  NodeID rhs = retPE->getRHSVarID();
1048  as[lhs] = as[rhs];
1049 }

◆ updateStateOnSelect()

void AbstractInterpretation::updateStateOnSelect ( const SelectStmt select)
private

Definition at line 978 of file AbstractInterpretation.cpp.

979 {
981  u32_t res = select->getResID();
982  u32_t tval = select->getTrueValue()->getId();
983  u32_t fval = select->getFalseValue()->getId();
984  u32_t cond = select->getCondition()->getId();
985  if (as[cond].getInterval().is_numeral())
986  {
987  as[res] = as[cond].getInterval().is_zero() ? as[fval] : as[tval];
988  }
989  else
990  {
991  as[res] = as[tval];
992  as[res].join_with(as[fval]);
993  }
994 }
const SVFVar * getTrueValue() const
const SVFVar * getCondition() const
const SVFVar * getFalseValue() const

◆ updateStateOnStore()

void AbstractInterpretation::updateStateOnStore ( const StoreStmt store)
private

Definition at line 1344 of file AbstractInterpretation.cpp.

1345 {
1347  u32_t rhs = store->getRHSVarID();
1348  u32_t lhs = store->getLHSVarID();
1349  as.storeValue(lhs, as[rhs]);
1350 }
void storeValue(NodeID varId, AbstractValue val)

Friends And Related Function Documentation

◆ AEAPI

friend class AEAPI
friend

Definition at line 105 of file AbstractInterpretation.h.

◆ AEStat

friend class AEStat
friend

Definition at line 104 of file AbstractInterpretation.h.

◆ BufOverflowDetector

friend class BufOverflowDetector
friend

Definition at line 106 of file AbstractInterpretation.h.

Member Data Documentation

◆ _reverse_predicate

Map<s32_t, s32_t> SVF::AbstractInterpretation::_reverse_predicate
private
Initial value:
=
{
{CmpStmt::Predicate::FCMP_OEQ, CmpStmt::Predicate::FCMP_ONE},
{CmpStmt::Predicate::FCMP_UEQ, CmpStmt::Predicate::FCMP_UNE},
{CmpStmt::Predicate::FCMP_OGT, CmpStmt::Predicate::FCMP_OLE},
{CmpStmt::Predicate::FCMP_OGE, CmpStmt::Predicate::FCMP_OLT},
{CmpStmt::Predicate::FCMP_OLT, CmpStmt::Predicate::FCMP_OGE},
{CmpStmt::Predicate::FCMP_OLE, CmpStmt::Predicate::FCMP_OGT},
{CmpStmt::Predicate::FCMP_ONE, CmpStmt::Predicate::FCMP_OEQ},
{CmpStmt::Predicate::FCMP_UNE, CmpStmt::Predicate::FCMP_UEQ},
{CmpStmt::Predicate::ICMP_EQ, CmpStmt::Predicate::ICMP_NE},
{CmpStmt::Predicate::ICMP_NE, CmpStmt::Predicate::ICMP_EQ},
{CmpStmt::Predicate::ICMP_UGT, CmpStmt::Predicate::ICMP_ULE},
{CmpStmt::Predicate::ICMP_ULT, CmpStmt::Predicate::ICMP_UGE},
{CmpStmt::Predicate::ICMP_UGE, CmpStmt::Predicate::ICMP_ULT},
{CmpStmt::Predicate::ICMP_SGT, CmpStmt::Predicate::ICMP_SLE},
{CmpStmt::Predicate::ICMP_SLT, CmpStmt::Predicate::ICMP_SGE},
{CmpStmt::Predicate::ICMP_SGE, CmpStmt::Predicate::ICMP_SLT},
}

Definition at line 308 of file AbstractInterpretation.h.

◆ _switch_lhsrhs_predicate

Map<s32_t, s32_t> SVF::AbstractInterpretation::_switch_lhsrhs_predicate
private
Initial value:
=
{
{CmpStmt::Predicate::FCMP_OEQ, CmpStmt::Predicate::FCMP_OEQ},
{CmpStmt::Predicate::FCMP_UEQ, CmpStmt::Predicate::FCMP_UEQ},
{CmpStmt::Predicate::FCMP_OGT, CmpStmt::Predicate::FCMP_OLT},
{CmpStmt::Predicate::FCMP_OGE, CmpStmt::Predicate::FCMP_OLE},
{CmpStmt::Predicate::FCMP_OLT, CmpStmt::Predicate::FCMP_OGT},
{CmpStmt::Predicate::FCMP_OLE, CmpStmt::Predicate::FCMP_OGE},
{CmpStmt::Predicate::FCMP_ONE, CmpStmt::Predicate::FCMP_ONE},
{CmpStmt::Predicate::FCMP_UNE, CmpStmt::Predicate::FCMP_UNE},
{CmpStmt::Predicate::ICMP_EQ, CmpStmt::Predicate::ICMP_EQ},
{CmpStmt::Predicate::ICMP_NE, CmpStmt::Predicate::ICMP_NE},
{CmpStmt::Predicate::ICMP_UGT, CmpStmt::Predicate::ICMP_ULT},
{CmpStmt::Predicate::ICMP_ULT, CmpStmt::Predicate::ICMP_UGT},
{CmpStmt::Predicate::ICMP_UGE, CmpStmt::Predicate::ICMP_ULE},
{CmpStmt::Predicate::ICMP_SGT, CmpStmt::Predicate::ICMP_SLT},
{CmpStmt::Predicate::ICMP_SLT, CmpStmt::Predicate::ICMP_SGT},
{CmpStmt::Predicate::ICMP_SGE, CmpStmt::Predicate::ICMP_SLE},
}

Definition at line 329 of file AbstractInterpretation.h.

◆ abstractTrace

Map<const ICFGNode*, AbstractState> SVF::AbstractInterpretation::abstractTrace
private

Definition at line 295 of file AbstractInterpretation.h.

◆ api

AEAPI* SVF::AbstractInterpretation::api {nullptr}
private

Execution State, used to store the Interval Value of every SVF variable.

Definition at line 248 of file AbstractInterpretation.h.

◆ callSiteStack

std::vector<const CallICFGNode*> SVF::AbstractInterpretation::callSiteStack
private

Definition at line 253 of file AbstractInterpretation.h.

◆ checkpoints

Set<const CallICFGNode*> SVF::AbstractInterpretation::checkpoints

Definition at line 132 of file AbstractInterpretation.h.

◆ detectors

std::vector<std::unique_ptr<AEDetector> > SVF::AbstractInterpretation::detectors
private

Definition at line 298 of file AbstractInterpretation.h.

◆ func_map

Map<std::string, std::function<void(const CallICFGNode*)> > SVF::AbstractInterpretation::func_map
private

Definition at line 293 of file AbstractInterpretation.h.

◆ funcToWTO

Map<const SVFFunction*, ICFGWTO*> SVF::AbstractInterpretation::funcToWTO
private

Definition at line 254 of file AbstractInterpretation.h.

◆ icfg

ICFG* SVF::AbstractInterpretation::icfg
private

Definition at line 250 of file AbstractInterpretation.h.

◆ moduleName

std::string SVF::AbstractInterpretation::moduleName
private

Definition at line 296 of file AbstractInterpretation.h.

◆ recursiveFuns

Set<const SVFFunction*> SVF::AbstractInterpretation::recursiveFuns
private

Definition at line 255 of file AbstractInterpretation.h.

◆ stat

AEStat* SVF::AbstractInterpretation::stat
private

Definition at line 251 of file AbstractInterpretation.h.

◆ svfir

SVFIR* SVF::AbstractInterpretation::svfir
private

protected data members, also used in subclasses

Definition at line 246 of file AbstractInterpretation.h.

◆ utils

AbsExtAPI* SVF::AbstractInterpretation::utils
private

Definition at line 299 of file AbstractInterpretation.h.


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