svf-tools 1.0.993 → 1.0.995
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/svf/include/Graphs/CDG.h +18 -1
- package/svf/include/Graphs/CFLGraph.h +19 -1
- package/svf/include/Graphs/CHG.h +19 -1
- package/svf/include/Graphs/CallGraph.h +19 -1
- package/svf/include/Graphs/ConsGNode.h +19 -1
- package/svf/include/Graphs/GenericGraph.h +243 -17
- package/svf/include/Graphs/ICFG.h +0 -96
- package/svf/include/Graphs/ICFGNode.h +55 -22
- package/svf/include/Graphs/SVFG.h +2 -2
- package/svf/include/Graphs/SVFGNode.h +5 -17
- package/svf/include/Graphs/SVFGOPT.h +2 -1
- package/svf/include/Graphs/ThreadCallGraph.h +5 -4
- package/svf/include/Graphs/VFG.h +2 -2
- package/svf/include/Graphs/VFGNode.h +99 -26
- package/svf/include/MTA/TCT.h +19 -1
- package/svf/include/MemoryModel/PointerAnalysis.h +1 -1
- package/svf/include/MemoryModel/PointerAnalysisImpl.h +4 -0
- package/svf/include/SABER/SaberCondAllocator.h +2 -2
- package/svf/include/SVFIR/SVFFileSystem.h +1 -1
- package/svf/include/SVFIR/SVFIR.h +2 -2
- package/svf/include/SVFIR/SVFVariables.h +68 -38
- package/svf/include/SVFIR/SymbolTableInfo.h +11 -1
- package/svf/include/Util/SVFUtil.h +1 -1
- package/svf/include/Util/ThreadAPI.h +8 -2
- package/svf/include/WPA/Andersen.h +26 -13
- package/svf/include/WPA/Steensgaard.h +10 -20
- package/svf/include/WPA/TypeAnalysis.h +10 -3
- package/svf/lib/AE/Svfexe/AEDetector.cpp +4 -2
- package/svf/lib/AE/Svfexe/AbsExtAPI.cpp +10 -12
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +2 -0
- package/svf/lib/DDA/ContextDDA.cpp +12 -8
- package/svf/lib/Graphs/ICFG.cpp +9 -93
- package/svf/lib/Graphs/SVFG.cpp +1 -1
- package/svf/lib/Graphs/ThreadCallGraph.cpp +10 -2
- package/svf/lib/Graphs/VFG.cpp +2 -4
- package/svf/lib/MSSA/MemRegion.cpp +2 -2
- package/svf/lib/MemoryModel/PointerAnalysisImpl.cpp +37 -0
- package/svf/lib/SABER/LeakChecker.cpp +1 -2
- package/svf/lib/SABER/SaberCondAllocator.cpp +13 -16
- package/svf/lib/SABER/SaberSVFGBuilder.cpp +2 -2
- package/svf/lib/SVFIR/SVFFileSystem.cpp +0 -6
- package/svf/lib/SVFIR/SVFVariables.cpp +3 -0
- package/svf/lib/SVFIR/SymbolTableInfo.cpp +3 -2
- package/svf/lib/Util/ThreadAPI.cpp +15 -5
- package/svf/lib/WPA/Andersen.cpp +205 -151
- package/svf/lib/WPA/Steensgaard.cpp +1 -163
- package/svf-llvm/include/SVF-LLVM/DCHG.h +1 -1
- package/svf-llvm/include/SVF-LLVM/ICFGBuilder.h +93 -23
- package/svf-llvm/include/SVF-LLVM/LLVMModule.h +84 -0
- package/svf-llvm/include/SVF-LLVM/LLVMUtil.h +15 -0
- package/svf-llvm/include/SVF-LLVM/SVFIRBuilder.h +19 -12
- package/svf-llvm/lib/ICFGBuilder.cpp +125 -54
- package/svf-llvm/lib/LLVMLoopAnalysis.cpp +6 -11
- package/svf-llvm/lib/LLVMModule.cpp +54 -0
- package/svf-llvm/lib/LLVMUtil.cpp +15 -0
- package/svf-llvm/lib/SVFIRBuilder.cpp +92 -76
- package/svf-llvm/lib/SVFIRExtAPI.cpp +5 -5
- package/svf-llvm/lib/SymbolTableBuilder.cpp +4 -4
package/svf/lib/WPA/Andersen.cpp
CHANGED
|
@@ -187,6 +187,211 @@ void AndersenBase::cleanConsCG(NodeID id)
|
|
|
187
187
|
assert(!consCG->hasGNode(id) && "this is either a rep nodeid or a sub nodeid should have already been merged to its field-insensitive base! ");
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
bool AndersenBase::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
191
|
+
{
|
|
192
|
+
|
|
193
|
+
double cgUpdateStart = stat->getClk();
|
|
194
|
+
|
|
195
|
+
CallEdgeMap newEdges;
|
|
196
|
+
onTheFlyCallGraphSolve(callsites, newEdges);
|
|
197
|
+
NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
|
|
198
|
+
for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
|
|
199
|
+
it != eit; ++it)
|
|
200
|
+
{
|
|
201
|
+
for (FunctionSet::iterator cit = it->second.begin(),
|
|
202
|
+
ecit = it->second.end();
|
|
203
|
+
cit != ecit; ++cit)
|
|
204
|
+
{
|
|
205
|
+
connectCaller2CalleeParams(it->first, *cit, cpySrcNodes);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
bool hasNewForkEdges = updateThreadCallGraph(callsites, cpySrcNodes);
|
|
210
|
+
|
|
211
|
+
for (NodePairSet::iterator it = cpySrcNodes.begin(),
|
|
212
|
+
eit = cpySrcNodes.end();
|
|
213
|
+
it != eit; ++it)
|
|
214
|
+
{
|
|
215
|
+
pushIntoWorklist(it->first);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
double cgUpdateEnd = stat->getClk();
|
|
219
|
+
timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
|
|
220
|
+
|
|
221
|
+
return ((!newEdges.empty()) || hasNewForkEdges);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
bool AndersenBase::updateThreadCallGraph(const CallSiteToFunPtrMap& callsites,
|
|
225
|
+
NodePairSet& cpySrcNodes)
|
|
226
|
+
{
|
|
227
|
+
CallEdgeMap newForkEdges;
|
|
228
|
+
onTheFlyThreadCallGraphSolve(callsites, newForkEdges);
|
|
229
|
+
for (CallEdgeMap::iterator it = newForkEdges.begin(), eit = newForkEdges.end(); it != eit; it++)
|
|
230
|
+
{
|
|
231
|
+
for (FunctionSet::iterator cit = it->second.begin(),
|
|
232
|
+
ecit = it->second.end();
|
|
233
|
+
cit != ecit; ++cit)
|
|
234
|
+
{
|
|
235
|
+
connectCaller2ForkedFunParams(it->first, *cit, cpySrcNodes);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return !newForkEdges.empty();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/*!
|
|
242
|
+
* Connect formal and actual parameters for indirect forksites
|
|
243
|
+
*/
|
|
244
|
+
void AndersenBase::connectCaller2ForkedFunParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
245
|
+
NodePairSet& cpySrcNodes)
|
|
246
|
+
{
|
|
247
|
+
assert(F);
|
|
248
|
+
|
|
249
|
+
DBOUT(DAndersen, outs() << "connect parameters from indirect forksite "
|
|
250
|
+
<< cs.getInstruction()->toString() << " to forked function "
|
|
251
|
+
<< *F << "\n");
|
|
252
|
+
|
|
253
|
+
ThreadCallGraph *tdCallGraph = SVFUtil::dyn_cast<ThreadCallGraph>(callgraph);
|
|
254
|
+
|
|
255
|
+
const PAGNode *cs_arg = tdCallGraph->getThreadAPI()->getActualParmAtForkSite(cs);
|
|
256
|
+
const PAGNode *fun_arg = tdCallGraph->getThreadAPI()->getFormalParmOfForkedFun(F);
|
|
257
|
+
|
|
258
|
+
if(cs_arg->isPointer() && fun_arg->isPointer())
|
|
259
|
+
{
|
|
260
|
+
DBOUT(DAndersen, outs() << "process actual parm"
|
|
261
|
+
<< cs_arg->toString() << "\n");
|
|
262
|
+
NodeID srcAA = sccRepNode(cs_arg->getId());
|
|
263
|
+
NodeID dstFA = sccRepNode(fun_arg->getId());
|
|
264
|
+
if (addCopyEdge(srcAA, dstFA))
|
|
265
|
+
{
|
|
266
|
+
cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
///*!
|
|
272
|
+
// * Connect formal and actual parameters for indirect callsites
|
|
273
|
+
// */
|
|
274
|
+
void AndersenBase::connectCaller2CalleeParams(const CallICFGNode* cs,
|
|
275
|
+
const SVFFunction* F, NodePairSet &cpySrcNodes)
|
|
276
|
+
{
|
|
277
|
+
assert(F);
|
|
278
|
+
|
|
279
|
+
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " <<
|
|
280
|
+
cs.getInstruction()->toString() << " to callee " << *F << "\n");
|
|
281
|
+
|
|
282
|
+
const CallICFGNode* callBlockNode = cs;
|
|
283
|
+
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
284
|
+
|
|
285
|
+
if(SVFUtil::isHeapAllocExtFunViaRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
286
|
+
{
|
|
287
|
+
heapAllocatorViaIndCall(cs,cpySrcNodes);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
291
|
+
{
|
|
292
|
+
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
293
|
+
const PAGNode* fun_return = pag->getFunRet(F);
|
|
294
|
+
if (cs_return->isPointer() && fun_return->isPointer())
|
|
295
|
+
{
|
|
296
|
+
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
297
|
+
NodeID srcret = sccRepNode(fun_return->getId());
|
|
298
|
+
if(addCopyEdge(srcret, dstrec))
|
|
299
|
+
{
|
|
300
|
+
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else
|
|
304
|
+
{
|
|
305
|
+
DBOUT(DAndersen, outs() << "not a pointer ignored\n");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
|
|
310
|
+
{
|
|
311
|
+
|
|
312
|
+
// connect actual and formal param
|
|
313
|
+
const SVFIR::SVFVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
|
|
314
|
+
const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
|
|
315
|
+
//Go through the fixed parameters.
|
|
316
|
+
DBOUT(DPAGBuild, outs() << " args:");
|
|
317
|
+
SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
|
|
318
|
+
SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
|
|
319
|
+
for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
|
|
320
|
+
{
|
|
321
|
+
//Some programs (e.g. Linux kernel) leave unneeded parameters empty.
|
|
322
|
+
if (csArgIt == csArgEit)
|
|
323
|
+
{
|
|
324
|
+
DBOUT(DAndersen, outs() << " !! not enough args\n");
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
const PAGNode *cs_arg = *csArgIt ;
|
|
328
|
+
const PAGNode *fun_arg = *funArgIt;
|
|
329
|
+
|
|
330
|
+
if (cs_arg->isPointer() && fun_arg->isPointer())
|
|
331
|
+
{
|
|
332
|
+
DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
|
|
333
|
+
NodeID srcAA = sccRepNode(cs_arg->getId());
|
|
334
|
+
NodeID dstFA = sccRepNode(fun_arg->getId());
|
|
335
|
+
if(addCopyEdge(srcAA, dstFA))
|
|
336
|
+
{
|
|
337
|
+
cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
//Any remaining actual args must be varargs.
|
|
343
|
+
if (F->isVarArg())
|
|
344
|
+
{
|
|
345
|
+
NodeID vaF = sccRepNode(pag->getVarargNode(F));
|
|
346
|
+
DBOUT(DPAGBuild, outs() << "\n varargs:");
|
|
347
|
+
for (; csArgIt != csArgEit; ++csArgIt)
|
|
348
|
+
{
|
|
349
|
+
const PAGNode *cs_arg = *csArgIt;
|
|
350
|
+
if (cs_arg->isPointer())
|
|
351
|
+
{
|
|
352
|
+
NodeID vnAA = sccRepNode(cs_arg->getId());
|
|
353
|
+
if (addCopyEdge(vnAA,vaF))
|
|
354
|
+
{
|
|
355
|
+
cpySrcNodes.insert(std::make_pair(vnAA,vaF));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if(csArgIt != csArgEit)
|
|
361
|
+
{
|
|
362
|
+
writeWrnMsg("too many args to non-vararg func.");
|
|
363
|
+
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
void AndersenBase::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet &cpySrcNodes)
|
|
369
|
+
{
|
|
370
|
+
assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
|
|
371
|
+
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
372
|
+
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
373
|
+
NodeID srcret;
|
|
374
|
+
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
375
|
+
if(it != callsite2DummyValPN.end())
|
|
376
|
+
{
|
|
377
|
+
srcret = sccRepNode(it->second);
|
|
378
|
+
}
|
|
379
|
+
else
|
|
380
|
+
{
|
|
381
|
+
NodeID valNode = pag->addDummyValNode();
|
|
382
|
+
NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
|
|
383
|
+
addPts(valNode,objNode);
|
|
384
|
+
callsite2DummyValPN.insert(std::make_pair(cs,valNode));
|
|
385
|
+
consCG->addConstraintNode(new ConstraintNode(valNode),valNode);
|
|
386
|
+
consCG->addConstraintNode(new ConstraintNode(objNode),objNode);
|
|
387
|
+
srcret = valNode;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
391
|
+
if(addCopyEdge(srcret, dstrec))
|
|
392
|
+
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
393
|
+
}
|
|
394
|
+
|
|
190
395
|
void AndersenBase::normalizePointsTo()
|
|
191
396
|
{
|
|
192
397
|
SVFIR::MemObjToFieldsMap &memToFieldsMap = pag->getMemToFieldsMap();
|
|
@@ -648,157 +853,6 @@ NodeStack& Andersen::SCCDetect()
|
|
|
648
853
|
return getSCCDetector()->topoNodeStack();
|
|
649
854
|
}
|
|
650
855
|
|
|
651
|
-
/*!
|
|
652
|
-
* Update call graph for the input indirect callsites
|
|
653
|
-
*/
|
|
654
|
-
bool Andersen::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
655
|
-
{
|
|
656
|
-
|
|
657
|
-
double cgUpdateStart = stat->getClk();
|
|
658
|
-
|
|
659
|
-
CallEdgeMap newEdges;
|
|
660
|
-
onTheFlyCallGraphSolve(callsites,newEdges);
|
|
661
|
-
NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
|
|
662
|
-
for(CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end(); it!=eit; ++it )
|
|
663
|
-
{
|
|
664
|
-
for(FunctionSet::iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
|
|
665
|
-
{
|
|
666
|
-
connectCaller2CalleeParams(it->first,*cit,cpySrcNodes);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
for(NodePairSet::iterator it = cpySrcNodes.begin(), eit = cpySrcNodes.end(); it!=eit; ++it)
|
|
670
|
-
{
|
|
671
|
-
pushIntoWorklist(it->first);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
double cgUpdateEnd = stat->getClk();
|
|
675
|
-
timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
|
|
676
|
-
|
|
677
|
-
return (!newEdges.empty());
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
void Andersen::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet &cpySrcNodes)
|
|
681
|
-
{
|
|
682
|
-
assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
|
|
683
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
684
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
685
|
-
NodeID srcret;
|
|
686
|
-
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
687
|
-
if(it != callsite2DummyValPN.end())
|
|
688
|
-
{
|
|
689
|
-
srcret = sccRepNode(it->second);
|
|
690
|
-
}
|
|
691
|
-
else
|
|
692
|
-
{
|
|
693
|
-
NodeID valNode = pag->addDummyValNode();
|
|
694
|
-
NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
|
|
695
|
-
addPts(valNode,objNode);
|
|
696
|
-
callsite2DummyValPN.insert(std::make_pair(cs,valNode));
|
|
697
|
-
consCG->addConstraintNode(new ConstraintNode(valNode),valNode);
|
|
698
|
-
consCG->addConstraintNode(new ConstraintNode(objNode),objNode);
|
|
699
|
-
srcret = valNode;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
703
|
-
if(addCopyEdge(srcret, dstrec))
|
|
704
|
-
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
/*!
|
|
708
|
-
* Connect formal and actual parameters for indirect callsites
|
|
709
|
-
*/
|
|
710
|
-
void Andersen::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F, NodePairSet &cpySrcNodes)
|
|
711
|
-
{
|
|
712
|
-
assert(F);
|
|
713
|
-
|
|
714
|
-
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs.getInstruction()->toString() << " to callee " << *F << "\n");
|
|
715
|
-
|
|
716
|
-
const CallICFGNode* callBlockNode = cs;
|
|
717
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
718
|
-
|
|
719
|
-
if(SVFUtil::isHeapAllocExtFunViaRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
720
|
-
{
|
|
721
|
-
heapAllocatorViaIndCall(cs,cpySrcNodes);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
725
|
-
{
|
|
726
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
727
|
-
const PAGNode* fun_return = pag->getFunRet(F);
|
|
728
|
-
if (cs_return->isPointer() && fun_return->isPointer())
|
|
729
|
-
{
|
|
730
|
-
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
731
|
-
NodeID srcret = sccRepNode(fun_return->getId());
|
|
732
|
-
if(addCopyEdge(srcret, dstrec))
|
|
733
|
-
{
|
|
734
|
-
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
else
|
|
738
|
-
{
|
|
739
|
-
DBOUT(DAndersen, outs() << "not a pointer ignored\n");
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
|
|
744
|
-
{
|
|
745
|
-
|
|
746
|
-
// connect actual and formal param
|
|
747
|
-
const SVFIR::SVFVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
|
|
748
|
-
const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
|
|
749
|
-
//Go through the fixed parameters.
|
|
750
|
-
DBOUT(DPAGBuild, outs() << " args:");
|
|
751
|
-
SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
|
|
752
|
-
SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
|
|
753
|
-
for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
|
|
754
|
-
{
|
|
755
|
-
//Some programs (e.g. Linux kernel) leave unneeded parameters empty.
|
|
756
|
-
if (csArgIt == csArgEit)
|
|
757
|
-
{
|
|
758
|
-
DBOUT(DAndersen, outs() << " !! not enough args\n");
|
|
759
|
-
break;
|
|
760
|
-
}
|
|
761
|
-
const PAGNode *cs_arg = *csArgIt ;
|
|
762
|
-
const PAGNode *fun_arg = *funArgIt;
|
|
763
|
-
|
|
764
|
-
if (cs_arg->isPointer() && fun_arg->isPointer())
|
|
765
|
-
{
|
|
766
|
-
DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
|
|
767
|
-
NodeID srcAA = sccRepNode(cs_arg->getId());
|
|
768
|
-
NodeID dstFA = sccRepNode(fun_arg->getId());
|
|
769
|
-
if(addCopyEdge(srcAA, dstFA))
|
|
770
|
-
{
|
|
771
|
-
cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
//Any remaining actual args must be varargs.
|
|
777
|
-
if (F->isVarArg())
|
|
778
|
-
{
|
|
779
|
-
NodeID vaF = sccRepNode(pag->getVarargNode(F));
|
|
780
|
-
DBOUT(DPAGBuild, outs() << "\n varargs:");
|
|
781
|
-
for (; csArgIt != csArgEit; ++csArgIt)
|
|
782
|
-
{
|
|
783
|
-
const PAGNode *cs_arg = *csArgIt;
|
|
784
|
-
if (cs_arg->isPointer())
|
|
785
|
-
{
|
|
786
|
-
NodeID vnAA = sccRepNode(cs_arg->getId());
|
|
787
|
-
if (addCopyEdge(vnAA,vaF))
|
|
788
|
-
{
|
|
789
|
-
cpySrcNodes.insert(std::make_pair(vnAA,vaF));
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
if(csArgIt != csArgEit)
|
|
795
|
-
{
|
|
796
|
-
writeWrnMsg("too many args to non-vararg func.");
|
|
797
|
-
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
856
|
/*!
|
|
803
857
|
* merge nodeId to newRepId. Return true if the newRepId is a PWC node
|
|
804
858
|
*/
|
|
@@ -122,166 +122,4 @@ void Steensgaard::processAllAddr()
|
|
|
122
122
|
pushIntoWorklist(dst);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
bool Steensgaard::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
128
|
-
{
|
|
129
|
-
|
|
130
|
-
double cgUpdateStart = stat->getClk();
|
|
131
|
-
|
|
132
|
-
CallEdgeMap newEdges;
|
|
133
|
-
onTheFlyCallGraphSolve(callsites, newEdges);
|
|
134
|
-
NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
|
|
135
|
-
for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
|
|
136
|
-
it != eit; ++it)
|
|
137
|
-
{
|
|
138
|
-
for (FunctionSet::iterator cit = it->second.begin(),
|
|
139
|
-
ecit = it->second.end();
|
|
140
|
-
cit != ecit; ++cit)
|
|
141
|
-
{
|
|
142
|
-
connectCaller2CalleeParams(it->first, *cit, cpySrcNodes);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
for (NodePairSet::iterator it = cpySrcNodes.begin(),
|
|
146
|
-
eit = cpySrcNodes.end();
|
|
147
|
-
it != eit; ++it)
|
|
148
|
-
{
|
|
149
|
-
pushIntoWorklist(it->first);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
double cgUpdateEnd = stat->getClk();
|
|
153
|
-
timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
|
|
154
|
-
|
|
155
|
-
return (!newEdges.empty());
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
void Steensgaard::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes)
|
|
159
|
-
{
|
|
160
|
-
assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
|
|
161
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
162
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
163
|
-
NodeID srcret;
|
|
164
|
-
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
165
|
-
if (it != callsite2DummyValPN.end())
|
|
166
|
-
{
|
|
167
|
-
srcret = getEC(it->second);
|
|
168
|
-
}
|
|
169
|
-
else
|
|
170
|
-
{
|
|
171
|
-
NodeID valNode = pag->addDummyValNode();
|
|
172
|
-
NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
|
|
173
|
-
addPts(valNode, objNode);
|
|
174
|
-
callsite2DummyValPN.insert(std::make_pair(cs, valNode));
|
|
175
|
-
consCG->addConstraintNode(new ConstraintNode(valNode), valNode);
|
|
176
|
-
consCG->addConstraintNode(new ConstraintNode(objNode), objNode);
|
|
177
|
-
srcret = valNode;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
NodeID dstrec = getEC(cs_return->getId());
|
|
181
|
-
if (addCopyEdge(srcret, dstrec))
|
|
182
|
-
cpySrcNodes.insert(std::make_pair(srcret, dstrec));
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/*!
|
|
186
|
-
* Connect formal and actual parameters for indirect callsites
|
|
187
|
-
*/
|
|
188
|
-
void Steensgaard::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
189
|
-
NodePairSet& cpySrcNodes)
|
|
190
|
-
{
|
|
191
|
-
assert(F);
|
|
192
|
-
|
|
193
|
-
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite "
|
|
194
|
-
<< cs.getInstruction()->toString() << " to callee "
|
|
195
|
-
<< *F << "\n");
|
|
196
|
-
|
|
197
|
-
const CallICFGNode* callBlockNode = cs;
|
|
198
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
199
|
-
|
|
200
|
-
if (SVFUtil::isHeapAllocExtFunViaRet(F) &&
|
|
201
|
-
pag->callsiteHasRet(retBlockNode))
|
|
202
|
-
{
|
|
203
|
-
heapAllocatorViaIndCall(cs, cpySrcNodes);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
207
|
-
{
|
|
208
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
209
|
-
const PAGNode* fun_return = pag->getFunRet(F);
|
|
210
|
-
if (cs_return->isPointer() && fun_return->isPointer())
|
|
211
|
-
{
|
|
212
|
-
NodeID dstrec = getEC(cs_return->getId());
|
|
213
|
-
NodeID srcret = getEC(fun_return->getId());
|
|
214
|
-
if (addCopyEdge(srcret, dstrec))
|
|
215
|
-
{
|
|
216
|
-
cpySrcNodes.insert(std::make_pair(srcret, dstrec));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
else
|
|
220
|
-
{
|
|
221
|
-
DBOUT(DAndersen, outs() << "not a pointer ignored\n");
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
|
|
226
|
-
{
|
|
227
|
-
|
|
228
|
-
// connect actual and formal param
|
|
229
|
-
const SVFIR::SVFVarList& csArgList =
|
|
230
|
-
pag->getCallSiteArgsList(callBlockNode);
|
|
231
|
-
const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
|
|
232
|
-
// Go through the fixed parameters.
|
|
233
|
-
DBOUT(DPAGBuild, outs() << " args:");
|
|
234
|
-
SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(),
|
|
235
|
-
funArgEit = funArgList.end();
|
|
236
|
-
SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(),
|
|
237
|
-
csArgEit = csArgList.end();
|
|
238
|
-
for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
|
|
239
|
-
{
|
|
240
|
-
// Some programs (e.g. Linux kernel) leave unneeded parameters
|
|
241
|
-
// empty.
|
|
242
|
-
if (csArgIt == csArgEit)
|
|
243
|
-
{
|
|
244
|
-
DBOUT(DAndersen, outs() << " !! not enough args\n");
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
const PAGNode* cs_arg = *csArgIt;
|
|
248
|
-
const PAGNode* fun_arg = *funArgIt;
|
|
249
|
-
|
|
250
|
-
if (cs_arg->isPointer() && fun_arg->isPointer())
|
|
251
|
-
{
|
|
252
|
-
DBOUT(DAndersen, outs() << "process actual parm "
|
|
253
|
-
<< cs_arg->toString() << " \n");
|
|
254
|
-
NodeID srcAA = getEC(cs_arg->getId());
|
|
255
|
-
NodeID dstFA = getEC(fun_arg->getId());
|
|
256
|
-
if (addCopyEdge(srcAA, dstFA))
|
|
257
|
-
{
|
|
258
|
-
cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Any remaining actual args must be varargs.
|
|
264
|
-
if (F->isVarArg())
|
|
265
|
-
{
|
|
266
|
-
NodeID vaF = getEC(pag->getVarargNode(F));
|
|
267
|
-
DBOUT(DPAGBuild, outs() << "\n varargs:");
|
|
268
|
-
for (; csArgIt != csArgEit; ++csArgIt)
|
|
269
|
-
{
|
|
270
|
-
const PAGNode* cs_arg = *csArgIt;
|
|
271
|
-
if (cs_arg->isPointer())
|
|
272
|
-
{
|
|
273
|
-
NodeID vnAA = getEC(cs_arg->getId());
|
|
274
|
-
if (addCopyEdge(vnAA, vaF))
|
|
275
|
-
{
|
|
276
|
-
cpySrcNodes.insert(std::make_pair(vnAA, vaF));
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (csArgIt != csArgEit)
|
|
282
|
-
{
|
|
283
|
-
writeWrnMsg("too many args to non-vararg func.");
|
|
284
|
-
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
125
|
+
}
|
|
@@ -73,7 +73,7 @@ public:
|
|
|
73
73
|
|
|
74
74
|
typedef std::vector<const Function*> FuncVector;
|
|
75
75
|
|
|
76
|
-
DCHNode(const DIType* diType, NodeID i = 0, GNodeK k =
|
|
76
|
+
DCHNode(const DIType* diType, NodeID i = 0, GNodeK k = GNodeK::DCHNodeKd)
|
|
77
77
|
: GenericNode<DCHNode, DCHEdge>(i, k), vtable(nullptr), flags(0)
|
|
78
78
|
{
|
|
79
79
|
this->diType = diType;
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
#include "Graphs/ICFG.h"
|
|
34
34
|
#include "Util/WorkList.h"
|
|
35
35
|
#include "BasicTypes.h"
|
|
36
|
+
#include "LLVMModule.h"
|
|
36
37
|
|
|
37
38
|
namespace SVF
|
|
38
39
|
{
|
|
@@ -44,6 +45,12 @@ public:
|
|
|
44
45
|
|
|
45
46
|
typedef std::vector<const Instruction*> InstVec;
|
|
46
47
|
typedef Set<const Instruction*> BBSet;
|
|
48
|
+
typedef Map<const Instruction*, CallICFGNode *> CSToCallNodeMapTy;
|
|
49
|
+
typedef Map<const Instruction*, RetICFGNode *> CSToRetNodeMapTy;
|
|
50
|
+
typedef Map<const Instruction*, IntraICFGNode *> InstToBlockNodeMapTy;
|
|
51
|
+
typedef Map<const Function*, FunEntryICFGNode *> FunToFunEntryNodeMapTy;
|
|
52
|
+
typedef Map<const Function*, FunExitICFGNode *> FunToFunExitNodeMapTy;
|
|
53
|
+
|
|
47
54
|
|
|
48
55
|
private:
|
|
49
56
|
ICFG* icfg;
|
|
@@ -55,9 +62,42 @@ public:
|
|
|
55
62
|
{
|
|
56
63
|
|
|
57
64
|
}
|
|
58
|
-
void build(
|
|
65
|
+
void build();
|
|
59
66
|
|
|
60
67
|
private:
|
|
68
|
+
|
|
69
|
+
LLVMModuleSet* llvmModuleSet()
|
|
70
|
+
{
|
|
71
|
+
return LLVMModuleSet::getLLVMModuleSet();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
CSToRetNodeMapTy& csToRetNodeMap()
|
|
75
|
+
{
|
|
76
|
+
return llvmModuleSet()->CSToRetNodeMap;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
CSToCallNodeMapTy& csToCallNodeMap()
|
|
80
|
+
{
|
|
81
|
+
return llvmModuleSet()->CSToCallNodeMap;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
InstToBlockNodeMapTy& instToBlockNodeMap()
|
|
85
|
+
{
|
|
86
|
+
return llvmModuleSet()->InstToBlockNodeMap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
FunToFunEntryNodeMapTy& funToFunEntryNodeMap()
|
|
90
|
+
{
|
|
91
|
+
return llvmModuleSet()->FunToFunEntryNodeMap;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
FunToFunExitNodeMapTy& funToFunExitNodeMap()
|
|
95
|
+
{
|
|
96
|
+
return llvmModuleSet()->FunToFunExitNodeMap;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private:
|
|
100
|
+
|
|
61
101
|
/// Create edges between ICFG nodes within a function
|
|
62
102
|
///@{
|
|
63
103
|
void processFunEntry(const Function* fun, WorkList& worklist);
|
|
@@ -71,41 +111,71 @@ private:
|
|
|
71
111
|
|
|
72
112
|
void checkICFGNodesVisited(const Function* fun);
|
|
73
113
|
|
|
74
|
-
void connectGlobalToProgEntry(
|
|
114
|
+
void connectGlobalToProgEntry();
|
|
75
115
|
|
|
76
|
-
/// Add/Get an inter block ICFGNode
|
|
77
|
-
InterICFGNode* addInterBlockICFGNode(const SVFInstruction* inst);
|
|
78
116
|
|
|
79
|
-
///
|
|
80
|
-
|
|
117
|
+
/// Create edges between ICFG nodes across functions
|
|
118
|
+
void addICFGInterEdges(const Instruction* cs, const Function* callee);
|
|
119
|
+
|
|
120
|
+
inline ICFGNode* getICFGNode(const Instruction* inst)
|
|
81
121
|
{
|
|
82
|
-
|
|
83
|
-
if(SVFUtil::isNonInstricCallSite(inst))
|
|
84
|
-
node = addInterBlockICFGNode(inst);
|
|
85
|
-
else
|
|
86
|
-
node = addIntraBlockICFGNode(inst);
|
|
87
|
-
const_cast<SVFBasicBlock*>(inst->getParent())->addICFGNode(node);
|
|
88
|
-
return node;
|
|
122
|
+
return llvmModuleSet()->getICFGNode(inst);
|
|
89
123
|
}
|
|
90
124
|
|
|
91
|
-
|
|
92
|
-
|
|
125
|
+
inline bool hasICFGNode(const Instruction* inst)
|
|
126
|
+
{
|
|
127
|
+
return llvmModuleSet()->hasICFGNode(inst);
|
|
128
|
+
}
|
|
93
129
|
|
|
94
|
-
///
|
|
95
|
-
inline CallICFGNode* getCallICFGNode(const
|
|
130
|
+
/// get a call node
|
|
131
|
+
inline CallICFGNode* getCallICFGNode(const Instruction* cs)
|
|
96
132
|
{
|
|
97
|
-
return
|
|
133
|
+
return llvmModuleSet()->getCallICFGNode(cs);
|
|
98
134
|
}
|
|
99
|
-
///
|
|
100
|
-
inline RetICFGNode* getRetICFGNode(const
|
|
135
|
+
/// get a return node
|
|
136
|
+
inline RetICFGNode* getRetICFGNode(const Instruction* cs)
|
|
101
137
|
{
|
|
102
|
-
return
|
|
138
|
+
return llvmModuleSet()->getRetICFGNode(cs);
|
|
139
|
+
}
|
|
140
|
+
/// get a intra node
|
|
141
|
+
inline IntraICFGNode* getIntraICFGNode(const Instruction* inst)
|
|
142
|
+
{
|
|
143
|
+
return llvmModuleSet()->getIntraICFGNode(inst);
|
|
103
144
|
}
|
|
104
145
|
|
|
146
|
+
/// get a function entry node
|
|
147
|
+
inline FunEntryICFGNode* getFunEntryICFGNode(const Function* fun)
|
|
148
|
+
{
|
|
149
|
+
return llvmModuleSet()->getFunEntryICFGNode(fun);
|
|
150
|
+
}
|
|
151
|
+
/// get a function exit node
|
|
152
|
+
inline FunExitICFGNode* getFunExitICFGNode(const Function* fun)
|
|
153
|
+
{
|
|
154
|
+
return llvmModuleSet()->getFunExitICFGNode(fun);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
inline GlobalICFGNode* getGlobalICFGNode() const
|
|
158
|
+
{
|
|
159
|
+
return icfg->getGlobalICFGNode();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// Add/Get an inter block ICFGNode
|
|
163
|
+
InterICFGNode* addInterBlockICFGNode(const Instruction* inst);
|
|
164
|
+
|
|
165
|
+
/// Add/Get a basic block ICFGNode
|
|
166
|
+
inline ICFGNode* addBlockICFGNode(const Instruction* inst);
|
|
167
|
+
|
|
105
168
|
/// Add and get IntraBlock ICFGNode
|
|
106
|
-
IntraICFGNode* addIntraBlockICFGNode(const
|
|
169
|
+
IntraICFGNode* addIntraBlockICFGNode(const Instruction* inst);
|
|
170
|
+
|
|
171
|
+
FunEntryICFGNode* addFunEntryBlock(const Function* fun);
|
|
172
|
+
|
|
173
|
+
FunExitICFGNode* addFunExitBlock(const Function* fun);
|
|
174
|
+
|
|
175
|
+
inline void addGlobalICFGNode()
|
|
107
176
|
{
|
|
108
|
-
|
|
177
|
+
icfg->globalBlockNode = new GlobalICFGNode(icfg->totalICFGNode++);
|
|
178
|
+
icfg->addICFGNode(icfg->globalBlockNode);
|
|
109
179
|
}
|
|
110
180
|
|
|
111
181
|
private:
|