From 7e4203829f7d9d19cc3bb094e4e94d20485f7d79 Mon Sep 17 00:00:00 2001 From: jumormt Date: Thu, 9 Jan 2025 16:27:36 +1100 Subject: [PATCH] add argvalvar --- svf-llvm/lib/SVFIRBuilder.cpp | 7 +++ svf/include/Graphs/GenericGraph.h | 5 +- svf/include/SVFIR/SVFIR.h | 7 +++ svf/include/SVFIR/SVFVariables.h | 81 +++++++++++++++++++++++++++++-- svf/include/Util/SVFUtil.h | 2 + svf/lib/SVFIR/SVFFileSystem.cpp | 1 + svf/lib/SVFIR/SVFIR.cpp | 11 ++--- svf/lib/SVFIR/SVFVariables.cpp | 35 ++++++++++++- svf/lib/Util/SVFUtil.cpp | 8 +++ svf/lib/Util/ThreadAPI.cpp | 4 +- 10 files changed, 145 insertions(+), 16 deletions(-) diff --git a/svf-llvm/lib/SVFIRBuilder.cpp b/svf-llvm/lib/SVFIRBuilder.cpp index 0ee96aec3..173ba2f52 100644 --- a/svf-llvm/lib/SVFIRBuilder.cpp +++ b/svf-llvm/lib/SVFIRBuilder.cpp @@ -244,6 +244,13 @@ void SVFIRBuilder::initialiseNodes() const CallGraphNode* cgn = llvmModuleSet()->getCallGraphNode(func); // add value node representing the function pag->addFunValNode(cgn, iter->second, icfgNode); + } else if (auto argval = SVFUtil::dyn_cast(llvmValue)) { + pag->addArgValNode( + llvmModuleSet()->getCallGraphNode(argval->getParent()), + argval->getArgNo(), LLVMUtil::isArgOfUncalledFunction(argval), iter->second, + icfgNode); + llvmModuleSet()->addToLLVMVal2SVFVarMap( + argval, pag->getGNode(iter->second)); } else if (auto fpValue = SVFUtil::dyn_cast(llvmValue)) { diff --git a/svf/include/Graphs/GenericGraph.h b/svf/include/Graphs/GenericGraph.h index 790c1330d..8f116b049 100644 --- a/svf/include/Graphs/GenericGraph.h +++ b/svf/include/Graphs/GenericGraph.h @@ -154,6 +154,7 @@ class SVFBaseNode // ┌── SVFVar: Classes of top-level variables (ValVar) and address-taken variables (ObjVar) // │ └── ValVar: Classes of top-level variable nodes ValNode, // ├──Represents a standard value variable + ArgNode, // ├──Represents an argument value variable FunValNode, // ├──Represents a Function value variable GepValNode, // ├──Represents a GEP value variable RetNode, // ├──Represents a return value node @@ -289,7 +290,7 @@ class SVFBaseNode static inline bool isSVFVarKind(GNodeK n) { - static_assert(DummyObjNode - ValNode == 23, + static_assert(DummyObjNode - ValNode == 24, "The number of SVFVarKinds has changed, make sure the " "range is correct"); @@ -298,7 +299,7 @@ class SVFBaseNode static inline bool isValVarKinds(GNodeK n) { - static_assert(DummyValNode - ValNode == 11, + static_assert(DummyValNode - ValNode == 12, "The number of ValVarKinds has changed, make sure the " "range is correct"); return n <= DummyValNode && n >= ValNode; diff --git a/svf/include/SVFIR/SVFIR.h b/svf/include/SVFIR/SVFIR.h index a9ab9edab..36970934d 100644 --- a/svf/include/SVFIR/SVFIR.h +++ b/svf/include/SVFIR/SVFIR.h @@ -578,6 +578,13 @@ class SVFIR : public IRGraph return addValNode(nullptr, node, i); } + NodeID addArgValNode(const CallGraphNode* callGraphNode, u32_t argNo, + bool isUncalled, NodeID i, const ICFGNode* icfgNode) { + ArgValVar* node = + new ArgValVar(i, callGraphNode, argNo, isUncalled, icfgNode); + return addValNode(nullptr, node, i); + } + inline NodeID addConstantFPValNode(const SVFValue* curInst, double dval, const NodeID i, const ICFGNode* icfgNode) { diff --git a/svf/include/SVFIR/SVFVariables.h b/svf/include/SVFIR/SVFVariables.h index 1cf11ef2d..9f2df3a89 100644 --- a/svf/include/SVFIR/SVFVariables.h +++ b/svf/include/SVFIR/SVFVariables.h @@ -133,11 +133,6 @@ class SVFVar : public GenericPAGNodeTy { return inst->getParent()->getParent(); } - // For function arguments, return their parent function - else if (auto arg = SVFUtil::dyn_cast(value)) - { - return arg->getParent(); - } } // Return nullptr for globals/constants with no parent function @@ -388,6 +383,82 @@ class ObjVar: public SVFVar }; +/** + * @brief Class representing a function argument variable in the SVFIR + * + * This class models function argument in the program analysis. It extends ValVar + * to specifically handle function argument. + */ +class ArgValVar: public ValVar { + friend class SVFIRWriter; + friend class SVFIRReader; + +private: + const CallGraphNode* cgNode; + u32_t argNo; + bool uncalled; + +protected: + /// Constructor to create function argument (for SVFIRReader/deserialization) + ArgValVar(NodeID i, PNODEK ty = ArgNode) : ValVar(i, ty) {} + +public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + //@{ + static inline bool classof(const ArgValVar*) + { + return true; + } + static inline bool classof(const ValVar* node) + { + return node->getNodeKind() == ArgNode; + } + static inline bool classof(const SVFVar* node) + { + return node->getNodeKind() == ArgNode; + } + static inline bool classof(const GenericPAGNodeTy* node) + { + return node->getNodeKind() == ArgNode; + } + static inline bool classof(const SVFBaseNode* node) + { + return node->getNodeKind() == ArgNode; + } + //@} + + /// Constructor + ArgValVar(NodeID i, const CallGraphNode* callGraphNode, u32_t argNo, + bool isUncalled, const ICFGNode* icn, PNODEK ty = ArgNode); + + /// Return name of a LLVM value + inline const std::string getValueName() const + { + if (value) + return value->getName() + " (argument valvar)"; + return " (argument valvar)"; + } + + virtual const SVFFunction* getFunction() const; + + const SVFFunction* getParent() const; + + /// Return the index of this formal argument in its containing function. + /// For example in "void foo(int a, float b)" a is 0 and b is 1. + inline u32_t getArgNo() const + { + return argNo; + } + + inline bool isArgOfUncalledFunction() const + { + return uncalled; + } + + virtual const std::string toString() const; +}; + + /* * Gep Value (Pointer) variable, this variable can be dynamic generated for field sensitive analysis * e.g. memcpy, temp gep value variable needs to be created diff --git a/svf/include/Util/SVFUtil.h b/svf/include/Util/SVFUtil.h index 9327def15..437f05f54 100644 --- a/svf/include/Util/SVFUtil.h +++ b/svf/include/Util/SVFUtil.h @@ -351,6 +351,8 @@ inline bool isArgOfUncalledFunction(const SVFValue* svfval) return false; } +bool isArgOfUncalledFunction(const SVFVar* svfvar); + const ObjVar* getObjVarOfValVar(const ValVar* valVar); /// Return thread fork function diff --git a/svf/lib/SVFIR/SVFFileSystem.cpp b/svf/lib/SVFIR/SVFFileSystem.cpp index 7181f58dd..da7dd8681 100644 --- a/svf/lib/SVFIR/SVFFileSystem.cpp +++ b/svf/lib/SVFIR/SVFFileSystem.cpp @@ -222,6 +222,7 @@ cJSON* SVFIRWriter::virtToJson(const SVFVar* var) CASE(DummyValNode, DummyValVar); CASE(DummyObjNode, DummyObjVar); CASE(FunObjNode, FunObjVar); + CASE(ArgNode, ArgValVar); CASE(FunValNode, FunValVar); CASE(HeapObjNode, HeapObjVar); CASE(StackObjNode, StackObjVar); diff --git a/svf/lib/SVFIR/SVFIR.cpp b/svf/lib/SVFIR/SVFIR.cpp index 869b48953..12621c98b 100644 --- a/svf/lib/SVFIR/SVFIR.cpp +++ b/svf/lib/SVFIR/SVFIR.cpp @@ -670,11 +670,10 @@ bool SVFIR::isValidPointer(NodeID nodeId) const if (node->hasValue() && node->isPointer()) { - if(const SVFArgument* arg = SVFUtil::dyn_cast(node->getValue())) - { - if (!(arg->getParent()->isDeclaration())) - return true; - } + if (const ValVar* pVar = pag->getBaseValVar(nodeId)) + if (const ArgValVar* arg = SVFUtil::dyn_cast(pVar)) + if (!(arg->getParent()->isDeclaration())) + return true; } if ((node->getInEdges().empty() && node->getOutEdges().empty())) @@ -694,7 +693,7 @@ bool SVFIR::isValidTopLevelPtr(const SVFVar* node) return true; } else if(node->hasValue()) - return !SVFUtil::isArgOfUncalledFunction(node->getValue()); + return !SVFUtil::isArgOfUncalledFunction(node); } } return false; diff --git a/svf/lib/SVFIR/SVFVariables.cpp b/svf/lib/SVFIR/SVFVariables.cpp index 4cbb9c9a0..0e109a53f 100644 --- a/svf/lib/SVFIR/SVFVariables.cpp +++ b/svf/lib/SVFIR/SVFVariables.cpp @@ -46,6 +46,7 @@ SVFVar::SVFVar(const SVFValue* val, NodeID i, PNODEK k) : switch (k) { case ValNode: + case ArgNode: case ConstantDataValNode: case GlobalValNode: case BlackHoleNode: @@ -144,6 +145,39 @@ const std::string ObjVar::toString() const return rawstr.str(); } +ArgValVar::ArgValVar(SVF::NodeID i, const SVF::CallGraphNode* callGraphNode, + SVF::u32_t argNo, bool isUncalled, + const SVF::ICFGNode* icn, SVF::SVFVar::PNODEK ty) + : ValVar(callGraphNode->getFunction()->getArg(argNo), i, ty, icn), cgNode(callGraphNode), + argNo(argNo), uncalled(isUncalled) +{ + isPtr = + callGraphNode->getFunction()->getArg(argNo)->getType()->isPointerTy(); +} + +const SVFFunction* ArgValVar::getFunction() const +{ + return getParent(); +} + +const SVFFunction* ArgValVar::getParent() const +{ + return cgNode->getFunction(); +} + +const std::string ArgValVar::toString() const +{ + std::string str; + std::stringstream rawstr(str); + rawstr << "ArgValVar ID: " << getId(); + if (Options::ShowSVFIRValue()) + { + rawstr << "\n"; + rawstr << valueOnlyToString(); + } + return rawstr.str(); +} + const std::string GepValVar::toString() const { std::string str; @@ -468,4 +502,3 @@ bool SVFVar::isConstDataOrAggDataButNotNullPtr() const else return false; } - diff --git a/svf/lib/Util/SVFUtil.cpp b/svf/lib/Util/SVFUtil.cpp index bf3568ec7..08de0becf 100644 --- a/svf/lib/Util/SVFUtil.cpp +++ b/svf/lib/Util/SVFUtil.cpp @@ -425,6 +425,14 @@ const SVFFunction* SVFUtil::getProgEntryFunction() return nullptr; } +bool SVFUtil::isArgOfUncalledFunction(const SVFVar* svfvar) +{ + const ValVar* pVar = PAG::getPAG()->getBaseValVar(svfvar->getId()); + if(const ArgValVar* arg = SVFUtil::dyn_cast(pVar)) + return arg->isArgOfUncalledFunction(); + else + return false; +} const ObjVar* SVFUtil::getObjVarOfValVar(const SVF::ValVar* valVar) { diff --git a/svf/lib/Util/ThreadAPI.cpp b/svf/lib/Util/ThreadAPI.cpp index 2cf335753..2cca866a5 100644 --- a/svf/lib/Util/ThreadAPI.cpp +++ b/svf/lib/Util/ThreadAPI.cpp @@ -207,13 +207,13 @@ const SVFVar* ThreadAPI::getLockVal(const ICFGNode *cs) const const SVFVar* ThreadAPI::getJoinedThread(const CallICFGNode *cs) const { assert(isTDJoin(cs) && "not a thread join function!"); - const SVFVar* join = cs->getArgument(0); + const ValVar* join = cs->getArgument(0); for(const SVFStmt* stmt : join->getInEdges()) { if(SVFUtil::isa(stmt)) return stmt->getSrcNode(); } - if(SVFUtil::isa(join->getValue())) + if(SVFUtil::isa(join)) return join; assert(false && "the value of the first argument at join is not a load instruction?");