diff --git a/svf-llvm/include/SVF-LLVM/ICFGBuilder.h b/svf-llvm/include/SVF-LLVM/ICFGBuilder.h index 6ce771c2a..204e2e968 100644 --- a/svf-llvm/include/SVF-LLVM/ICFGBuilder.h +++ b/svf-llvm/include/SVF-LLVM/ICFGBuilder.h @@ -148,7 +148,7 @@ class ICFGBuilder inline void addGlobalICFGNode() { icfg->globalBlockNode = new GlobalICFGNode(icfg->totalICFGNode++); - icfg->addICFGNode(icfg->globalBlockNode); + icfg->addGlobalICFGNode(icfg->globalBlockNode); } private: diff --git a/svf-llvm/include/SVF-LLVM/SVFIRBuilder.h b/svf-llvm/include/SVF-LLVM/SVFIRBuilder.h index dc79337ff..e337475e1 100644 --- a/svf-llvm/include/SVF-LLVM/SVFIRBuilder.h +++ b/svf-llvm/include/SVF-LLVM/SVFIRBuilder.h @@ -46,6 +46,7 @@ namespace SVF */ class SVFIRBuilder: public llvm::InstVisitor { +friend class GraphDBSVFIRBuilder; private: SVFIR* pag; diff --git a/svf-llvm/lib/SVFIRBuilder.cpp b/svf-llvm/lib/SVFIRBuilder.cpp index 9168faed1..cc19f223a 100644 --- a/svf-llvm/lib/SVFIRBuilder.cpp +++ b/svf-llvm/lib/SVFIRBuilder.cpp @@ -56,14 +56,7 @@ SVFIR* SVFIRBuilder::build() double startTime = SVFStat::getClk(true); DBOUT(DGENERAL, outs() << pasMsg("\t Building SVFIR ...\n")); - - // We read SVFIR from a user-defined txt instead of parsing SVFIR from LLVM IR - if (SVFIR::pagReadFromTXT()) - { - PAGBuilderFromFile fileBuilder(SVFIR::pagFileName()); - return fileBuilder.build(); - } - + // If the SVFIR has been built before, then we return the unique SVFIR of the program if(pag->getNodeNumAfterPAGBuild() > 1) return pag; @@ -1597,7 +1590,9 @@ const Value* SVFIRBuilder::getBaseValueForExtArg(const Value* V) void SVFIRBuilder::handleIndCall(CallBase* cs) { const CallICFGNode* cbn = llvmModuleSet()->getCallICFGNode(cs); - pag->addIndirectCallsites(cbn,llvmModuleSet()->getValueNode(cs->getCalledOperand())); + NodeID indFunPtrId = llvmModuleSet()->getValueNode(cs->getCalledOperand()); + const_cast(cbn)->setIndFunPtr(pag->getGNode(indFunPtrId)); + pag->addIndirectCallsites(cbn,indFunPtrId); } void SVFIRBuilder::updateCallGraph(CallGraph* callgraph) diff --git a/svf-llvm/tools/SABER/saber.cpp b/svf-llvm/tools/SABER/saber.cpp index 15555a4bd..86c1a2fd5 100644 --- a/svf-llvm/tools/SABER/saber.cpp +++ b/svf-llvm/tools/SABER/saber.cpp @@ -47,9 +47,24 @@ int main(int argc, char ** argv) argc, argv, "Source-Sink Bug Detector", "[options] " ); - LLVMModuleSet::buildSVFModule(moduleNameVec); SVFIRBuilder builder; - SVFIR* pag = builder.build(); + SVFIR* pag; + + if (Options::ReadFromDB()) + { + pag = builder.build(); + pag->setPagFromTXT("ReadFromDB"); + } + else + { + if (Options::WriteAnder() == "ir_annotator") + { + LLVMModuleSet::preProcessBCs(moduleNameVec); + } + + LLVMModuleSet::buildSVFModule(moduleNameVec); + pag = builder.build(); + } std::unique_ptr saber; diff --git a/svf-llvm/tools/WPA/wpa.cpp b/svf-llvm/tools/WPA/wpa.cpp index ebb6b80e9..a64023efb 100644 --- a/svf-llvm/tools/WPA/wpa.cpp +++ b/svf-llvm/tools/WPA/wpa.cpp @@ -46,9 +46,11 @@ int main(int argc, char** argv) // Refers to content of a singleton unique_ptr in SVFIR. SVFIR* pag; - if (Options::ReadJson()) + if (Options::ReadFromDB()) { - assert(false && "please implement SVFIRReader::read"); + SVFIRBuilder builder; + pag = builder.build(); + pag->setPagFromTXT("ReadFromDB"); } else { diff --git a/svf/include/Graphs/BasicBlockG.h b/svf/include/Graphs/BasicBlockG.h index 495c3f335..2507f23cc 100644 --- a/svf/include/Graphs/BasicBlockG.h +++ b/svf/include/Graphs/BasicBlockG.h @@ -74,6 +74,7 @@ class SVFBasicBlock : public GenericBasicBlockNodeTy friend class FunObjVar; friend class ICFGBuilder; friend class ICFG; + friend class GraphDBClient; public: typedef std::vector::const_iterator const_iterator; @@ -98,6 +99,17 @@ class SVFBasicBlock : public GenericBasicBlockNodeTy /// @} + // Getters of predecessor and successor basic blocks, used for writing bb to DB + const std::vector getSuccBBs() const + { + return succBBs; + } + + const std::vector getPredBBs() const + { + return predBBs; + } + public: /// Constructor without name SVFBasicBlock(NodeID id, const FunObjVar* f): GenericBasicBlockNodeTy(id, BasicBlockKd), fun(f) @@ -293,20 +305,23 @@ class BasicBlockGraph: public GenericBasicBlockGraphTy NodeID id{0}; public: /// Constructor - BasicBlockGraph() + BasicBlockGraph(): GenericBasicBlockGraphTy() { } + SVFBasicBlock* addBasicBlock(const std::string& bbname) { id++; SVFBasicBlock* bb = new SVFBasicBlock(id, nullptr); - addGNode(id, bb); bb->setName(bbname); + addBasicBlock(bb); return bb; } + void addBasicBlock(SVFBasicBlock* bb); + }; } diff --git a/svf/include/Graphs/CHG.h b/svf/include/Graphs/CHG.h index d0ca8fa46..6723cba0b 100644 --- a/svf/include/Graphs/CHG.h +++ b/svf/include/Graphs/CHG.h @@ -105,6 +105,7 @@ class CHEdge: public GenericCHEdgeTy typedef GenericNode GenericCHNodeTy; class CHNode: public GenericCHNodeTy { + friend class GraphDBClient; public: typedef enum @@ -222,6 +223,16 @@ class CHNode: public GenericCHNodeTy * virtualFunctionVectors = {{Af1, Af2, ...}, {Bg1, Bg2, ...}} */ std::vector virtualFunctionVectors; + +protected: + inline size_t getFlags() const + { + return flags; + } + inline void setFlags(size_t f) + { + flags = f; + } }; /// class hierarchy graph @@ -229,6 +240,7 @@ typedef GenericGraph GenericCHGraphTy; class CHGraph: public CommonCHGraph, public GenericCHGraphTy { friend class CHGBuilder; + friend class GraphDBClient; public: typedef Set CHNodeSetTy; diff --git a/svf/include/Graphs/CallGraph.h b/svf/include/Graphs/CallGraph.h index 8270da169..c7f129efe 100644 --- a/svf/include/Graphs/CallGraph.h +++ b/svf/include/Graphs/CallGraph.h @@ -224,6 +224,20 @@ class CallGraphNode : public GenericPTACallGraphNodeTy { return node->getNodeKind() == CallNodeKd; } + + std::string sourceLocToDBString() const + { + std::string sourceLoc = ""; + if (!getSourceLoc().empty()) + { + sourceLoc = ", source_loc: '" + getSourceLoc() + "'"; + } + else + { + sourceLoc = ", source_loc: ''"; + } + return sourceLoc; + } //@} }; @@ -233,6 +247,8 @@ class CallGraphNode : public GenericPTACallGraphNodeTy typedef GenericGraph GenericPTACallGraphTy; class CallGraph : public GenericPTACallGraphTy { + friend class GraphDBClient; + public: typedef CallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet; @@ -281,13 +297,14 @@ class CallGraph : public GenericPTACallGraphTy if(it == csToIdMap.end()) { CallSiteID id = totalCallSiteNum++; - csToIdMap.insert(std::make_pair(newCS, id)); - idToCSMap.insert(std::make_pair(id, newCS)); + addCallSite(cs,callee,id); return id; } return it->second; } + CallSiteID addCallSite(const CallICFGNode* cs, const FunObjVar* callee, const CallSiteID csid); + /// Add call graph edge inline void addEdge(CallGraphEdge* edge) { @@ -295,6 +312,17 @@ class CallGraph : public GenericPTACallGraphTy edge->getSrcNode()->addOutgoingEdge(edge); } + /// add direct call graph edge from database [only used this function when loading cgEdges from db results] + void addDirectCallGraphEdge(CallGraphEdge* cgEdge); + + /// add call graph node from database [only used this function when loading cgNodes from db results] + void addCallGraphNode(CallGraphNode* cgNode); + + /// Whether we have already created this call graph edge, only used when adding new edge from db query results + CallGraphEdge* hasGraphEdge(CallGraphEdge* cgEdge) const; + + /// Add indirect call graph edge from database [only used this function when loading cgEdges from db results] + void addIndirectCallGraphEdge(CallGraphEdge* cgEdge); public: /// Constructor CallGraph(CGEK k = NormCallGraph); diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 88234a551..f0d31130b 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -48,6 +48,7 @@ class ICFG : public GenericICFGTy { friend class ICFGBuilder; friend class ICFGSimplification; + friend class GraphDBClient; public: @@ -198,23 +199,32 @@ class ICFG : public GenericICFGTy virtual inline FunEntryICFGNode* addFunEntryICFGNode(const FunObjVar* svfFunc) { FunEntryICFGNode* sNode = new FunEntryICFGNode(totalICFGNode++,svfFunc); - addICFGNode(sNode); - return FunToFunEntryNodeMap[svfFunc] = sNode; + return addFunEntryICFGNode(sNode); } + virtual inline FunEntryICFGNode* addFunEntryICFGNode(FunEntryICFGNode* funEntryICFGNode) + { + addICFGNode(funEntryICFGNode); + return FunToFunEntryNodeMap[funEntryICFGNode->getFun()] = funEntryICFGNode; + } + + virtual void addGlobalICFGNode(GlobalICFGNode* globalICFGNode); + virtual inline FunExitICFGNode* addFunExitICFGNode(const FunObjVar* svfFunc) { FunExitICFGNode* sNode = new FunExitICFGNode(totalICFGNode++, svfFunc); - addICFGNode(sNode); - return FunToFunExitNodeMap[svfFunc] = sNode; + return addFunExitICFGNode(sNode); } - /// Add a ICFG node - virtual inline void addICFGNode(ICFGNode* node) + virtual inline FunExitICFGNode* addFunExitICFGNode(FunExitICFGNode* funExitICFGNode) { - addGNode(node->getId(),node); + addICFGNode(funExitICFGNode); + return FunToFunExitNodeMap[funExitICFGNode->getFun()] = funExitICFGNode; } + /// Add a ICFG node + virtual void addICFGNode(ICFGNode* node); + public: /// Get a basic block ICFGNode /// TODO:: need to fix the assertions diff --git a/svf/include/Graphs/ICFGEdge.h b/svf/include/Graphs/ICFGEdge.h index 1beeac6bf..233ec4110 100644 --- a/svf/include/Graphs/ICFGEdge.h +++ b/svf/include/Graphs/ICFGEdge.h @@ -112,6 +112,7 @@ class IntraCFGEdge : public ICFGEdge { friend class ICFG; friend class SVFIRBuilder; + friend class GraphDBClient; public: /// Constructor diff --git a/svf/include/Graphs/ICFGNode.h b/svf/include/Graphs/ICFGNode.h index 5a62e6952..53f20a3c9 100644 --- a/svf/include/Graphs/ICFGNode.h +++ b/svf/include/Graphs/ICFGNode.h @@ -141,6 +141,19 @@ class ICFGNode : public GenericICFGNodeTy } + std::string sourceLocToDBString() const + { + std::string sourceLoc = ""; + if (getSourceLoc().empty() == false) + { + sourceLoc = ", source_loc: '" + getSourceLoc() + "'"; + } + else + { + sourceLoc = ", source_loc: ''"; + } + return sourceLoc; + } protected: const FunObjVar* fun; @@ -192,6 +205,16 @@ class GlobalICFGNode : public ICFGNode */ class IntraICFGNode : public ICFGNode { + friend class GraphDBClient; + +protected: + IntraICFGNode(NodeID id, const SVFBasicBlock* b, const FunObjVar* f, bool isReturn): ICFGNode(id, IntraBlock),isRet(isReturn) + { + + this->fun = f; + this->bb = b; + } + private: bool isRet; @@ -270,6 +293,15 @@ class InterICFGNode : public ICFGNode */ class FunEntryICFGNode : public InterICFGNode { + friend class GraphDBClient; + +protected: + FunEntryICFGNode(NodeID id, const FunObjVar* f, SVFBasicBlock* b) + : InterICFGNode(id, FunEntryBlock) + { + this->fun = f; + this->bb = b; + } public: typedef std::vector FormalParmNodeVec; @@ -335,6 +367,15 @@ class FunEntryICFGNode : public InterICFGNode */ class FunExitICFGNode : public InterICFGNode { + friend class GraphDBClient; + +protected: + FunExitICFGNode(NodeID id, const FunObjVar* f, SVFBasicBlock* b) + : InterICFGNode(id, FunExitBlock), formalRet(nullptr) + { + this->fun = f; + this->bb = b; + } private: const SVFVar *formalRet; @@ -398,6 +439,7 @@ class FunExitICFGNode : public InterICFGNode */ class CallICFGNode : public InterICFGNode { + friend class GraphDBClient; public: typedef std::vector ActualParmNodeVec; @@ -411,6 +453,20 @@ class CallICFGNode : public InterICFGNode SVFVar* vtabPtr; /// virtual table pointer s32_t virtualFunIdx; /// virtual function index of the virtual table(s) at a virtual call std::string funNameOfVcall; /// the function name of this virtual call + const SVFVar* indFunPtr; + + CallICFGNode(NodeID id, const SVFBasicBlock* b, const SVFType* ty, + const FunObjVar* f, const FunObjVar* cf, const RetICFGNode* ret, + bool iv, bool ivc, s32_t vfi, SVFVar* vtabPtr, const std::string& fnv) + : InterICFGNode(id, FunCallBlock), ret(ret), calledFunc(cf), + isvararg(iv), isVirCallInst(ivc), vtabPtr(vtabPtr), + virtualFunIdx(vfi), funNameOfVcall(fnv) + { + this->fun = f; + this->bb = b; + this->type = ty; + } + public: CallICFGNode(NodeID id, const SVFBasicBlock* b, const SVFType* ty, @@ -561,6 +617,18 @@ class CallICFGNode : public InterICFGNode { return "CallICFGNode: " + ICFGNode::getSourceLoc(); } + + inline void setIndFunPtr(const SVFVar* indFun) + { + assert(isIndirectCall() && "not a indirect call?"); + indFunPtr = indFun; + } + + inline const SVFVar* getIndFunPtr() const + { + assert(isIndirectCall() && "not a indirect call?"); + return indFunPtr; + } }; @@ -569,6 +637,22 @@ class CallICFGNode : public InterICFGNode */ class RetICFGNode : public InterICFGNode { + friend class GraphDBClient; + +protected: + RetICFGNode(NodeID id, const SVFType* ty, const SVFBasicBlock* b, const FunObjVar* f) : + InterICFGNode(id, FunRetBlock), actualRet(nullptr), callBlockNode(nullptr) + { + this->fun = f; + this->bb = b; + this->type = ty; + } + + /// Add call block node from database for the new RetICFGNode [only used this function when loading from db results] + inline void addCallBlockNodeFromDB(const CallICFGNode* cb) + { + callBlockNode = cb; + } private: const SVFVar *actualRet; diff --git a/svf/include/Graphs/IRGraph.h b/svf/include/Graphs/IRGraph.h index 6fd878a6f..ca6f0f453 100644 --- a/svf/include/Graphs/IRGraph.h +++ b/svf/include/Graphs/IRGraph.h @@ -52,6 +52,7 @@ class IRGraph : public GenericGraph { friend class SVFIRBuilder; friend class SymbolTableBuilder; + friend class GraphDBClient; public: @@ -129,6 +130,7 @@ class IRGraph : public GenericGraph /// blocks, thus flags are needed to distinguish them SVFStmt* hasLabeledEdge(SVFVar* src, SVFVar* dst, SVFStmt::PEDGEK kind, const ICFGNode* cs); + SVFStmt* hasEdge(SVFStmt* edge, SVFStmt::PEDGEK kind); /// Return MultiOpndStmt since it has more than one operands (we use operand /// 2 here to make the flag) SVFStmt* hasLabeledEdge(SVFVar* src, SVFVar* op1, SVFStmt::PEDGEK kind, @@ -270,6 +272,15 @@ class IRGraph : public GenericGraph return svfTypes; } + inline const SVFType* getSVFType(u32_t id) const + { + for(const SVFType* type : svfTypes) + { + if(type->getId() == id) + return type; + } + return nullptr; + } inline const Set& getStInfos() const { return stInfos; @@ -360,6 +371,7 @@ class IRGraph : public GenericGraph inline void addStInfo(StInfo* stInfo) { + stInfo->setStinfoId(stInfos.size()); stInfos.insert(stInfo); } diff --git a/svf/include/MemoryModel/AccessPath.h b/svf/include/MemoryModel/AccessPath.h index 9eb41e69d..9edc6df0e 100644 --- a/svf/include/MemoryModel/AccessPath.h +++ b/svf/include/MemoryModel/AccessPath.h @@ -51,7 +51,7 @@ class SVFVar; */ class AccessPath { - + friend class GraphDBClient; public: enum LSRelation { @@ -161,6 +161,12 @@ class AccessPath /// Dump location set std::string dump() const; +protected: + inline void addIdxOperandPair(std::pair pair) + { + idxOperandPairs.push_back(pair); + } + private: /// Check relations of two location sets diff --git a/svf/include/SVFIR/ObjTypeInfo.h b/svf/include/SVFIR/ObjTypeInfo.h index fc960d56a..4e6158aad 100644 --- a/svf/include/SVFIR/ObjTypeInfo.h +++ b/svf/include/SVFIR/ObjTypeInfo.h @@ -42,6 +42,14 @@ namespace SVF class ObjTypeInfo { friend class SymbolTableBuilder; + friend class GraphDBClient; + +protected: +/// Constructors +ObjTypeInfo(const SVFType* t, u32_t flags, u32_t max, u32_t elemNum, u32_t byteSize) : type(t), flags(flags), maxOffsetLimit(max), elemNum(elemNum), byteSize(byteSize) +{ + assert(t && "no type information for this object?"); +} public: typedef enum @@ -148,6 +156,10 @@ class ObjTypeInfo { flags |= mask; } + inline u32_t getFlag() const + { + return flags; + } inline bool hasFlag(MEMTYPE mask) { return (flags & mask) == mask; diff --git a/svf/include/SVFIR/SVFIR.h b/svf/include/SVFIR/SVFIR.h index ab9334417..46aede3ad 100644 --- a/svf/include/SVFIR/SVFIR.h +++ b/svf/include/SVFIR/SVFIR.h @@ -46,6 +46,8 @@ class SVFIR : public IRGraph friend class PAGBuilderFromFile; friend class TypeBasedHeapCloning; friend class BVDataPTAImpl; + friend class GraphDBClient; + friend class GraphDBSVFIRBuilder; public: typedef Set CallSiteSet; @@ -181,6 +183,11 @@ class SVFIR : public IRGraph return callGraph; } + inline void setCallGraph(CallGraph* cg) + { + callGraph = cg; + } + const FunObjVar* getFunObjVar(const std::string& name); inline const std::string& getModuleIdentifier() const @@ -500,6 +507,22 @@ class SVFIR : public IRGraph /// Print SVFIR void print(); +protected: + inline NodeID addBaseObjNode(BaseObjVar* node) + { + memToFieldsMap[node->getId()].set(node->getId()); + return addObjNode(node); + } + + NodeID addDummyObjNode(DummyObjVar* node); + + NodeID addGepObjNode(GepObjVar* gepObj, NodeID base, const APOffset& apOffset); + + inline void addGepValObjFromDB(NodeID curInstID, const GepValVar* gepValvar) + { + GepValObjMap[curInstID][std::make_pair(gepValvar->getBaseNode()->getId(), gepValvar->getAccessPath())] = gepValvar->getId(); + } + private: /// Map a SVFStatement type to a set of corresponding SVF statements @@ -521,6 +544,11 @@ class SVFIR : public IRGraph inline void addFunArgs(const FunObjVar* fun, const SVFVar* arg) { FunEntryICFGNode* funEntryBlockNode = icfg->getFunEntryICFGNode(fun); + addFunArgs(funEntryBlockNode, fun, arg); + } + + inline void addFunArgs(FunEntryICFGNode* funEntryBlockNode, const FunObjVar* fun, const SVFVar* arg) + { funEntryBlockNode->addFormalParms(arg); funArgsListMap[fun].push_back(arg); } @@ -528,6 +556,11 @@ class SVFIR : public IRGraph inline void addFunRet(const FunObjVar* fun, const SVFVar* ret) { FunExitICFGNode* funExitBlockNode = icfg->getFunExitICFGNode(fun); + addFunRet(funExitBlockNode, fun, ret); + } + + inline void addFunRet(FunExitICFGNode* funExitBlockNode, const FunObjVar* fun, const SVFVar* ret) + { funExitBlockNode->addFormalRet(ret); funRetMap[fun] = ret; } @@ -557,7 +590,7 @@ class SVFIR : public IRGraph /// Add a value (pointer) node inline NodeID addValNode(NodeID i, const SVFType* type, const ICFGNode* icfgNode) { - SVFVar *node = new ValVar(i, type, icfgNode, ValVar::ValNode); + ValVar *node = new ValVar(i, type, icfgNode, ValVar::ValNode); return addValNode(node); } @@ -624,9 +657,8 @@ class SVFIR : public IRGraph */ inline NodeID addHeapObjNode(NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); HeapObjVar *heapObj = new HeapObjVar(i, ti, type, node); - return addObjNode(heapObj); + return addBaseObjNode(heapObj); } /** @@ -634,60 +666,52 @@ class SVFIR : public IRGraph */ inline NodeID addStackObjNode(NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); StackObjVar *stackObj = new StackObjVar(i, ti, type, node); - return addObjNode(stackObj); + return addBaseObjNode(stackObj); } NodeID addFunObjNode(NodeID id, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[id].set(id); FunObjVar* funObj = new FunObjVar(id, ti, type, node); - return addObjNode(funObj); + return addBaseObjNode(funObj); } inline NodeID addConstantFPObjNode(NodeID i, ObjTypeInfo* ti, double dval, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); ConstFPObjVar* conObj = new ConstFPObjVar(i, dval, ti, type, node); - return addObjNode(conObj); + return addBaseObjNode(conObj); } inline NodeID addConstantIntObjNode(NodeID i, ObjTypeInfo* ti, const std::pair& intValue, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); ConstIntObjVar* conObj = new ConstIntObjVar(i, intValue.first, intValue.second, ti, type, node); - return addObjNode(conObj); + return addBaseObjNode(conObj); } inline NodeID addConstantNullPtrObjNode(const NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); ConstNullPtrObjVar* conObj = new ConstNullPtrObjVar(i, ti, type, node); - return addObjNode(conObj); + return addBaseObjNode(conObj); } inline NodeID addGlobalObjNode(const NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); GlobalObjVar* gObj = new GlobalObjVar(i, ti, type, node); - return addObjNode(gObj); + return addBaseObjNode(gObj); } inline NodeID addConstantAggObjNode(const NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); ConstAggObjVar* conObj = new ConstAggObjVar(i, ti, type, node); - return addObjNode(conObj); + return addBaseObjNode(conObj); } inline NodeID addConstantDataObjNode(const NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); ConstDataObjVar* conObj = new ConstDataObjVar(i, ti, type, node); - return addObjNode(conObj); + return addBaseObjNode(conObj); } /// Add a unique return node for a procedure @@ -710,9 +734,8 @@ class SVFIR : public IRGraph /// Add a field-insensitive node, this method can only invoked by getFIGepObjNode NodeID addFIObjNode(NodeID i, ObjTypeInfo* ti, const SVFType* type, const ICFGNode* node) { - memToFieldsMap[i].set(i); BaseObjVar* baseObj = new BaseObjVar(i, ti, type, node); - return addObjNode(baseObj); + return addBaseObjNode(baseObj); } @@ -730,11 +753,11 @@ class SVFIR : public IRGraph { ObjTypeInfo* ti = createObjTypeInfo(type); idToObjTypeInfoMap()[i] = ti; - return addObjNode(new DummyObjVar(i, ti, nullptr, type)); + return addDummyObjNode(new DummyObjVar(i, ti, nullptr, type)); } else { - return addObjNode(new DummyObjVar(i, getObjTypeInfo(i), nullptr, type)); + return addDummyObjNode(new DummyObjVar(i, getObjTypeInfo(i), nullptr, type)); } } @@ -753,23 +776,9 @@ class SVFIR : public IRGraph //@} /// Add a value (pointer) node - inline NodeID addValNode(SVFVar *node) - { - assert(node && "node cannot be nullptr."); - assert(hasGNode(node->getId()) == false && - "This NodeID clashes here. Please check NodeIDAllocator. Switch " - "Strategy::DBUG to SEQ or DENSE"); - return addNode(node); - } + NodeID addValNode(ValVar* node); /// Add a memory obj node - inline NodeID addObjNode(SVFVar *node) - { - assert(node && "node cannot be nullptr."); - assert(hasGNode(node->getId()) == false && - "This NodeID clashes here. Please check NodeIDAllocator. Switch " - "Strategy::DBUG to SEQ or DENSE"); - return addNode(node); - } + NodeID addObjNode(ObjVar *node); /// Add a unique return node for a procedure inline NodeID addRetNode(const FunObjVar*, SVFVar *node) { @@ -795,36 +804,49 @@ class SVFIR : public IRGraph //@{ /// Add Address edge AddrStmt* addAddrStmt(NodeID src, NodeID dst); + void addAddrStmt(AddrStmt* edge); /// Add Copy edge CopyStmt* addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type); + void addCopyStmt(CopyStmt* edge); /// Add phi node information PhiStmt* addPhiStmt(NodeID res, NodeID opnd, const ICFGNode* pred); + void addPhiStmt(PhiStmt* edge, SVFVar* src, SVFVar* dst); /// Add SelectStmt SelectStmt* addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond); + void addSelectStmt(SelectStmt* edge, SVFVar* src, SVFVar* dst); /// Add Copy edge CmpStmt* addCmpStmt(NodeID op1, NodeID op2, NodeID dst, u32_t predict); + void addCmpStmt(CmpStmt* edge, SVFVar* src, SVFVar* dst); /// Add Copy edge BinaryOPStmt* addBinaryOPStmt(NodeID op1, NodeID op2, NodeID dst, u32_t opcode); + void addBinaryOPStmt(BinaryOPStmt* edge, SVFVar* src, SVFVar* dst); /// Add Unary edge UnaryOPStmt* addUnaryOPStmt(NodeID src, NodeID dst, u32_t opcode); + void addUnaryOPStmt(UnaryOPStmt* edge, SVFVar* src, SVFVar* dst); /// Add BranchStmt BranchStmt* addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec& succs); + void addBranchStmt(BranchStmt* edge, SVFVar* src, SVFVar* dst); /// Add Load edge LoadStmt* addLoadStmt(NodeID src, NodeID dst); + void addLoadStmt(LoadStmt* edge); /// Add Store edge StoreStmt* addStoreStmt(NodeID src, NodeID dst, const ICFGNode* val); + void addStoreStmt(StoreStmt* edge, SVFVar* src, SVFVar* dst); /// Add Call edge CallPE* addCallPE(NodeID src, NodeID dst, const CallICFGNode* cs, const FunEntryICFGNode* entry); + void addCallPE(CallPE* edge, SVFVar* src, SVFVar* dst); /// Add Return edge RetPE* addRetPE(NodeID src, NodeID dst, const CallICFGNode* cs, const FunExitICFGNode* exit); + void addRetPE(RetPE* edge, SVFVar* src, SVFVar* dst); /// Add Gep edge GepStmt* addGepStmt(NodeID src, NodeID dst, const AccessPath& ap, bool constGep); + void addGepStmt(GepStmt* edge); /// Add Offset(Gep) edge GepStmt* addNormalGepStmt(NodeID src, NodeID dst, const AccessPath& ap); /// Add Variant(Gep) edge diff --git a/svf/include/SVFIR/SVFStatements.h b/svf/include/SVFIR/SVFStatements.h index 73d66d6d0..8c552e274 100644 --- a/svf/include/SVFIR/SVFStatements.h +++ b/svf/include/SVFIR/SVFStatements.h @@ -51,6 +51,7 @@ class SVFBasicBlock; typedef GenericEdge GenericPAGEdgeTy; class SVFStmt : public GenericPAGEdgeTy { + friend class GraphDBClient; public: /// Types of SVFIR statements @@ -89,8 +90,54 @@ class SVFStmt : public GenericPAGEdgeTy { } + SVFStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, bool real = true); + + /** + * Set the SVF BasicBlock for the new statements, this is used when loading statements from DB + */ + inline void setBasicBlock(const SVFBasicBlock* bb) + { + basicBlock = bb; + } + + /** + * set the call edge lanbel counter for the new statements, this is used when loading statements from DB + */ + inline void setCallEdgeLabelCounter(u64_t counter) + { + callEdgeLabelCounter = counter; + } + + /** + * set the store edge lanbel counter for the new statements, this is used when loading statements from DB + */ + inline void setStoreEdgeLabelCounter(u64_t counter) + { + storeEdgeLabelCounter = counter; + } + + /** + * set the multi operand edge lanbel counter for the new statements, this is used when loading statements from DB + */ + inline void setMultiOpndLabelCounter(u64_t counter) + { + multiOpndLabelCounter = counter; + } + + /** + * Add a call site Instruction to label mapping, this is used when loading statements from DB + */ + static inline void addInst2Labeled(const ICFGNode* cs, u32_t label) + { + inst2LabelMap.emplace(cs, label); + } + + static inline void addVar2Labeled(const SVFVar* var, u32_t label) + { + var2LabelMap.emplace(var, label); + } + public: - static u32_t totalEdgeNum; ///< Total edge number /// Constructor SVFStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, bool real = true); @@ -222,6 +269,33 @@ class SVFStmt : public GenericPAGEdgeTy static u64_t callEdgeLabelCounter; ///< Call site Instruction counter static u64_t storeEdgeLabelCounter; ///< Store Instruction counter static u64_t multiOpndLabelCounter; ///< MultiOpndStmt counter + +public: + static inline const Inst2LabelMap* getInst2LabelMap() + { + return &inst2LabelMap; + } + + static inline const Var2LabelMap* getVar2LabelMap() + { + return &var2LabelMap; + } + + static inline const u64_t* getCallEdgeLabelCounter() + { + return &callEdgeLabelCounter; + } + + static inline const u64_t* getStoreEdgeLabelCounter() + { + return &storeEdgeLabelCounter; + } + + static inline const u64_t* getMultiOpndLabelCounter() + { + return &multiOpndLabelCounter; + } + }; /* @@ -231,6 +305,7 @@ class SVFStmt : public GenericPAGEdgeTy */ class AssignStmt : public SVFStmt { + friend class GraphDBClient; private: AssignStmt(); ///< place holder @@ -244,6 +319,7 @@ class AssignStmt : public SVFStmt protected: /// constructor AssignStmt(SVFVar* s, SVFVar* d, GEdgeFlag k) : SVFStmt(s, d, k) {} + AssignStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode) : SVFStmt(s, d, k, eid, value, icfgNode) {} public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -303,6 +379,10 @@ class AssignStmt : public SVFStmt */ class AddrStmt: public AssignStmt { + friend class GraphDBClient; + +protected: + AddrStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode): AssignStmt(s, d, k, eid, value, icfgNode) {} private: AddrStmt(const AddrStmt&); ///< place holder @@ -351,6 +431,11 @@ class AddrStmt: public AssignStmt class CopyStmt: public AssignStmt { + friend class GraphDBClient; + +protected: + CopyStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, u32_t copyKind, ICFGNode* icfgNode): AssignStmt(s, d, k, eid, value, icfgNode), copyKind(copyKind) {} + private: CopyStmt(const CopyStmt&); ///< place holder void operator=(const CopyStmt&); ///< place holder @@ -426,6 +511,7 @@ class CopyStmt: public AssignStmt CopyStmt(SVFVar* s, SVFVar* d, CopyKind k) : AssignStmt(s, d, SVFStmt::Copy), copyKind(k) {} virtual const std::string toString() const override; + private: u32_t copyKind; }; @@ -435,6 +521,10 @@ class CopyStmt: public AssignStmt */ class StoreStmt: public AssignStmt { + friend class GraphDBClient; + +protected: + StoreStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode); private: StoreStmt(const StoreStmt&); ///< place holder @@ -461,6 +551,7 @@ class StoreStmt: public AssignStmt StoreStmt(SVFVar* s, SVFVar* d, const ICFGNode* st); virtual const std::string toString() const override; + }; /*! @@ -468,6 +559,10 @@ class StoreStmt: public AssignStmt */ class LoadStmt: public AssignStmt { + friend class GraphDBClient; + +protected: + LoadStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode): AssignStmt(s, d, k, eid, value, icfgNode) {} private: LoadStmt(const LoadStmt&); ///< place holder @@ -501,6 +596,12 @@ class LoadStmt: public AssignStmt */ class GepStmt: public AssignStmt { + friend class GraphDBClient; + +protected: + GepStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const AccessPath& ap, bool varfld = false) + : AssignStmt(s, d, k, eid, value, icfgNode), ap(ap), variantField(varfld){} + private: GepStmt(const GepStmt &); ///< place holder @@ -574,6 +675,7 @@ class GepStmt: public AssignStmt virtual const std::string toString() const; + }; @@ -582,6 +684,12 @@ class GepStmt: public AssignStmt */ class CallPE: public AssignStmt { + friend class GraphDBClient; + +protected: + CallPE(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const CallICFGNode* call, + const FunEntryICFGNode* entry); + private: CallPE(const CallPE&); ///< place holder @@ -637,6 +745,12 @@ class CallPE: public AssignStmt */ class RetPE: public AssignStmt { + friend class GraphDBClient; + +protected: + RetPE(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const CallICFGNode* call, + const FunExitICFGNode* exit); + private: RetPE(const RetPE&); ///< place holder @@ -685,6 +799,7 @@ class RetPE: public AssignStmt //@} virtual const std::string toString() const override; + }; /* @@ -692,6 +807,9 @@ class RetPE: public AssignStmt */ class MultiOpndStmt : public SVFStmt { + friend class GraphDBClient; + + public: typedef std::vector OPVars; @@ -709,6 +827,8 @@ class MultiOpndStmt : public SVFStmt OPVars opVars; /// Constructor, only used by subclasses but not external users MultiOpndStmt(SVFVar* r, const OPVars& opnds, GEdgeFlag k); + MultiOpndStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const OPVars& opnds) + : SVFStmt(s, d, k, eid, value, icfgNode), opVars(opnds) {} public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -770,6 +890,11 @@ class MultiOpndStmt : public SVFStmt */ class PhiStmt: public MultiOpndStmt { + friend class GraphDBClient; + +protected: + PhiStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const OPVars& opnds) + : MultiOpndStmt(s, d, k, eid, value, icfgNode, opnds) {} public: typedef std::vector OpICFGNodeVec; @@ -816,6 +941,18 @@ class PhiStmt: public MultiOpndStmt "Numbers of operands and their ICFGNodes are not consistent?"); } + void setOpICFGNodeVec(OpICFGNodeVec& icfgNodes) + { + assert(opVars.size() == icfgNodes.size() && + "Numbers of operands and their ICFGNodes are not consistent?"); + opICFGNodes = icfgNodes; + } + + inline const OpICFGNodeVec* getOpICFGNodeVec() const + { + return &opICFGNodes; + } + /// Return the corresponding ICFGNode of this operand inline const ICFGNode* getOpICFGNode(u32_t op_idx) const { @@ -827,6 +964,7 @@ class PhiStmt: public MultiOpndStmt bool isFunctionRetPhi() const; virtual const std::string toString() const override; + }; /*! @@ -834,6 +972,11 @@ class PhiStmt: public MultiOpndStmt */ class SelectStmt: public MultiOpndStmt { + friend class GraphDBClient; + +protected: + SelectStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, SVFVar* condition, ICFGNode* icfgNode, const OPVars& opnds); + private: SelectStmt(const SelectStmt&); ///< place holder @@ -878,6 +1021,7 @@ class SelectStmt: public MultiOpndStmt { return getOpVar(1); } + }; /*! @@ -885,6 +1029,10 @@ class SelectStmt: public MultiOpndStmt */ class CmpStmt: public MultiOpndStmt { + friend class GraphDBClient; + +protected: + CmpStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, u32_t predicate, ICFGNode* icfgNode, const OPVars& opnds); private: CmpStmt(const CmpStmt&); ///< place holder @@ -960,6 +1108,7 @@ class CmpStmt: public MultiOpndStmt } virtual const std::string toString() const override; + }; /*! @@ -967,6 +1116,10 @@ class CmpStmt: public MultiOpndStmt */ class BinaryOPStmt: public MultiOpndStmt { + friend class GraphDBClient; + +protected: + BinaryOPStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, u32_t opcode, ICFGNode* icfgNode, const OPVars& opnds); private: BinaryOPStmt(const BinaryOPStmt&); ///< place holder @@ -1026,6 +1179,7 @@ class BinaryOPStmt: public MultiOpndStmt } virtual const std::string toString() const override; + }; /*! @@ -1033,6 +1187,11 @@ class BinaryOPStmt: public MultiOpndStmt */ class UnaryOPStmt: public SVFStmt { + friend class GraphDBClient; + +protected: + UnaryOPStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, u32_t opcode, ICFGNode* icfgNode) + : SVFStmt(s, d, k, eid, value, icfgNode), opcode(opcode) {} private: UnaryOPStmt(const UnaryOPStmt&); ///< place holder @@ -1089,6 +1248,7 @@ class UnaryOPStmt: public SVFStmt NodeID getResID() const; virtual const std::string toString() const override; + }; /*! @@ -1096,6 +1256,7 @@ class UnaryOPStmt: public SVFStmt */ class BranchStmt: public SVFStmt { + friend class GraphDBClient; public: typedef std::vector> SuccAndCondPairVec; @@ -1112,6 +1273,10 @@ class BranchStmt: public SVFStmt const SVFVar* cond; const SVFVar* brInst; +protected: +BranchStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, SuccAndCondPairVec& successors, const SVFVar* cond,const SVFVar* brInst, ICFGNode* icfgNode) + : SVFStmt(s, d, k, eid, value, icfgNode), successors(successors), cond(cond), brInst(brInst){} + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -1175,6 +1340,7 @@ class BranchStmt: public SVFStmt } //@} virtual const std::string toString() const override; + }; /*! @@ -1182,6 +1348,11 @@ class BranchStmt: public SVFStmt */ class TDForkPE: public CallPE { + friend class GraphDBClient; + +protected: + TDForkPE(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const CallICFGNode* call, + const FunEntryICFGNode* entry): CallPE(s, d, k, eid, value, icfgNode, call, entry) {} private: TDForkPE(const TDForkPE&); ///< place holder @@ -1212,6 +1383,7 @@ class TDForkPE: public CallPE } virtual const std::string toString() const; + }; /*! @@ -1219,6 +1391,12 @@ class TDForkPE: public CallPE */ class TDJoinPE: public RetPE { + friend class GraphDBClient; + +protected: + TDJoinPE(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const CallICFGNode* call, + const FunExitICFGNode* exit): RetPE(s, d, k, eid, value, icfgNode, call, exit) {} + private: TDJoinPE(const TDJoinPE&); ///< place holder @@ -1249,6 +1427,7 @@ class TDJoinPE: public RetPE } virtual const std::string toString() const; + }; } // End namespace SVF diff --git a/svf/include/SVFIR/SVFType.h b/svf/include/SVFIR/SVFType.h index d75c82743..3970e7031 100644 --- a/svf/include/SVFIR/SVFType.h +++ b/svf/include/SVFIR/SVFType.h @@ -46,7 +46,35 @@ class SVFPointerType; class StInfo { + friend class GraphDBClient; + friend class IRGraph; + +protected: + StInfo (u32_t id, std::vector fldIdxVec, std::vector elemIdxVec, Map fldIdx2TypeMap, + std::vector finfo,u32_t stride,u32_t numOfFlattenElements,u32_t numOfFlattenFields, std::vector flattenElementTypes ) + :StInfoId(id), fldIdxVec(fldIdxVec), elemIdxVec(elemIdxVec), fldIdx2TypeMap(fldIdx2TypeMap), finfo(finfo), stride(stride), + numOfFlattenElements(numOfFlattenElements), numOfFlattenFields(numOfFlattenFields), flattenElementTypes(flattenElementTypes) + { + + } + + inline const u32_t getStinfoId() const + { + return StInfoId; + } + + inline const Map& getFldIdx2TypeMap() const + { + return fldIdx2TypeMap; + } + + inline void setStinfoId(u32_t id) + { + StInfoId = id; + } + private: + u32_t StInfoId; /// flattened field indices of a struct (ignoring arrays) std::vector fldIdxVec; /// flattened element indices including structs and arrays by considering @@ -77,6 +105,7 @@ class StInfo : stride(s), numOfFlattenElements(s), numOfFlattenFields(s) { } + /// Destructor ~StInfo() = default; @@ -170,6 +199,20 @@ class SVFType SVFOtherTy, }; +protected: + + /// set svfptrty and svfi8ty when initializing SVFType from db query results + inline static void setSVFPtrType(SVFType* ptrTy) + { + svfPtrTy = ptrTy; + } + + inline static void setSVFInt8Type(SVFType* i8Ty) + { + svfI8Ty = i8Ty; + } + + public: inline static SVFType* getSVFPtrType() @@ -274,6 +317,14 @@ std::ostream& operator<<(std::ostream& os, const SVFType& type); class SVFPointerType : public SVFType { + friend class GraphDBClient; +protected: + SVFPointerType(u32_t id, u32_t byteSize, bool isSingleValTy) + : SVFType(isSingleValTy, SVFPointerTy, id, byteSize) + { + + } + public: SVFPointerType(u32_t i, u32_t byteSize = 1) : SVFType(true, SVFPointerTy, i, byteSize) @@ -290,10 +341,23 @@ class SVFPointerType : public SVFType class SVFIntegerType : public SVFType { + friend class GraphDBClient; private: short signAndWidth; ///< For printing +protected: + SVFIntegerType(u32_t i, u32_t byteSize, bool isSingleValTy,short signAndWidth) + : SVFType(isSingleValTy, SVFIntegerTy, i, byteSize) + { + this->signAndWidth = signAndWidth; + } + + short getSignAndWidth() const + { + return signAndWidth; + } + public: SVFIntegerType(u32_t i, u32_t byteSize = 1) : SVFType(true, SVFIntegerTy, i, byteSize) {} static inline bool classof(const SVFType* node) @@ -317,11 +381,31 @@ class SVFIntegerType : public SVFType class SVFFunctionType : public SVFType { + friend class GraphDBClient; private: const SVFType* retTy; std::vector params; bool varArg; +protected: + /** + * Set return type of function, this is used when loading from DB + */ + const void setReturnType(const SVFType* rt) + { + retTy = rt; + } + + SVFFunctionType(u32_t id, bool svt, u32_t byteSize) + : SVFType(svt, SVFFunctionTy, id, byteSize) + { + } + + void addParamType(const SVFType* type) + { + params.push_back(type); + } + public: SVFFunctionType(u32_t i, const SVFType* rt, const std::vector& p, bool isvararg) : SVFType(false, SVFFunctionTy, i, 1), retTy(rt), params(p), varArg(isvararg) @@ -342,7 +426,6 @@ class SVFFunctionType : public SVFType return params; } - bool isVarArg() const { return varArg; @@ -353,6 +436,20 @@ class SVFFunctionType : public SVFType class SVFStructType : public SVFType { + friend class GraphDBClient; + +protected: + SVFStructType(u32_t i, bool svt, u32_t byteSize, std::string name) : SVFType(svt, SVFStructTy, i, byteSize),name(name) {} + + const std::string& getName() const + { + return name; + } + + void addFieldsType(const SVFType* type) + { + fields.push_back(type); + } private: /// @brief Field for printing & debugging @@ -376,6 +473,7 @@ class SVFStructType : public SVFType { return name; } + void setName(const std::string& structName) { name = structName; @@ -389,10 +487,23 @@ class SVFStructType : public SVFType { return fields; } + }; class SVFArrayType : public SVFType { + friend class GraphDBClient; + +protected: + SVFArrayType(u32_t id, bool svt, u32_t byteSize, unsigned elemNum) + : SVFType(svt, SVFArrayTy, id, byteSize), numOfElement(elemNum), typeOfElement(nullptr) + { + + } + const unsigned getNumOfElement() const + { + return numOfElement; + } private: unsigned numOfElement; /// For printing & debugging @@ -431,6 +542,14 @@ class SVFArrayType : public SVFType class SVFOtherType : public SVFType { + friend class GraphDBClient; + +protected: + SVFOtherType(u32_t i, bool isSingleValueTy, u32_t byteSize, std::string repr) : SVFType(isSingleValueTy, SVFOtherTy, i, byteSize),repr(repr) {} + const std::string& getRepr() const + { + return repr; + } private: std::string repr; /// Field representation for printing diff --git a/svf/include/SVFIR/SVFVariables.h b/svf/include/SVFIR/SVFVariables.h index bc5e2d1ca..c60646f48 100644 --- a/svf/include/SVFIR/SVFVariables.h +++ b/svf/include/SVFIR/SVFVariables.h @@ -52,6 +52,7 @@ class SVFVar : public GenericPAGNodeTy friend class IRGraph; friend class SVFIR; friend class VFG; + friend class GraphDBClient; public: /// Node kinds for SVFIR variables: @@ -71,8 +72,16 @@ class SVFVar : public GenericPAGNodeTy SVFStmt::KindToSVFStmtMapTy InEdgeKindToSetMap; SVFStmt::KindToSVFStmtMapTy OutEdgeKindToSetMap; - /// Empty constructor for deserialization - SVFVar(NodeID i, PNODEK k) : GenericPAGNodeTy(i, k) {} + inline const SVFStmt::KindToSVFStmtMapTy& getInEdgeKindToSetMap() const + { + return InEdgeKindToSetMap; + } + + + inline const SVFStmt::KindToSVFStmtMapTy& getOutEdgeKindToSetMap() const + { + return OutEdgeKindToSetMap; + } public: @@ -192,6 +201,20 @@ class SVFVar : public GenericPAGNodeTy return false; } + std::string sourceLocToDBString() const + { + std::string sourceLoc = ""; + if (getSourceLoc().empty() == false) + { + sourceLoc = ", source_loc: '" + getSourceLoc() + "'"; + } + else + { + sourceLoc = ", source_loc: ''"; + } + return sourceLoc; + } + private: /// Edge management methods @@ -247,13 +270,25 @@ class SVFVar : public GenericPAGNodeTy */ class ValVar: public SVFVar { + friend class GraphDBClient; private: const ICFGNode* icfgNode; // icfgnode related to valvar +protected: + ValVar(NodeID i, const SVFType* type, PNODEK ty = ValNode) : SVFVar(i, type, ty), icfgNode(nullptr) {} public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ + inline void updateSVFValVarFromDB(const SVFType* type, const ICFGNode* icfgNode) + { + this->type = type; + this->icfgNode = icfgNode; + } + inline void updateSVFValVarFromDB(const ICFGNode* icfgNode) + { + this->icfgNode = icfgNode; + } static inline bool classof(const ValVar*) { return true; @@ -291,6 +326,9 @@ class ValVar: public SVFVar virtual const FunObjVar* getFunction() const; virtual const std::string toString() const; + + std::string getValVarNodeFieldsStmt() const; + }; /* @@ -298,6 +336,7 @@ class ValVar: public SVFVar */ class ObjVar: public SVFVar { + friend class GraphDBClient; protected: /// Constructor @@ -306,6 +345,10 @@ class ObjVar: public SVFVar { } public: + void updateObjVarFromDB(const SVFType* type) + { + this->type = type; + } /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ static inline bool classof(const ObjVar*) @@ -333,6 +376,9 @@ class ObjVar: public SVFVar } virtual const std::string toString() const; + + std::string getObjVarNodeFieldsStmt() const; + }; @@ -344,11 +390,15 @@ class ObjVar: public SVFVar */ class ArgValVar: public ValVar { + friend class GraphDBClient; private: const FunObjVar* cgNode; u32_t argNo; +protected: + ArgValVar(NodeID i, const SVFType* type, u32_t argNo, PNODEK ty = ArgValNode) : ValVar(i, type, ty), argNo(argNo) {} + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -384,6 +434,11 @@ class ArgValVar: public ValVar return getName() + " (argument valvar)"; } + inline void addCGNodeFromDB(const FunObjVar* cgNode) + { + this->cgNode = cgNode; + } + virtual const FunObjVar* getFunction() const; const FunObjVar* getParent() const; @@ -410,11 +465,20 @@ class ArgValVar: public ValVar */ class GepValVar: public ValVar { + friend class GraphDBClient; + +protected: + GepValVar(NodeID i, const SVFType* type, const SVFType* gepValType, PNODEK ty = GepValNode) + : ValVar(i, type, GepValNode), gepValType(gepValType) + { + } private: AccessPath ap; // AccessPath const ValVar* base; // base node const SVFType* gepValType; + NodeID llvmVarID; + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -439,6 +503,16 @@ class GepValVar: public ValVar { return node->getNodeKind() == SVFVar::GepValNode; } + + inline const AccessPath& getAccessPath() const + { + return ap; + } + + inline const void setAccessPath(const AccessPath* ap) + { + this->ap = *ap; + } //@} /// Constructor @@ -456,6 +530,10 @@ class GepValVar: public ValVar { return base; } + inline void setBaseNode(const ValVar* baseNode) + { + base = baseNode; + } /// Return name of a LLVM value inline const std::string getValueName() const @@ -494,6 +572,18 @@ class GepValVar: public ValVar { return base->isConstDataOrAggData(); } + + /// Get the LLVM variable ID associated with this GepValVar + inline NodeID getLLVMVarInstID() const + { + return llvmVarID; + } + + /// Set the LLVM variable ID associated with this GepValVar + inline void setLLVMVarInstID(NodeID id) + { + llvmVarID = id; + } }; /* @@ -502,11 +592,16 @@ class GepValVar: public ValVar class BaseObjVar : public ObjVar { friend class SVFIRBuilder; + friend class GraphDBClient; + private: ObjTypeInfo* typeInfo; const ICFGNode* icfgNode; /// ICFGNode related to the creation of this object +protected: + BaseObjVar(NodeID i, const SVFType* type, ObjTypeInfo* typeInfo, PNODEK ty = BaseObjNode) : ObjVar(i, type, ty), typeInfo(typeInfo), icfgNode(nullptr) {} + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -544,12 +639,26 @@ class BaseObjVar : public ObjVar return this; } + inline const ObjTypeInfo* getTypeInfo() const + { + return typeInfo; + } + inline ObjTypeInfo* getTypeInfo() + { + return typeInfo; + } + /// Get the ICFGNode related to the creation of this object inline const ICFGNode* getICFGNode() const { return icfgNode; } + inline void setICFGNode(const ICFGNode* node) + { + icfgNode = node; + } + /// Return name of a LLVM value inline const std::string getValueName() const { @@ -570,6 +679,11 @@ class BaseObjVar : public ObjVar return typeInfo->getType(); } + const SVFType* getVarType() const + { + return type; + } + /// Get the number of elements of this object u32_t getNumOfElements() const { @@ -698,6 +812,11 @@ class BaseObjVar : public ObjVar */ class GepObjVar: public ObjVar { + friend class GraphDBClient; + +protected: + GepObjVar(NodeID i, const SVFType* type, u64_t apOffset, const BaseObjVar* baseObj, PNODEK ty = GepObjNode) + : ObjVar(i, type, ty), apOffset(apOffset), base(baseObj) {} private: APOffset apOffset = 0; @@ -802,6 +921,11 @@ class GepObjVar: public ObjVar class HeapObjVar: public BaseObjVar { + friend class GraphDBClient; + +protected: + HeapObjVar(NodeID i, const SVFType* type, ObjTypeInfo* ti, PNODEK ty = HeapObjNode) : + BaseObjVar(i, type, ti, ty) {} public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -858,6 +982,12 @@ class HeapObjVar: public BaseObjVar class StackObjVar: public BaseObjVar { + friend class GraphDBClient; + +protected: + StackObjVar(NodeID i, const SVFType* type, ObjTypeInfo* ti, PNODEK ty = StackObjNode) : + BaseObjVar(i, type, ti, ty) {} + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -909,6 +1039,33 @@ class FunObjVar : public BaseObjVar { friend class SVFIRBuilder; friend class LLVMModuleSet; + friend class GraphDBClient; + +protected: + FunObjVar(NodeID i, const SVFType* type, ObjTypeInfo* ti, + bool isDecl, bool intrinsic, bool isAddrTaken, bool isUncalled, + bool isNotRet, bool supVarArg, const SVFFunctionType* funcType, PNODEK ty = FunObjNode) + : BaseObjVar(i, type, ti, ty), isDecl(isDecl), intrinsic(intrinsic), + isAddrTaken(isAddrTaken), isUncalled(isUncalled), isNotRet(isNotRet), + supVarArg(supVarArg),funcType(funcType) {} + + inline void updateExitBlock(SVFBasicBlock *bb) + { + exitBlock = bb; + } + + inline void setLoopAndDomInfo(SVFLoopAndDomInfo *ld) + { + loopAndDom = ld; + } + inline bool getIsNotRet() const + { + return isNotRet; + } + inline const std::vector &getArgs() const + { + return allArgs; + } public: typedef SVFLoopAndDomInfo::BBSet BBSet; @@ -932,6 +1089,7 @@ class FunObjVar : public BaseObjVar std::vector allArgs; /// all formal arguments of this function const SVFBasicBlock *exitBlock; /// a 'single' basic block having no successors and containing return instruction in a function + public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -1146,7 +1304,6 @@ class FunObjVar : public BaseObjVar assert (idx < allArgs.size() && "getArg() out of range!"); return allArgs[idx]; } - inline const SVFBasicBlock* front() const { return getEntryBlock(); @@ -1178,6 +1335,16 @@ class FunObjVar : public BaseObjVar class FunValVar : public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty FunValNode (for GraphDBClient) + FunValVar(NodeID i, const SVFType* type, PNODEK ty = FunValNode) : ValVar(i, type, ty) {} + inline void setFunction(const FunObjVar* cgn) + { + funObjVar = cgn; + } + private: const FunObjVar* funObjVar; @@ -1227,6 +1394,11 @@ class FunValVar : public ValVar class GlobalValVar : public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty GlobalValVar (for GraphDBClient) + GlobalValVar(NodeID i, const SVFType* type, PNODEK ty = GlobalValNode) : ValVar(i, type, ty) {} public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1266,6 +1438,11 @@ class GlobalValVar : public ValVar class ConstAggValVar: public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty ConstAggValVar (for GraphDBClient) + ConstAggValVar(NodeID i, const SVFType* type, PNODEK ty = ConstAggValNode) : ValVar(i, type, ty) {} public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1316,6 +1493,14 @@ class ConstAggValVar: public ValVar class ConstDataValVar : public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor + ConstDataValVar(NodeID i, const SVFType* svfType, PNODEK ty = ConstDataValNode) + : ValVar(i, svfType, ty) + { + } public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1366,6 +1551,7 @@ class ConstDataValVar : public ValVar class BlackHoleValVar : public ConstDataValVar { + friend class GraphDBClient; public: /// Methods for support type inquiry through isa, cast, and dyn_cast: //@{ @@ -1416,6 +1602,14 @@ class BlackHoleValVar : public ConstDataValVar class ConstFPValVar : public ConstDataValVar { + friend class GraphDBClient; + +protected: + /// Constructor + ConstFPValVar(NodeID i, double dv, const SVFType* svfType, PNODEK ty = ConstFPValNode) + : ConstDataValVar(i, svfType, ConstFPValNode), dval(dv) + { + } private: double dval; @@ -1466,6 +1660,16 @@ class ConstFPValVar : public ConstDataValVar class ConstIntValVar : public ConstDataValVar { + friend class GraphDBClient; + +protected: + /// Constructor + ConstIntValVar(NodeID i, s64_t sv, u64_t zv, const SVFType* svfType, PNODEK ty = ConstIntValNode) + : ConstDataValVar(i, svfType, ConstIntValNode), zval(zv), sval(sv) + { + + } + private: u64_t zval; s64_t sval; @@ -1521,6 +1725,13 @@ class ConstIntValVar : public ConstDataValVar class ConstNullPtrValVar : public ConstDataValVar { + friend class GraphDBClient; + +protected: + ConstNullPtrValVar(NodeID i, const SVFType* svfType, PNODEK ty = ConstNullptrValNode) + : ConstDataValVar(i, svfType, ty) + { + } public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1568,6 +1779,14 @@ class ConstNullPtrValVar : public ConstDataValVar class GlobalObjVar : public BaseObjVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty ObjVar (for GraphDBClient) + GlobalObjVar(NodeID i, const SVFType* svfType, ObjTypeInfo* ti, PNODEK ty = GlobalObjNode) + : BaseObjVar(i, svfType, ti, ty) + { + } public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1611,6 +1830,13 @@ class GlobalObjVar : public BaseObjVar class ConstAggObjVar : public BaseObjVar { + friend class GraphDBClient; + +protected: + ConstAggObjVar(NodeID i, const SVFType* svfType, ObjTypeInfo* ti, PNODEK ty = ConstAggObjNode) + : BaseObjVar(i, svfType, ti, ty) + { + } public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1664,6 +1890,13 @@ class ConstAggObjVar : public BaseObjVar class ConstDataObjVar : public BaseObjVar { + friend class GraphDBClient; + +protected: + ConstDataObjVar(NodeID i, const SVFType* svfType, ObjTypeInfo* typeInfo, PNODEK ty = ConstDataObjNode) + : BaseObjVar(i, svfType, typeInfo, ty) + { + } public: //@{ Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1716,6 +1949,15 @@ class ConstDataObjVar : public BaseObjVar class ConstFPObjVar : public ConstDataObjVar { + friend class GraphDBClient; + +protected: + /// Constructor + ConstFPObjVar(NodeID i, float dval, const SVFType* svfType, ObjTypeInfo* ti, PNODEK ty = ConstFPObjNode) + : ConstDataObjVar(i, svfType, ti, ty), dval(dval) + { + } + private: float dval; @@ -1773,6 +2015,15 @@ class ConstFPObjVar : public ConstDataObjVar class ConstIntObjVar : public ConstDataObjVar { + friend class GraphDBClient; + +protected: + ConstIntObjVar(NodeID i, s64_t sval, u64_t zval, const SVFType* svfType, ObjTypeInfo* objTypeInfo, PNODEK ty = ConstIntObjNode) + : ConstDataObjVar(i, svfType, objTypeInfo, ty), zval(zval), sval(sval) + { + } + + private: u64_t zval; s64_t sval; @@ -1837,6 +2088,12 @@ class ConstIntObjVar : public ConstDataObjVar class ConstNullPtrObjVar : public ConstDataObjVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty DummyObjVar (for GraphDBClient) + ConstNullPtrObjVar(NodeID i, const SVFType* type, ObjTypeInfo* typeInfo, PNODEK ty = ConstNullptrObjNode) : ConstDataObjVar(i, type, typeInfo, ty) {} + public: //@{ Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstNullPtrObjVar*) @@ -1889,6 +2146,15 @@ class ConstNullPtrObjVar : public ConstDataObjVar */ class RetValPN : public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty RetValPN (for GraphDBClient) + RetValPN(NodeID i, const SVFType* type, PNODEK ty = RetValNode) : ValVar(i, type, ty) {} + inline void setCallGraphNode(const FunObjVar* node) + { + callGraphNode = node; + } private: const FunObjVar* callGraphNode; @@ -1942,6 +2208,15 @@ class RetValPN : public ValVar class VarArgValPN : public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty VarArgValPN (for GraphDBClient) + VarArgValPN(NodeID i, const SVFType* type, PNODEK ty = VarargValNode) : ValVar(i, type, VarargValNode) {} + inline void setCallGraphNode(const FunObjVar* node) + { + callGraphNode = node; + } private: const FunObjVar* callGraphNode; @@ -1992,6 +2267,11 @@ class VarArgValPN : public ValVar */ class DummyValVar: public ValVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty DummyValVar (for GraphDBClient) + DummyValVar(NodeID i, const SVFType* type, PNODEK ty = DummyValNode) : ValVar(i, type, DummyValNode) {} public: //@{ Methods for support type inquiry through isa, cast, and dyn_cast: @@ -2043,6 +2323,12 @@ class DummyValVar: public ValVar class DummyObjVar: public BaseObjVar { + friend class GraphDBClient; + +protected: + /// Constructor to create empty DummyObjVar (for GraphDBClient) + DummyObjVar(NodeID i, const SVFType* type, ObjTypeInfo* typeInfo, PNODEK ty = DummyObjNode) : BaseObjVar(i, type, typeInfo, ty) {} + public: //@{ Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const DummyObjVar*) @@ -2094,4 +2380,4 @@ class DummyObjVar: public BaseObjVar } // End namespace SVF -#endif /* INCLUDE_SVFIR_SVFVARIABLE_H_ */ +#endif /* INCLUDE_SVFIR_SVFVARIABLE_H_ */ \ No newline at end of file diff --git a/svf/include/Util/ExtAPI.h b/svf/include/Util/ExtAPI.h index cf949bbe6..d7ebf326b 100644 --- a/svf/include/Util/ExtAPI.h +++ b/svf/include/Util/ExtAPI.h @@ -47,6 +47,7 @@ class ExtAPI { friend class LLVMModuleSet; friend class SVFIRBuilder; + friend class GraphDBClient; private: diff --git a/svf/include/Util/NodeIDAllocator.h b/svf/include/Util/NodeIDAllocator.h index 27803385e..b52eff696 100644 --- a/svf/include/Util/NodeIDAllocator.h +++ b/svf/include/Util/NodeIDAllocator.h @@ -89,6 +89,17 @@ class NodeIDAllocator ++numNodes; } + inline void increaseNumOfValues() + { + ++numValues; + ++numNodes; + } + + inline int getNumOfNodes() + { + return numNodes; + } + private: /// Builds a node ID allocator with the strategy specified on the command line. NodeIDAllocator(void); diff --git a/svf/include/Util/Options.h b/svf/include/Util/Options.h index 0fa17910d..6b711975c 100644 --- a/svf/include/Util/Options.h +++ b/svf/include/Util/Options.h @@ -212,6 +212,8 @@ class Options static const Option DiffPts; static Option DetectPWC; static const Option VtableInSVFIR; + static const Option Write2DB; + static const Option ReadFromDB; // WPAPass.cpp static const Option ExtAPIPath; diff --git a/svf/include/Util/SVFLoopAndDomInfo.h b/svf/include/Util/SVFLoopAndDomInfo.h index 559947493..37d90a0e9 100644 --- a/svf/include/Util/SVFLoopAndDomInfo.h +++ b/svf/include/Util/SVFLoopAndDomInfo.h @@ -41,6 +41,7 @@ namespace SVF class SVFLoopAndDomInfo { + friend class GraphDBClient; public: typedef Set BBSet; typedef std::vector BBList; @@ -54,6 +55,42 @@ class SVFLoopAndDomInfo Map bb2LoopMap; ///< map a BasicBlock (if it is in a loop) to all the BasicBlocks in this loop Map bb2PdomLevel; ///< map a BasicBlock to its level in pdom tree, used in findNearestCommonPDominator Map bb2PIdom; ///< map a BasicBlock to its immediate dominator in pdom tree, used in findNearestCommonPDominator + +protected: +inline void setDomTreeMap(Map& dtMap) +{ + dtBBsMap = dtMap; +} + +inline void setPostDomTreeMap(Map& pdtMap) +{ + pdtBBsMap = pdtMap; +} + +inline void setDomFrontierMap(Map& dfMap) +{ + dfBBsMap = dfMap; +} + +inline void setBB2LoopMap(Map& bb2Loop) +{ + bb2LoopMap = bb2Loop; +} + +inline void setBB2PdomLevel(Map& bb2Pdom) +{ + bb2PdomLevel = bb2Pdom; +} + +inline void setBB2PIdom(Map& bb2PIdomMap) +{ + bb2PIdom = bb2PIdomMap; +} + +inline const Map& getBB2LoopMap() const +{ + return bb2LoopMap; +} public: SVFLoopAndDomInfo() @@ -71,7 +108,7 @@ class SVFLoopAndDomInfo { return dfBBsMap; } - + inline bool hasLoopInfo(const SVFBasicBlock* bb) const { return bb2LoopMap.find(bb) != bb2LoopMap.end(); diff --git a/svf/lib/Graphs/BasicBlockG.cpp b/svf/lib/Graphs/BasicBlockG.cpp index f82c49f23..8cdc0af28 100644 --- a/svf/lib/Graphs/BasicBlockG.cpp +++ b/svf/lib/Graphs/BasicBlockG.cpp @@ -1,5 +1,6 @@ #include "Graphs/BasicBlockG.h" #include "Graphs/ICFGNode.h" +#include "Util/Options.h" using namespace SVF; const std::string BasicBlockEdge::toString() const @@ -22,3 +23,12 @@ const std::string SVFBasicBlock::toString() const rawstr << "\n----------------------------------------\n"; return rawstr.str(); } + +void BasicBlockGraph::addBasicBlock(SVFBasicBlock* bb) +{ + if (Options::ReadFromDB()) + { + id++; + } + addGNode(bb->getId(), bb); +} diff --git a/svf/lib/Graphs/CallGraph.cpp b/svf/lib/Graphs/CallGraph.cpp index 1038c849c..4b53b8de4 100644 --- a/svf/lib/Graphs/CallGraph.cpp +++ b/svf/lib/Graphs/CallGraph.cpp @@ -33,6 +33,7 @@ #include "Util/Options.h" #include "Util/SVFUtil.h" #include +#include "Util/Options.h" using namespace SVF; using namespace SVFUtil; @@ -159,6 +160,24 @@ CallGraph::CallGraph(const CallGraph& other) } +CallSiteID CallGraph::addCallSite(const CallICFGNode* cs, const FunObjVar* callee, const CallSiteID csid) +{ + std::pair newCS(std::make_pair(cs, callee)); + if (Options::ReadFromDB()) + { + CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS); + if(it != csToIdMap.end()) + { + return it->second; + } + totalCallSiteNum++; + } + csToIdMap.insert(std::make_pair(newCS, csid)); + idToCSMap.insert(std::make_pair(csid, newCS)); + return csid; + +} + /*! * Memory has been cleaned up at GenericGraph */ @@ -174,8 +193,13 @@ CallGraphEdge* CallGraph::hasGraphEdge(CallGraphNode* src, CallGraphEdge::CEDGEK kind, CallSiteID csId) const { CallGraphEdge edge(src,dst,kind,csId); - CallGraphEdge* outEdge = src->hasOutgoingEdge(&edge); - CallGraphEdge* inEdge = dst->hasIncomingEdge(&edge); + return hasGraphEdge(&edge); +} + +CallGraphEdge* CallGraph::hasGraphEdge(CallGraphEdge* cgEdge) const +{ + CallGraphEdge* outEdge = cgEdge->getSrcNode()->hasOutgoingEdge(cgEdge); + CallGraphEdge* inEdge = cgEdge->getDstNode()->hasIncomingEdge(cgEdge); if (outEdge && inEdge) { assert(outEdge == inEdge && "edges not match"); @@ -220,11 +244,26 @@ void CallGraph::addIndirectCallGraphEdge(const CallICFGNode* cs,const FunObjVar* { CallGraphEdge* edge = new CallGraphEdge(caller,callee, CallGraphEdge::CallRetEdge, csId); edge->addInDirectCallSite(cs); - addEdge(edge); + addIndirectCallGraphEdge(edge); callinstToCallGraphEdgesMap[cs].insert(edge); } } +void CallGraph::addIndirectCallGraphEdge(CallGraphEdge* cgEdge) +{ + if (Options::ReadFromDB()) + { + if (!hasGraphEdge(cgEdge)) + { + addEdge(cgEdge); + } + } + else + { + addEdge(cgEdge); + } +} + /*! * Get all callsite invoking this callee */ @@ -359,8 +398,13 @@ void CallGraph::addCallGraphNode(const FunObjVar* fun) { NodeID id = callGraphNodeNum; CallGraphNode*callGraphNode = new CallGraphNode(id, fun); - addGNode(id, callGraphNode); - funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode; + addCallGraphNode(callGraphNode); +} + +void CallGraph::addCallGraphNode(CallGraphNode* cgNode) +{ + addGNode(cgNode->getId(), cgNode); + funToCallGraphNodeMap[cgNode->getFunction()] = cgNode; callGraphNodeNum++; } @@ -388,11 +432,26 @@ void CallGraph::addDirectCallGraphEdge(const CallICFGNode* cs,const FunObjVar* c { CallGraphEdge* edge = new CallGraphEdge(caller,callee, CallGraphEdge::CallRetEdge, csId); edge->addDirectCallSite(cs); - addEdge(edge); + addDirectCallGraphEdge(edge); callinstToCallGraphEdgesMap[cs].insert(edge); } } +void CallGraph::addDirectCallGraphEdge(CallGraphEdge* cgEdge) +{ + if (Options::ReadFromDB()) + { + if (!hasGraphEdge(cgEdge)) + { + addEdge(cgEdge); + } + } + else + { + addEdge(cgEdge); + } +} + namespace SVF { diff --git a/svf/lib/Graphs/ICFG.cpp b/svf/lib/Graphs/ICFG.cpp index f6a8f5bbe..c66c944d7 100644 --- a/svf/lib/Graphs/ICFG.cpp +++ b/svf/lib/Graphs/ICFG.cpp @@ -237,6 +237,24 @@ ICFG::~ICFG() icfgNodeToSVFLoopVec.clear(); } +void ICFG::addICFGNode(ICFGNode* node) +{ + if (Options::ReadFromDB()) + { + totalICFGNode++; + } + addGNode(node->getId(),node); +} + +void ICFG::addGlobalICFGNode(GlobalICFGNode* globalICFGNode) +{ + if (Options::ReadFromDB()) + { + this->globalBlockNode = globalICFGNode; + } + addICFGNode(globalICFGNode); +} + /// Add a function entry node FunEntryICFGNode* ICFG::getFunEntryICFGNode(const FunObjVar* fun) diff --git a/svf/lib/Graphs/IRGraph.cpp b/svf/lib/Graphs/IRGraph.cpp index 497ddfd7e..c8f577f5a 100644 --- a/svf/lib/Graphs/IRGraph.cpp +++ b/svf/lib/Graphs/IRGraph.cpp @@ -268,12 +268,7 @@ bool IRGraph::addEdge(SVFVar* src, SVFVar* dst, SVFStmt* edge) SVFStmt* IRGraph::hasNonlabeledEdge(SVFVar* src, SVFVar* dst, SVFStmt::PEDGEK kind) { SVFStmt edge(src,dst,kind, false); - SVFStmt::SVFStmtSetTy::iterator it = KindToSVFStmtSetMap[kind].find(&edge); - if (it != KindToSVFStmtSetMap[kind].end()) - { - return *it; - } - return nullptr; + return hasEdge(&edge, kind); } /*! @@ -304,6 +299,17 @@ SVFStmt* IRGraph::hasLabeledEdge(SVFVar* src, SVFVar* dst, SVFStmt::PEDGEK kind, return nullptr; } +SVFStmt* IRGraph::hasEdge(SVFStmt* edge, SVFStmt::PEDGEK kind) +{ + SVFStmt::SVFStmtSetTy::iterator it = KindToSVFStmtSetMap[kind].find(edge); + if (it != KindToSVFStmtSetMap[kind].end()) + { + return *it; + } + return nullptr; +} + + /*! * Dump this IRGraph */ diff --git a/svf/lib/SABER/LeakChecker.cpp b/svf/lib/SABER/LeakChecker.cpp index 1b12ec22d..48ad2ae47 100644 --- a/svf/lib/SABER/LeakChecker.cpp +++ b/svf/lib/SABER/LeakChecker.cpp @@ -230,16 +230,31 @@ void LeakChecker::validateSuccessTests(const SVFGNode* source, const FunObjVar* if (success) { - outs() << sucMsg("\t SUCCESS :") << funName << " check getId() + if (!Options::ReadFromDB()) + { + outs() << sucMsg("\t SUCCESS :") << funName << " check getId() << ", cs id:" << (getSrcCSID(source))->valueOnlyToString() << "> at (" << cs->getSourceLoc() << ")\n"; + } + else + { + outs() << sucMsg("\t SUCCESS :") << funName<<"\n"; + } } else { - SVFUtil::errs() << errMsg("\t FAILURE :") << funName << " check getId() + if (!Options::ReadFromDB()) + { + SVFUtil::errs() << errMsg("\t FAILURE :") << funName << " check getId() << ", cs id:" << (getSrcCSID(source))->valueOnlyToString() << "> at (" << cs->getSourceLoc() << ")\n"; - assert(false && "test case failed!"); + assert(false && "test case failed!"); + } + else + { + SVFUtil::errs() << errMsg("\t FAILURE :") << funName << "\n"; + assert(false && "test case failed!"); + } } } @@ -280,12 +295,23 @@ void LeakChecker::validateExpectedFailureTests(const SVFGNode* source, const Fun if (expectedFailure) { + if (Options::ReadFromDB()) + { + outs() << sucMsg("\t EXPECTED-FAILURE :") << funName <<"\n"; + return; + } outs() << sucMsg("\t EXPECTED-FAILURE :") << funName << " check getId() << ", cs id:" << (getSrcCSID(source))->valueOnlyToString() << "> at (" << cs->getSourceLoc() << ")\n"; } else { + if (Options::ReadFromDB()) + { + SVFUtil::errs() << errMsg("\t UNEXPECTED FAILURE :") << funName <<"\n"; + assert(false && "test case failed!"); + return; + } SVFUtil::errs() << errMsg("\t UNEXPECTED FAILURE :") << funName << " check getId() << ", cs id:" << (getSrcCSID(source))->valueOnlyToString() << "> at (" diff --git a/svf/lib/SVFIR/SVFIR.cpp b/svf/lib/SVFIR/SVFIR.cpp index 1c51ff313..702af01e1 100644 --- a/svf/lib/SVFIR/SVFIR.cpp +++ b/svf/lib/SVFIR/SVFIR.cpp @@ -69,11 +69,15 @@ AddrStmt* SVFIR::addAddrStmt(NodeID src, NodeID dst) else { AddrStmt* addrPE = new AddrStmt(srcNode, dstNode); - addToStmt2TypeMap(addrPE); - addEdge(srcNode,dstNode, addrPE); + addAddrStmt(addrPE); return addrPE; } } +void SVFIR::addAddrStmt(AddrStmt* edge) +{ + addToStmt2TypeMap(edge); + addEdge(edge->getRHSVar(),edge->getLHSVar(), edge); +} /*! * Add Copy edge @@ -87,12 +91,17 @@ CopyStmt* SVFIR::addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type) else { CopyStmt* copyPE = new CopyStmt(srcNode, dstNode, type); - addToStmt2TypeMap(copyPE); - addEdge(srcNode,dstNode, copyPE); + addCopyStmt(copyPE); return copyPE; } } +void SVFIR::addCopyStmt(CopyStmt* edge) +{ + addToStmt2TypeMap(edge); + addEdge(edge->getRHSVar(),edge->getLHSVar(), edge); +} + /*! * Add Phi statement */ @@ -104,9 +113,7 @@ PhiStmt* SVFIR::addPhiStmt(NodeID res, NodeID opnd, const ICFGNode* pred) if(it == phiNodeMap.end()) { PhiStmt* phi = new PhiStmt(resNode, {opNode}, {pred}); - addToStmt2TypeMap(phi); - addEdge(opNode, resNode, phi); - phiNodeMap[resNode] = phi; + addPhiStmt(phi, opNode, resNode); return phi; } else @@ -117,6 +124,19 @@ PhiStmt* SVFIR::addPhiStmt(NodeID res, NodeID opnd, const ICFGNode* pred) } } +void SVFIR::addPhiStmt(PhiStmt* edge, SVFVar* src, SVFVar* dst) +{ + SVFVar* opNode = src; + SVFVar* resNode = dst; + if (Options::ReadFromDB() && phiNodeMap.count(resNode)) + return; + + addToStmt2TypeMap(edge); + addEdge(opNode, resNode, edge); + phiNodeMap[resNode] = edge; + +} + /*! * Add Phi statement */ @@ -132,12 +152,17 @@ SelectStmt* SVFIR::addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond { std::vector opnds = {op1Node, op2Node}; SelectStmt* select = new SelectStmt(dstNode, opnds, condNode); - addToStmt2TypeMap(select); - addEdge(op1Node, dstNode, select); + addSelectStmt(select, op1Node, dstNode); return select; } } +void SVFIR::addSelectStmt(SelectStmt* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src, dst, edge); +} + /*! * Add Compare edge */ @@ -152,12 +177,17 @@ CmpStmt* SVFIR::addCmpStmt(NodeID op1, NodeID op2, NodeID dst, u32_t predicate) { std::vector opnds = {op1Node, op2Node}; CmpStmt* cmp = new CmpStmt(dstNode, opnds, predicate); - addToStmt2TypeMap(cmp); - addEdge(op1Node, dstNode, cmp); + addCmpStmt(cmp, op1Node, dstNode); return cmp; } } +void SVFIR::addCmpStmt(CmpStmt* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src, dst, edge); +} + /*! * Add Compare edge @@ -173,12 +203,16 @@ BinaryOPStmt* SVFIR::addBinaryOPStmt(NodeID op1, NodeID op2, NodeID dst, u32_t o { std::vector opnds = {op1Node, op2Node}; BinaryOPStmt* binaryOP = new BinaryOPStmt(dstNode, opnds, opcode); - addToStmt2TypeMap(binaryOP); - addEdge(op1Node,dstNode, binaryOP); + addBinaryOPStmt(binaryOP,op1Node,dstNode); return binaryOP; } } +void SVFIR::addBinaryOPStmt(BinaryOPStmt* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src, dst, edge); +} /*! * Add Unary edge */ @@ -191,12 +225,17 @@ UnaryOPStmt* SVFIR::addUnaryOPStmt(NodeID src, NodeID dst, u32_t opcode) else { UnaryOPStmt* unaryOP = new UnaryOPStmt(srcNode, dstNode, opcode); - addToStmt2TypeMap(unaryOP); - addEdge(srcNode,dstNode, unaryOP); + addUnaryOPStmt(unaryOP, srcNode,dstNode); return unaryOP; } } +void SVFIR::addUnaryOPStmt(UnaryOPStmt* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src, dst, edge); +} + /* * Add BranchStmt */ @@ -209,12 +248,17 @@ BranchStmt* SVFIR::addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccA else { BranchStmt* branch = new BranchStmt(brNode, condNode, succs); - addToStmt2TypeMap(branch); - addEdge(condNode,brNode, branch); + addBranchStmt(branch,condNode,brNode); return branch; } } +void SVFIR::addBranchStmt(BranchStmt* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src, dst, edge); +} + /*! * Add Load edge */ @@ -227,12 +271,17 @@ LoadStmt* SVFIR::addLoadStmt(NodeID src, NodeID dst) else { LoadStmt* loadPE = new LoadStmt(srcNode, dstNode); - addToStmt2TypeMap(loadPE); - addEdge(srcNode,dstNode, loadPE); + addLoadStmt(loadPE); return loadPE; } } +void SVFIR::addLoadStmt(LoadStmt* edge) +{ + addToStmt2TypeMap(edge); + addEdge(edge->getRHSVar(),edge->getLHSVar(), edge); +} + /*! * Add Store edge * Note that two store instructions may share the same Store SVFStmt @@ -246,12 +295,17 @@ StoreStmt* SVFIR::addStoreStmt(NodeID src, NodeID dst, const ICFGNode* curVal) else { StoreStmt* storePE = new StoreStmt(srcNode, dstNode, curVal); - addToStmt2TypeMap(storePE); - addEdge(srcNode,dstNode, storePE); + addStoreStmt(storePE,srcNode,dstNode); return storePE; } } +void SVFIR::addStoreStmt(StoreStmt* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src,dst, edge); +} + /*! * Add Call edge */ @@ -264,12 +318,17 @@ CallPE* SVFIR::addCallPE(NodeID src, NodeID dst, const CallICFGNode* cs, const F else { CallPE* callPE = new CallPE(srcNode, dstNode, cs,entry); - addToStmt2TypeMap(callPE); - addEdge(srcNode,dstNode, callPE); + addCallPE(callPE,srcNode,dstNode); return callPE; } } +void SVFIR::addCallPE(CallPE* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src,dst, edge); +} + /*! * Add Return edge */ @@ -282,12 +341,17 @@ RetPE* SVFIR::addRetPE(NodeID src, NodeID dst, const CallICFGNode* cs, const Fun else { RetPE* retPE = new RetPE(srcNode, dstNode, cs, exit); - addToStmt2TypeMap(retPE); - addEdge(srcNode,dstNode, retPE); + addRetPE(retPE,srcNode,dstNode); return retPE; } } +void SVFIR::addRetPE(RetPE* edge, SVFVar* src, SVFVar* dst) +{ + addToStmt2TypeMap(edge); + addEdge(src, dst, edge); +} + /*! * Add blackhole/constant edge */ @@ -311,8 +375,7 @@ TDForkPE* SVFIR::addThreadForkPE(NodeID src, NodeID dst, const CallICFGNode* cs, else { TDForkPE* forkPE = new TDForkPE(srcNode, dstNode, cs, entry); - addToStmt2TypeMap(forkPE); - addEdge(srcNode,dstNode, forkPE); + addCallPE(forkPE,srcNode,dstNode); return forkPE; } } @@ -329,8 +392,7 @@ TDJoinPE* SVFIR::addThreadJoinPE(NodeID src, NodeID dst, const CallICFGNode* cs, else { TDJoinPE* joinPE = new TDJoinPE(srcNode, dstNode, cs, exit); - addToStmt2TypeMap(joinPE); - addEdge(srcNode,dstNode, joinPE); + addRetPE(joinPE,srcNode,dstNode); return joinPE; } } @@ -369,12 +431,20 @@ GepStmt* SVFIR::addNormalGepStmt(NodeID src, NodeID dst, const AccessPath& ap) else { GepStmt* gepPE = new GepStmt(baseNode, dstNode, ap); - addToStmt2TypeMap(gepPE); - addEdge(baseNode, dstNode, gepPE); + addGepStmt(gepPE); return gepPE; } } +void SVFIR::addGepStmt(GepStmt* gepPE) +{ + SVFVar* baseNode = gepPE->getRHSVar(); + SVFVar* dstNode = gepPE->getLHSVar(); + addToStmt2TypeMap(gepPE); + addEdge(baseNode, dstNode, gepPE); + +} + /*! * Add variant(Gep) edge * Find the base node id of src and connect base node to dst node @@ -408,6 +478,7 @@ NodeID SVFIR::addGepValNode(NodeID curInst,const ValVar* baseVar, const AccessPa && "this node should not be created before"); GepValObjMap[curInst][std::make_pair(base, ap)] = i; GepValVar *node = new GepValVar(baseVar, i, ap, type, icn); + node->setLLVMVarInstID(curInst); return addValNode(node); } @@ -460,6 +531,15 @@ NodeID SVFIR::getGepObjVar(const BaseObjVar* baseObj, const APOffset& apOffset) } +NodeID SVFIR::addGepObjNode(GepObjVar* gepObj, NodeID base, const APOffset& apOffset) +{ + assert(0==GepObjVarMap.count(std::make_pair(base, apOffset)) + && "this node should not be created before"); + GepObjVarMap[std::make_pair(base, apOffset)] = gepObj->getId(); + memToFieldsMap[base].set(gepObj->getId()); + return addObjNode(gepObj); +} + /*! * Add a field obj node, this method can only invoked by getGepObjVar */ @@ -469,12 +549,9 @@ NodeID SVFIR::addGepObjNode(const BaseObjVar* baseObj, const APOffset& apOffset, NodeID base = baseObj->getId(); assert(0==GepObjVarMap.count(std::make_pair(base, apOffset)) && "this node should not be created before"); - - GepObjVarMap[std::make_pair(base, apOffset)] = gepId; //ABTest GepObjVar *node = new GepObjVar(baseObj, gepId, apOffset); - memToFieldsMap[base].set(gepId); - return addObjNode(node); + return addGepObjNode(node, base, apOffset); } /*! @@ -692,5 +769,43 @@ void SVFIR::handleBlackHole(bool b) Options::HandBlackHole.setValue(b); } +NodeID SVFIR::addValNode(ValVar* node) +{ + assert(node && "node cannot be nullptr."); + assert(hasGNode(node->getId()) == false && + "This NodeID clashes here. Please check NodeIDAllocator. Switch " + "Strategy::DBUG to SEQ or DENSE"); + if (Options::ReadFromDB() && hasGNode(node->getId())) + { + ValVar* valvar = SVFUtil::cast(getGNode(node->getId())); + valvar->updateSVFValVarFromDB(node->getType(), node->getICFGNode()); + return valvar->getId(); + } + return addNode(node); +} +NodeID SVFIR::addObjNode(ObjVar* node) +{ + assert(node && "node cannot be nullptr."); + assert(hasGNode(node->getId()) == false && + "This NodeID clashes here. Please check NodeIDAllocator. Switch " + "Strategy::DBUG to SEQ or DENSE"); + if (Options::ReadFromDB() && hasGNode(node->getId())) + { + ObjVar* objVar = SVFUtil::cast(getGNode(node->getId())); + objVar->updateObjVarFromDB(node->getType()); + return objVar->getId(); + } + return addNode(node); +} +NodeID SVFIR::addDummyObjNode(DummyObjVar* node) +{ + if (Options::ReadFromDB() && idToObjTypeInfoMap().find(node->getId()) == idToObjTypeInfoMap().end()) + { + ObjTypeInfo* ti = node->getTypeInfo(); + idToObjTypeInfoMap()[node->getId()] = ti; + return addObjNode(node); + } + return addObjNode(node); +} \ No newline at end of file diff --git a/svf/lib/SVFIR/SVFStatements.cpp b/svf/lib/SVFIR/SVFStatements.cpp index f9eb02a0c..486631c1b 100644 --- a/svf/lib/SVFIR/SVFStatements.cpp +++ b/svf/lib/SVFIR/SVFStatements.cpp @@ -55,6 +55,16 @@ SVFStmt::SVFStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, bool real) : } } +SVFStmt::SVFStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, bool real) : +GenericPAGEdgeTy(s,d,k),value(value),basicBlock(nullptr),icfgNode(icfgNode),edgeId(eid) +{ + if(real) + { + edgeId = eid; + SVFIR::getPAG()->incEdgeNum(); + } +} + /*! * Whether src and dst nodes are both pointer type */ @@ -329,6 +339,8 @@ StoreStmt::StoreStmt(SVFVar* s, SVFVar* d, const ICFGNode* st) : AssignStmt(s, d, makeEdgeFlagWithStoreInst(SVFStmt::Store, st)) { } +StoreStmt::StoreStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode) +: AssignStmt(s, d, k, eid, value, icfgNode) {} CallPE::CallPE(SVFVar* s, SVFVar* d, const CallICFGNode* i, const FunEntryICFGNode* e, GEdgeKind k) @@ -336,12 +348,21 @@ CallPE::CallPE(SVFVar* s, SVFVar* d, const CallICFGNode* i, { } +CallPE::CallPE(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const CallICFGNode* call, + const FunEntryICFGNode* entry): AssignStmt(s, d, k, eid, value, icfgNode), call(call), entry(entry) +{ + +} + RetPE::RetPE(SVFVar* s, SVFVar* d, const CallICFGNode* i, const FunExitICFGNode* e, GEdgeKind k) : AssignStmt(s, d, makeEdgeFlagWithCallInst(k, i)), call(i), exit(e) { } +RetPE::RetPE(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, ICFGNode* icfgNode, const CallICFGNode* call, + const FunExitICFGNode* exit): AssignStmt(s, d, k, eid, value, icfgNode), call(call), exit(exit) {} + MultiOpndStmt::MultiOpndStmt(SVFVar* r, const OPVars& opnds, GEdgeFlag k) : SVFStmt(opnds.at(0), r, k), opVars(opnds) { @@ -355,6 +376,12 @@ CmpStmt::CmpStmt(SVFVar* s, const OPVars& opnds, u32_t pre) assert(opnds.size() == 2 && "CmpStmt can only have two operands!"); } +CmpStmt::CmpStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, u32_t predicate, ICFGNode* icfgNode, const OPVars& opnds) +: MultiOpndStmt(s, d, k, eid, value, icfgNode, opnds), predicate(predicate) +{ + assert(opnds.size() == 2 && "CmpStmt can only have two operands!"); +} + SelectStmt::SelectStmt(SVFVar* s, const OPVars& opnds, const SVFVar* cond) : MultiOpndStmt(s, opnds, makeEdgeFlagWithAddionalOpnd(SVFStmt::Select, opnds.at(1))), @@ -363,6 +390,12 @@ SelectStmt::SelectStmt(SVFVar* s, const OPVars& opnds, const SVFVar* cond) assert(opnds.size() == 2 && "SelectStmt can only have two operands!"); } +SelectStmt::SelectStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, SVFVar* condition, ICFGNode* icfgNode, const OPVars& opnds) + : MultiOpndStmt(s, d, k, eid, value, icfgNode, opnds), condition(condition) +{ + assert(opnds.size() == 2 && "SelectStmt can only have two operands!"); +} + BinaryOPStmt::BinaryOPStmt(SVFVar* s, const OPVars& opnds, u32_t oc) : MultiOpndStmt( s, opnds, @@ -371,3 +404,9 @@ BinaryOPStmt::BinaryOPStmt(SVFVar* s, const OPVars& opnds, u32_t oc) { assert(opnds.size() == 2 && "BinaryOPStmt can only have two operands!"); } + +BinaryOPStmt::BinaryOPStmt(SVFVar* s, SVFVar* d, GEdgeFlag k, EdgeID eid, SVFVar* value, u32_t opcode, ICFGNode* icfgNode, const OPVars& opnds) + : MultiOpndStmt(s, d, k, eid, value, icfgNode, opnds), opcode(opcode) +{ + assert(opnds.size() == 2 && "BinaryOPStmt can only have two operands!"); +} diff --git a/svf/lib/Util/Options.cpp b/svf/lib/Util/Options.cpp index a783ce4e9..05a2c1ecc 100644 --- a/svf/lib/Util/Options.cpp +++ b/svf/lib/Util/Options.cpp @@ -629,6 +629,18 @@ const Option Options::PrintCGGraph( false ); +const Option Options::Write2DB( + "write2db", + "Write Graphs' nodes & edges to a graphDB", + false +); + +const Option Options::ReadFromDB( + "read-from-db", + "Read Graphs' nodes & edges from a graphDB", + false +); + const Option Options::WriteAnder( "write-ander", "Write Andersen's analysis results to a user-specified text file",