svf-tools 1.0.1000 → 1.0.1001
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/ICFG.h +43 -0
- package/svf/include/Graphs/ICFGNode.h +48 -33
- package/svf/lib/CFL/CFLAlias.cpp +4 -3
- package/svf/lib/DDA/DDAClient.cpp +3 -3
- package/svf/lib/MemoryModel/PointerAnalysisImpl.cpp +3 -3
- package/svf/lib/SVFIR/SVFFileSystem.cpp +0 -4
- package/svf/lib/WPA/TypeAnalysis.cpp +2 -2
- package/svf-llvm/lib/ICFGBuilder.cpp +27 -25
- package/svf-llvm/lib/SVFIRBuilder.cpp +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1001",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -172,6 +172,49 @@ protected:
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
virtual inline IntraICFGNode* addIntraICFGNode(const SVFBasicBlock* bb, bool isRet)
|
|
176
|
+
{
|
|
177
|
+
IntraICFGNode* intraIcfgNode =
|
|
178
|
+
new IntraICFGNode(totalICFGNode++, bb, isRet);
|
|
179
|
+
addICFGNode(intraIcfgNode);
|
|
180
|
+
return intraIcfgNode;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
virtual inline CallICFGNode* addCallICFGNode(
|
|
184
|
+
const SVFBasicBlock* bb, const SVFType* ty,
|
|
185
|
+
const SVFFunction* calledFunc, bool isVararg, bool isvcall,
|
|
186
|
+
s32_t vcallIdx, const std::string& funNameOfVcall)
|
|
187
|
+
{
|
|
188
|
+
|
|
189
|
+
CallICFGNode* callICFGNode =
|
|
190
|
+
new CallICFGNode(totalICFGNode++, bb, ty, calledFunc, isVararg,
|
|
191
|
+
isvcall, vcallIdx, funNameOfVcall);
|
|
192
|
+
addICFGNode(callICFGNode);
|
|
193
|
+
return callICFGNode;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
virtual inline RetICFGNode* addRetICFGNode(CallICFGNode* call)
|
|
197
|
+
{
|
|
198
|
+
RetICFGNode* retICFGNode = new RetICFGNode(totalICFGNode++, call);
|
|
199
|
+
call->setRetICFGNode(retICFGNode);
|
|
200
|
+
addICFGNode(retICFGNode);
|
|
201
|
+
return retICFGNode;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
virtual inline FunEntryICFGNode* addFunEntryICFGNode(const SVFFunction* svfFunc)
|
|
205
|
+
{
|
|
206
|
+
FunEntryICFGNode* sNode = new FunEntryICFGNode(totalICFGNode++,svfFunc);
|
|
207
|
+
addICFGNode(sNode);
|
|
208
|
+
return FunToFunEntryNodeMap[svfFunc] = sNode;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
virtual inline FunExitICFGNode* addFunExitICFGNode(const SVFFunction* svfFunc)
|
|
212
|
+
{
|
|
213
|
+
FunExitICFGNode* sNode = new FunExitICFGNode(totalICFGNode++, svfFunc);
|
|
214
|
+
addICFGNode(sNode);
|
|
215
|
+
return FunToFunExitNodeMap[svfFunc] = sNode;
|
|
216
|
+
}
|
|
217
|
+
|
|
175
218
|
/// Add a ICFG node
|
|
176
219
|
virtual inline void addICFGNode(ICFGNode* node)
|
|
177
220
|
{
|
|
@@ -428,19 +428,28 @@ public:
|
|
|
428
428
|
typedef std::vector<const SVFVar *> ActualParmNodeVec;
|
|
429
429
|
|
|
430
430
|
protected:
|
|
431
|
-
const SVFInstruction* cs;
|
|
432
431
|
const RetICFGNode* ret;
|
|
433
|
-
ActualParmNodeVec APNodes;
|
|
432
|
+
ActualParmNodeVec APNodes; /// arguments
|
|
433
|
+
const SVFFunction* calledFunc; /// called function
|
|
434
|
+
bool isvararg; /// is variable argument
|
|
435
|
+
bool isVirCallInst; /// is virtual call inst
|
|
436
|
+
SVFVar* vtabPtr; /// virtual table pointer
|
|
437
|
+
s32_t virtualFunIdx; /// virtual function index of the virtual table(s) at a virtual call
|
|
438
|
+
std::string funNameOfVcall; /// the function name of this virtual call
|
|
434
439
|
|
|
435
440
|
/// Constructor to create empty CallICFGNode (for SVFIRReader/deserialization)
|
|
436
|
-
CallICFGNode(NodeID id) : InterICFGNode(id, FunCallBlock),
|
|
441
|
+
CallICFGNode(NodeID id) : InterICFGNode(id, FunCallBlock), ret{} {}
|
|
437
442
|
|
|
438
443
|
public:
|
|
439
|
-
CallICFGNode(NodeID id, const
|
|
440
|
-
|
|
444
|
+
CallICFGNode(NodeID id, const SVFBasicBlock* b, const SVFType* ty,
|
|
445
|
+
const SVFFunction* cf, bool iv, bool ivc, s32_t vfi,
|
|
446
|
+
const std::string& fnv)
|
|
447
|
+
: InterICFGNode(id, FunCallBlock), ret(nullptr), calledFunc(cf),
|
|
448
|
+
isvararg(iv), isVirCallInst(ivc), vtabPtr(nullptr),
|
|
449
|
+
virtualFunIdx(vfi), funNameOfVcall(fnv)
|
|
441
450
|
{
|
|
442
|
-
fun =
|
|
443
|
-
bb =
|
|
451
|
+
fun = b->getFunction();
|
|
452
|
+
bb = b;
|
|
444
453
|
type = ty;
|
|
445
454
|
}
|
|
446
455
|
|
|
@@ -472,7 +481,7 @@ public:
|
|
|
472
481
|
/// Return true if this is an indirect call
|
|
473
482
|
inline bool isIndirectCall() const
|
|
474
483
|
{
|
|
475
|
-
return nullptr ==
|
|
484
|
+
return nullptr == calledFunc;
|
|
476
485
|
}
|
|
477
486
|
|
|
478
487
|
/// Return the set of actual parameters
|
|
@@ -488,54 +497,61 @@ public:
|
|
|
488
497
|
}
|
|
489
498
|
/// Parameter operations
|
|
490
499
|
//@{
|
|
491
|
-
const SVFVar* getArgument(u32_t ArgNo) const
|
|
500
|
+
inline const SVFVar* getArgument(u32_t ArgNo) const
|
|
492
501
|
{
|
|
493
502
|
return getActualParms()[ArgNo];
|
|
494
503
|
}
|
|
495
504
|
|
|
496
|
-
u32_t arg_size() const
|
|
505
|
+
inline u32_t arg_size() const
|
|
497
506
|
{
|
|
498
507
|
return APNodes.size();
|
|
499
508
|
}
|
|
500
|
-
bool arg_empty() const
|
|
509
|
+
inline bool arg_empty() const
|
|
501
510
|
{
|
|
502
511
|
return APNodes.empty();
|
|
503
512
|
}
|
|
504
513
|
|
|
505
|
-
u32_t getNumArgOperands() const
|
|
514
|
+
inline u32_t getNumArgOperands() const
|
|
506
515
|
{
|
|
507
516
|
return arg_size();
|
|
508
517
|
}
|
|
509
|
-
const SVFFunction* getCalledFunction() const
|
|
518
|
+
inline const SVFFunction* getCalledFunction() const
|
|
510
519
|
{
|
|
511
|
-
return
|
|
520
|
+
return calledFunc;
|
|
512
521
|
}
|
|
513
|
-
|
|
522
|
+
|
|
523
|
+
inline bool isVarArg() const
|
|
514
524
|
{
|
|
515
|
-
return
|
|
525
|
+
return isvararg;
|
|
516
526
|
}
|
|
517
|
-
bool
|
|
527
|
+
inline bool isVirtualCall() const
|
|
518
528
|
{
|
|
519
|
-
return
|
|
529
|
+
return isVirCallInst;
|
|
520
530
|
}
|
|
521
|
-
|
|
531
|
+
|
|
532
|
+
inline void setVtablePtr(SVFVar* v)
|
|
522
533
|
{
|
|
523
|
-
|
|
534
|
+
vtabPtr = v;
|
|
524
535
|
}
|
|
525
|
-
|
|
536
|
+
|
|
537
|
+
inline const SVFVar* getVtablePtr() const
|
|
526
538
|
{
|
|
527
539
|
assert(isVirtualCall() && "not a virtual call?");
|
|
528
|
-
return
|
|
540
|
+
return vtabPtr;
|
|
529
541
|
}
|
|
530
|
-
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
inline s32_t getFunIdxInVtable() const
|
|
531
545
|
{
|
|
532
546
|
assert(isVirtualCall() && "not a virtual call?");
|
|
533
|
-
|
|
547
|
+
assert(virtualFunIdx >=0 && "virtual function idx is less than 0? not set yet?");
|
|
548
|
+
return virtualFunIdx;
|
|
534
549
|
}
|
|
535
|
-
|
|
550
|
+
|
|
551
|
+
inline const std::string& getFunNameOfVirtualCall() const
|
|
536
552
|
{
|
|
537
553
|
assert(isVirtualCall() && "not a virtual call?");
|
|
538
|
-
return
|
|
554
|
+
return funNameOfVcall;
|
|
539
555
|
}
|
|
540
556
|
//@}
|
|
541
557
|
|
|
@@ -585,23 +601,22 @@ class RetICFGNode : public InterICFGNode
|
|
|
585
601
|
friend class SVFIRReader;
|
|
586
602
|
|
|
587
603
|
private:
|
|
588
|
-
const SVFInstruction* cs;
|
|
589
604
|
const SVFVar *actualRet;
|
|
590
605
|
const CallICFGNode* callBlockNode;
|
|
591
606
|
|
|
592
607
|
/// Constructor to create empty RetICFGNode (for SVFIRReader/deserialization)
|
|
593
608
|
RetICFGNode(NodeID id)
|
|
594
|
-
: InterICFGNode(id, FunRetBlock),
|
|
609
|
+
: InterICFGNode(id, FunRetBlock), actualRet{}, callBlockNode{}
|
|
595
610
|
{
|
|
596
611
|
}
|
|
597
612
|
|
|
598
613
|
public:
|
|
599
|
-
RetICFGNode(NodeID id,
|
|
600
|
-
InterICFGNode(id, FunRetBlock),
|
|
614
|
+
RetICFGNode(NodeID id, CallICFGNode* cb) :
|
|
615
|
+
InterICFGNode(id, FunRetBlock), actualRet(nullptr), callBlockNode(cb)
|
|
601
616
|
{
|
|
602
|
-
fun =
|
|
603
|
-
bb =
|
|
604
|
-
type =
|
|
617
|
+
fun = cb->getFun();
|
|
618
|
+
bb = cb->getBB();
|
|
619
|
+
type = cb->getType();
|
|
605
620
|
}
|
|
606
621
|
|
|
607
622
|
inline const CallICFGNode* getCallICFGNode() const
|
package/svf/lib/CFL/CFLAlias.cpp
CHANGED
|
@@ -44,9 +44,10 @@ void CFLAlias::onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites, Call
|
|
|
44
44
|
|
|
45
45
|
if (cs->isVirtualCall())
|
|
46
46
|
{
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
const SVFVar* vtbl = cs->getVtablePtr();
|
|
48
|
+
|
|
49
|
+
assert(vtbl != nullptr);
|
|
50
|
+
NodeID vtblId = vtbl->getId();
|
|
50
51
|
resolveCPPIndCalls(cs, getCFLPts(vtblId), newEdges);
|
|
51
52
|
}
|
|
52
53
|
else
|
|
@@ -83,9 +83,9 @@ OrderedNodeSet& FunptrDDAClient::collectCandidateQueries(SVFIR* p)
|
|
|
83
83
|
{
|
|
84
84
|
if (it->first->isVirtualCall())
|
|
85
85
|
{
|
|
86
|
-
const
|
|
87
|
-
assert(
|
|
88
|
-
NodeID vtblId =
|
|
86
|
+
const SVFVar* vtblPtr = it->first->getVtablePtr();
|
|
87
|
+
assert(vtblPtr != nullptr && "not a vtable pointer?");
|
|
88
|
+
NodeID vtblId = vtblPtr->getId();
|
|
89
89
|
addCandidate(vtblId);
|
|
90
90
|
vtableToCallSiteMap[vtblId] = it->first;
|
|
91
91
|
}
|
|
@@ -497,9 +497,9 @@ void BVDataPTAImpl::onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites,
|
|
|
497
497
|
|
|
498
498
|
if (cs->isVirtualCall())
|
|
499
499
|
{
|
|
500
|
-
const
|
|
501
|
-
assert(
|
|
502
|
-
NodeID vtblId =
|
|
500
|
+
const SVFVar* vtbl = cs->getVtablePtr();
|
|
501
|
+
assert(vtbl != nullptr);
|
|
502
|
+
NodeID vtblId = vtbl->getId();
|
|
503
503
|
resolveCPPIndCalls(cs, getPts(vtblId), newEdges);
|
|
504
504
|
}
|
|
505
505
|
else
|
|
@@ -412,7 +412,6 @@ cJSON* SVFIRWriter::contentToJson(const FunExitICFGNode* node)
|
|
|
412
412
|
cJSON* SVFIRWriter::contentToJson(const CallICFGNode* node)
|
|
413
413
|
{
|
|
414
414
|
cJSON* root = contentToJson(static_cast<const ICFGNode*>(node));
|
|
415
|
-
JSON_WRITE_FIELD(root, node, cs);
|
|
416
415
|
JSON_WRITE_FIELD(root, node, ret);
|
|
417
416
|
JSON_WRITE_FIELD(root, node, APNodes);
|
|
418
417
|
return root;
|
|
@@ -421,7 +420,6 @@ cJSON* SVFIRWriter::contentToJson(const CallICFGNode* node)
|
|
|
421
420
|
cJSON* SVFIRWriter::contentToJson(const RetICFGNode* node)
|
|
422
421
|
{
|
|
423
422
|
cJSON* root = contentToJson(static_cast<const ICFGNode*>(node));
|
|
424
|
-
JSON_WRITE_FIELD(root, node, cs);
|
|
425
423
|
JSON_WRITE_FIELD(root, node, actualRet);
|
|
426
424
|
JSON_WRITE_FIELD(root, node, callBlockNode);
|
|
427
425
|
return root;
|
|
@@ -2205,7 +2203,6 @@ void SVFIRReader::fill(const cJSON*& fieldJson, FunExitICFGNode* node)
|
|
|
2205
2203
|
void SVFIRReader::fill(const cJSON*& fieldJson, CallICFGNode* node)
|
|
2206
2204
|
{
|
|
2207
2205
|
fill(fieldJson, static_cast<ICFGNode*>(node));
|
|
2208
|
-
JSON_READ_FIELD_FWD(fieldJson, node, cs);
|
|
2209
2206
|
JSON_READ_FIELD_FWD(fieldJson, node, ret);
|
|
2210
2207
|
JSON_READ_FIELD_FWD(fieldJson, node, APNodes);
|
|
2211
2208
|
}
|
|
@@ -2213,7 +2210,6 @@ void SVFIRReader::fill(const cJSON*& fieldJson, CallICFGNode* node)
|
|
|
2213
2210
|
void SVFIRReader::fill(const cJSON*& fieldJson, RetICFGNode* node)
|
|
2214
2211
|
{
|
|
2215
2212
|
fill(fieldJson, static_cast<ICFGNode*>(node));
|
|
2216
|
-
JSON_READ_FIELD_FWD(fieldJson, node, cs);
|
|
2217
2213
|
JSON_READ_FIELD_FWD(fieldJson, node, actualRet);
|
|
2218
2214
|
JSON_READ_FIELD_FWD(fieldJson, node, callBlockNode);
|
|
2219
2215
|
}
|
|
@@ -79,9 +79,9 @@ void TypeAnalysis::callGraphSolveBasedOnCHA(const CallSiteToFunPtrMap& callsites
|
|
|
79
79
|
const CallICFGNode* cbn = iter->first;
|
|
80
80
|
if (cbn->isVirtualCall())
|
|
81
81
|
{
|
|
82
|
-
const
|
|
82
|
+
const SVFVar* vtbl = cbn->getVtablePtr();
|
|
83
83
|
(void)vtbl; // Suppress warning of unused variable under release build
|
|
84
|
-
assert(
|
|
84
|
+
assert(vtbl != nullptr);
|
|
85
85
|
VFunSet vfns;
|
|
86
86
|
getVFnsFromCHA(cbn, vfns);
|
|
87
87
|
connectVCallToVFns(cbn, vfns, newEdges);
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
#include "SVF-LLVM/ICFGBuilder.h"
|
|
32
|
+
#include "SVF-LLVM/CppUtil.h"
|
|
32
33
|
#include "SVF-LLVM/LLVMModule.h"
|
|
33
34
|
#include "SVF-LLVM/LLVMUtil.h"
|
|
34
35
|
|
|
@@ -239,17 +240,30 @@ InterICFGNode* ICFGBuilder::addInterBlockICFGNode(const Instruction* inst)
|
|
|
239
240
|
assert(LLVMUtil::isCallSite(inst) && "not a call instruction?");
|
|
240
241
|
assert(LLVMUtil::isNonInstricCallSite(inst) && "associating an intrinsic debug instruction with an ICFGNode!");
|
|
241
242
|
assert(llvmModuleSet()->getCallBlock(inst)==nullptr && "duplicate CallICFGNode");
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
const CallBase* cb = SVFUtil::dyn_cast<CallBase>(inst);
|
|
244
|
+
bool isvcall = cppUtil::isVirtualCallSite(cb);
|
|
245
|
+
SVFFunction* calledFunc = nullptr;
|
|
246
|
+
auto called_llvmval = cb->getCalledOperand()->stripPointerCasts();
|
|
247
|
+
if (const Function* called_llvmfunc = SVFUtil::dyn_cast<Function>(called_llvmval))
|
|
248
|
+
{
|
|
249
|
+
calledFunc = llvmModuleSet()->getSVFFunction(called_llvmfunc);
|
|
250
|
+
}
|
|
251
|
+
else
|
|
252
|
+
{
|
|
253
|
+
calledFunc = SVFUtil::dyn_cast<SVFFunction>(
|
|
254
|
+
llvmModuleSet()->getSVFValue(called_llvmval));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
CallICFGNode* callICFGNode = icfg->addCallICFGNode(
|
|
258
|
+
svfInst->getParent(), llvmModuleSet()->getSVFType(inst->getType()),
|
|
259
|
+
calledFunc, cb->getFunctionType()->isVarArg(), isvcall,
|
|
260
|
+
isvcall ? cppUtil::getVCallIdx(cb) : 0,
|
|
261
|
+
isvcall ? cppUtil::getFunNameOfVCallSite(cb) : "");
|
|
246
262
|
csToCallNodeMap()[inst] = callICFGNode;
|
|
247
263
|
llvmModuleSet()->setValueAttr(inst, callICFGNode);
|
|
248
264
|
|
|
249
265
|
assert(llvmModuleSet()->getRetBlock(inst)==nullptr && "duplicate RetICFGNode");
|
|
250
|
-
RetICFGNode* retICFGNode =
|
|
251
|
-
callICFGNode->setRetICFGNode(retICFGNode);
|
|
252
|
-
icfg->addICFGNode(retICFGNode);
|
|
266
|
+
RetICFGNode* retICFGNode = icfg->addRetICFGNode(callICFGNode);
|
|
253
267
|
csToRetNodeMap()[inst] = retICFGNode;
|
|
254
268
|
llvmModuleSet()->setValueAttr(inst, retICFGNode);
|
|
255
269
|
|
|
@@ -333,10 +347,8 @@ IntraICFGNode* ICFGBuilder::addIntraBlockICFGNode(const Instruction* inst)
|
|
|
333
347
|
llvmModuleSet()->getSVFInstruction(inst);
|
|
334
348
|
IntraICFGNode* node = llvmModuleSet()->getIntraBlock(inst);
|
|
335
349
|
assert (node==nullptr && "no IntraICFGNode for this instruction?");
|
|
336
|
-
IntraICFGNode* sNode =
|
|
337
|
-
|
|
338
|
-
SVFUtil::isa<ReturnInst>(inst));
|
|
339
|
-
icfg->addICFGNode(sNode);
|
|
350
|
+
IntraICFGNode* sNode = icfg->addIntraICFGNode(
|
|
351
|
+
svfInst->getParent(), SVFUtil::isa<ReturnInst>(inst));
|
|
340
352
|
instToBlockNodeMap()[inst] = sNode;
|
|
341
353
|
llvmModuleSet()->setValueAttr(inst, sNode);
|
|
342
354
|
return sNode;
|
|
@@ -344,22 +356,12 @@ IntraICFGNode* ICFGBuilder::addIntraBlockICFGNode(const Instruction* inst)
|
|
|
344
356
|
|
|
345
357
|
FunEntryICFGNode* ICFGBuilder::addFunEntryBlock(const Function* fun)
|
|
346
358
|
{
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
FunEntryICFGNode* sNode = new FunEntryICFGNode(icfg->totalICFGNode++,svfFunc);
|
|
350
|
-
icfg->addICFGNode(sNode);
|
|
351
|
-
funToFunEntryNodeMap()[fun] = sNode;
|
|
352
|
-
icfg->FunToFunEntryNodeMap[svfFunc] = sNode;
|
|
353
|
-
return sNode;
|
|
359
|
+
return funToFunEntryNodeMap()[fun] =
|
|
360
|
+
icfg->addFunEntryICFGNode(llvmModuleSet()->getSVFFunction(fun));
|
|
354
361
|
}
|
|
355
362
|
|
|
356
363
|
inline FunExitICFGNode* ICFGBuilder::addFunExitBlock(const Function* fun)
|
|
357
364
|
{
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
FunExitICFGNode* sNode = new FunExitICFGNode(icfg->totalICFGNode++, svfFunc);
|
|
361
|
-
icfg->addICFGNode(sNode);
|
|
362
|
-
funToFunExitNodeMap()[fun] = sNode;
|
|
363
|
-
icfg->FunToFunExitNodeMap[svfFunc] = sNode;
|
|
364
|
-
return sNode;
|
|
365
|
+
return funToFunExitNodeMap()[fun] =
|
|
366
|
+
icfg->addFunExitICFGNode(llvmModuleSet()->getSVFFunction(fun));
|
|
365
367
|
}
|
|
@@ -871,6 +871,11 @@ void SVFIRBuilder::visitCallSite(CallBase* cs)
|
|
|
871
871
|
if(!cs->getType()->isVoidTy())
|
|
872
872
|
pag->addCallSiteRets(retBlockNode,pag->getGNode(getValueNode(cs)));
|
|
873
873
|
|
|
874
|
+
if (callBlockNode->isVirtualCall())
|
|
875
|
+
{
|
|
876
|
+
const Value* value = cppUtil::getVCallVtblPtr(cs);
|
|
877
|
+
callBlockNode->setVtablePtr(pag->getGNode(getValueNode(value)));
|
|
878
|
+
}
|
|
874
879
|
if (const Function *callee = LLVMUtil::getCallee(cs))
|
|
875
880
|
{
|
|
876
881
|
const SVFFunction* svfcallee = llvmModuleSet()->getSVFFunction(callee);
|