Skip to content

Commit

Permalink
add argvalvar
Browse files Browse the repository at this point in the history
  • Loading branch information
jumormt committed Jan 9, 2025
1 parent 4e366d1 commit 7e42038
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 16 deletions.
7 changes: 7 additions & 0 deletions svf-llvm/lib/SVFIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Argument>(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<ConstantFP>(llvmValue))
{
Expand Down
5 changes: 3 additions & 2 deletions svf/include/Graphs/GenericGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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");

Expand All @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions svf/include/SVFIR/SVFIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
81 changes: 76 additions & 5 deletions svf/include/SVFIR/SVFVariables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<SVFArgument>(value))
{
return arg->getParent();
}
}

// Return nullptr for globals/constants with no parent function
Expand Down Expand Up @@ -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

Check warning on line 435 in svf/include/SVFIR/SVFVariables.h

View check run for this annotation

Codecov / codecov/patch

svf/include/SVFIR/SVFVariables.h#L435

Added line #L435 was not covered by tests
{
if (value)
return value->getName() + " (argument valvar)";
return " (argument valvar)";

Check warning on line 439 in svf/include/SVFIR/SVFVariables.h

View check run for this annotation

Codecov / codecov/patch

svf/include/SVFIR/SVFVariables.h#L437-L439

Added lines #L437 - L439 were not covered by tests
}

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
Expand Down
2 changes: 2 additions & 0 deletions svf/include/Util/SVFUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions svf/lib/SVFIR/SVFFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 5 additions & 6 deletions svf/lib/SVFIR/SVFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,11 +670,10 @@ bool SVFIR::isValidPointer(NodeID nodeId) const

if (node->hasValue() && node->isPointer())
{
if(const SVFArgument* arg = SVFUtil::dyn_cast<SVFArgument>(node->getValue()))
{
if (!(arg->getParent()->isDeclaration()))
return true;
}
if (const ValVar* pVar = pag->getBaseValVar(nodeId))
if (const ArgValVar* arg = SVFUtil::dyn_cast<ArgValVar>(pVar))
if (!(arg->getParent()->isDeclaration()))
return true;
}

if ((node->getInEdges().empty() && node->getOutEdges().empty()))
Expand All @@ -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;
Expand Down
35 changes: 34 additions & 1 deletion svf/lib/SVFIR/SVFVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -468,4 +502,3 @@ bool SVFVar::isConstDataOrAggDataButNotNullPtr() const
else
return false;
}

8 changes: 8 additions & 0 deletions svf/lib/Util/SVFUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ArgValVar>(pVar))
return arg->isArgOfUncalledFunction();
else
return false;
}

const ObjVar* SVFUtil::getObjVarOfValVar(const SVF::ValVar* valVar)
{
Expand Down
4 changes: 2 additions & 2 deletions svf/lib/Util/ThreadAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<LoadStmt>(stmt))
return stmt->getSrcNode();
}
if(SVFUtil::isa<SVFArgument>(join->getValue()))
if(SVFUtil::isa<ArgValVar>(join))
return join;

assert(false && "the value of the first argument at join is not a load instruction?");
Expand Down

0 comments on commit 7e42038

Please sign in to comment.