Static Value-Flow Analysis
Loading...
Searching...
No Matches
Andersen.cpp
Go to the documentation of this file.
1//===- Andersen.cpp -- Field-sensitive Andersen's analysis-------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <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 * Andersen.cpp
25 *
26 * Created on: Nov 12, 2013
27 * Author: Yulei Sui
28 */
29
32#include "WPA/Andersen.h"
33#include "WPA/Steensgaard.h"
34#include "WPA/WPAStat.h"
35#include "Util/CoreBitVector.h"
36#include "Util/GeneralType.h"
37#include "Util/Options.h"
38#include "Util/SVFUtil.h"
39
40#include <utility>
41
42#include <algorithm>
43#include <cstdint>
44#include <vector>
45
46using namespace SVF;
47using namespace SVFUtil;
48using namespace std;
49
50
58
63
69
74{
75 delete consCG;
76 consCG = nullptr;
77}
78
83{
87 stat = new AndersenStat(this);
92 consCG->dump("consCG_initial");
93}
94
99{
102 consCG->dump("consCG_final");
103
105 consCG->print();
107}
108
110{
111 // Start solving constraints
112 DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Start Solving Constraints\n"));
113
115 if (timeLimited)
116 {
117 assert(Options::FsTimeLimit() == 0 && "both -ander-time-limit and -fs-time-limit set.");
119 }
120
121 initWorklist();
122 do
123 {
126 printStat();
127
128 reanalyze = false;
129
131
133 reanalyze = true;
134
135 }
136 while (reanalyze);
137
138 // Analysis is finished, reset the alarm if we set it.
139 if (timeLimited)
140 {
142 }
143
144 DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Finish Solving Constraints\n"));
145}
146
151{
152 if(!Options::ReadAnder().empty())
153 {
155 }
156 else
157 {
158 if(Options::WriteAnder().empty())
159 {
160 initialize();
162 finalize();
163 }
164 else
165 {
167 }
168 }
169}
170
175{
176 initialize();
177 if (!filename.empty())
178 this->readFromFile(filename);
179 finalize();
180}
181
186{
188 initialize();
189 if (!filename.empty())
190 this->writeObjVarToFile(filename);
192 if (!filename.empty())
193 this->writeToFile(filename);
194 finalize();
195}
196
198{
199 // Remove only this node from its representative's members. Erasing the whole
200 // member set would leave every other member mapped to a representative that no
201 // longer lists it, so sccSubNodes would stop being the inverse of sccRepNode.
203 for (NodeID sub: consCG->getSubs(id))
205 consCG->resetSubs(id);
206 consCG->resetRep(id);
207 assert(!consCG->hasGNode(id) && "this is either a rep nodeid or a sub nodeid should have already been merged to its field-insensitive base! ");
208}
209
211{
212
213 double cgUpdateStart = stat->getClk();
214
218 for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
219 it != eit; ++it)
220 {
221 for (FunctionSet::iterator cit = it->second.begin(),
222 ecit = it->second.end();
223 cit != ecit; ++cit)
224 {
226 }
227 }
228
230
231 for (NodePairSet::iterator it = cpySrcNodes.begin(),
232 eit = cpySrcNodes.end();
233 it != eit; ++it)
234 {
235 pushIntoWorklist(it->first);
236 }
237
238 double cgUpdateEnd = stat->getClk();
240
241 return ((!newEdges.empty()) || hasNewForkEdges);
242}
243
246{
249 for (CallEdgeMap::iterator it = newForkEdges.begin(), eit = newForkEdges.end(); it != eit; it++)
250 {
251 for (FunctionSet::iterator cit = it->second.begin(),
252 ecit = it->second.end();
253 cit != ecit; ++cit)
254 {
256 }
257 }
258 return !newForkEdges.empty();
259}
260
266{
267 assert(F);
268
269 DBOUT(DAndersen, outs() << "connect parameters from indirect forksite "
270 << cs->valueOnlyToString() << " to forked function "
271 << *F << "\n");
272
273 ThreadCallGraph *tdCallGraph = SVFUtil::dyn_cast<ThreadCallGraph>(callgraph);
274
275 const PAGNode *cs_arg = tdCallGraph->getThreadAPI()->getActualParmAtForkSite(cs);
276 const PAGNode *fun_arg = tdCallGraph->getThreadAPI()->getFormalParmOfForkedFun(F);
277
278 if(cs_arg->isPointer() && fun_arg->isPointer())
279 {
280 DBOUT(DAndersen, outs() << "process actual parm"
281 << cs_arg->toString() << "\n");
282 NodeID srcAA = sccRepNode(cs_arg->getId());
283 NodeID dstFA = sccRepNode(fun_arg->getId());
284 if (addCopyEdge(srcAA, dstFA))
285 {
286 cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
287 }
288 }
289}
290
292// * Connect formal and actual parameters for indirect callsites
293// */
296{
297 assert(F);
298
299 DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs->valueOnlyToString() << " to callee " << *F << "\n");
300
301 const CallICFGNode* callBlockNode = cs;
303
305 {
307 }
308
310 {
312 const PAGNode* fun_return = pag->getFunRet(F);
313 if (cs_return->isPointer() && fun_return->isPointer())
314 {
315 NodeID dstrec = sccRepNode(cs_return->getId());
318 {
319 cpySrcNodes.insert(std::make_pair(srcret,dstrec));
320 }
321 }
322 else
323 {
324 DBOUT(DAndersen, outs() << "not a pointer ignored\n");
325 }
326 }
327
328 if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
329 {
330
331 // connect actual and formal param
332 const SVFIR::ValVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
334 //Go through the fixed parameters.
335 DBOUT(DPAGBuild, outs() << " args:");
336 SVFIR::ValVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
337 SVFIR::ValVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
338 for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
339 {
340 //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
341 if (csArgIt == csArgEit)
342 {
343 DBOUT(DAndersen, outs() << " !! not enough args\n");
344 break;
345 }
346 const PAGNode *cs_arg = *csArgIt ;
347 const PAGNode *fun_arg = *funArgIt;
348
349 if (cs_arg->isPointer() && fun_arg->isPointer())
350 {
351 DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
352 NodeID srcAA = sccRepNode(cs_arg->getId());
353 NodeID dstFA = sccRepNode(fun_arg->getId());
355 {
356 cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
357 }
358 }
359 }
360
361 //Any remaining actual args must be varargs.
362 if (F->isVarArg())
363 {
365 DBOUT(DPAGBuild, outs() << "\n varargs:");
366 for (; csArgIt != csArgEit; ++csArgIt)
367 {
368 const PAGNode *cs_arg = *csArgIt;
369 if (cs_arg->isPointer())
370 {
371 NodeID vnAA = sccRepNode(cs_arg->getId());
372 if (addCopyEdge(vnAA,vaF))
373 {
374 cpySrcNodes.insert(std::make_pair(vnAA,vaF));
375 }
376 }
377 }
378 }
379 if(csArgIt != csArgEit)
380 {
381 writeWrnMsg("too many args to non-vararg func.");
382 writeWrnMsg("(" + cs->getSourceLoc() + ")");
383 }
384 }
385}
386
388{
389 assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
393 CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
394 if(it != callsite2DummyValPN.end())
395 {
396 srcret = sccRepNode(it->second);
397 }
398 else
399 {
403 callsite2DummyValPN.insert(std::make_pair(cs,valNode));
406 srcret = valNode;
407 }
408
409 NodeID dstrec = sccRepNode(cs_return->getId());
411 cpySrcNodes.insert(std::make_pair(srcret,dstrec));
412}
413
415{
418
419 // clear GepObjVarMap/memToFieldsMap/nodeToSubsMap/nodeToRepMap
420 // for redundant gepnodes and remove those nodes from pag
422 {
423 NodeID base = pag->getBaseObjVarID(n);
425 assert(gepNode && "Not a gep node in redundantGepNodes set");
426 const APOffset apOffset = gepNode->getConstantFieldIdx();
427 GepObjVarMap.erase(std::make_pair(base, apOffset));
428 memToFieldsMap[base].reset(n);
429 cleanConsCG(n);
430
431 pag->removeGNode(const_cast<GepObjVar*>(gepNode));
432 }
433}
434
439{
440 resetData();
442
444
447}
448
453{
454 // TODO: broken
456 {
458 const PTDataTy *ptd = getPTDataTy();
459 // TODO: should we use liveOnly?
460 // TODO: parameterise final arg.
462 if (print_stat)
463 {
465 }
466 }
467
470 // sanitizePts();
472}
473
478{
479 // sub nodes do not need to be processed
480 if (sccRepNode(nodeId) != nodeId)
481 return;
482
484 double insertStart = stat->getClk();
485 handleLoadStore(node);
486 double insertEnd = stat->getClk();
488
489 double propStart = stat->getClk();
490 handleCopyGep(node);
491 double propEnd = stat->getClk();
493}
494
499{
500 NodeID nodeId = node->getId();
502
503 if (!getDiffPts(nodeId).empty())
504 {
505 for (ConstraintEdge* edge : node->getCopyOutEdges())
507 for (ConstraintEdge* edge : node->getGepOutEdges())
508 {
509 if (GepCGEdge* gepEdge = SVFUtil::dyn_cast<GepCGEdge>(edge))
511 }
512 }
513}
514
519{
520 NodeID nodeId = node->getId();
521 for (PointsTo::iterator piter = getPts(nodeId).begin(), epiter =
522 getPts(nodeId).end(); piter != epiter; ++piter)
523 {
524 NodeID ptd = *piter;
525 // handle load
527 eit = node->outgoingLoadsEnd(); it != eit; ++it)
528 {
529 if (processLoad(ptd, *it))
531 }
532
533 // handle store
535 eit = node->incomingStoresEnd(); it != eit; ++it)
536 {
537 if (processStore(ptd, *it))
538 pushIntoWorklist((*it)->getSrcID());
539 }
540 }
541}
542
547{
549 {
550 ConstraintNode * cgNode = nodeIt->second;
552 it != eit; ++it)
553 processAddr(SVFUtil::cast<AddrCGEdge>(*it));
554 }
555}
556
561{
563
564 NodeID dst = addr->getDstID();
565 NodeID src = addr->getSrcID();
566 if(addPts(dst,src))
567 pushIntoWorklist(dst);
568}
569
576{
580// if (pag->isBlkObjOrConstantObj(node))
581 if (pag->isConstantObj(node) || pag->getSVFVar(load->getDstID())->isPointer() == false)
582 return false;
583
585
586 NodeID dst = load->getDstID();
587 return addCopyEdge(node, dst);
588}
589
596{
600// if (pag->isBlkObjOrConstantObj(node))
601 if (pag->isConstantObj(node) || pag->getSVFVar(store->getSrcID())->isPointer() == false)
602 return false;
603
605
606 NodeID src = store->getSrcID();
607 return addCopyEdge(src, node);
608}
609
616{
618
619 assert((SVFUtil::isa<CopyCGEdge>(edge)) && "not copy/call/ret ??");
620 NodeID dst = edge->getDstID();
621 const PointsTo& srcPts = getDiffPts(node);
622
623 bool changed = unionPts(dst, srcPts);
624 if (changed)
625 pushIntoWorklist(dst);
626 return changed;
627}
628
636{
637 const PointsTo& srcPts = getDiffPts(edge->getSrcID());
638 return processGepPts(srcPts, edge);
639}
640
645{
647
649 if (SVFUtil::isa<VariantGepCGEdge>(edge))
650 {
651 // If a pointer is connected by a variant gep edge,
652 // then set this memory object to be field insensitive,
653 // unless the object is a black hole/constant.
654 for (NodeID o : pts)
655 {
657 {
658 tmpDstPts.set(o);
659 continue;
660 }
661
662 if (!isFieldInsensitive(o))
663 {
666 }
667
668 // Add the field-insensitive node into pts.
670 tmpDstPts.set(baseId);
671 }
672 }
673 else if (const NormalGepCGEdge* normalGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge))
674 {
675 // TODO: after the node is set to field insensitive, handling invariant
676 // gep edge may lose precision because offsets here are ignored, and the
677 // base object is always returned.
678 for (NodeID o : pts)
679 {
681 {
682 tmpDstPts.set(o);
683 continue;
684 }
685
686 NodeID fieldSrcPtdNode = consCG->getGepObjVar(o, normalGepEdge->getAccessPath().getConstantStructFldIdx());
688 }
689 }
690 else
691 {
692 assert(false && "Andersen::processGepPts: New type GEP edge type?");
693 }
694
695 NodeID dstId = edge->getDstID();
697 {
699 return true;
700 }
701
702 return false;
703}
704
709{
710 // If a node is a PWC node, collapse all its points-to target.
711 // collapseNodePts() may change the points-to set of the nodes which have been processed
712 // before, in this case, we may need to re-do the analysis.
714 reanalyze = true;
715}
716
718{
720 {
722 // collapseField() may change the points-to set of the nodes which have been processed
723 // before, in this case, we may need to re-do the analysis.
724 if (collapseField(node))
725 reanalyze = true;
726 }
727}
728
729/*
730 * Merge constraint graph nodes based on SCC cycle detected.
731 */
733{
734 NodeStack topoOrder = getSCCDetector()->topoNodeStack();
735
736 while (!topoOrder.empty())
737 {
738 NodeID repNodeId = topoOrder.top();
739 topoOrder.pop();
740 const NodeBS& subNodes = getSCCDetector()->subNodes(repNodeId);
741 // merge sub nodes to rep node
742 mergeSccNodes(repNodeId, subNodes);
743 if (subNodes.count() > 1)
744 {
746 reanalyze = true;
747 }
748 }
749}
750
751
757{
758 for (NodeBS::iterator nodeIt = subNodes.begin(); nodeIt != subNodes.end(); nodeIt++)
759 {
761 if (subNodeId != repNodeId)
762 {
764 }
765 }
766}
767
772{
773 bool changed = false;
774 const PointsTo& nodePts = getPts(nodeId);
777 for (PointsTo::iterator ptsIt = ptsClone.begin(), ptsEit = ptsClone.end(); ptsIt != ptsEit; ptsIt++)
778 {
780 continue;
781
782 if (collapseField(*ptsIt))
783 changed = true;
784 }
785 return changed;
786}
787
792{
798 return false;
799
800 bool changed = false;
801
802 double start = stat->getClk();
803
804 // set base node field-insensitive.
806
807 // replace all occurrences of each field with the field-insensitive node
812 {
814 if (fieldId != baseId)
815 {
816 // use the reverse pts of this field node to find all pointers point to it
818 for (const NodeID o : revPts)
819 {
820 // change the points-to target from field to base node
822 addPts(o, baseId);
824
825 changed = true;
826 }
827 // merge field node into base node, including edges and pts.
830 if (fieldId != baseRepNodeId)
831 {
832 // gep node fieldId becomes redundant if it is merged to its base node who is set as field-insensitive
833 // two node IDs should be different otherwise this field is actually the base and should not be removed.
835 }
836 }
837 }
838
841 changed = true;
842
843 double end = stat->getClk();
844 timeOfCollapse += (end - start) / TIMEINTERVAL;
845
846 return changed;
847}
848
853{
855
856 double sccStart = stat->getClk();
858 double sccEnd = stat->getClk();
859
861
862 double mergeStart = stat->getClk();
863
865
866 double mergeEnd = stat->getClk();
867
869
870 return getSCCDetector()->topoNodeStack();
871}
872
877{
878
879 if(nodeId==newRepId)
880 return false;
881
885
889
894 if(node->isPWCNode())
895 pwc = true;
896
899
901
902 return pwc;
903}
904/*
905 * Merge a node to its rep node based on SCC detection
906 */
913
914/*
915 * Updates subnodes of its rep, and rep node of its subs
916 */
918{
923 // update nodeToSubsMap, union its subs with its rep Subs
925 for(NodeBS::iterator sit = nodeSubs.begin(), esit = nodeSubs.end(); sit!=esit; ++sit)
926 {
927 NodeID subId = *sit;
929 }
930 repSubs |= nodeSubs;
933}
934
939{
940 // Reuse this expansion for the index lookup and, when necessary, every
941 // comparison in the exhaustive fallback.
945 return std::move(*aliases);
946
949 for (SVFIR::iterator it = pag->begin(), eit = pag->end(); it != eit; ++it)
950 {
951 const NodeID candidate = it->first;
953 {
954 aliases.set(candidate);
955 continue;
956 }
957
961 expandedPts.intersects(candidatePts))
962 aliases.set(candidate);
963 }
964 return aliases;
965}
966
981{
982 if (!getPTDataTy()->hasReversePts() || containBlackHoleNode(expandedPts))
983 return std::nullopt;
984
987 for (NodeID object : expandedPts)
988 {
989 objects.set(object);
990 const NodeID base = pag->getBaseObjVarID(object);
991 objects.set(base);
992 if (isFieldInsensitive(base))
994 }
996
997 const size_t wordCount = (static_cast<size_t>(nodeBound) +
1000 for (NodeID object : objects)
1001 {
1002 for (NodeID key : getRevPts(object))
1003 {
1004 const NodeID representative = sccRepNode(key);
1005 // Reverse points-to sets can retain stale postings. Confirm the
1006 // posting with one current-set bit test before treating it as an
1007 // alias witness, unless an earlier object already confirmed it.
1008 if (!representatives.test(representative) &&
1009 getPts(representative).test(object))
1010 representatives.set(representative);
1011 }
1012 }
1013
1014 // SCC subnode sets are individually ordered, but their concatenation is
1015 // not globally ordered. Collect them densely before inserting into the
1016 // sparse result, where backward insertions would be costly.
1018 for (NodeID representative : representatives)
1019 {
1020 for (NodeID subNode : sccSubNodes(representative))
1021 answer.set(subNode);
1022 }
1023
1024 // normalizePointsTo can remove field nodes while their ids remain in
1025 // points-to sets. Do not return those stale nodes.
1027 for (NodeID id : answer)
1028 {
1029 if (pag->hasGNode(id))
1030 aliases.set(id);
1031 }
1032 return aliases;
1033}
1034
1040{
1042
1043 PointerAnalysis* pta = this;
1044 const FunObjVar* checkFun = pag->getFunObjVar(fun);
1045 if (!checkFun)
1046 return;
1047 for (const CallICFGNode* callNode : pag->getCallSiteSet())
1048 {
1049 if (callNode->getCalledFunction() != checkFun)
1050 continue;
1051 for (u32_t i = 0; i < callNode->arg_size(); ++i)
1052 {
1053 NodeID ptr = callNode->getArgument(i)->getId();
1055 for (SVFIR::iterator it = pag->begin(), eit = pag->end(); it != eit; ++it)
1056 {
1057 if (mayAlias(ptr, it->first))
1058 expected.set(it->first);
1059 }
1060 if (pta->getMayAliases(ptr) == expected)
1061 outs() << sucMsg("\t SUCCESS :") << "getMayAliases check <id:" << ptr << "> at ("
1062 << callNode->getSourceLoc() << ")\n";
1063 else
1064 {
1065 SVFUtil::errs() << errMsg("\t FAILURE :") << "getMayAliases check <id:" << ptr
1066 << "> at (" << callNode->getSourceLoc() << ")\n";
1067 assert(false && "getMayAliases disagrees with mayAlias!");
1068 }
1069 }
1070 }
1071}
1072
1073void Andersen::cluster(void) const
1074{
1075 assert(Options::MaxFieldLimit() == 0 && "Andersen::cluster: clustering for Andersen's is currently only supported in field-insensitive analysis");
1077 std::vector<std::pair<unsigned, unsigned>> keys;
1078 for (SVFIR::iterator pit = pag->begin(); pit != pag->end(); ++pit)
1079 {
1080 keys.push_back(std::make_pair(pit->first, 1));
1081 }
1082
1083 std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> candidates;
1084 PointsTo::MappingPtr nodeMapping =
1085 std::make_shared<std::vector<NodeID>>(
1086 NodeIDAllocator::Clusterer::cluster(steens, keys, candidates, "aux-steens", print_stat)
1087 );
1088 PointsTo::MappingPtr reverseNodeMapping =
1089 std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::getReverseNodeMapping(*nodeMapping));
1090
1091 PointsTo::setCurrentBestNodeMapping(nodeMapping, reverseNodeMapping);
1092}
1093
1098{
1099 for (OrderedNodeSet::iterator nIter = this->getAllValidPtrs().begin();
1100 nIter != this->getAllValidPtrs().end(); ++nIter)
1101 {
1102 const SVFVar* node = getPAG()->getSVFVar(*nIter);
1103 if (getPAG()->isValidTopLevelPtr(node))
1104 {
1105 const PointsTo& pts = this->getPts(node->getId());
1106 outs() << "\nNodeID " << node->getId() << " ";
1107
1108 if (pts.empty())
1109 {
1110 outs() << "\t\tPointsTo: {empty}\n";
1111 }
1112 else
1113 {
1114 outs() << "\t\tPointsTo: { ";
1115
1117 for (PointsTo::iterator it = pts.begin(), eit = pts.end();
1118 it != eit; ++it)
1119 {
1120 line.insert(*it);
1121 }
1122 for (multiset<u32_t>::const_iterator it = line.begin(); it != line.end(); ++it)
1123 {
1125 if (auto gepNode = pag->getGepObjVar(*it))
1126 outs() << gepNode->getBaseNode() << "_" << gepNode->getConstantFieldIdx() << " ";
1127 else
1128 outs() << *it << " ";
1129 else
1130 outs() << *it << " ";
1131 }
1132 outs() << "}\n";
1133 }
1134 }
1135 }
1136
1137 outs().flush();
1138}
unsigned u32_t
Definition CommandLine.h:18
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define TIMEINTERVAL
Definition SVFType.h:604
#define DGENERAL
Definition SVFType.h:582
#define DPAGBuild
Definition SVFType.h:584
#define DAndersen
Definition SVFType.h:595
cJSON * n
Definition cJSON.cpp:2558
static double timeOfSCCMerges
Definition Andersen.h:169
static u32_t numOfProcessedCopy
Number of processed Addr edge.
Definition Andersen.h:160
NodeBS & sccSubNodes(NodeID repId)
Definition Andersen.h:135
static u32_t numOfSCCDetection
Definition Andersen.h:167
virtual void normalizePointsTo() override
static u32_t numOfSfrs
Number of processed Store edge.
Definition Andersen.h:164
virtual void finalize() override
Finalize analysis.
Definition Andersen.cpp:98
static double timeOfUpdateCallGraph
Definition Andersen.h:175
static u32_t numOfProcessedStore
Number of processed Load edge.
Definition Andersen.h:163
virtual void connectCaller2ForkedFunParams(const CallICFGNode *cs, const FunObjVar *F, NodePairSet &cpySrcNodes)
Connect formal and actual parameters for indirect forksites.
Definition Andersen.cpp:264
static u32_t numOfProcessedAddr
Statistics.
Definition Andersen.h:159
virtual bool updateCallGraph(const CallSiteToFunPtrMap &) override
Update call graph.
Definition Andersen.cpp:210
void printStat()
dump statistics
Definition Andersen.h:145
void heapAllocatorViaIndCall(const CallICFGNode *cs, NodePairSet &cpySrcNodes)
CallSite2DummyValPN callsite2DummyValPN
Definition Andersen.h:182
virtual void readPtsFromFile(const std::string &filename)
Definition Andersen.cpp:174
static u32_t numOfProcessedLoad
Number of processed Gep edge.
Definition Andersen.h:162
static double timeOfSCCDetection
Definition Andersen.h:168
NodeBS redundantGepNodes
Definition Andersen.h:155
virtual bool addCopyEdge(NodeID src, NodeID dst)=0
Add copy edge on constraint graph.
virtual void initialize() override
Initialize analysis.
Definition Andersen.cpp:82
~AndersenBase() override
Destructor.
Definition Andersen.cpp:73
virtual void analyze() override
Andersen analysis.
Definition Andersen.cpp:150
static u32_t numOfFieldExpand
Definition Andersen.h:165
static double timeOfProcessLoadStore
Definition Andersen.h:174
static u32_t numOfProcessedGep
Number of processed Copy edge.
Definition Andersen.h:161
static double timeOfProcessCopyGep
Definition Andersen.h:173
static u32_t MaxPointsToSetSize
Definition Andersen.h:172
virtual void solveConstraints()
Definition Andersen.cpp:109
virtual bool updateThreadCallGraph(const CallSiteToFunPtrMap &, NodePairSet &)
Update thread call graph.
Definition Andersen.cpp:244
virtual void connectCaller2CalleeParams(const CallICFGNode *cs, const FunObjVar *F, NodePairSet &cpySrcNodes)
Connect formal and actual parameters for indirect callsites.
static double timeOfCollapse
Definition Andersen.h:170
static u32_t AveragePointsToSetSize
Definition Andersen.h:171
virtual void solveAndwritePtsToFile(const std::string &filename)
Definition Andersen.cpp:185
ConstraintGraph * consCG
Constraint Graph.
Definition Andersen.h:180
void cleanConsCG(NodeID id)
remove redundant gepnodes in constraint graph
Definition Andersen.cpp:197
NodeID sccRepNode(NodeID id) const override
SCC methods.
Definition Andersen.h:131
virtual void handleLoadStore(ConstraintNode *node)
Definition Andersen.cpp:518
virtual NodeBS getMayAliases(NodeID node)
Collect exactly the SVFIR nodes q for which mayAlias(node, q) holds.
Definition Andersen.cpp:938
void mergeSccNodes(NodeID repNodeId, const NodeBS &subNodes)
Merge sub node in a SCC cycle to their rep node.
Definition Andersen.cpp:756
virtual void processNode(NodeID nodeId)
Override WPASolver function in order to use the default solver.
Definition Andersen.cpp:477
virtual void initialize()
Initialize analysis.
Definition Andersen.cpp:438
virtual NodeStack & SCCDetect()
SCC detection.
Definition Andersen.cpp:852
virtual void mergeNodeToRep(NodeID nodeId, NodeID newRepId)
Merge sub node to its rep.
Definition Andersen.cpp:907
bool collapseNodePts(NodeID nodeId)
Definition Andersen.cpp:771
void dumpTopLevelPtsTo()
void updatePropaPts(NodeID dstId, NodeID srcId)
Handle propagated points-to set.
Definition Andersen.h:291
std::optional< NodeBS > collectMayAliasesFromIndex(const PointsTo &expandedPts)
Definition Andersen.cpp:980
virtual void computeDiffPts(NodeID id)
Handle diff points-to set.
Definition Andersen.h:273
virtual bool addCopyEdge(NodeID src, NodeID dst)
Add copy edge on constraint graph.
Definition Andersen.h:328
void resetData()
Reset data.
Definition Andersen.h:217
virtual const PointsTo & getDiffPts(NodeID id)
Definition Andersen.h:281
virtual bool processGep(NodeID node, const GepCGEdge *edge)
Definition Andersen.cpp:635
virtual void handleCopyGep(ConstraintNode *node)
Definition Andersen.cpp:498
virtual bool unionPts(NodeID id, const PointsTo &target)
Definition Andersen.h:245
virtual bool processLoad(NodeID node, const ConstraintEdge *load)
Definition Andersen.cpp:575
virtual const PointsTo & getPts(NodeID id)
Operation of points-to set.
Definition Andersen.h:241
void collapseFields()
collapse positive weight cycles of a graph
Definition Andersen.cpp:717
virtual bool processStore(NodeID node, const ConstraintEdge *load)
Definition Andersen.cpp:595
virtual bool processCopy(NodeID node, const ConstraintEdge *edge)
Definition Andersen.cpp:615
virtual bool processGepPts(const PointsTo &pts, const GepCGEdge *edge)
Definition Andersen.cpp:644
void mergeSccCycle()
Definition Andersen.cpp:732
virtual void processAddr(const AddrCGEdge *addr)
Definition Andersen.cpp:560
void updateNodeRepAndSubs(NodeID nodeId, NodeID newRepId)
Updates subnodes of its rep, and rep node of its subs.
Definition Andersen.cpp:917
virtual void finalize()
Finalize analysis.
Definition Andersen.cpp:452
void processAllAddr()
handling various constraints
Definition Andersen.cpp:546
virtual void cluster(void) const
virtual bool mergeSrcToTgt(NodeID srcId, NodeID tgtId)
Definition Andersen.cpp:876
virtual void collapsePWCNode(NodeID nodeId)
Collapse a field object into its base for field insensitive analysis.
Definition Andersen.cpp:708
virtual void validateSuccessTests(std::string fun)
Also check getMayAliases on the pointers that the alias tests use.
bool collapseField(NodeID nodeId)
Definition Andersen.cpp:791
virtual void writeToFile(const std::string &filename)
Interface for analysis result storage on filesystem.
virtual bool readFromFile(const std::string &filename)
virtual void writeObjVarToFile(const std::string &filename)
const NodeSet & getRevPts(NodeID nodeId) override
virtual void clearPts(NodeID id, NodeID element)
Remove element from the points-to set of id.
void finalize() override
Finalization of pointer analysis, and normalize points-to information to Bit Vector representation.
bool mayAlias(const PointsTo &pts1, const PointsTo &pts2)
Convenience bool wrappers: return true if the two operands may/must/partial alias.
virtual void expandFIObjs(const PointsTo &pts, PointsTo &expandedPts)
Expand FI objects.
virtual void onTheFlyThreadCallGraphSolve(const CallSiteToFunPtrMap &callsites, CallEdgeMap &newForkEdges)
On the fly thread call graph construction respecting forksite.
virtual void onTheFlyCallGraphSolve(const CallSiteToFunPtrMap &callsites, CallEdgeMap &newEdges)
On the fly call graph construction.
PTData< NodeID, NodeSet, NodeID, PointsTo > PTDataTy
PTDataTy * getPTDataTy() const
Get points-to data structure.
virtual bool addPts(NodeID id, NodeID ptd)
NodeID getId() const
Get the memory object id.
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:501
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:440
const std::string getSourceLoc() const override
Definition ICFGNode.h:571
NodeID getNextCollapseNode()
Definition ConsG.h:365
void setPWCNode(NodeID nodeId)
Definition ConsG.h:349
void setSubs(NodeID node, NodeBS &subs)
Definition ConsG.h:247
void addNodeToBeCollapsed(NodeID id)
Definition ConsG.h:361
NodeID getBaseObjVarID(NodeID id)
Definition ConsG.h:315
NodeID sccRepNode(NodeID id) const
SCC rep/sub nodes methods.
Definition ConsG.h:230
void addConstraintNode(ConstraintNode *node, NodeID id)
Definition ConsG.h:109
void resetSubs(NodeID node)
Definition ConsG.h:251
NodeID getGepObjVar(NodeID id, const APOffset &apOffset)
Get a field of a memory object.
Definition ConsG.h:325
NodeID getFIObjVar(NodeID id)
Get a field-insensitive node of a memory object.
Definition ConsG.h:334
NodeBS & getSubs(NodeID node)
Definition ConsG.h:255
bool isPWCNode(NodeID nodeId)
Check/Set PWC (positive weight cycle) flag.
Definition ConsG.h:345
bool isBlkObjOrConstantObj(NodeID id)
Definition ConsG.h:307
void removeConstraintNode(ConstraintNode *node)
Definition ConsG.h:118
void resetRep(NodeID node)
Definition ConsG.h:263
ConstraintNode * getConstraintNode(NodeID id) const
Get/add/remove constraint node.
Definition ConsG.h:104
bool hasNodesToBeCollapsed() const
Add/get nodes to be collapsed.
Definition ConsG.h:357
void print()
Print CG into terminal.
Definition ConsG.cpp:603
bool moveEdgesToRepNode(ConstraintNode *node, ConstraintNode *rep)
Definition ConsG.h:281
NodeBS & sccSubNodes(NodeID id)
Definition ConsG.h:238
void setRep(NodeID node, NodeID rep)
Definition ConsG.h:243
NodeBS & getAllFieldsObjVars(NodeID id)
Definition ConsG.h:311
void dump(std::string name)
Dump graph into dot file.
Definition ConsG.cpp:595
bool isPWCNode() const
Whether a node involves in PWC, if so, all its points-to elements should become field-insensitive.
Definition ConsGNode.h:81
const_iterator outgoingLoadsEnd() const
Definition ConsGNode.h:194
const_iterator incomingAddrsBegin() const
Definition ConsGNode.h:181
const ConstraintEdge::ConstraintEdgeSetTy & getGepOutEdges() const
Definition ConsGNode.h:123
const_iterator incomingStoresBegin() const
Definition ConsGNode.h:215
const_iterator incomingStoresEnd() const
Definition ConsGNode.h:219
ConstraintEdge::ConstraintEdgeSetTy::const_iterator const_iterator
Definition ConsGNode.h:45
const ConstraintEdge::ConstraintEdgeSetTy & getCopyOutEdges() const
Definition ConsGNode.h:115
const_iterator incomingAddrsEnd() const
Definition ConsGNode.h:185
const_iterator outgoingLoadsBegin() const
Definition ConsGNode.h:190
static const size_t WordSize
bool isVarArg() const
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
iterator begin()
Iterators.
void removeGNode(NodeType *node)
Delete a node.
bool hasGNode(NodeID id) const
Has a node.
u32_t getTotalNodeNum() const
Get total number of node/edge.
IDToNodeMapTy::iterator iterator
Node Iterators.
NodeID getBlackHoleNode() const
Definition IRGraph.h:246
NodeID getVarargNode(const FunObjVar *func) const
getVarargNode - Return the unique node representing the variadic argument of a variadic function.
Definition IRGraph.cpp:71
static std::vector< NodeID > getReverseNodeMapping(const std::vector< NodeID > &nodeMapping)
static std::vector< NodeID > cluster(BVDataPTAImpl *pta, const std::vector< std::pair< NodeID, unsigned > > keys, std::vector< std::pair< hclust_fast_methods, std::vector< NodeID > > > &candidates, std::string evalSubtitle="", bool printStat=true)
static void printStats(std::string title, Map< std::string, std::string > &stats)
static void evaluate(const std::vector< NodeID > &nodeMap, const Map< PointsTo, unsigned > pointsToSets, Map< std::string, std::string > &stats, bool accountForOcc)
Fills in *NumWords statistics in stats..
static const Option< u32_t > AnderTimeLimit
Time limit for the Andersen's analyses.
Definition Options.h:71
static const Option< bool > PrintFieldWithBasePrefix
Definition Options.h:114
static const Option< std::string > ReadAnder
Definition Options.h:204
static const Option< bool > ClusterAnder
Whether to stage Andersen's with Steensgaard and cluster based on that data.
Definition Options.h:37
static const Option< u32_t > FsTimeLimit
Time limit for the main phase (i.e., the actual solving) of FS analyses.
Definition Options.h:68
static const Option< bool > PrintCGGraph
Definition Options.h:200
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34
static const Option< std::string > WriteAnder
Definition Options.h:202
static const Option< bool > ConsCGDotGraph
Definition Options.h:198
virtual NodeBS getMayAliases(NodeID node)
bool isFieldInsensitive(NodeID id) const
bool print_stat
User input flags.
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
virtual void initialize()
Initialization of a pointer analysis, including building symbol table and SVFIR etc.
bool containBlackHoleNode(const PointsTo &pts)
Determine whether a points-to contains a black hole or constant node.
PTAStat * stat
Statistics.
SVFIR * getPAG() const
OrderedNodeSet & getAllValidPtrs()
Get all Valid Pointers for resolution.
virtual void validateSuccessTests(std::string fun)
const CallSiteToFunPtrMap & getIndirectCallsites() const
Return all indirect callsites.
CallGraph * callgraph
Call graph used for pointer analysis.
void setObjFieldInsensitive(NodeID id)
SVFIR::CallSiteToFunPtrMap CallSiteToFunPtrMap
static SVFIR * pag
SVFIR.
std::shared_ptr< std::vector< NodeID > > MappingPtr
Definition PointsTo.h:43
static void setCurrentBestNodeMapping(MappingPtr newCurrentBestNodeMapping, MappingPtr newCurrentBestReverseNodeMapping)
Definition PointsTo.cpp:383
void set(u32_t n)
Inserts n in the set.
Definition PointsTo.cpp:169
static MappingPtr getCurrentBestNodeMapping()
Definition PointsTo.cpp:373
const CallSiteSet & getCallSiteSet() const
Get all callsites.
Definition SVFIR.h:351
bool funHasRet(const FunObjVar *func) const
Definition SVFIR.h:429
bool hasFunArgsList(const FunObjVar *func) const
Function has arguments list.
Definition SVFIR.h:368
NodeID getBaseObjVarID(NodeID id) const
Base and Offset methods for Value and Object node.
Definition SVFIR.h:554
const ValVar * getCallSiteRet(const RetICFGNode *cs) const
Get callsite return.
Definition SVFIR.h:407
const ValVarList & getFunArgsList(const FunObjVar *func) const
Get function arguments list.
Definition SVFIR.h:378
std::vector< const ValVar * > ValVarList
Definition SVFIR.h:60
bool isConstantObj(NodeID id) const
Definition SVFIR.h:542
const FunObjVar * getFunObjVar(const std::string &name)
Definition SVFIR.cpp:48
bool hasCallSiteArgsMap(const CallICFGNode *cs) const
Callsite has argument list.
Definition SVFIR.h:385
NodeBS & getAllFieldsObjVars(const BaseObjVar *obj)
Get all fields of an object.
Definition SVFIR.cpp:573
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:135
bool callsiteHasRet(const RetICFGNode *cs) const
Definition SVFIR.h:413
NodeID addDummyValNode()
Definition SVFIR.h:566
OffsetToGepVarMap & getGepObjNodeMap()
Return GepObjVarMap.
Definition SVFIR.h:203
Map< NodeID, NodeBS > MemObjToFieldsMap
Definition SVFIR.h:58
Map< GepOffset, NodeID > OffsetToGepVarMap
Definition SVFIR.h:72
const ValVar * getFunRet(const FunObjVar *func) const
Get function return list.
Definition SVFIR.h:423
const ValVarList & getCallSiteArgsList(const CallICFGNode *cs) const
Get callsite argument list.
Definition SVFIR.h:395
const GepObjVar * getGepObjVar(NodeID id) const
Definition SVFIR.h:169
NodeID addDummyObjNode(const SVFType *type)
Definition SVFIR.h:570
MemObjToFieldsMap & getMemToFieldsMap()
Return memToFieldsMap.
Definition SVFIR.h:198
static double getClk(bool mark=false)
Definition SVFStat.cpp:52
NodeID getId() const
Get ID.
Definition SVFValue.h:158
virtual const SVFType * getType() const
Definition SVFValue.h:169
const std::string valueOnlyToString() const
Definition LLVMUtil.cpp:751
virtual bool isPointer() const
Check if this variable represents a pointer.
void set(unsigned Idx)
unsigned count() const
iterator begin() const
void reset(unsigned Idx)
static Steensgaard * createSteensgaard(SVFIR *_pag)
Create an singleton instance.
Definition Steensgaard.h:36
SCC * getSCCDetector() const
Get SCC detector.
Definition WPASolver.h:68
virtual void pushIntoWorklist(NodeID id)
Definition WPASolver.h:157
virtual void initWorklist()
Definition WPASolver.h:98
void setGraph(GraphType g)
Definition WPASolver.h:79
virtual NodeStack & SCCDetect()
SCC detection.
Definition WPASolver.h:87
u32_t iterationForPrintStat
print out statistics for i-th iteration
Definition WPASolver.h:174
u32_t numOfIteration
num of iterations during constraint solving
Definition WPASolver.h:201
bool reanalyze
Reanalyze if any constraint value changed.
Definition WPASolver.h:172
virtual void solveWorklist()
Definition WPASolver.h:109
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:75
bool isHeapAllocExtFunViaRet(const FunObjVar *fun)
Return true if the call is a heap allocator/reallocator.
Definition SVFUtil.h:284
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:121
void stopAnalysisLimitTimer(void)
Stops analysis timer.
Definition SVFUtil.cpp:383
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:98
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64
void startAnalysisLimitTimer(unsigned timeLimit)
Starts analysis timer. timeLimit must be non-0. Timer must not be already set.
Definition SVFUtil.cpp:364
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:88
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:58
for isBitcode
Definition BasicTypes.h:70
std::stack< NodeID > NodeStack
Definition GeneralType.h:92
Set< NodeID > NodeSet
Definition GeneralType.h:87
u32_t NodeID
Definition GeneralType.h:76
s64_t APOffset
Definition GeneralType.h:80
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
Set< NodePair > NodePairSet
Definition GeneralType.h:88
unsigned u32_t
Definition GeneralType.h:67