Static Value-Flow Analysis
Loading...
Searching...
No Matches
AbstractInterpretation.cpp
Go to the documentation of this file.
1//===- AbstractExecution.cpp -- Abstract Execution---------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23
24//
25// Created by Jiawei Wang on 2024/1/10.
26//
27
29#include "AE/Svfexe/AbsExtAPI.h"
30#include "SVFIR/SVFIR.h"
31#include "Util/Options.h"
32#include "Util/WorkList.h"
33#include "Graphs/CallGraph.h"
34#include <cmath>
35
36using namespace SVF;
37using namespace SVFUtil;
38using namespace z3;
39
40
42{
43 stat->startClk();
44 icfg = _icfg;
47
50
51 analyse();
53 stat->endClk();
55 if (Options::PStat())
57 for (auto& detector: detectors)
58 detector->reportBug();
59}
60
67{
68 delete stat;
69 for (auto it: funcToWTO)
70 delete it.second;
71
72}
73
82{
84 // Detect if the call graph has cycles by finding its strongly connected components (SCC)
86 callGraphScc->find();
88
89 // Iterate through the call graph
90 for (auto it = svfirCallGraph->begin(); it != svfirCallGraph->end(); it++)
91 {
92 // Check if the current function is part of a cycle
93 if (callGraphScc->isInCycle(it->second->getId()))
94 recursiveFuns.insert(it->second); // Mark the function as recursive
95 if (it->second->getFunction()->isDeclaration())
96 continue;
97 auto* wto = new ICFGWTO(icfg, icfg->getFunEntryICFGNode(it->second->getFunction()));
98 wto->init();
99 funcToWTO[it->second] = wto;
100 }
101}
104{
105 initWTO();
106 // handle Global ICFGNode of SVFModule
110 if (const CallGraphNode* cgn = svfir->getCallGraph()->getCallGraphNode("main"))
111 {
113 handleWTOComponents(wto->getWTOComponents());
114 }
115}
116
119{
120 const ICFGNode* node = icfg->getGlobalICFGNode();
123 // Global Node, we just need to handle addr, load, store, copy and gep
124 for (const SVFStmt *stmt: node->getSVFStmts())
125 {
127 }
128}
129
134{
135 std::vector<AbstractState> workList;
137 for (auto& edge: icfgNode->getInEdges())
138 {
139 if (abstractTrace.find(edge->getSrcNode()) != abstractTrace.end())
140 {
141 const IntraCFGEdge *intraCfgEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge);
142 if (intraCfgEdge && intraCfgEdge->getCondition())
143 {
144 AbstractState tmpEs = abstractTrace[edge->getSrcNode()];
146 {
147 workList.push_back(tmpEs);
148 }
149 else
150 {
151 // do nothing
152 }
153 }
154 else
155 {
156 workList.push_back(abstractTrace[edge->getSrcNode()]);
157 }
158 }
159 else
160 {
161
162 }
163 }
164 if (workList.size() == 0)
165 {
166 return false;
167 }
168 else
169 {
170 while (!workList.empty())
171 {
172 preAs.joinWith(workList.back());
173 workList.pop_back();
174 }
175 // Has ES on the in edges - Feasible block
176 // update post as
177 abstractTrace[icfgNode] = preAs;
178 return true;
179 }
180}
181
182
185{
187 // get cmp stmt's op0, op1, and predicate
188 NodeID op0 = cmpStmt->getOpVarID(0);
189 NodeID op1 = cmpStmt->getOpVarID(1);
190 NodeID res_id = cmpStmt->getResID();
191 s32_t predicate = cmpStmt->getPredicate();
192
193 // if op0 or op1 is undefined, return;
194 // skip address compare
195 if (new_es.inVarToAddrsTable(op0) || new_es.inVarToAddrsTable(op1))
196 {
197 as = new_es;
198 return true;
199 }
200 const LoadStmt *load_op0 = nullptr;
201 const LoadStmt *load_op1 = nullptr;
202 // get '%1 = load i32 s', and load inst may not exist
204 if (!loadVar0->getInEdges().empty())
205 {
206 SVFStmt *loadVar0InStmt = *loadVar0->getInEdges().begin();
207 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt))
208 {
210 }
211 else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar0InStmt))
212 {
213 loadVar0 = svfir->getGNode(copyStmt->getRHSVarID());
214 if (!loadVar0->getInEdges().empty())
215 {
216 SVFStmt *loadVar0InStmt2 = *loadVar0->getInEdges().begin();
217 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt2))
218 {
220 }
221 }
222 }
223 }
224
226 if (!loadVar1->getInEdges().empty())
227 {
228 SVFStmt *loadVar1InStmt = *loadVar1->getInEdges().begin();
229 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt))
230 {
232 }
233 else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar1InStmt))
234 {
235 loadVar1 = svfir->getGNode(copyStmt->getRHSVarID());
236 if (!loadVar1->getInEdges().empty())
237 {
238 SVFStmt *loadVar1InStmt2 = *loadVar1->getInEdges().begin();
239 if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt2))
240 {
242 }
243 }
244 }
245 }
246 // for const X const, we may get concrete resVal instantly
247 // for var X const, we may get [0,1] if the intersection of var and const is not empty set
248 IntervalValue resVal = new_es[res_id].getInterval();
250 // If Var X const generates bottom value, it means this branch path is not feasible.
251 if (resVal.isBottom())
252 {
253 return false;
254 }
255
256 bool b0 = new_es[op0].getInterval().is_numeral();
257 bool b1 = new_es[op1].getInterval().is_numeral();
258
259 // if const X var, we should reverse op0 and op1.
260 if (b0 && !b1)
261 {
262 std::swap(op0, op1);
263 std::swap(load_op0, load_op1);
264 predicate = _switch_lhsrhs_predicate[predicate];
265 }
266 else
267 {
268 // if var X var, we cannot preset the branch condition to infer the intervals of var0,var1
269 if (!b0 && !b1)
270 {
271 as = new_es;
272 return true;
273 }
274 // if const X const, we can instantly get the resVal
275 else if (b0 && b1)
276 {
277 as = new_es;
278 return true;
279 }
280 }
281 // if cmp is 'var X const == false', we should reverse predicate 'var X' const == true'
282 // X' is reverse predicate of X
283 if (succ == 0)
284 {
285 predicate = _reverse_predicate[predicate];
286 }
287 else {}
288 // change interval range according to the compare predicate
289 AddressValue addrs;
290 if(load_op0 && new_es.inVarToAddrsTable(load_op0->getRHSVarID()))
291 addrs = new_es[load_op0->getRHSVarID()].getAddrs();
292
293 IntervalValue &lhs = new_es[op0].getInterval(), &rhs = new_es[op1].getInterval();
294 switch (predicate)
295 {
299 {
300 // Var == Const, so [var.lb, var.ub].meet_with(const)
302 // if lhs is register value, we should also change its mem obj
303 for (const auto &addr: addrs)
304 {
305 NodeID objId = new_es.getInternalID(addr);
306 if (new_es.inAddrToValTable(objId))
307 {
308 new_es.load(addr).meet_with(rhs);
309 }
310 }
311 break;
312 }
316 // Compliment set
317 break;
322 // Var > Const, so [var.lb, var.ub].meet_with([Const+1, +INF])
323 lhs.meet_with(IntervalValue(rhs.lb() + 1, IntervalValue::plus_infinity()));
324 // if lhs is register value, we should also change its mem obj
325 for (const auto &addr: addrs)
326 {
327 NodeID objId = new_es.getInternalID(addr);
328 if (new_es.inAddrToValTable(objId))
329 {
330 new_es.load(addr).meet_with(
332 }
333 }
334 break;
339 {
340 // Var >= Const, so [var.lb, var.ub].meet_with([Const, +INF])
342 // if lhs is register value, we should also change its mem obj
343 for (const auto &addr: addrs)
344 {
345 NodeID objId = new_es.getInternalID(addr);
346 if (new_es.inAddrToValTable(objId))
347 {
348 new_es.load(addr).meet_with(
350 }
351 }
352 break;
353 }
358 {
359 // Var < Const, so [var.lb, var.ub].meet_with([-INF, const.ub-1])
360 lhs.meet_with(IntervalValue(IntervalValue::minus_infinity(), rhs.ub() - 1));
361 // if lhs is register value, we should also change its mem obj
362 for (const auto &addr: addrs)
363 {
364 NodeID objId = new_es.getInternalID(addr);
365 if (new_es.inAddrToValTable(objId))
366 {
367 new_es.load(addr).meet_with(
369 }
370 }
371 break;
372 }
377 {
378 // Var <= Const, so [var.lb, var.ub].meet_with([-INF, const.ub])
380 // if lhs is register value, we should also change its mem obj
381 for (const auto &addr: addrs)
382 {
383 NodeID objId = new_es.getInternalID(addr);
384 if (new_es.inAddrToValTable(objId))
385 {
386 new_es.load(addr).meet_with(
388 }
389 }
390 break;
391 }
393 break;
395 break;
396 default:
397 assert(false && "implement this part");
398 abort();
399 }
400 as = new_es;
401 return true;
402}
403
406{
408 IntervalValue& switch_cond = new_es[var->getId()].getInterval();
409 s64_t value = succ;
411 for (SVFStmt *cmpVarInStmt: var->getInEdges())
412 {
414 }
415 switch_cond.meet_with(IntervalValue(value, value));
416 if (switch_cond.isBottom())
417 {
418 return false;
419 }
420 while(!workList.empty())
421 {
422 const SVFStmt* stmt = workList.pop();
423 if (SVFUtil::isa<CopyStmt>(stmt))
424 {
425 IntervalValue& copy_cond = new_es[var->getId()].getInterval();
426 copy_cond.meet_with(IntervalValue(value, value));
427 }
428 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
429 {
430 if (new_es.inVarToAddrsTable(load->getRHSVarID()))
431 {
432 AddressValue &addrs = new_es[load->getRHSVarID()].getAddrs();
433 for (const auto &addr: addrs)
434 {
436 if (new_es.inAddrToValTable(objId))
437 {
438 new_es.load(addr).meet_with(switch_cond);
439 }
440 }
441 }
442 }
443 }
444 as = new_es;
445 return true;
446}
447
450{
451 const SVFVar *cmpVar = intraEdge->getCondition();
452 if (cmpVar->getInEdges().empty())
453 {
455 intraEdge->getSuccessorCondValue(), as);
456 }
457 else
458 {
459 assert(!cmpVar->getInEdges().empty() &&
460 "no in edges?");
461 SVFStmt *cmpVarInStmt = *cmpVar->getInEdges().begin();
462 if (const CmpStmt *cmpStmt = SVFUtil::dyn_cast<CmpStmt>(cmpVarInStmt))
463 {
465 intraEdge->getSuccessorCondValue(), as);
466 }
467 else
468 {
470 cmpVar, intraEdge->getSuccessorCondValue(), as);
471 }
472 }
473 return true;
474}
477{
478 const ICFGNode* node = icfgSingletonWto->getICFGNode();
479 stat->getBlockTrace()++;
480
481 std::deque<const ICFGNode*> worklist;
482
483 const std::vector<const ICFGNode*>& worklist_vec = icfg->getSubNodes(node);
484 for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it)
485 {
486 const ICFGNode* curNode = *it;
488 // handle SVF Stmt
489 for (const SVFStmt *stmt: curNode->getSVFStmts())
490 {
492 }
493 // inlining the callee by calling handleFunc for the callee function
494 if (const CallICFGNode* callnode = SVFUtil::dyn_cast<CallICFGNode>(curNode))
495 {
497 }
498 for (auto& detector: detectors)
499 detector->detect(getAbsStateFromTrace(node), node);
501 }
502}
503
507void AbstractInterpretation::handleWTOComponents(const std::list<const ICFGWTOComp*>& wtoComps)
508{
509 for (const ICFGWTOComp* wtoNode : wtoComps)
510 {
512 }
513}
514
516{
517 if (const ICFGSingletonWTO* node = SVFUtil::dyn_cast<ICFGSingletonWTO>(wtoNode))
518 {
519 if (mergeStatesFromPredecessors(node->getICFGNode()))
520 handleSingletonWTO(node);
521 }
522 // Handle WTO cycles
523 else if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(wtoNode))
524 {
525 if (mergeStatesFromPredecessors(cycle->head()->getICFGNode()))
527 }
528 // Assert false for unknown WTO types
529 else
530 {
531 assert(false && "unknown WTO type!");
532 }
533}
534
536{
537 if (const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node))
538 {
539 if (isExtCall(callNode))
540 {
542 }
543 else if (isRecursiveCall(callNode))
544 {
546 }
547 else if (isDirectCall(callNode))
548 {
550 }
551 else if (isIndirectCall(callNode))
552 {
554 }
555 else
556 {
557 assert(false && "implement this part");
558 }
559 }
560 else
561 {
562 assert (false && "it is not call node");
563 }
564}
565
567{
568 return SVFUtil::isExtCall(callNode->getCalledFunction());
569}
570
572{
573 callSiteStack.push_back(callNode);
575 for (auto& detector : detectors)
576 {
577 detector->handleStubFunctions(callNode);
578 }
579 callSiteStack.pop_back();
580}
581
583{
584 const SVFFunction *callfun = callNode->getCalledFunction();
585 if (!callfun)
586 return false;
587 else
588 return recursiveFuns.find(callfun->getCallGraphNode()) != recursiveFuns.end();
589}
590
592{
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 }
608}
609
611{
612 const SVFFunction *callfun =callNode->getCalledFunction();
613 if (!callfun)
614 return false;
615 else
616 return funcToWTO.find(callfun->getCallGraphNode()) != funcToWTO.end();
617}
619{
621 callSiteStack.push_back(callNode);
622
624
625 const SVFFunction *callfun =callNode->getCalledFunction();
626 ICFGWTO* wto = funcToWTO[callfun->getCallGraphNode()];
627 handleWTOComponents(wto->getWTOComponents());
628
629 callSiteStack.pop_back();
630 // handle Ret node
631 const RetICFGNode *retNode = callNode->getRetICFGNode();
632 // resume ES to callnode
634}
635
641
643{
647 if (!as.inVarToAddrsTable(call_id))
648 {
649 return;
650 }
654 if(const FunObjVar*funObjVar = SVFUtil::dyn_cast<FunObjVar>(func_var))
655 {
656 const CallGraphNode* callfun = funObjVar->getCallGraphNode();
657 callSiteStack.push_back(callNode);
659
661 handleWTOComponents(wto->getWTOComponents());
662 callSiteStack.pop_back();
663 // handle Ret node
664 const RetICFGNode* retNode = callNode->getRetICFGNode();
666 }
667}
668
669
670
673{
674 const ICFGNode* cycle_head = cycle->head()->getICFGNode();
675 // Flag to indicate if we are in the increasing phase
676 bool increasing = true;
677 // Infinite loop until a fixpoint is reached,
678 for (u32_t cur_iter = 0;; cur_iter++)
679 {
680 // Start widening or narrowing if cur_iter >= widen threshold (widen delay)
682 {
683 // Widen or narrow after processing cycle head node
685 handleWTOComponent(cycle->head());
687 if (increasing)
688 {
689 // Widening phase
692 {
693 increasing = false;
694 continue;
695 }
696 }
697 else
698 {
699 // Widening's fixpoint reached in the widening phase, switch to narrowing
702 {
703 // Narrowing's fixpoint reached in the narrowing phase, exit loop
704 break;
705 }
706 }
707 }
708 else
709 {
710 // Handle the cycle head
711 handleSingletonWTO(cycle->head());
712 }
713 // Handle the cycle body
714 handleWTOComponents(cycle->getWTOComponents());
715 }
716}
717
719{
720 if (const AddrStmt *addr = SVFUtil::dyn_cast<AddrStmt>(stmt))
721 {
723 }
724 else if (const BinaryOPStmt *binary = SVFUtil::dyn_cast<BinaryOPStmt>(stmt))
725 {
727 }
728 else if (const CmpStmt *cmp = SVFUtil::dyn_cast<CmpStmt>(stmt))
729 {
731 }
732 else if (SVFUtil::isa<UnaryOPStmt>(stmt))
733 {
734 }
735 else if (SVFUtil::isa<BranchStmt>(stmt))
736 {
737 // branch stmt is handled in hasBranchES
738 }
739 else if (const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(stmt))
740 {
741 updateStateOnLoad(load);
742 }
743 else if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
744 {
745 updateStateOnStore(store);
746 }
747 else if (const CopyStmt *copy = SVFUtil::dyn_cast<CopyStmt>(stmt))
748 {
750 }
751 else if (const GepStmt *gep = SVFUtil::dyn_cast<GepStmt>(stmt))
752 {
754 }
755 else if (const SelectStmt *select = SVFUtil::dyn_cast<SelectStmt>(stmt))
756 {
758 }
759 else if (const PhiStmt *phi = SVFUtil::dyn_cast<PhiStmt>(stmt))
760 {
762 }
763 else if (const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
764 {
765 // To handle Call Edge
767 }
768 else if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
769 {
770 updateStateOnRet(retPE);
771 }
772 else
773 assert(false && "implement this part");
774}
775
776
778{
780 const RetICFGNode *retNode = callNode->getRetICFGNode();
781 if (retNode->getSVFStmts().size() > 0)
782 {
783 if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
784 {
786 if (!retPE->getLHSVar()->isPointer() && !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
787 as[retPE->getLHSVarID()] = IntervalValue::top();
788 }
789 }
790 if (!retNode->getOutEdges().empty())
791 {
792 if (retNode->getOutEdges().size() == 1)
793 {
794
795 }
796 else
797 {
798 return;
799 }
800 }
803 for (const SVFBasicBlock * bb: callNode->getCalledFunction()->getReachableBBs())
804 {
805 for (const ICFGNode* node: bb->getICFGNodeList())
806 {
807 for (const SVFStmt *stmt: node->getSVFStmts())
808 {
809 if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
810 {
811 const SVFVar *rhsVar = store->getRHSVar();
812 u32_t lhs = store->getLHSVarID();
813 if (as.inVarToAddrsTable(lhs))
814 {
815 if (!rhsVar->isPointer() && !rhsVar->isConstDataOrAggDataButNotNullPtr())
816 {
817 const AbstractValue &addrs = as[lhs];
818 for (const auto &addr: addrs.getAddrs())
819 {
820 as.store(addr, IntervalValue::top());
821 }
822 }
823 }
824 }
825 }
826 }
827 }
828}
829
830// count the size of memory map
832{
833 if (count == 0)
834 {
835 generalNumMap["ES_Var_AVG_Num"] = 0;
836 generalNumMap["ES_Loc_AVG_Num"] = 0;
837 generalNumMap["ES_Var_Addr_AVG_Num"] = 0;
838 generalNumMap["ES_Loc_Addr_AVG_Num"] = 0;
839 }
840 ++count;
841}
842
844{
846 if (count > 0)
847 {
848 generalNumMap["ES_Var_AVG_Num"] /= count;
849 generalNumMap["ES_Loc_AVG_Num"] /= count;
850 generalNumMap["ES_Var_Addr_AVG_Num"] /= count;
851 generalNumMap["ES_Loc_Addr_AVG_Num"] /= count;
852 }
853 generalNumMap["SVF_STMT_NUM"] = count;
854 generalNumMap["ICFG_Node_Num"] = _ae->svfir->getICFG()->nodeNum;
855 u32_t callSiteNum = 0;
858 for (const auto &it: *_ae->svfir->getICFG())
859 {
860 if (it.second->getFun())
861 {
862 funs.insert(it.second->getFun());
863 }
864 if (const CallICFGNode *callNode = dyn_cast<CallICFGNode>(it.second))
865 {
866 if (!isExtCall(callNode))
867 {
868 callSiteNum++;
869 }
870 else
871 {
873 }
874 }
875 }
876 generalNumMap["Func_Num"] = funs.size();
877 generalNumMap["EXT_CallSite_Num"] = extCallSiteNum;
878 generalNumMap["NonEXT_CallSite_Num"] = callSiteNum;
879 timeStatMap["Total_Time(sec)"] = (double)(endTime - startTime) / TIMEINTERVAL;
880
881}
882
884{
885 std::string fullName(_ae->moduleName);
886 std::string name;
887 std::string moduleName;
888 if (fullName.find('/') == std::string::npos)
889 {
890 std::string name = fullName;
891 moduleName = name.substr(0, fullName.find('.'));
892 }
893 else
894 {
895 std::string name = fullName.substr(fullName.find('/'), fullName.size());
896 moduleName = name.substr(0, fullName.find('.'));
897 }
898
899 SVFUtil::outs() << "\n************************\n";
900 SVFUtil::outs() << "################ (program : " << moduleName << ")###############\n";
901 SVFUtil::outs().flags(std::ios::left);
902 unsigned field_width = 30;
903 for (NUMStatMap::iterator it = generalNumMap.begin(), eit = generalNumMap.end(); it != eit; ++it)
904 {
905 // format out put with width 20 space
906 std::cout << std::setw(field_width) << it->first << it->second << "\n";
907 }
908 SVFUtil::outs() << "-------------------------------------------------------\n";
909 for (TIMEStatMap::iterator it = timeStatMap.begin(), eit = timeStatMap.end(); it != eit; ++it)
910 {
911 // format out put with width 20 space
912 SVFUtil::outs() << std::setw(field_width) << it->first << it->second << "\n";
913 }
914 SVFUtil::outs() << "Memory usage: " << memUsage << "\n";
915
916 SVFUtil::outs() << "#######################################################" << std::endl;
917 SVFUtil::outs().flush();
918}
919
921{
922 // traverse every ICFGNode
923 Set<std::string> ae_checkpoint_names = {"svf_assert"};
924 Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
925
926 for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
927 {
928 const ICFGNode* node = it->second;
929 if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
930 {
931 if (const SVFFunction *fun = call->getCalledFunction())
932 {
933 if (ae_checkpoint_names.find(fun->getName()) !=
935 {
936 checkpoints.insert(call);
937 }
939 {
940 if (buf_checkpoint_names.find(fun->getName()) !=
942 {
943 checkpoints.insert(call);
944 }
945 }
946 }
947 }
948 }
949}
950
952{
953 if (checkpoints.size() == 0)
954 {
955 return;
956 }
957 else
958 {
959 SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
960 for (const CallICFGNode* call: checkpoints)
961 SVFUtil::errs() << call->toString() + "\n";
962 assert(false);
963 }
964
965}
966
968{
969 AbstractState& as = getAbsStateFromTrace(gep->getICFGNode());
970 u32_t rhs = gep->getRHSVarID();
971 u32_t lhs = gep->getLHSVarID();
972 IntervalValue offsetPair = as.getElementIndex(gep);
974 APOffset lb = offsetPair.lb().getIntNumeral() < Options::MaxFieldLimit()?
975 offsetPair.lb().getIntNumeral(): Options::MaxFieldLimit();
976 APOffset ub = offsetPair.ub().getIntNumeral() < Options::MaxFieldLimit()?
977 offsetPair.ub().getIntNumeral(): Options::MaxFieldLimit();
978 for (APOffset i = lb; i <= ub; i++)
979 gepAddrs.join_with(as.getGepObjAddrs(rhs,IntervalValue(i)));
980 as[lhs] = gepAddrs;
981}
982
984{
985 AbstractState& as = getAbsStateFromTrace(select->getICFGNode());
986 u32_t res = select->getResID();
987 u32_t tval = select->getTrueValue()->getId();
988 u32_t fval = select->getFalseValue()->getId();
989 u32_t cond = select->getCondition()->getId();
990 if (as[cond].getInterval().is_numeral())
991 {
992 as[res] = as[cond].getInterval().is_zero() ? as[fval] : as[tval];
993 }
994 else
995 {
996 as[res] = as[tval];
997 as[res].join_with(as[fval]);
998 }
999}
1000
1002{
1003 const ICFGNode* icfgNode = phi->getICFGNode();
1005 u32_t res = phi->getResID();
1007 for (u32_t i = 0; i < phi->getOpVarNum(); i++)
1008 {
1009 NodeID curId = phi->getOpVarID(i);
1010 const ICFGNode* opICFGNode = phi->getOpICFGNode(i);
1012 {
1016 // if IntraEdge, check the condition, if it is feasible, join the value
1017 // if IntraEdge but not conditional edge, join the value
1018 // if not IntraEdge, join the value
1019 if (edge)
1020 {
1021 const IntraCFGEdge* intraEdge = SVFUtil::cast<IntraCFGEdge>(edge);
1022 if (intraEdge->getCondition())
1023 {
1025 rhs.join_with(opAs[curId]);
1026 }
1027 else
1028 rhs.join_with(opAs[curId]);
1029 }
1030 else
1031 {
1032 rhs.join_with(opAs[curId]);
1033 }
1034 }
1035 }
1036 as[res] = rhs;
1037}
1038
1039
1041{
1042 AbstractState& as = getAbsStateFromTrace(callPE->getICFGNode());
1043 NodeID lhs = callPE->getLHSVarID();
1044 NodeID rhs = callPE->getRHSVarID();
1045 as[lhs] = as[rhs];
1046}
1047
1049{
1051 NodeID lhs = retPE->getLHSVarID();
1052 NodeID rhs = retPE->getRHSVarID();
1053 as[lhs] = as[rhs];
1054}
1055
1056
1058{
1059 AbstractState& as = getAbsStateFromTrace(addr->getICFGNode());
1060 as.initObjVar(SVFUtil::cast<ObjVar>(addr->getRHSVar()));
1061 if (addr->getRHSVar()->getType()->getKind() == SVFType::SVFIntegerTy)
1062 as[addr->getRHSVarID()].getInterval().meet_with(utils->getRangeLimitFromType(addr->getRHSVar()->getType()));
1063 as[addr->getLHSVarID()] = as[addr->getRHSVarID()];
1064}
1065
1066
1068{
1072 const ICFGNode* node = binary->getICFGNode();
1074 u32_t op0 = binary->getOpVarID(0);
1075 u32_t op1 = binary->getOpVarID(1);
1076 u32_t res = binary->getResID();
1077 if (!as.inVarToValTable(op0)) as[op0] = IntervalValue::top();
1078 if (!as.inVarToValTable(op1)) as[op1] = IntervalValue::top();
1079 IntervalValue &lhs = as[op0].getInterval(), &rhs = as[op1].getInterval();
1081 switch (binary->getOpcode())
1082 {
1083 case BinaryOPStmt::Add:
1084 case BinaryOPStmt::FAdd:
1085 resVal = (lhs + rhs);
1086 break;
1087 case BinaryOPStmt::Sub:
1088 case BinaryOPStmt::FSub:
1089 resVal = (lhs - rhs);
1090 break;
1091 case BinaryOPStmt::Mul:
1092 case BinaryOPStmt::FMul:
1093 resVal = (lhs * rhs);
1094 break;
1095 case BinaryOPStmt::SDiv:
1096 case BinaryOPStmt::FDiv:
1097 case BinaryOPStmt::UDiv:
1098 resVal = (lhs / rhs);
1099 break;
1100 case BinaryOPStmt::SRem:
1101 case BinaryOPStmt::FRem:
1102 case BinaryOPStmt::URem:
1103 resVal = (lhs % rhs);
1104 break;
1105 case BinaryOPStmt::Xor:
1106 resVal = (lhs ^ rhs);
1107 break;
1108 case BinaryOPStmt::And:
1109 resVal = (lhs & rhs);
1110 break;
1111 case BinaryOPStmt::Or:
1112 resVal = (lhs | rhs);
1113 break;
1114 case BinaryOPStmt::AShr:
1115 resVal = (lhs >> rhs);
1116 break;
1117 case BinaryOPStmt::Shl:
1118 resVal = (lhs << rhs);
1119 break;
1120 case BinaryOPStmt::LShr:
1121 resVal = (lhs >> rhs);
1122 break;
1123 default:
1124 assert(false && "undefined binary: ");
1125 }
1126 as[res] = resVal;
1127}
1128
1130{
1131 AbstractState& as = getAbsStateFromTrace(cmp->getICFGNode());
1132 u32_t op0 = cmp->getOpVarID(0);
1133 u32_t op1 = cmp->getOpVarID(1);
1134 // if it is address
1135 if (as.inVarToAddrsTable(op0) && as.inVarToAddrsTable(op1))
1136 {
1138 AddressValue addrOp0 = as[op0].getAddrs();
1139 AddressValue addrOp1 = as[op1].getAddrs();
1140 u32_t res = cmp->getResID();
1141 if (addrOp0.equals(addrOp1))
1142 {
1143 resVal = IntervalValue(1, 1);
1144 }
1145 else if (addrOp0.hasIntersect(addrOp1))
1146 {
1147 resVal = IntervalValue(0, 1);
1148 }
1149 else
1150 {
1151 resVal = IntervalValue(0, 0);
1152 }
1153 as[res] = resVal;
1154 }
1155 else
1156 {
1157 if (!as.inVarToValTable(op0))
1159 if (!as.inVarToValTable(op1))
1161 u32_t res = cmp->getResID();
1162 if (as.inVarToValTable(op0) && as.inVarToValTable(op1))
1163 {
1165 if (as[op0].isInterval() && as[op1].isInterval())
1166 {
1167 IntervalValue &lhs = as[op0].getInterval(),
1168 &rhs = as[op1].getInterval();
1169 // AbstractValue
1170 auto predicate = cmp->getPredicate();
1171 switch (predicate)
1172 {
1173 case CmpStmt::ICMP_EQ:
1174 case CmpStmt::FCMP_OEQ:
1175 case CmpStmt::FCMP_UEQ:
1176 resVal = (lhs == rhs);
1177 // resVal = (lhs.getInterval() == rhs.getInterval());
1178 break;
1179 case CmpStmt::ICMP_NE:
1180 case CmpStmt::FCMP_ONE:
1181 case CmpStmt::FCMP_UNE:
1182 resVal = (lhs != rhs);
1183 break;
1184 case CmpStmt::ICMP_UGT:
1185 case CmpStmt::ICMP_SGT:
1186 case CmpStmt::FCMP_OGT:
1187 case CmpStmt::FCMP_UGT:
1188 resVal = (lhs > rhs);
1189 break;
1190 case CmpStmt::ICMP_UGE:
1191 case CmpStmt::ICMP_SGE:
1192 case CmpStmt::FCMP_OGE:
1193 case CmpStmt::FCMP_UGE:
1194 resVal = (lhs >= rhs);
1195 break;
1196 case CmpStmt::ICMP_ULT:
1197 case CmpStmt::ICMP_SLT:
1198 case CmpStmt::FCMP_OLT:
1199 case CmpStmt::FCMP_ULT:
1200 resVal = (lhs < rhs);
1201 break;
1202 case CmpStmt::ICMP_ULE:
1203 case CmpStmt::ICMP_SLE:
1204 case CmpStmt::FCMP_OLE:
1205 case CmpStmt::FCMP_ULE:
1206 resVal = (lhs <= rhs);
1207 break;
1209 resVal = IntervalValue(0, 0);
1210 break;
1211 case CmpStmt::FCMP_TRUE:
1212 resVal = IntervalValue(1, 1);
1213 break;
1214 default:
1215 {
1216 assert(false && "undefined compare: ");
1217 }
1218 }
1219 as[res] = resVal;
1220 }
1221 else if (as[op0].isAddr() && as[op1].isAddr())
1222 {
1223 AddressValue &lhs = as[op0].getAddrs(),
1224 &rhs = as[op1].getAddrs();
1225 auto predicate = cmp->getPredicate();
1226 switch (predicate)
1227 {
1228 case CmpStmt::ICMP_EQ:
1229 case CmpStmt::FCMP_OEQ:
1230 case CmpStmt::FCMP_UEQ:
1231 {
1232 if (lhs.hasIntersect(rhs))
1233 {
1234 resVal = IntervalValue(0, 1);
1235 }
1236 else if (lhs.empty() && rhs.empty())
1237 {
1238 resVal = IntervalValue(1, 1);
1239 }
1240 else
1241 {
1242 resVal = IntervalValue(0, 0);
1243 }
1244 break;
1245 }
1246 case CmpStmt::ICMP_NE:
1247 case CmpStmt::FCMP_ONE:
1248 case CmpStmt::FCMP_UNE:
1249 {
1250 if (lhs.hasIntersect(rhs))
1251 {
1252 resVal = IntervalValue(0, 1);
1253 }
1254 else if (lhs.empty() && rhs.empty())
1255 {
1256 resVal = IntervalValue(0, 0);
1257 }
1258 else
1259 {
1260 resVal = IntervalValue(1, 1);
1261 }
1262 break;
1263 }
1264 case CmpStmt::ICMP_UGT:
1265 case CmpStmt::ICMP_SGT:
1266 case CmpStmt::FCMP_OGT:
1267 case CmpStmt::FCMP_UGT:
1268 {
1269 if (lhs.size() == 1 && rhs.size() == 1)
1270 {
1271 resVal = IntervalValue(*lhs.begin() > *rhs.begin());
1272 }
1273 else
1274 {
1275 resVal = IntervalValue(0, 1);
1276 }
1277 break;
1278 }
1279 case CmpStmt::ICMP_UGE:
1280 case CmpStmt::ICMP_SGE:
1281 case CmpStmt::FCMP_OGE:
1282 case CmpStmt::FCMP_UGE:
1283 {
1284 if (lhs.size() == 1 && rhs.size() == 1)
1285 {
1286 resVal = IntervalValue(*lhs.begin() >= *rhs.begin());
1287 }
1288 else
1289 {
1290 resVal = IntervalValue(0, 1);
1291 }
1292 break;
1293 }
1294 case CmpStmt::ICMP_ULT:
1295 case CmpStmt::ICMP_SLT:
1296 case CmpStmt::FCMP_OLT:
1297 case CmpStmt::FCMP_ULT:
1298 {
1299 if (lhs.size() == 1 && rhs.size() == 1)
1300 {
1301 resVal = IntervalValue(*lhs.begin() < *rhs.begin());
1302 }
1303 else
1304 {
1305 resVal = IntervalValue(0, 1);
1306 }
1307 break;
1308 }
1309 case CmpStmt::ICMP_ULE:
1310 case CmpStmt::ICMP_SLE:
1311 case CmpStmt::FCMP_OLE:
1312 case CmpStmt::FCMP_ULE:
1313 {
1314 if (lhs.size() == 1 && rhs.size() == 1)
1315 {
1316 resVal = IntervalValue(*lhs.begin() <= *rhs.begin());
1317 }
1318 else
1319 {
1320 resVal = IntervalValue(0, 1);
1321 }
1322 break;
1323 }
1325 resVal = IntervalValue(0, 0);
1326 break;
1327 case CmpStmt::FCMP_TRUE:
1328 resVal = IntervalValue(1, 1);
1329 break;
1330 default:
1331 {
1332 assert(false && "undefined compare: ");
1333 }
1334 }
1335 as[res] = resVal;
1336 }
1337 }
1338 }
1339}
1340
1342{
1344 u32_t rhs = load->getRHSVarID();
1345 u32_t lhs = load->getLHSVarID();
1346 as[lhs] = as.loadValue(rhs);
1347}
1348
1350{
1352 u32_t rhs = store->getRHSVarID();
1353 u32_t lhs = store->getLHSVarID();
1354 as.storeValue(lhs, as[rhs]);
1355}
1356
1358{
1359 auto getZExtValue = [](AbstractState& as, const SVFVar* var)
1360 {
1361 const SVFType* type = var->getType();
1362 if (SVFUtil::isa<SVFIntegerType>(type))
1363 {
1364 u32_t bits = type->getByteSize() * 8;
1365 if (as[var->getId()].getInterval().is_numeral())
1366 {
1367 if (bits == 8)
1368 {
1369 int8_t signed_i8_value = as[var->getId()].getInterval().getIntNumeral();
1372 }
1373 else if (bits == 16)
1374 {
1375 s16_t signed_i16_value = as[var->getId()].getInterval().getIntNumeral();
1378 }
1379 else if (bits == 32)
1380 {
1381 s32_t signed_i32_value = as[var->getId()].getInterval().getIntNumeral();
1384 }
1385 else if (bits == 64)
1386 {
1387 s64_t signed_i64_value = as[var->getId()].getInterval().getIntNumeral();
1389 // we only support i64 at most
1390 }
1391 else
1392 {
1393 assert(false && "cannot support int type other than u8/16/32/64");
1394 }
1395 }
1396 else
1397 {
1398 return IntervalValue::top(); // TODO: may have better solution
1399 }
1400 }
1401 return IntervalValue::top(); // TODO: may have better solution
1402 };
1403
1404 auto getTruncValue = [&](const AbstractState& as, const SVF::SVFVar* var,
1405 const SVFType* dstType)
1406 {
1407 const IntervalValue& itv = as[var->getId()].getInterval();
1408 if(itv.isBottom()) return itv;
1409 // get the value of ub and lb
1411 s64_t int_ub = itv.ub().getIntNumeral();
1412 // get dst type
1413 u32_t dst_bits = dstType->getByteSize() * 8;
1414 if (dst_bits == 8)
1415 {
1416 // get the signed value of ub and lb
1417 int8_t s8_lb = static_cast<int8_t>(int_lb);
1418 int8_t s8_ub = static_cast<int8_t>(int_ub);
1419 if (s8_lb > s8_ub)
1420 {
1421 // return range of s8
1423 }
1424 return IntervalValue(s8_lb, s8_ub);
1425 }
1426 else if (dst_bits == 16)
1427 {
1428 // get the signed value of ub and lb
1429 s16_t s16_lb = static_cast<s16_t>(int_lb);
1430 s16_t s16_ub = static_cast<s16_t>(int_ub);
1431 if (s16_lb > s16_ub)
1432 {
1433 // return range of s16
1435 }
1436 return IntervalValue(s16_lb, s16_ub);
1437 }
1438 else if (dst_bits == 32)
1439 {
1440 // get the signed value of ub and lb
1441 s32_t s32_lb = static_cast<s32_t>(int_lb);
1442 s32_t s32_ub = static_cast<s32_t>(int_ub);
1443 if (s32_lb > s32_ub)
1444 {
1445 // return range of s32
1447 }
1448 return IntervalValue(s32_lb, s32_ub);
1449 }
1450 else
1451 {
1452 assert(false && "cannot support dst int type other than u8/16/32");
1453 }
1454 };
1455
1456 AbstractState& as = getAbsStateFromTrace(copy->getICFGNode());
1457 u32_t lhs = copy->getLHSVarID();
1458 u32_t rhs = copy->getRHSVarID();
1459
1460 if (copy->getCopyKind() == CopyStmt::COPYVAL)
1461 {
1462 as[lhs] = as[rhs];
1463 }
1464 else if (copy->getCopyKind() == CopyStmt::ZEXT)
1465 {
1466 as[lhs] = getZExtValue(as, copy->getRHSVar());
1467 }
1468 else if (copy->getCopyKind() == CopyStmt::SEXT)
1469 {
1470 as[lhs] = as[rhs].getInterval();
1471 }
1472 else if (copy->getCopyKind() == CopyStmt::FPTOSI)
1473 {
1474 as[lhs] = as[rhs].getInterval();
1475 }
1476 else if (copy->getCopyKind() == CopyStmt::FPTOUI)
1477 {
1478 as[lhs] = as[rhs].getInterval();
1479 }
1480 else if (copy->getCopyKind() == CopyStmt::SITOFP)
1481 {
1482 as[lhs] = as[rhs].getInterval();
1483 }
1484 else if (copy->getCopyKind() == CopyStmt::UITOFP)
1485 {
1486 as[lhs] = as[rhs].getInterval();
1487 }
1488 else if (copy->getCopyKind() == CopyStmt::TRUNC)
1489 {
1490 as[lhs] = getTruncValue(as, copy->getRHSVar(), copy->getLHSVar()->getType());
1491 }
1492 else if (copy->getCopyKind() == CopyStmt::FPTRUNC)
1493 {
1494 as[lhs] = as[rhs].getInterval();
1495 }
1496 else if (copy->getCopyKind() == CopyStmt::INTTOPTR)
1497 {
1498 //insert nullptr
1499 }
1500 else if (copy->getCopyKind() == CopyStmt::PTRTOINT)
1501 {
1503 }
1504 else if (copy->getCopyKind() == CopyStmt::BITCAST)
1505 {
1506 if (as[rhs].isAddr())
1507 {
1508 as[lhs] = as[rhs];
1509 }
1510 else
1511 {
1512 // do nothing
1513 }
1514 }
1515 else
1516 {
1517 assert(false && "undefined copy kind");
1518 abort();
1519 }
1520}
1521
1522
1523
#define TIMEINTERVAL
Definition SVFType.h:512
newitem type
Definition cJSON.cpp:2739
copy
Definition cJSON.cpp:414
const char *const name
Definition cJSON.h:264
void performStat() override
std::string getMemUsage()
AbstractInterpretation * _ae
Handles external API calls and manages abstract states.
Definition AbsExtAPI.h:46
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)
virtual bool isRecursiveCall(const CallICFGNode *callNode)
virtual void recursiveCallPass(const CallICFGNode *callNode)
void updateStateOnStore(const StoreStmt *store)
virtual bool isDirectCall(const CallICFGNode *callNode)
bool hasAbsStateFromTrace(const ICFGNode *node)
virtual void handleCycleWTO(const ICFGCycleWTO *cycle)
handle wto cycle (loop)
Map< const CallGraphNode *, ICFGWTO * > funcToWTO
void updateStateOnGep(const GepStmt *gep)
virtual void extCallPass(const CallICFGNode *callNode)
virtual void handleGlobalNode()
Global ICFGNode is handled at the entry of the program,.
bool mergeStatesFromPredecessors(const ICFGNode *icfgNode)
virtual void directCallFunPass(const CallICFGNode *callNode)
void handleWTOComponent(const ICFGWTOComp *wtoComp)
virtual bool isExtCall(const CallICFGNode *callNode)
virtual bool isIndirectCall(const CallICFGNode *callNode)
void initWTO()
Mark recursive functions in the call graph.
void updateStateOnPhi(const PhiStmt *phi)
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
std::vector< std::unique_ptr< AEDetector > > detectors
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Set< const CallGraphNode * > recursiveFuns
Set< const CallICFGNode * > checkpoints
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
void updateStateOnSelect(const SelectStmt *select)
virtual void handleSVFStatement(const SVFStmt *stmt)
virtual void indirectCallFunPass(const CallICFGNode *callNode)
SVFIR * svfir
protected data members, also used in subclasses
virtual void runOnModule(ICFG *icfg)
void updateStateOnAddr(const AddrStmt *addr)
virtual ~AbstractInterpretation()
Destructor.
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
virtual void handleCallSite(const ICFGNode *node)
void updateStateOnRet(const RetPE *retPE)
void handleWTOComponents(const std::list< const ICFGWTOComp * > &wtoComps)
Hanlde two types of WTO components (singleton and cycle)
void updateStateOnCopy(const CopyStmt *copy)
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
Map< s32_t, s32_t > _switch_lhsrhs_predicate
void updateStateOnCmp(const CmpStmt *cmp)
virtual void SkipRecursiveCall(const CallICFGNode *callnode)
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.
AbstractState narrowing(const AbstractState &other)
domain narrow with other, and return the narrowed domain
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
AbstractState widening(const AbstractState &other)
domain widen with other, and return the widened domain
AddressValue & getAddrs()
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
AddrSet::const_iterator begin() const
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition Andersen.h:408
NodeID getRHSVarID() const
NodeID getLHSVarID() const
s64_t getIntNumeral() const
const CallGraphNode * getCallGraphNode(const std::string &name)
@ 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
iterator begin()
Iterators.
u32_t nodeNum
total num of edge
NodeType * getGNode(NodeID id) const
Get a node.
const GEdgeSetTy & getInEdges() const
virtual const std::string toString() const
Definition ICFG.cpp:61
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:117
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition ICFG.cpp:234
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition ICFG.cpp:303
const std::vector< const ICFGNode * > & getSubNodes(const ICFGNode *node) const
Definition ICFG.h:241
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:236
NodeID getBlkPtr() const
Definition IRGraph.h:169
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 Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:38
static const Option< u32_t > WidenDelay
Definition Options.h:246
static const Option< bool > PStat
Definition Options.h:119
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition Options.h:252
SCCDetection< PTACallGraph * > CallGraphSCC
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
const_iterator end() const
Definition SVFValue.h:451
CallGraph * getCallGraph()
Definition SVFIR.h:193
ICFG * getICFG() const
Definition SVFIR.h:172
const CallSiteToFunPtrMap & getIndirectCallsites() const
Add/get indirect callsites.
Definition SVFIR.h:351
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116
NUMStatMap generalNumMap
Definition SVFStat.h:76
virtual void endClk()
Definition SVFStat.h:63
std::string moduleName
Definition SVFStat.h:99
TIMEStatMap timeStatMap
Definition SVFStat.h:78
virtual void startClk()
Definition SVFStat.h:58
double endTime
Definition SVFStat.h:81
double startTime
Definition SVFStat.h:80
ICFGNode * getICFGNode() const
u32_t getByteSize() const
Definition SVFType.h:244
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:77
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
s64_t APOffset
Definition GeneralType.h:60
signed short s16_t
Definition GeneralType.h:53
unsigned short u16_t
Definition GeneralType.h:52
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
signed s32_t
Definition GeneralType.h:47
unsigned u32_t
Definition GeneralType.h:46
signed long long s64_t
Definition GeneralType.h:49