Static Value-Flow Analysis
Loading...
Searching...
No Matches
PointerAnalysis.cpp
Go to the documentation of this file.
1//===- PointerAnalysis.cpp -- Base class of pointer analyses------------------//
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 * PointerAnalysis.cpp
25 *
26 * Created on: May 14, 2013
27 * Author: Yulei Sui
28 */
29
30#include "Util/Options.h"
31#include "Util/SVFUtil.h"
32
33#include "MemoryModel/PTATY.h"
36#include "Util/PTAStat.h"
38#include "Graphs/ICFG.h"
39#include "Graphs/CallGraph.h"
41
42#include <iomanip>
43#include <iostream>
44#include <fstream>
45#include <sstream>
46
47using namespace SVF;
48using namespace SVFUtil;
49
50
52
53const std::string PointerAnalysis::aliasTestMayAlias = "MAYALIAS";
54const std::string PointerAnalysis::aliasTestMayAliasMangled = "_Z8MAYALIASPvS_";
55const std::string PointerAnalysis::aliasTestNoAlias = "NOALIAS";
56const std::string PointerAnalysis::aliasTestNoAliasMangled = "_Z7NOALIASPvS_";
57const std::string PointerAnalysis::aliasTestPartialAlias = "PARTIALALIAS";
58const std::string PointerAnalysis::aliasTestPartialAliasMangled = "_Z12PARTIALALIASPvS_";
59const std::string PointerAnalysis::aliasTestMustAlias = "MUSTALIAS";
60const std::string PointerAnalysis::aliasTestMustAliasMangled = "_Z9MUSTALIASPvS_";
61const std::string PointerAnalysis::aliasTestFailMayAlias = "EXPECTEDFAIL_MAYALIAS";
62const std::string PointerAnalysis::aliasTestFailMayAliasMangled = "_Z21EXPECTEDFAIL_MAYALIASPvS_";
63const std::string PointerAnalysis::aliasTestFailNoAlias = "EXPECTEDFAIL_NOALIAS";
64const std::string PointerAnalysis::aliasTestFailNoAliasMangled = "_Z20EXPECTEDFAIL_NOALIASPvS_";
65
79
84{
85 destroy();
86 // do not delete the SVFIR for now
87 //delete pag;
88}
89
90
92{
93 delete callgraph;
94 callgraph = nullptr;
95
96 delete callGraphSCC;
97 callGraphSCC = nullptr;
98
99 delete stat;
100 stat = nullptr;
101}
102
107{
108 assert(pag && "SVFIR has not been built!");
109
110 chgraph = pag->getCHG();
111
114 {
116 callgraph = bd.buildThreadCallGraph();
117 }
118 else
119 {
121 callgraph = bd.buildPTACallGraph();
122 }
124
125 // dump callgraph
127 getCallGraph()->dump("callgraph_initial");
128}
129
130
135{
137 assert(baseObjVar && "base object not found!!");
138 if(SVFUtil::isa<StackObjVar>(baseObjVar))
139 {
140 if(const FunObjVar* svffun = pag->getSVFVar(id)->getFunction())
141 {
142 return callGraphSCC->isInCycle(getCallGraph()->getCallGraphNode(svffun)->getId());
143 }
144 }
145 return false;
146}
147
152{
153 for (SVFIR::iterator nIter = pag->begin(); nIter != pag->end(); ++nIter)
154 {
155 if(ObjVar* node = SVFUtil::dyn_cast<ObjVar>(nIter->second))
156 const_cast<BaseObjVar*>(pag->getBaseObject(node->getId()))->setFieldSensitive();
157 }
158}
159
160/*
161 * Dump statistics
162 */
163
165{
166
167 if(print_stat && stat)
168 {
169 stat->performStat();
170 }
171}
172
178{
179
181 dumpStat();
182
184 if (Options::PTSPrint())
185 {
187 //dumpAllPts();
188 //dumpCPts();
189 }
190
191 if (Options::TypePrint())
192 dumpAllTypes();
193
195 dumpAllPts();
196
199
201
203 getCallGraph()->dump("callgraph_final");
204
207
210}
211
231
232
234{
235 for (OrderedNodeSet::iterator nIter = this->getAllValidPtrs().begin();
236 nIter != this->getAllValidPtrs().end(); ++nIter)
237 {
238 const SVFVar* node = getPAG()->getSVFVar(*nIter);
239 if (SVFUtil::isa<DummyObjVar, DummyValVar>(node))
240 continue;
241
242 outs() << "##<" << node->getName() << "> ";
243 outs() << "Source Loc: " << node->getSourceLoc();
244 outs() << "\nNodeID " << node->getId() << "\n";
245
246 const SVFType* type = node->getType();
248 }
249}
250
255{
256
257 const SVFVar* node = pag->getSVFVar(ptr);
259 if (SVFUtil::isa<DummyObjVar> (node))
260 {
261 outs() << "##<Dummy Obj > id:" << node->getId();
262 }
263 else if (!SVFUtil::isa<DummyValVar>(node) && !SVFIR::pagReadFromTXT())
264 {
265 outs() << "##<" << node->getName() << "> ";
266 outs() << "Source Loc: " << node->getSourceLoc();
267 }
268 outs() << "\nPtr " << node->getId() << " ";
269
270 if (pts.empty())
271 {
272 outs() << "\t\tPointsTo: {empty}\n\n";
273 }
274 else
275 {
276 outs() << "\t\tPointsTo: { ";
277 for (PointsTo::iterator it = pts.begin(), eit = pts.end(); it != eit;
278 ++it)
279 outs() << *it << " ";
280 outs() << "}\n\n";
281 }
282
283 outs() << "";
284
285 for (PointsTo::iterator it = pts.begin(), eit = pts.end(); it != eit; ++it)
286 {
287 const SVFVar* node = pag->getSVFVar(*it);
288 if(SVFUtil::isa<ObjVar>(node) == false)
289 continue;
290 NodeID ptd = node->getId();
291 outs() << "!!Target NodeID " << ptd << "\t [";
292 const SVFVar* pagNode = pag->getSVFVar(ptd);
293 if (SVFUtil::isa<DummyValVar>(node))
294 outs() << "DummyVal\n";
295 else if (SVFUtil::isa<DummyObjVar>(node))
296 outs() << "Dummy Obj id: " << node->getId() << "]\n";
297 else
298 {
300 {
301 outs() << "<" << pagNode->getName() << "> ";
302 outs() << "Source Loc: "
303 << pagNode->getSourceLoc() << "] \n";
304 }
305 }
306 }
307}
308
313{
314 outs() << "\nNodeID: " << getFunPtr(cs);
315 outs() << "\nCallSite: ";
316 outs() << cs->toString();
317 outs() << "\tLocation: " << cs->getSourceLoc();
318 outs() << "\t with Targets: ";
319
320 if (!targets.empty())
321 {
322 FunctionSet::const_iterator fit = targets.begin();
323 FunctionSet::const_iterator feit = targets.end();
324 for (; fit != feit; ++fit)
325 {
326 const FunObjVar* callee = *fit;
327 outs() << "\n\t" << callee->getName();
328 }
329 }
330 else
331 {
332 outs() << "\n\tNo Targets!";
333 }
334
335 outs() << "\n";
336}
337
342{
343 outs() << "==================Function Pointer Targets==================\n";
345 CallEdgeMap::const_iterator it = callEdges.begin();
346 CallEdgeMap::const_iterator eit = callEdges.end();
347 for (; it != eit; ++it)
348 {
349 const CallICFGNode* cs = it->first;
350 const FunctionSet& targets = it->second;
352 }
353
355 CallSiteToFunPtrMap::const_iterator csIt = indCS.begin();
356 CallSiteToFunPtrMap::const_iterator csEit = indCS.end();
357 for (; csIt != csEit; ++csIt)
358 {
359 const CallICFGNode* cs = csIt->first;
360 if (hasIndCSCallees(cs) == false)
361 {
362 outs() << "\nNodeID: " << csIt->second;
363 outs() << "\nCallSite: ";
364 outs() << cs->toString();
365 outs() << "\tLocation: " << cs->getSourceLoc();
366 outs() << "\n\t!!!has no targets!!!\n";
367 }
368 }
369}
370
371
372
377{
378
379 assert(pag->isIndirectCallSites(cs) && "not an indirect callsite?");
381 for (PointsTo::iterator ii = target.begin(), ie = target.end();
382 ii != ie; ii++)
383 {
384
386 {
387 writeWrnMsg("Resolved Indirect Call Edges are Out-Of-Budget, please increase the limit");
388 return;
389 }
390
391 if(const ObjVar* objPN = pag->getObjVar(*ii))
392 {
393 const BaseObjVar* obj = pag->getBaseObject(objPN->getId());
394
395 if(obj->isFunction())
396 {
397 const FunObjVar* calleefun = SVFUtil::cast<FunObjVar>(obj)->getFunction();
399
400 if(SVFUtil::matchArgs(cs, callee) == false)
401 continue;
402
403 if(0 == getIndCallMap()[cs].count(callee))
404 {
405 newEdges[cs].insert(callee);
406 getIndCallMap()[cs].insert(callee);
407
409 // FIXME: do we need to update llvm call graph here?
410 // The indirect call is maintained by ourself, We may update llvm's when we need to
411 //PTACallGraphNode* callgraphNode = callgraph->getOrInsertFunction(cs.getCaller());
412 //callgraphNode->addCalledFunction(cs,callgraph->getOrInsertFunction(callee));
413 }
414 }
415 }
416 }
417}
418
419/*
420 * Get virtual functions "vfns" based on CHA
421 */
427
428/*
429 * Get virtual functions "vfns" from PoninsTo set "target" for callsite "cs"
430 */
432{
433
435 {
438 for (PointsTo::iterator it = target.begin(), eit = target.end(); it != eit; ++it)
439 {
440 const SVFVar* ptdnode = pag->getSVFVar(*it);
441 const GlobalObjVar* pVar = nullptr;
443 {
445
446 }
447 else if (isa<ValVar>(ptdnode) &&
449 pag->getBaseValVar(ptdnode->getId())))
450 {
453 pag->getBaseValVar(ptdnode->getId()))));
454 }
455
456 if (pVar && chaVtbls.find(pVar) != chaVtbls.end())
457 vtbls.insert(pVar);
458 }
460 }
461}
462
463/*
464 * Connect callsite "cs" to virtual functions in "vfns"
465 */
467{
469 for (VFunSet::const_iterator fit = vfns.begin(),
470 feit = vfns.end(); fit != feit; ++fit)
471 {
472 const FunObjVar* callee = *fit;
474 if (getIndCallMap()[cs].count(callee) > 0)
475 continue;
476 if(cs->arg_size() == callee->arg_size() ||
477 (cs->isVarArg() && callee->isVarArg()))
478 {
479 newEdges[cs].insert(callee);
480 getIndCallMap()[cs].insert(callee);
481 const CallICFGNode* callBlockNode = cs;
482 callgraph->addIndirectCallGraphEdge(callBlockNode, cs->getCaller(),callee);
483 }
484 }
485}
486
489{
490 assert(cs->isVirtualCall() && "not cpp virtual call");
491
494 getVFnsFromCHA(cs, vfns);
495 else
498}
499
505{
506 // check for must alias cases, whether our alias analysis produce the correct results
507 if (const FunObjVar* checkFun = pag->getFunObjVar(fun))
508 {
509 if(!checkFun->isUncalledFunction())
510 outs() << "[" << this->PTAName() << "] Checking " << fun << "\n";
511
512 for(const CallICFGNode* callNode : pag->getCallSiteSet())
513 {
514 if (callNode->getCalledFunction() == checkFun)
515 {
516 assert(callNode->getNumArgOperands() == 2
517 && "arguments should be two pointers!!");
518 const SVFVar* V1 = callNode->getArgument(0);
519 const SVFVar* V2 = callNode->getArgument(1);
520 AliasResult aliasRes = alias(V1->getId(), V2->getId());
521
522 bool checkSuccessful = false;
523 if (fun == aliasTestMayAlias || fun == aliasTestMayAliasMangled)
524 {
526 checkSuccessful = true;
527 }
528 else if (fun == aliasTestNoAlias || fun == aliasTestNoAliasMangled)
529 {
531 checkSuccessful = true;
532 }
533 else if (fun == aliasTestMustAlias || fun == aliasTestMustAliasMangled)
534 {
535 // change to must alias when our analysis support it
537 checkSuccessful = true;
538 }
539 else if (fun == aliasTestPartialAlias || fun == aliasTestPartialAliasMangled)
540 {
541 // change to partial alias when our analysis support it
543 checkSuccessful = true;
544 }
545 else
546 assert(false && "not supported alias check!!");
547
548 NodeID id1 = V1->getId();
549 NodeID id2 = V2->getId();
550
551 if (checkSuccessful)
552 outs() << sucMsg("\t SUCCESS :") << fun << " check <id:" << id1 << ", id:" << id2 << "> at ("
553 << callNode->getSourceLoc() << ")\n";
554 else
555 {
556 SVFUtil::errs() << errMsg("\t FAILURE :") << fun
557 << " check <id:" << id1 << ", id:" << id2
558 << "> at (" << callNode->getSourceLoc() << ")\n";
559 assert(false && "test case failed!");
560 }
561 }
562 }
563 }
564}
565
570{
571
572 if (const FunObjVar* checkFun = pag->getFunObjVar(fun))
573 {
574 if(!checkFun->isUncalledFunction())
575 outs() << "[" << this->PTAName() << "] Checking " << fun << "\n";
576
577 for(const CallICFGNode* callNode : pag->getCallSiteSet())
578 {
579 if (callNode->getCalledFunction() == checkFun)
580 {
581 assert(callNode->arg_size() == 2
582 && "arguments should be two pointers!!");
583 const SVFVar* V1 = callNode->getArgument(0);
584 const SVFVar* V2 = callNode->getArgument(1);
585 AliasResult aliasRes = alias(V1->getId(), V2->getId());
586
587 bool expectedFailure = false;
589 {
590 // change to must alias when our analysis support it
592 expectedFailure = true;
593 }
594 else if (fun == aliasTestFailNoAlias || fun == aliasTestFailNoAliasMangled)
595 {
596 // change to partial alias when our analysis support it
598 expectedFailure = true;
599 }
600 else
601 assert(false && "not supported alias check!!");
602
603 NodeID id1 = V1->getId();
604 NodeID id2 = V2->getId();
605
606 if (expectedFailure)
607 outs() << sucMsg("\t EXPECTED-FAILURE :") << fun << " check <id:" << id1 << ", id:" << id2 << "> at ("
608 << callNode->getSourceLoc() << ")\n";
609 else
610 {
611 SVFUtil::errs() << errMsg("\t UNEXPECTED FAILURE :") << fun << " check <id:" << id1 << ", id:" << id2 << "> at ("
612 << callNode->getSourceLoc() << ")\n";
613 assert(false && "test case failed!");
614 }
615 }
616 }
617 }
618}
cJSON * p
Definition cJSON.cpp:2559
newitem type
Definition cJSON.cpp:2739
int count
Definition cJSON.h:216
void addIndirectCallGraphEdge(const CallICFGNode *cs, const FunObjVar *callerFun, const FunObjVar *calleeFun)
Add indirect call edges.
void dump(const std::string &filename)
Dump the graph.
void verifyCallGraph()
Issue a warning if the function which has indirect call sites can not be reached from program entry.
const std::string toString() const override
Definition ICFG.cpp:128
bool isVarArg() const
Definition ICFGNode.h:505
const std::string getSourceLoc() const override
Definition ICFGNode.h:570
bool isVirtualCall() const
Definition ICFGNode.h:509
const FunObjVar * getCaller() const
Return callsite.
Definition ICFGNode.h:452
u32_t arg_size() const
Definition ICFGNode.h:487
virtual const VFunSet & getCSVFsBasedonCHA(const CallICFGNode *cs)=0
virtual bool csHasVFnsBasedonCHA(const CallICFGNode *cs)=0
virtual const VTableSet & getCSVtblsBasedonCHA(const CallICFGNode *cs)=0
virtual void getVFnsFromVtbls(const CallICFGNode *cs, const VTableSet &vtbls, VFunSet &virtualFunctions)=0
virtual bool csHasVtblsBasedonCHA(const CallICFGNode *cs)=0
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const FunObjVar * getDefFunForMultipleModule() const
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
Node Iterators.
void printFlattenFields(const SVFType *type)
Debug method.
Definition IRGraph.cpp:73
bool isBuiltFromFile()
Whether this SVFIR built from a txt file.
Definition IRGraph.h:150
static const Option< bool > CallGraphDotGraph
Definition Options.h:123
static const Option< bool > EnableThreadCallGraph
Definition Options.h:129
static const Option< bool > PTSPrint
Definition Options.h:113
static const Option< bool > EnableAliasCheck
Definition Options.h:127
static const Option< bool > PTSAllPrint
Definition Options.h:114
static const Option< bool > TypePrint
Definition Options.h:111
static Option< bool > UsePreCompFieldSensitive
Definition Options.h:126
static const Option< u32_t > IndirectCallLimit
Definition Options.h:125
static const Option< bool > FuncPointerPrint
Definition Options.h:112
static const Option< bool > ConnectVCallOnCHA
Definition Options.h:130
static const Option< bool > PStat
Definition Options.h:116
static const Option< u32_t > StatBudget
Definition Options.h:117
void performStat() override
Definition PTAStat.cpp:53
void getVFnsFromPts(const CallICFGNode *cs, const PointsTo &target, VFunSet &vfns)
void destroy()
Release the memory.
virtual void validateTests()
Alias check functions to verify correctness of pointer analysis.
CommonCHGraph * chgraph
CHGraph.
static const std::string aliasTestNoAliasMangled
bool isLocalVarInRecursiveFun(NodeID id) const
Whether a local variable is in function recursions.
virtual void finalize()
Finalization of a pointer analysis, including checking alias correctness.
static const std::string aliasTestMayAliasMangled
static const std::string aliasTestFailNoAlias
virtual void dumpPts(NodeID ptr, const PointsTo &pts)
static const std::string aliasTestFailMayAlias
bool print_stat
User input flags.
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
Set< const GlobalObjVar * > VTableSet
virtual void initialize()
Initialization of a pointer analysis, including building symbol table and SVFIR etc.
virtual ~PointerAnalysis()
Destructor.
PTAImplTy ptaImplTy
PTA implementation type.
PTAStat * stat
Statistics.
virtual void dumpTopLevelPtsTo()
static const std::string aliasTestFailMayAliasMangled
SVFIR * getPAG() const
void connectVCallToVFns(const CallICFGNode *cs, const VFunSet &vfns, CallEdgeMap &newEdges)
CallGraph * getCallGraph() const
Return call graph.
OrderedNodeSet & getAllValidPtrs()
Get all Valid Pointers for resolution.
void resetObjFieldSensitive()
Reset all object node as field-sensitive.
static const std::string aliasTestMustAlias
static const std::string aliasTestMayAlias
Set< const FunObjVar * > FunctionSet
virtual void validateSuccessTests(std::string fun)
const CallSiteToFunPtrMap & getIndirectCallsites() const
Return all indirect callsites.
static const std::string aliasTestPartialAlias
virtual void dumpAllPts()
virtual AliasResult alias(const SVFVar *V1, const SVFVar *V2)=0
Interface exposed to users of our pointer analysis, given Value infos.
virtual void resolveIndCalls(const CallICFGNode *cs, const PointsTo &target, CallEdgeMap &newEdges)
Resolve indirect call edges.
CallGraph * callgraph
Call graph used for pointer analysis.
PointerAnalysis(SVFIR *pag, PTATY ty=PTATY::Default_PTA, bool alias_check=true)
Constructor.
bool alias_validation
Flag for validating points-to/alias results.
void callGraphSCCDetection()
PTACallGraph SCC related methods.
void dumpStat()
Dump the statistics.
virtual void validateExpectedFailureTests(std::string fun)
bool hasIndCSCallees(const CallICFGNode *cs) const
virtual void resolveCPPIndCalls(const CallICFGNode *cs, const PointsTo &target, CallEdgeMap &newEdges)
Resolve cpp indirect call edges.
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
static const std::string aliasTestNoAlias
static const std::string aliasTestPartialAliasMangled
u32_t getNumOfResolvedIndCallEdge() const
Return number of resolved indirect call edges.
SVFIR::CallSiteToFunPtrMap CallSiteToFunPtrMap
NodeID getFunPtr(const CallICFGNode *cs) const
Return function pointer PAGNode at a callsite cs.
static SVFIR * pag
SVFIR.
void getVFnsFromCHA(const CallICFGNode *cs, VFunSet &vfns)
CallGraphSCC * callGraphSCC
SCC for PTACallGraph.
static const std::string aliasTestMustAliasMangled
virtual const std::string PTAName() const
Return PTA name.
static const std::string aliasTestFailNoAliasMangled
Set< const FunObjVar * > VFunSet
u32_t OnTheFlyIterBudgetForStat
Flag for iteration budget for on-the-fly statistics.
const CallSiteSet & getCallSiteSet() const
Get all callsites.
Definition SVFIR.h:349
bool isIndirectCallSites(const CallICFGNode *cs) const
Definition SVFIR.h:467
static bool pagReadFromTXT()
Definition SVFIR.h:278
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:496
const FunObjVar * getFunObjVar(const std::string &name)
Definition SVFIR.cpp:48
const ObjVar * getObjVar(NodeID id) const
Definition SVFIR.h:147
CommonCHGraph * getCHG()
Definition SVFIR.h:239
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:133
const ValVar * getBaseValVar(NodeID id) const
Definition SVFIR.h:506
NodeID getId() const
Get ID.
Definition SVFValue.h:161
virtual const SVFType * getType() const
Definition SVFValue.h:172
virtual const std::string getSourceLoc() const
Definition SVFValue.h:197
virtual const std::string & getName() const
Definition SVFValue.h:187
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:59
const ObjVar * getObjVarOfValVar(const ValVar *valVar)
Definition SVFUtil.cpp:435
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:82
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
bool matchArgs(const CallICFGNode *cs, const FunObjVar *callee)
Definition SVFUtil.cpp:312
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:72
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:70
@ BaseImpl
Represents PointerAnalaysis.
Definition PTATY.h:41
PTATY
Pointer analysis type list.
Definition PTATY.h:9
u32_t NodeID
Definition GeneralType.h:56
AliasResult
Definition SVFType.h:636
@ PartialAlias
Definition SVFType.h:640
@ MustAlias
Definition SVFType.h:639
@ MayAlias
Definition SVFType.h:638
@ NoAlias
Definition SVFType.h:637
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76