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 "SVFIR/SVFModule.h"
32#include "Util/SVFUtil.h"
33
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
78
83{
84 destroy();
85 // do not delete the SVFIR for now
86 //delete pag;
87}
88
89
91{
92 delete callgraph;
93 callgraph = nullptr;
94
95 delete callGraphSCC;
96 callGraphSCC = nullptr;
97
98 delete stat;
99 stat = nullptr;
100}
101
106{
107 assert(pag && "SVFIR has not been built!");
108
109 svfMod = pag->getModule();
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 SVFFunction* svffun = pag->getGNode(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<MemObj*>(node->getMemObj())->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 PAGNode* node = getPAG()->getGNode(*nIter);
239 if (SVFUtil::isa<DummyObjVar, DummyValVar>(node))
240 continue;
241
242 outs() << "##<" << node->getValue()->getName() << "> ";
243 outs() << "Source Loc: " << node->getValue()->getSourceLoc();
244 outs() << "\nNodeID " << node->getId() << "\n";
245
246 const SVFType* type = node->getValue()->getType();
248 }
249}
250
255{
256
257 const PAGNode* node = pag->getGNode(ptr);
259 if (SVFUtil::isa<DummyObjVar> (node))
260 {
261 outs() << "##<Dummy Obj > id:" << node->getId();
262 }
263 else if (!SVFUtil::isa<DummyValVar>(node) && !SVFModule::pagReadFromTXT())
264 {
265 if (node->hasValue())
266 {
267 outs() << "##<" << node->getValue()->getName() << "> ";
268 outs() << "Source Loc: " << node->getValue()->getSourceLoc();
269 }
270 }
271 outs() << "\nPtr " << node->getId() << " ";
272
273 if (pts.empty())
274 {
275 outs() << "\t\tPointsTo: {empty}\n\n";
276 }
277 else
278 {
279 outs() << "\t\tPointsTo: { ";
280 for (PointsTo::iterator it = pts.begin(), eit = pts.end(); it != eit;
281 ++it)
282 outs() << *it << " ";
283 outs() << "}\n\n";
284 }
285
286 outs() << "";
287
288 for (PointsTo::iterator it = pts.begin(), eit = pts.end(); it != eit; ++it)
289 {
290 const PAGNode* node = pag->getGNode(*it);
291 if(SVFUtil::isa<ObjVar>(node) == false)
292 continue;
293 NodeID ptd = node->getId();
294 outs() << "!!Target NodeID " << ptd << "\t [";
295 const PAGNode* pagNode = pag->getGNode(ptd);
296 if (SVFUtil::isa<DummyValVar>(node))
297 outs() << "DummyVal\n";
298 else if (SVFUtil::isa<DummyObjVar>(node))
299 outs() << "Dummy Obj id: " << node->getId() << "]\n";
300 else
301 {
303 {
304 if (node->hasValue())
305 {
306 outs() << "<" << pagNode->getValue()->getName() << "> ";
307 outs() << "Source Loc: "
308 << pagNode->getValue()->getSourceLoc() << "] \n";
309 }
310 }
311 }
312 }
313}
314
319{
320 outs() << "\nNodeID: " << getFunPtr(cs);
321 outs() << "\nCallSite: ";
322 outs() << cs->toString();
323 outs() << "\tLocation: " << cs->getSourceLoc();
324 outs() << "\t with Targets: ";
325
326 if (!targets.empty())
327 {
328 FunctionSet::const_iterator fit = targets.begin();
329 FunctionSet::const_iterator feit = targets.end();
330 for (; fit != feit; ++fit)
331 {
332 const SVFFunction* callee = *fit;
333 outs() << "\n\t" << callee->getName();
334 }
335 }
336 else
337 {
338 outs() << "\n\tNo Targets!";
339 }
340
341 outs() << "\n";
342}
343
348{
349 outs() << "==================Function Pointer Targets==================\n";
351 CallEdgeMap::const_iterator it = callEdges.begin();
352 CallEdgeMap::const_iterator eit = callEdges.end();
353 for (; it != eit; ++it)
354 {
355 const CallICFGNode* cs = it->first;
356 const FunctionSet& targets = it->second;
358 }
359
361 CallSiteToFunPtrMap::const_iterator csIt = indCS.begin();
362 CallSiteToFunPtrMap::const_iterator csEit = indCS.end();
363 for (; csIt != csEit; ++csIt)
364 {
365 const CallICFGNode* cs = csIt->first;
366 if (hasIndCSCallees(cs) == false)
367 {
368 outs() << "\nNodeID: " << csIt->second;
369 outs() << "\nCallSite: ";
370 outs() << cs->toString();
371 outs() << "\tLocation: " << cs->getSourceLoc();
372 outs() << "\n\t!!!has no targets!!!\n";
373 }
374 }
375}
376
377
378
383{
384
385 assert(pag->isIndirectCallSites(cs) && "not an indirect callsite?");
387 for (PointsTo::iterator ii = target.begin(), ie = target.end();
388 ii != ie; ii++)
389 {
390
392 {
393 wrnMsg("Resolved Indirect Call Edges are Out-Of-Budget, please increase the limit");
394 return;
395 }
396
397 if(ObjVar* objPN = SVFUtil::dyn_cast<ObjVar>(pag->getGNode(*ii)))
398 {
399 const MemObj* obj = pag->getObject(objPN);
400
401 if(obj->isFunction())
402 {
403 const SVFFunction* calleefun = SVFUtil::cast<CallGraphNode>(obj->getGNode())->getFunction();
405
406 if(SVFUtil::matchArgs(cs, callee) == false)
407 continue;
408
409 if(0 == getIndCallMap()[cs].count(callee))
410 {
411 newEdges[cs].insert(callee);
412 getIndCallMap()[cs].insert(callee);
413
415 // FIXME: do we need to update llvm call graph here?
416 // The indirect call is maintained by ourself, We may update llvm's when we need to
417 //PTACallGraphNode* callgraphNode = callgraph->getOrInsertFunction(cs.getCaller());
418 //callgraphNode->addCalledFunction(cs,callgraph->getOrInsertFunction(callee));
419 }
420 }
421 }
422 }
423}
424
425/*
426 * Get virtual functions "vfns" based on CHA
427 */
433
434/*
435 * Get virtual functions "vfns" from PoninsTo set "target" for callsite "cs"
436 */
438{
439
441 {
444 for (PointsTo::iterator it = target.begin(), eit = target.end(); it != eit; ++it)
445 {
446 const PAGNode *ptdnode = pag->getGNode(*it);
447 if (ptdnode->hasValue())
448 {
451 {
452 const SVFGlobalValue* globalValue = SVFUtil::dyn_cast<SVFGlobalValue>(ptdnode->getValue());
453 if (chaVtbls.find(globalValue) != chaVtbls.end())
454 vtbls.insert(globalValue);
455 }
456
457 }
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 SVFFunction* 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 SVFFunction* checkFun = svfMod->getSVFFunction(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 SVFFunction* checkFun = svfMod->getSVFFunction(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
const std::string toString() const override
Definition ICFG.cpp:131
bool isVarArg() const
Definition ICFGNode.h:523
const std::string getSourceLoc() const override
Definition ICFGNode.h:588
bool isVirtualCall() const
Definition ICFGNode.h:527
const SVFFunction * getCaller() const
Return callsite.
Definition ICFGNode.h:470
u32_t arg_size() const
Definition ICFGNode.h:505
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
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
Node Iterators.
NodeType * getGNode(NodeID id) const
Get a node.
bool isBuiltFromFile()
Whether this SVFIR built from a txt file.
Definition IRGraph.h:119
SymbolTableInfo * getSymbolInfo() const
Definition IRGraph.h:114
static const Option< bool > CallGraphDotGraph
Definition Options.h:126
static const Option< bool > EnableThreadCallGraph
Definition Options.h:132
static const Option< bool > PTSPrint
Definition Options.h:116
static const Option< bool > EnableAliasCheck
Definition Options.h:130
static const Option< bool > PTSAllPrint
Definition Options.h:117
static const Option< bool > UsePreCompFieldSensitive
Definition Options.h:129
static const Option< bool > TypePrint
Definition Options.h:114
static const Option< u32_t > IndirectCallLimit
Definition Options.h:128
static const Option< bool > FuncPointerPrint
Definition Options.h:115
static const Option< bool > ConnectVCallOnCHA
Definition Options.h:133
static const Option< bool > PStat
Definition Options.h:119
static const Option< u32_t > StatBudget
Definition Options.h:120
void addIndirectCallGraphEdge(const CallICFGNode *cs, const SVFFunction *callerFun, const SVFFunction *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.
void performStat() override
Definition PTAStat.cpp:52
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.
PTATY
Pointer analysis type list.
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
PointerAnalysis(SVFIR *pag, PTATY ty=Default_PTA, bool alias_check=true)
Constructor.
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
virtual void initialize()
Initialization of a pointer analysis, including building symbol table and SVFIR etc.
virtual ~PointerAnalysis()
Destructor.
Set< const SVFGlobalValue * > VTableSet
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)
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
virtual void validateSuccessTests(std::string fun)
SVFModule * svfMod
Module.
const CallSiteToFunPtrMap & getIndirectCallsites() const
Return all indirect callsites.
static const std::string aliasTestPartialAlias
virtual void dumpAllPts()
virtual void resolveIndCalls(const CallICFGNode *cs, const PointsTo &target, CallEdgeMap &newEdges)
Resolve indirect call edges.
PTACallGraph * getCallGraph() const
Return call graph.
Set< const SVFFunction * > VFunSet
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.
@ BaseImpl
Represents PointerAnalaysis.
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Set< const SVFFunction * > FunctionSet
static const std::string aliasTestNoAlias
static const std::string aliasTestPartialAliasMangled
PTACallGraph * callgraph
Call graph used for pointer analysis.
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)
virtual AliasResult alias(const SVFValue *V1, const SVFValue *V2)=0
Interface exposed to users of our pointer analysis, given Value infos.
CallGraphSCC * callGraphSCC
SCC for PTACallGraph.
static const std::string aliasTestMustAliasMangled
virtual const std::string PTAName() const
Return PTA name.
static const std::string aliasTestFailNoAliasMangled
u32_t OnTheFlyIterBudgetForStat
Flag for iteration budget for on-the-fly statistics.
NodeID getId() const
Get ID.
const SVFFunction * getDefFunForMultipleModule() const
Definition SVFValue.h:404
const CallSiteSet & getCallSiteSet() const
Get all callsites.
Definition SVFIR.h:255
bool isIndirectCallSites(const CallICFGNode *cs) const
Definition SVFIR.h:367
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:405
SVFModule * getModule()
Definition SVFIR.h:162
CommonCHGraph * getCHG()
Definition SVFIR.h:182
const MemObj * getObject(NodeID id) const
Definition SVFIR.h:396
const ValVar * getBaseValVar(NodeID id) const
Definition SVFIR.h:415
static bool pagReadFromTXT()
Definition SVFModule.h:98
const SVFFunction * getSVFFunction(const std::string &name)
Definition SVFModule.cpp:48
const std::string & getName() const
Definition SVFValue.h:243
virtual const SVFType * getType() const
Definition SVFValue.h:256
virtual const std::string getSourceLoc() const
Definition SVFValue.h:280
const SVFValue * getValue() const
Get/has methods of the components.
bool hasValue() const
virtual const SVFFunction * getFunction() const
void printFlattenFields(const SVFType *type)
Debug method.
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:54
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::string wrnMsg(const std::string &msg)
Returns warning message by converting a string into yellow string output.
Definition SVFUtil.cpp:62
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
bool matchArgs(const CallICFGNode *cs, const SVFFunction *callee)
Definition SVFUtil.cpp:321
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
AliasResult
Definition SVFType.h:527
@ PartialAlias
Definition SVFType.h:531
@ MustAlias
Definition SVFType.h:530
@ MayAlias
Definition SVFType.h:529
@ NoAlias
Definition SVFType.h:528
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74