Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
SVF::SVFIRBuilder Class Reference

#include <SVFIRBuilder.h>

Inheritance diagram for SVF::SVFIRBuilder:

Public Member Functions

 SVFIRBuilder (SVFModule *mod)
 Constructor.
 
virtual ~SVFIRBuilder ()
 Destructor.
 
virtual SVFIRbuild ()
 Start building SVFIR here.
 
SVFIRgetPAG () const
 Return SVFIR.
 
void initialiseNodes ()
 Initialize nodes and edges.
 
void addEdge (NodeID src, NodeID dst, SVFStmt::PEDGEK kind, APOffset offset=0, Instruction *cs=nullptr)
 
void sanityCheck ()
 Sanity check for SVFIR.
 
NodeID getValueNode (const Value *V)
 Get different kinds of node.
 
NodeID getObjectNode (const Value *V)
 GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.
 
NodeID getReturnNode (const SVFFunction *func)
 getReturnNode - Return the node representing the unique return value of a function.
 
NodeID getVarargNode (const SVFFunction *func)
 getVarargNode - Return the node representing the unique variadic argument of a function.
 
virtual void visitAllocaInst (AllocaInst &AI)
 Our visit overrides.
 
void visitPHINode (PHINode &I)
 
void visitStoreInst (StoreInst &I)
 
void visitLoadInst (LoadInst &I)
 
void visitGetElementPtrInst (GetElementPtrInst &I)
 
void visitCallInst (CallInst &I)
 
void visitInvokeInst (InvokeInst &II)
 
void visitCallBrInst (CallBrInst &I)
 
void visitCallSite (CallBase *cs)
 
void visitReturnInst (ReturnInst &I)
 
void visitCastInst (CastInst &I)
 
void visitSelectInst (SelectInst &I)
 
void visitExtractValueInst (ExtractValueInst &EVI)
 
void visitBranchInst (BranchInst &I)
 
void visitSwitchInst (SwitchInst &I)
 The following implementation follows ICFGBuilder::processFunBody.
 
void visitInsertValueInst (InsertValueInst &I)
 
void visitBinaryOperator (BinaryOperator &I)
 
void visitUnaryOperator (UnaryOperator &I)
 
void visitCmpInst (CmpInst &I)
 
void visitVAArgInst (VAArgInst &)
 
void visitVACopyInst (VACopyInst &)
 
void visitVAEndInst (VAEndInst &)
 
void visitVAStartInst (VAStartInst &)
 
void visitFreezeInst (FreezeInst &I)
 
void visitExtractElementInst (ExtractElementInst &I)
 
void visitInsertElementInst (InsertElementInst &I)
 
void visitShuffleVectorInst (ShuffleVectorInst &I)
 
void visitLandingPadInst (LandingPadInst &I)
 
void visitResumeInst (ResumeInst &)
 Instruction not that often.
 
void visitUnreachableInst (UnreachableInst &)
 
void visitFenceInst (FenceInst &I)
 
void visitAtomicCmpXchgInst (AtomicCmpXchgInst &I)
 
void visitAtomicRMWInst (AtomicRMWInst &I)
 
void visitInstruction (Instruction &)
 Provide base case for our instruction visit.
 
void updateCallGraph (PTACallGraph *callgraph)
 connect PAG edges based on callgraph
 

Protected Member Functions

void visitGlobal (SVFModule *svfModule)
 Handle globals including (global variable and functions)
 
void InitialGlobal (const GlobalVariable *gvar, Constant *C, u32_t offset)
 
NodeID getGlobalVarField (const GlobalVariable *gvar, u32_t offset, SVFType *tpy)
 
void processCE (const Value *val)
 Process constant expression.
 
u32_t inferFieldIdxFromByteOffset (const llvm::GEPOperator *gepOp, DataLayout *dl, AccessPath &ap, APOffset idx)
 Infer field index from byteoffset.
 
bool computeGepOffset (const User *V, AccessPath &ap)
 Compute offset of a gep instruction or gep constant expression.
 
const ValuegetBaseValueForExtArg (const Value *V)
 Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst, i8* src, int size))
 
void handleDirectCall (CallBase *cs, const Function *F)
 Handle direct call.
 
void handleIndCall (CallBase *cs)
 Handle indirect call.
 
virtual const TypegetBaseTypeAndFlattenedFields (const Value *V, std::vector< AccessPath > &fields, const Value *szValue)
 Handle external call.
 
virtual void addComplexConsForExt (Value *D, Value *S, const Value *sz)
 
virtual void handleExtCall (const CallBase *cs, const SVFFunction *svfCallee)
 
void setCurrentLocation (const Value *val, const BasicBlock *bb)
 Set current basic block in order to keep track of control flow information.
 
void setCurrentLocation (const SVFValue *val, const SVFBasicBlock *bb)
 
const SVFValuegetCurrentValue () const
 
const SVFBasicBlockgetCurrentBB () const
 
void addGlobalBlackHoleAddrEdge (NodeID node, const ConstantExpr *int2Ptrce)
 Add global black hole Address edge.
 
NodeID addNullPtrNode ()
 Add NullPtr PAGNode.
 
NodeID getGepValVar (const Value *val, const AccessPath &ap, const SVFType *elementType)
 
void setCurrentBBAndValueForPAGEdge (PAGEdge *edge)
 
void addBlackHoleAddrEdge (NodeID node)
 
AddrStmtaddAddrEdge (NodeID src, NodeID dst)
 Add Address edge.
 
AddrStmtaddAddrWithStackArraySz (NodeID src, NodeID dst, llvm::AllocaInst &inst)
 Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".
 
AddrStmtaddAddrWithHeapSz (NodeID src, NodeID dst, const CallBase *cs)
 Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".
 
CopyStmtaddCopyEdge (NodeID src, NodeID dst, CopyStmt::CopyKind kind)
 
CopyStmt::CopyKind getCopyKind (const Value *val)
 
void addPhiStmt (NodeID res, NodeID opnd, const ICFGNode *pred)
 Add Copy edge.
 
void addSelectStmt (NodeID res, NodeID op1, NodeID op2, NodeID cond)
 Add SelectStmt.
 
void addCmpEdge (NodeID op1, NodeID op2, NodeID dst, u32_t predict)
 Add Copy edge.
 
void addBinaryOPEdge (NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
 Add Copy edge.
 
void addUnaryOPEdge (NodeID src, NodeID dst, u32_t opcode)
 Add Unary edge.
 
void addBranchStmt (NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
 Add Branch statement.
 
void addLoadEdge (NodeID src, NodeID dst)
 Add Load edge.
 
void addStoreEdge (NodeID src, NodeID dst)
 Add Store edge.
 
void addCallEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
 Add Call edge.
 
void addRetEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
 Add Return edge.
 
void addGepEdge (NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
 Add Gep edge.
 
void addNormalGepEdge (NodeID src, NodeID dst, const AccessPath &ap)
 Add Offset(Gep) edge.
 
void addVariantGepEdge (NodeID src, NodeID dst, const AccessPath &ap)
 Add Variant(Gep) edge.
 
void addThreadForkEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
 Add Thread fork edge for parameter passing.
 
void addThreadJoinEdge (NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
 Add Thread join edge for parameter passing.
 
AccessPath getAccessPathFromBaseNode (NodeID nodeId)
 

Private Member Functions

LLVMModuleSetllvmModuleSet ()
 

Private Attributes

SVFIRpag
 
SVFModulesvfModule
 
const SVFBasicBlockcurBB
 Current basic block during SVFIR construction when visiting the module.
 
const SVFValuecurVal
 Current Value during SVFIR construction when visiting the module.
 

Detailed Description

SVFIR Builder to create SVF variables and statements and PAG

Definition at line 46 of file SVFIRBuilder.h.

Constructor & Destructor Documentation

◆ SVFIRBuilder()

SVF::SVFIRBuilder::SVFIRBuilder ( SVFModule mod)
inline

Constructor.

Definition at line 57 of file SVFIRBuilder.h.

57 : pag(SVFIR::getPAG()), svfModule(mod), curBB(nullptr),curVal(nullptr)
58 {
59 }
SVFModule * svfModule
const SVFBasicBlock * curBB
Current basic block during SVFIR construction when visiting the module.
const SVFValue * curVal
Current Value during SVFIR construction when visiting the module.
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116

◆ ~SVFIRBuilder()

virtual SVF::SVFIRBuilder::~SVFIRBuilder ( )
inlinevirtual

Destructor.

Definition at line 61 of file SVFIRBuilder.h.

62 {
63 }

Member Function Documentation

◆ addAddrEdge()

AddrStmt * SVF::SVFIRBuilder::addAddrEdge ( NodeID  src,
NodeID  dst 
)
inlineprotected

Add Address edge.

Definition at line 294 of file SVFIRBuilder.h.

295 {
296 if(AddrStmt *edge = pag->addAddrStmt(src, dst))
297 {
299 return edge;
300 }
301 return nullptr;
302 }
void setCurrentBBAndValueForPAGEdge(PAGEdge *edge)
AddrStmt * addAddrStmt(NodeID src, NodeID dst)
Add an edge into SVFIR.
Definition SVFIR.cpp:47
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

◆ addAddrWithHeapSz()

AddrStmt * SVF::SVFIRBuilder::addAddrWithHeapSz ( NodeID  src,
NodeID  dst,
const CallBase cs 
)
inlineprotected

Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".

Definition at line 317 of file SVFIRBuilder.h.

318 {
319 // get name of called function
320 AddrStmt* edge = addAddrEdge(src, dst);
321
322 llvm::Function* calledFunc = cs->getCalledFunction();
323 std::string functionName;
324 if (calledFunc)
325 {
326 functionName = calledFunc->getName().str();
327 }
328 else
329 {
330 SVFUtil::wrnMsg("not support indirect call to add AddrStmt.\n");
331 }
332 if (functionName == "malloc")
333 {
334 if (cs->arg_size() > 0)
335 {
336 const llvm::Value* val = cs->getArgOperand(0);
337 SVFValue* svfval = llvmModuleSet()->getSVFValue(val);
338 edge->addArrSize(svfval);
339 }
340 }
341 // Check if the function called is 'calloc' and process its arguments.
342 // e.g. "%5 = call i8* @calloc(1, 8)", edge should add two SVFValue (1 and 8)
343 else if (functionName == "calloc")
344 {
345 if (cs->arg_size() > 1)
346 {
347 edge->addArrSize(llvmModuleSet()->getSVFValue(cs->getArgOperand(0)));
348 edge->addArrSize(llvmModuleSet()->getSVFValue(cs->getArgOperand(1)));
349 }
350 }
351 else
352 {
353 if (cs->arg_size() > 0)
354 {
355 const llvm::Value* val = cs->getArgOperand(0);
356 SVFValue* svfval = llvmModuleSet()->getSVFValue(val);
357 edge->addArrSize(svfval);
358 }
359 }
360 return edge;
361 }
SVFValue * getSVFValue(const Value *value)
AddrStmt * addAddrEdge(NodeID src, NodeID dst)
Add Address edge.
LLVMModuleSet * llvmModuleSet()
std::string wrnMsg(const std::string &msg)
Returns warning message by converting a string into yellow string output.
Definition SVFUtil.cpp:62

◆ addAddrWithStackArraySz()

AddrStmt * SVF::SVFIRBuilder::addAddrWithStackArraySz ( NodeID  src,
NodeID  dst,
llvm::AllocaInst &  inst 
)
inlineprotected

Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".

Definition at line 305 of file SVFIRBuilder.h.

306 {
307 AddrStmt* edge = addAddrEdge(src, dst);
308 if (inst.getArraySize())
309 {
310 SVFValue* arrSz = llvmModuleSet()->getSVFValue(inst.getArraySize());
311 edge->addArrSize(arrSz);
312 }
313 return edge;
314 }

◆ addBinaryOPEdge()

void SVF::SVFIRBuilder::addBinaryOPEdge ( NodeID  op1,
NodeID  op2,
NodeID  dst,
u32_t  opcode 
)
inlineprotected

Add Copy edge.

Definition at line 429 of file SVFIRBuilder.h.

430 {
431 if(BinaryOPStmt *edge = pag->addBinaryOPStmt(op1, op2, dst, opcode))
433 }
BinaryOPStmt * addBinaryOPStmt(NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
Add Copy edge.
Definition SVFIR.cpp:149

◆ addBlackHoleAddrEdge()

void SVF::SVFIRBuilder::addBlackHoleAddrEdge ( NodeID  node)
inlineprotected

Definition at line 287 of file SVFIRBuilder.h.

288 {
291 }
SVFStmt * addBlackHoleAddrStmt(NodeID node)
Set a pointer points-to black hole (e.g. int2ptr)
Definition SVFIR.cpp:278
SVFStmt PAGEdge
Definition IRGraph.h:43

◆ addBranchStmt()

void SVF::SVFIRBuilder::addBranchStmt ( NodeID  br,
NodeID  cond,
const BranchStmt::SuccAndCondPairVec succs 
)
inlineprotected

Add Branch statement.

Definition at line 441 of file SVFIRBuilder.h.

442 {
443 if(BranchStmt *edge = pag->addBranchStmt(br, cond, succs))
445 }
BranchStmt * addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add BranchStmt.
Definition SVFIR.cpp:187

◆ addCallEdge()

void SVF::SVFIRBuilder::addCallEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunEntryICFGNode entry 
)
inlineprotected

Add Call edge.

Definition at line 465 of file SVFIRBuilder.h.

466 {
467 if (CallPE* edge = pag->addCallPE(src, dst, cs, entry))
469 }
CallPE * addCallPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge.
Definition SVFIR.cpp:242

◆ addCmpEdge()

void SVF::SVFIRBuilder::addCmpEdge ( NodeID  op1,
NodeID  op2,
NodeID  dst,
u32_t  predict 
)
inlineprotected

Add Copy edge.

Definition at line 423 of file SVFIRBuilder.h.

424 {
425 if(CmpStmt *edge = pag->addCmpStmt(op1, op2, dst, predict))
427 }
CmpStmt * addCmpStmt(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.
Definition SVFIR.cpp:128

◆ addComplexConsForExt()

void SVFIRBuilder::addComplexConsForExt ( Value D,
Value S,
const Value szValue 
)
protectedvirtual

Add the load/store constraints and temp. nodes for the complex constraint *D = *S (where D/S may point to structs).

If sz is 0, we will add edges for all fields.

Definition at line 79 of file SVFIRExtAPI.cpp.

80{
81 assert(D && S);
83 if(!vnD || !vnS)
84 return;
85
86 std::vector<AccessPath> fields;
87
88 //Get the max possible size of the copy, unless it was provided.
89 std::vector<AccessPath> srcFields;
90 std::vector<AccessPath> dstFields;
93 if(srcFields.size() > dstFields.size())
95 else
97
99 u32_t sz = fields.size();
100
102 {
106 return;
107 }
108
109 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
110 for (u32_t index = 0; index < sz; index++)
111 {
114 fields[index].getConstantStructFldIdx());
116 fields[index].getConstantStructFldIdx());
122 }
123}
unsigned u32_t
Definition CommandLine.h:18
int index
Definition cJSON.h:170
SymbolTableInfo * getSymbolInfo() const
Definition IRGraph.h:114
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:122
void addStoreEdge(NodeID src, NodeID dst)
Add Store edge.
void addLoadEdge(NodeID src, NodeID dst)
Add Load edge.
virtual const Type * getBaseTypeAndFlattenedFields(const Value *V, std::vector< AccessPath > &fields, const Value *szValue)
Handle external call.
NodeID getValueNode(const Value *V)
Get different kinds of node.
NodeID getGepValVar(const Value *val, const AccessPath &ap, const SVFType *elementType)
NodeID addDummyValNode()
Definition SVFIR.h:496
const SVFType * getFlatternedElemType(const SVFType *baseType, u32_t flatten_idx)
Return the type of a flattened element given a flattened index.
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:327
llvm::Type Type
Definition BasicTypes.h:83
u32_t NodeID
Definition GeneralType.h:55

◆ addCopyEdge()

CopyStmt * SVF::SVFIRBuilder::addCopyEdge ( NodeID  src,
NodeID  dst,
CopyStmt::CopyKind  kind 
)
inlineprotected

Definition at line 363 of file SVFIRBuilder.h.

364 {
365 if(CopyStmt *edge = pag->addCopyStmt(src, dst, kind))
366 {
368 return edge;
369 }
370 return nullptr;
371 }
CopyStmt * addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type)
Add Copy edge.
Definition SVFIR.cpp:65

◆ addEdge()

void SVF::SVFIRBuilder::addEdge ( NodeID  src,
NodeID  dst,
SVFStmt::PEDGEK  kind,
APOffset  offset = 0,
Instruction cs = nullptr 
)

◆ addGepEdge()

void SVF::SVFIRBuilder::addGepEdge ( NodeID  src,
NodeID  dst,
const AccessPath ap,
bool  constGep 
)
inlineprotected

Add Gep edge.

Definition at line 477 of file SVFIRBuilder.h.

478 {
479 if (GepStmt* edge = pag->addGepStmt(src, dst, ap, constGep))
481 }
GepStmt * addGepStmt(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
Definition SVFIR.cpp:328

◆ addGlobalBlackHoleAddrEdge()

void SVF::SVFIRBuilder::addGlobalBlackHoleAddrEdge ( NodeID  node,
const ConstantExpr int2Ptrce 
)
inlineprotected

Add global black hole Address edge.

Definition at line 261 of file SVFIRBuilder.h.

262 {
263 const SVFValue* cval = getCurrentValue();
264 const SVFBasicBlock* cbb = getCurrentBB();
268 }
void setCurrentLocation(const Value *val, const BasicBlock *bb)
Set current basic block in order to keep track of control flow information.
void addBlackHoleAddrEdge(NodeID node)
const SVFValue * getCurrentValue() const
const SVFBasicBlock * getCurrentBB() const

◆ addLoadEdge()

void SVF::SVFIRBuilder::addLoadEdge ( NodeID  src,
NodeID  dst 
)
inlineprotected

Add Load edge.

Definition at line 447 of file SVFIRBuilder.h.

448 {
449 if(LoadStmt *edge = pag->addLoadStmt(src, dst))
451 }
LoadStmt * addLoadStmt(NodeID src, NodeID dst)
Add Load edge.
Definition SVFIR.cpp:205

◆ addNormalGepEdge()

void SVF::SVFIRBuilder::addNormalGepEdge ( NodeID  src,
NodeID  dst,
const AccessPath ap 
)
inlineprotected

Add Offset(Gep) edge.

Definition at line 483 of file SVFIRBuilder.h.

484 {
485 if (GepStmt* edge = pag->addNormalGepStmt(src, dst, ap))
487 }
GepStmt * addNormalGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Offset(Gep) edge.
Definition SVFIR.cpp:347

◆ addNullPtrNode()

NodeID SVF::SVFIRBuilder::addNullPtrNode ( )
inlineprotected

Add NullPtr PAGNode.

Definition at line 271 of file SVFIRBuilder.h.

272 {
274 ConstantPointerNull* constNull = ConstantPointerNull::get(PointerType::getUnqual(cxt));
280 return nullPtr;
281 }
NodeType * getGNode(NodeID id) const
Get a node.
NodeID getBlkPtr() const
Definition IRGraph.h:169
NodeID getNullPtr() const
Definition IRGraph.h:173
void addToLLVMVal2SVFVarMap(const Value *val, SVFBaseNode *svfBaseNode)
LLVMContext & getContext() const
Definition LLVMModule.h:379
NodeID addConstantNullPtrValNode(const SVFValue *curInst, const NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:595
llvm::ConstantPointerNull ConstantPointerNull
Definition BasicTypes.h:127
llvm::LLVMContext LLVMContext
Definition BasicTypes.h:70

◆ addPhiStmt()

void SVF::SVFIRBuilder::addPhiStmt ( NodeID  res,
NodeID  opnd,
const ICFGNode pred 
)
inlineprotected

Add Copy edge.

If we already added this phi node, then skip this adding

Definition at line 410 of file SVFIRBuilder.h.

411 {
413 if(PhiStmt *edge = pag->addPhiStmt(res,opnd,pred))
415 }
PhiStmt * addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add phi node information.
Definition SVFIR.cpp:83

◆ addRetEdge()

void SVF::SVFIRBuilder::addRetEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunExitICFGNode exit 
)
inlineprotected

Add Return edge.

Definition at line 471 of file SVFIRBuilder.h.

472 {
473 if (RetPE* edge = pag->addRetPE(src, dst, cs, exit))
475 }
RetPE * addRetPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Return edge.
Definition SVFIR.cpp:260

◆ addSelectStmt()

void SVF::SVFIRBuilder::addSelectStmt ( NodeID  res,
NodeID  op1,
NodeID  op2,
NodeID  cond 
)
inlineprotected

Add SelectStmt.

Definition at line 417 of file SVFIRBuilder.h.

418 {
419 if(SelectStmt *edge = pag->addSelectStmt(res,op1,op2,cond))
421 }
SelectStmt * addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
Definition SVFIR.cpp:107

◆ addStoreEdge()

void SVF::SVFIRBuilder::addStoreEdge ( NodeID  src,
NodeID  dst 
)
inlineprotected

Add Store edge.

Definition at line 453 of file SVFIRBuilder.h.

454 {
455 ICFGNode* node;
456 if (const SVFInstruction* inst = SVFUtil::dyn_cast<SVFInstruction>(curVal))
457 node = llvmModuleSet()->getICFGNode(
458 SVFUtil::cast<Instruction>(llvmModuleSet()->getLLVMValue(inst)));
459 else
460 node = nullptr;
461 if (StoreStmt* edge = pag->addStoreStmt(src, dst, node))
463 }
ICFGNode * getICFGNode(const Instruction *inst)
Get a basic block ICFGNode.
StoreStmt * addStoreStmt(NodeID src, NodeID dst, const ICFGNode *val)
Add Store edge.
Definition SVFIR.cpp:224

◆ addThreadForkEdge()

void SVF::SVFIRBuilder::addThreadForkEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunEntryICFGNode entry 
)
inlineprotected

Add Thread fork edge for parameter passing.

Definition at line 495 of file SVFIRBuilder.h.

496 {
497 if (TDForkPE* edge = pag->addThreadForkPE(src, dst, cs, entry))
499 }
TDForkPE * addThreadForkPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Thread fork edge for parameter passing.
Definition SVFIR.cpp:289

◆ addThreadJoinEdge()

void SVF::SVFIRBuilder::addThreadJoinEdge ( NodeID  src,
NodeID  dst,
const CallICFGNode cs,
const FunExitICFGNode exit 
)
inlineprotected

Add Thread join edge for parameter passing.

Definition at line 501 of file SVFIRBuilder.h.

502 {
503 if (TDJoinPE* edge = pag->addThreadJoinPE(src, dst, cs, exit))
505 }
TDJoinPE * addThreadJoinPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Thread join edge for parameter passing.
Definition SVFIR.cpp:307

◆ addUnaryOPEdge()

void SVF::SVFIRBuilder::addUnaryOPEdge ( NodeID  src,
NodeID  dst,
u32_t  opcode 
)
inlineprotected

Add Unary edge.

Definition at line 435 of file SVFIRBuilder.h.

436 {
437 if(UnaryOPStmt *edge = pag->addUnaryOPStmt(src, dst, opcode))
439 }
UnaryOPStmt * addUnaryOPStmt(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.
Definition SVFIR.cpp:169

◆ addVariantGepEdge()

void SVF::SVFIRBuilder::addVariantGepEdge ( NodeID  src,
NodeID  dst,
const AccessPath ap 
)
inlineprotected

Add Variant(Gep) edge.

Definition at line 489 of file SVFIRBuilder.h.

490 {
491 if (GepStmt* edge = pag->addVariantGepStmt(src, dst, ap))
493 }
GepStmt * addVariantGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Variant(Gep) edge.
Definition SVFIR.cpp:366

◆ build()

SVFIR * SVFIRBuilder::build ( )
virtual

Start building SVFIR here.

Start building SVFIR here

initial external library information initial SVFIR nodes

initial SVFIR edges: // handle globals

handle functions

collect return node of function fun

Return SVFIR node will not be created for function which can not reach the return instruction due to call to abort(), exit(), etc. In 176.gcc of SPEC 2000, function build_objc_string() from c-lang.c shows an example when fun.doesNotReturn() evaluates to TRUE because of abort().

To be noted, we do not record arguments which are in declared function without body TODO: what about external functions with SVFIR imported by commandline?

Definition at line 55 of file SVFIRBuilder.cpp.

56{
57 double startTime = SVFStat::getClk(true);
58
59 DBOUT(DGENERAL, outs() << pasMsg("\t Building SVFIR ...\n"));
60
61 // Set SVFModule from SVFIRBuilder
63
64 // Build ICFG
65 pag->setICFG(llvmModuleSet()->getICFG());
66
67 // Set callgraph
68 pag->setCallGraph(llvmModuleSet()->callgraph);
69
70 // Set icfgnode in memobj
71 for (auto& it : SymbolTableInfo::SymbolInfo()->idToObjMap())
72 {
73 if(!it.second->getValue())
74 continue;
75 if (const Instruction* inst =
76 SVFUtil::dyn_cast<Instruction>(llvmModuleSet()->getLLVMValue(
77 it.second->getValue())))
78 {
79 if(llvmModuleSet()->hasICFGNode(inst))
80 it.second->gNode = llvmModuleSet()->getICFGNode(inst);
81 }
82 else if (const Function* func = SVFUtil::dyn_cast<Function>(llvmModuleSet()->getLLVMValue(
83 it.second->getValue())))
84 {
85 it.second->gNode = llvmModuleSet()->getCallGraphNode(func);
86 }
87 }
88
89 CHGraph* chg = new CHGraph(pag->getModule());
91 chgbuilder.buildCHG();
92 pag->setCHG(chg);
93
94 // We read SVFIR from a user-defined txt instead of parsing SVFIR from LLVM IR
96 {
98 return fileBuilder.build();
99 }
100
101 // If the SVFIR has been built before, then we return the unique SVFIR of the program
103 return pag;
104
112
114 for (Module& M : llvmModuleSet()->getLLVMModules())
115 {
116 for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
117 {
118 const Function& fun = *F;
121 if(!fun.isDeclaration())
122 {
128 if (fun.doesNotReturn() == false &&
129 fun.getReturnType()->isVoidTy() == false)
130 {
133 }
134
137 for (Function::const_arg_iterator I = fun.arg_begin(), E = fun.arg_end();
138 I != E; ++I)
139 {
140 setCurrentLocation(&*I,&fun.getEntryBlock());
141 NodeID argValNodeId = pag->getValueNode(llvmModuleSet()->getSVFValue(&*I));
142 // if this is the function does not have caller (e.g. main)
143 // or a dead function, shall we create a black hole address edge for it?
144 // it is (1) too conservative, and (2) make FormalParmVFGNode defined at blackhole address PAGEdge.
145 // if(SVFUtil::ArgInNoCallerFunction(&*I)) {
146 // if(I->getType()->isPointerTy())
147 // addBlackHoleAddrEdge(argValNodeId);
148 //}
150 }
151 }
152 for (Function::const_iterator bit = fun.begin(), ebit = fun.end();
153 bit != ebit; ++bit)
154 {
155 const BasicBlock& bb = *bit;
156 for (BasicBlock::const_iterator it = bb.begin(), eit = bb.end();
157 it != eit; ++it)
158 {
159 const Instruction& inst = *it;
160 setCurrentLocation(&inst,&bb);
161 visit(const_cast<Instruction&>(inst));
162 }
163 }
164 }
165 }
166
167 sanityCheck();
168
170
172
173 // dump SVFIR
175 pag->dump("svfir_initial");
176
177 // print to command line of the SVFIR graph
178 if (Options::PAGPrint())
179 pag->print();
180
181 // dump ICFG
182 if (Options::DumpICFG())
183 pag->getICFG()->dump("icfg_initial");
184
186 {
189 }
190
191 // dump SVFIR as JSON
192 if (!Options::DumpJson().empty())
193 {
195 }
196
197 double endTime = SVFStat::getClk(true);
198 SVFStat::timeOfBuildingSVFIR = (endTime - startTime) / TIMEINTERVAL;
199
200 return pag;
201}
#define F(f)
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:484
#define TIMEINTERVAL
Definition SVFType.h:512
#define DGENERAL
Definition SVFType.h:490
u32_t getTotalNodeNum() const
Get total number of node/edge.
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition ICFG.cpp:403
u32_t getNodeNumAfterPAGBuild() const
Definition IRGraph.h:194
void dump(std::string name)
Dump SVFIR.
Definition IRGraph.cpp:102
NodeID getValueNode(const SVFValue *V)
Definition IRGraph.h:137
void setNodeNumAfterPAGBuild(u32_t num)
Definition IRGraph.h:198
NodeID getReturnNode(const SVFFunction *func) const
GetReturnNode - Return the unique node representing the return value of a function.
Definition IRGraph.h:152
virtual void build(ICFG *icfg)
Start from here.
CallGraphNode * getCallGraphNode(const Function *fun) const
Definition LLVMModule.h:253
SVFFunction * getSVFFunction(const Function *fun) const
Definition LLVMModule.h:260
static const Option< bool > PAGDotGraph
Definition Options.h:121
static const Option< std::string > DumpJson
Definition Options.h:124
static const Option< bool > PAGPrint
Definition Options.h:127
static const Option< bool > LoopAnalysis
Definition Options.h:242
static const Option< bool > DumpICFG
Definition Options.h:123
void sanityCheck()
Sanity check for SVFIR.
void visitGlobal(SVFModule *svfModule)
Handle globals including (global variable and functions)
void initialiseNodes()
Initialize nodes and edges.
static void writeJsonToPath(const SVFIR *svfir, const std::string &path)
void print()
Print SVFIR.
Definition SVFIR.cpp:566
void setModule(SVFModule *mod)
Set/Get LLVM Module.
Definition SVFIR.h:158
void addFunRet(const SVFFunction *fun, const SVFVar *ret)
Add function returns.
Definition SVFIR.h:539
void setICFG(ICFG *i)
Set/Get ICFG.
Definition SVFIR.h:168
ICFG * getICFG() const
Definition SVFIR.h:172
void setCHG(CommonCHGraph *c)
Set/Get CHG.
Definition SVFIR.h:178
SVFModule * getModule()
Definition SVFIR.h:162
void addFunArgs(const SVFFunction *fun, const SVFVar *arg)
Get/set method for function/callsite arguments and returns.
Definition SVFIR.h:532
void setCallGraph(CallGraph *c)
Set/Get CG.
Definition SVFIR.h:189
void initialiseCandidatePointers()
Initialize candidate pointers.
Definition SVFIR.cpp:651
static bool pagReadFromTXT()
Definition SVFModule.h:98
static std::string pagFileName()
Definition SVFModule.h:93
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
static double timeOfBuildingSVFIR
Definition SVFStat.h:95
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:100
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
llvm::BasicBlock BasicBlock
Definition BasicTypes.h:86
llvm::Function Function
Definition BasicTypes.h:85
llvm::Instruction Instruction
Definition BasicTypes.h:87
llvm::Module Module
Definition BasicTypes.h:84

◆ computeGepOffset()

bool SVFIRBuilder::computeGepOffset ( const User V,
AccessPath ap 
)
protected

Compute offset of a gep instruction or gep constant expression.

Return the object node offset according to GEP insn (V). Given a gep edge p = q + i, if "i" is a constant then we return its offset size otherwise if "i" is a variable determined by runtime, then it is a variant offset Return TRUE if the offset of this GEP insn is a constant.

Definition at line 424 of file SVFIRBuilder.cpp.

425{
426 assert(V);
427
428 const llvm::GEPOperator *gepOp = SVFUtil::dyn_cast<const llvm::GEPOperator>(V);
429 DataLayout * dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
430 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gepOp->getPointerAddressSpace()),0,true);
431 if(gepOp && dataLayout && gepOp->accumulateConstantOffset(*dataLayout,byteOffset))
432 {
433 //s32_t bo = byteOffset.getSExtValue();
434 }
435
436 bool isConst = true;
437
438 bool prevPtrOperand = false;
440 gi != ge; ++gi)
441 {
442 const Type* gepTy = *gi;
444
445 assert((prevPtrOperand && svfGepTy->isPointerTy()) == false &&
446 "Expect no more than one gep operand to be of a pointer type");
447 if(!prevPtrOperand && svfGepTy->isPointerTy()) prevPtrOperand = true;
448 const Value* offsetVal = gi.getOperand();
450 assert(gepTy != offsetVal->getType() && "iteration and operand have the same type?");
452
453 //The int value of the current index operand
454 const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(offsetVal);
455
456 // if Options::ModelConsts() is disabled. We will treat whole array as one,
457 // but we can distinguish different field of an array of struct, e.g. s[1].f1 is different from s[0].f2
458 if(const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(gepTy))
459 {
460 if(!op || (arrTy->getArrayNumElements() <= (u32_t)op->getSExtValue()))
461 continue;
462 APOffset idx = op->getSExtValue();
465 }
466 else if (const StructType *ST = SVFUtil::dyn_cast<StructType>(gepTy))
467 {
468 assert(op && "non-const offset accessing a struct");
469 //The actual index
470 APOffset idx = op->getSExtValue();
473 }
474 else if (gepTy->isSingleValueType())
475 {
476 // If it's a non-constant offset access
477 // If its point-to target is struct or array, it's likely an array accessing (%result = gep %struct.A* %a, i32 %non-const-index)
478 // If its point-to target is single value (pointer arithmetic), then it's a variant gep (%result = gep i8* %p, i32 %non-const-index)
479 if(!op && gepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
480 {
481 isConst = false;
482 }
483
484 // The actual index
485 //s32_t idx = op->getSExtValue();
486
487 // For pointer arithmetic we ignore the byte offset
488 // consider using inferFieldIdxFromByteOffset(geopOp,dataLayout,ap,idx)?
489 // ap.setFldIdx(ap.getConstantFieldIdx() + inferFieldIdxFromByteOffset(geopOp,idx));
490 }
491 }
492 return isConst;
493}
buffer offset
Definition cJSON.cpp:1113
bool addOffsetVarAndGepTypePair(const SVFVar *var, const SVFType *gepIterType)
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:100
void setFldIdx(APOffset idx)
Definition AccessPath.h:104
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
SVFIR * getPAG() const
Return SVFIR.
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
static DataLayout * getDataLayout(Module *mod)
Definition LLVMUtil.h:279
llvm::DataLayout DataLayout
Definition BasicTypes.h:108
llvm::ArrayType ArrayType
Definition BasicTypes.h:95
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:94
s64_t APOffset
Definition GeneralType.h:60
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:82
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:125
bridge_gep_iterator bridge_gep_end(const User *GEP)
bridge_gep_iterator bridge_gep_begin(const User *GEP)

◆ getAccessPathFromBaseNode()

AccessPath SVFIRBuilder::getAccessPathFromBaseNode ( NodeID  nodeId)
protected

Get a base SVFVar given a pointer Return the source node of its connected normal gep edge Otherwise return the node id itself s32_t offset : gep offset

if this node is already a base node

Definition at line 1517 of file SVFIRBuilder.cpp.

1518{
1519 SVFVar* node = pag->getGNode(nodeId);
1522 if(geps.empty())
1523 return AccessPath(0);
1524
1525 assert(geps.size()==1 && "one node can only be connected by at most one gep edge!");
1526 SVFVar::iterator it = geps.begin();
1527 const GepStmt* gepEdge = SVFUtil::cast<GepStmt>(*it);
1528 if(gepEdge->isVariantFieldGep())
1529 return AccessPath(0);
1530 else
1531 return gepEdge->getAccessPath();
1532}
GEdgeSetTy::iterator iterator
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
SVFStmt::SVFStmtSetTy & getIncomingEdges(SVFStmt::PEDGEK kind)
Get incoming SVFIR statements (edges)

◆ getBaseTypeAndFlattenedFields()

const Type * SVFIRBuilder::getBaseTypeAndFlattenedFields ( const Value V,
std::vector< AccessPath > &  fields,
const Value szValue 
)
protectedvirtual

Handle external call.

Find the base type and the max possible offset of an object pointed to by (V).

use user-specified size for this copy operation if the size is a constaint int

Definition at line 44 of file SVFIRExtAPI.cpp.

45{
46 assert(V);
47 const Value* value = getBaseValueForExtArg(V);
51 if(szValue && SVFUtil::isa<ConstantInt>(szValue))
52 {
53 numOfElems = (numOfElems > SVFUtil::cast<ConstantInt>(szValue)->getSExtValue()) ? SVFUtil::cast<ConstantInt>(szValue)->getSExtValue() : numOfElems;
54 }
55
57 for(u32_t ei = 0; ei < numOfElems; ei++)
58 {
60 // make a ConstantInt and create char for the content type due to byte-wise copy
61 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
64 {
66 builder.collectSym(offset);
67 pag->addConstantIntValNode(svfOffset, offset->getSExtValue(), offset->getZExtValue(), pag->getSymbolInfo()->getValSym(svfOffset), nullptr);
68 }
69 ls.addOffsetVarAndGepTypePair(getPAG()->getGNode(getPAG()->getValueNode(svfOffset)), nullptr);
70 fields.push_back(ls);
71 }
72 return objType;
73}
ObjTypeInference * getTypeInference()
const Type * inferObjType(const Value *var)
get or infer the type of the object pointed by the value
const Value * getBaseValueForExtArg(const Value *V)
Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst,...
NodeID addConstantIntValNode(const SVFValue *curInst, s64_t sval, u64_t zval, const NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:588
SymID getValSym(const SVFValue *val)
Get different kinds of syms.
u32_t getNumOfFlattenElements(const SVFType *T)
Number of flattened elements of an array or struct.
bool hasValSym(const SVFValue *val)

◆ getBaseValueForExtArg()

const Value * SVFIRBuilder::getBaseValueForExtArg ( const Value V)
protected

Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst, i8* src, int size))

Definition at line 1290 of file SVFIRBuilder.cpp.

1291{
1292 const Value* value = stripAllCasts(V);
1293 assert(value && "null ptr?");
1294 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(value))
1295 {
1296 APOffset totalidx = 0;
1298 {
1299 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
1300 totalidx += op->getSExtValue();
1301 }
1302 if(totalidx == 0 && !SVFUtil::isa<StructType>(value->getType()))
1303 value = gep->getPointerOperand();
1304 }
1305 return value;
1306}
const Value * stripAllCasts(const Value *val)
Strip off the all casts.
Definition LLVMUtil.cpp:250
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:162

◆ getCopyKind()

CopyStmt::CopyKind SVF::SVFIRBuilder::getCopyKind ( const Value val)
inlineprotected

Definition at line 373 of file SVFIRBuilder.h.

374 {
375 // COPYVAL, ZEXT, SEXT, BITCAST, FPTRUNC, FPTOUI, FPTOSI, UITOFP, SITOFP, INTTOPTR, PTRTOINT
376 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(val))
377 {
378 switch (inst->getOpcode())
379 {
380 case Instruction::ZExt:
381 return CopyStmt::ZEXT;
382 case Instruction::SExt:
383 return CopyStmt::SEXT;
384 case Instruction::BitCast:
385 return CopyStmt::BITCAST;
386 case Instruction ::Trunc:
387 return CopyStmt::TRUNC;
388 case Instruction::FPTrunc:
389 return CopyStmt::FPTRUNC;
390 case Instruction::FPToUI:
391 return CopyStmt::FPTOUI;
392 case Instruction::FPToSI:
393 return CopyStmt::FPTOSI;
394 case Instruction::UIToFP:
395 return CopyStmt::UITOFP;
396 case Instruction::SIToFP:
397 return CopyStmt::SITOFP;
398 case Instruction::IntToPtr:
399 return CopyStmt::INTTOPTR;
400 case Instruction::PtrToInt:
401 return CopyStmt::PTRTOINT;
402 default:
403 return CopyStmt::COPYVAL;
404 }
405 }
406 assert (false && "Unknown cast inst!");
407 }

◆ getCurrentBB()

const SVFBasicBlock * SVF::SVFIRBuilder::getCurrentBB ( ) const
inlineprotected

Definition at line 255 of file SVFIRBuilder.h.

256 {
257 return curBB;
258 }

◆ getCurrentValue()

const SVFValue * SVF::SVFIRBuilder::getCurrentValue ( ) const
inlineprotected

Definition at line 251 of file SVFIRBuilder.h.

252 {
253 return curVal;
254 }

◆ getGepValVar()

NodeID SVFIRBuilder::getGepValVar ( const Value val,
const AccessPath ap,
const SVFType elementType 
)
protected

Add a temp field value node according to base value and offset this node is after the initial node method, it is out of scope of symInfo table

Definition at line 1381 of file SVFIRBuilder.cpp.

1382{
1383 NodeID base = getValueNode(val);
1384 NodeID gepval = pag->getGepValVar(curVal, base, ap);
1385 if (gepval==UINT_MAX)
1386 {
1387 assert(((int) UINT_MAX)==-1 && "maximum limit of unsigned int is not -1?");
1388 /*
1389 * getGepValVar can only be called from two places:
1390 * 1. SVFIRBuilder::addComplexConsForExt to handle external calls
1391 * 2. SVFIRBuilder::getGlobalVarField to initialize global variable
1392 * so curVal can only be
1393 * 1. Instruction
1394 * 2. GlobalVariable
1395 */
1396 assert((SVFUtil::isa<SVFInstruction, SVFGlobalValue>(curVal)) && "curVal not an instruction or a globalvariable?");
1397
1398 // We assume every GepValNode and its GepEdge to the baseNode are unique across the whole program
1399 // We preserve the current BB information to restore it after creating the gepNode
1400 const SVFValue* cval = getCurrentValue();
1401 const SVFBasicBlock* cbb = getCurrentBB();
1402 setCurrentLocation(curVal, nullptr);
1404 NodeID gepNode = pag->addGepValNode(curVal, llvmmodule->getSVFValue(val), ap,
1406 llvmmodule->getSVFType(PointerType::getUnqual(llvmmodule->getContext())));
1407 addGepEdge(base, gepNode, ap, true);
1409 return gepNode;
1410 }
1411 else
1412 return gepval;
1413}
NodeID allocateValueId(void)
Allocate a value ID as determined by the strategy.
static NodeIDAllocator * get(void)
Return (singleton) allocator.
void addGepEdge(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
NodeID addGepValNode(const SVFValue *curInst, const SVFValue *val, const AccessPath &ap, NodeID i, const SVFType *type)
Add a temp field value node, this method can only invoked by getGepValVar.
Definition SVFIR.cpp:387
NodeID getGepValVar(const SVFValue *curInst, NodeID base, const AccessPath &ap) const
Due to constraint expression, curInst is used to distinguish different instructions (e....
Definition SVFIR.cpp:529

◆ getGlobalVarField()

NodeID SVFIRBuilder::getGlobalVarField ( const GlobalVariable gvar,
u32_t  offset,
SVFType tpy 
)
protected

Get the field of the global variable node FIXME:Here we only get the field that actually used in the program We ignore the initialization of global variable field that not used in the program

if we did not find the constant expression in the program, then we need to create a gep node for this field

Definition at line 629 of file SVFIRBuilder.cpp.

630{
631
632 // if the global variable do not have any field needs to be initialized
633 if (offset == 0 && gvar->getInitializer()->getType()->isSingleValueType())
634 {
635 return getValueNode(gvar);
636 }
639 else
640 {
642 }
643}

◆ getObjectNode()

NodeID SVF::SVFIRBuilder::getObjectNode ( const Value V)
inline

GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.

Definition at line 98 of file SVFIRBuilder.h.

99 {
100 SVFValue* svfVal = llvmModuleSet()->getSVFValue(V);
101 return pag->getObjectNode(svfVal);
102 }
NodeID getObjectNode(const SVFValue *V)
Definition IRGraph.h:147

◆ getPAG()

SVFIR * SVF::SVFIRBuilder::getPAG ( ) const
inline

Return SVFIR.

Definition at line 69 of file SVFIRBuilder.h.

70 {
71 return pag;
72 }

◆ getReturnNode()

NodeID SVF::SVFIRBuilder::getReturnNode ( const SVFFunction func)
inline

getReturnNode - Return the node representing the unique return value of a function.

Definition at line 105 of file SVFIRBuilder.h.

106 {
107 return pag->getReturnNode(func);
108 }

◆ getValueNode()

NodeID SVF::SVFIRBuilder::getValueNode ( const Value V)
inline

Get different kinds of node.

Definition at line 87 of file SVFIRBuilder.h.

88 {
89 // first handle gep edge if val if a constant expression
90 processCE(V);
91
92 // strip off the constant cast and return the value node
93 SVFValue* svfVal = llvmModuleSet()->getSVFValue(V);
94 return pag->getValueNode(svfVal);
95 }
void processCE(const Value *val)
Process constant expression.

◆ getVarargNode()

NodeID SVF::SVFIRBuilder::getVarargNode ( const SVFFunction func)
inline

getVarargNode - Return the node representing the unique variadic argument of a function.

Definition at line 111 of file SVFIRBuilder.h.

112 {
113 return pag->getVarargNode(func);
114 }
NodeID getVarargNode(const SVFFunction *func) const
getVarargNode - Return the unique node representing the variadic argument of a variadic function.
Definition IRGraph.h:157

◆ handleDirectCall()

void SVFIRBuilder::handleDirectCall ( CallBase cs,
const Function F 
)
protected

Handle direct call.

Add the constraints for a direct, non-external call.

FIXME: this assertion should be placed for correct checking except bug program like 188.ammp, 300.twolf

Definition at line 1227 of file SVFIRBuilder.cpp.

1228{
1229
1230 assert(F);
1234 outs() << "handle direct call " << LLVMUtil::dumpValue(cs) << " callee " << F->getName().str() << "\n");
1235
1236 //Only handle the ret.val. if it's used as a ptr.
1238 //Does it actually return a ptr?
1239 if (!cs->getType()->isVoidTy())
1240 {
1244 }
1245 //Iterators for the actual and formal parameters
1246 u32_t itA = 0, ieA = cs->arg_size();
1247 Function::const_arg_iterator itF = F->arg_begin(), ieF = F->arg_end();
1248 //Go through the fixed parameters.
1249 DBOUT(DPAGBuild, outs() << " args:");
1250 for (; itF != ieF; ++itA, ++itF)
1251 {
1252 //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
1253 if (itA == ieA)
1254 {
1255 DBOUT(DPAGBuild, outs() << " !! not enough args\n");
1256 break;
1257 }
1258 const Value* AA = cs->getArgOperand(itA), *FA = &*itF; //current actual/formal arg
1259
1260 DBOUT(DPAGBuild, outs() << "process actual parm " << llvmModuleSet()->getSVFValue(AA)->toString() << " \n");
1261
1266 }
1267 //Any remaining actual args must be varargs.
1268 if (F->isVarArg())
1269 {
1271 DBOUT(DPAGBuild, outs() << "\n varargs:");
1272 for (; itA != ieA; ++itA)
1273 {
1274 const Value* AA = cs->getArgOperand(itA);
1278 }
1279 }
1280 if(itA != ieA)
1281 {
1284 writeWrnMsg("too many args to non-vararg func.");
1285 writeWrnMsg("(" + callICFGNode->getSourceLoc() + ")");
1286
1287 }
1288}
#define DPAGBuild
Definition SVFType.h:492
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition ICFG.cpp:234
FunExitICFGNode * getFunExitICFGNode(const SVFFunction *fun)
Add a function exit node.
Definition ICFG.cpp:241
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
NodeID getVarargNode(const SVFFunction *func)
getVarargNode - Return the node representing the unique variadic argument of a function.
void addRetEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Return edge.
void addCallEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge.
NodeID getReturnNode(const SVFFunction *func)
getReturnNode - Return the node representing the unique return value of a function.
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:584
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67

◆ handleExtCall()

void SVFIRBuilder::handleExtCall ( const CallBase cs,
const SVFFunction svfCallee 
)
protectedvirtual

pthread_create has 1 arg. apr_thread_create has 2 arg.

Connect actual parameter to formal parameter of the start routine

handle indirect calls at pthread create APIs e.g., pthread_create(&t1, nullptr, fp, ...); const Value* fun = ThreadAPI::getThreadAPI()->getForkedFun(inst); if(!SVFUtilisa<Function>(fun)) pag->addIndirectCallsites(cs,pag->getValueNode(fun));

If forkedFun does not pass to spawnee as function type but as void pointer remember to update inter-procedural callgraph/SVFIR/SVFG etc. when indirect call targets are resolved We don't connect the callgraph here, further investigation is need to handle mod-ref during SVFG construction.

TODO: inter-procedural SVFIR edges for thread joins

Definition at line 125 of file SVFIRExtAPI.cpp.

126{
128 const SVFCallInst* svfCall = SVFUtil::cast<SVFCallInst>(svfInst);
130
132 {
136 }
138 {
140 const SVFValue* arg = svfCall->getArgOperand(arg_pos);
141 if (arg->getType()->isPointerTy())
142 {
145 NodeID obj = pag->addDummyObjNode(arg->getType());
146 if (vnArg && dummy && obj)
147 {
150 }
151 }
152 else
153 {
154 writeWrnMsg("Arg receiving new object must be pointer type");
155 }
156 }
157 else if (isMemcpyExtFun(svfCallee))
158 {
159 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
160 // which copies n characters from memory area 'src' to memory area 'dest'.
161 if(svfCallee->getName().find("iconv") != std::string::npos)
162 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
163 else if(svfCallee->getName().find("bcopy") != std::string::npos)
164 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
165 if(svfCall->arg_size() == 3)
166 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
167 else
168 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
169 if(SVFUtil::isa<PointerType>(cs->getType()))
170 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
171 }
172 else if(isMemsetExtFun(svfCallee))
173 {
174 // Side-effects similar to memset(void *str, int c, size_t n)
175 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
176 std::vector<AccessPath> dstFields;
177 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
178 u32_t sz = dstFields.size();
179 //For each field (i), add store edge *(arg0 + i) = arg1
180 for (u32_t index = 0; index < sz; index++)
181 {
184 dstFields[index].getConstantStructFldIdx());
185 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
186 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
187 }
188 if(SVFUtil::isa<PointerType>(cs->getType()))
189 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
190 }
191 else if(svfCallee->getName().compare("dlsym") == 0)
192 {
193 /*
194 Side-effects of void* dlsym( void* handle, const char* funName),
195 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
196 dlsym() example:
197 int main() {
198 // Open the shared library
199 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
200 // Find the function address
201 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
202 // Call the function
203 myFunctionPtr();
204 }
205 */
206 const Value* src = cs->getArgOperand(1);
207 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(src))
208 src = stripConstantCasts(gep->getPointerOperand());
209
210 auto getHookFn = [](const Value* src)->const Function*
211 {
212 if (!SVFUtil::isa<GlobalVariable>(src))
213 return nullptr;
214
215 auto *glob = SVFUtil::cast<GlobalVariable>(src);
216 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
217 return nullptr;
218
219 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
220 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
221 };
222
223 if (const Function *fn = getHookFn(src))
224 {
227 }
228 }
229 else if(svfCallee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
230 {
231 // The purpose of this function is to insert a new node into the red-black tree and then rebalance the tree to ensure that the red-black tree properties are maintained.
232 assert(svfCall->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
233
234 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
235 // Now we calculate the offset from base to vArg3
236 NodeID vnArg3 = pag->getValueNode(svfCall->getArgOperand(3));
239
240 // We get all flattened fields of base
242
243 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
244 // Note that arg0 is aligned with "offset".
245 for (APOffset i = offset + 1; i <= offset + 3; ++i)
246 {
247 if((u32_t)i >= fields.size())
248 break;
250 fields[i].getConstantStructFldIdx());
251 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
252 NodeID vnS = pag->getValueNode(svfCall->getArgOperand(1));
253 if(vnD && vnS)
255 }
256 }
257
259 {
261 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
262 {
268 assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
269 if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
270 {
271 const SVFArgument* formalParm = forkedFun->getArg(0);
273 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
274 {
277 }
278 }
279 }
280 else
281 {
286 }
290 }
291
293}
const SVFFunction * getFunction() const
Get function of this call node.
Definition CallGraph.h:131
SVFInstruction * getSVFInstruction(const Instruction *inst) const
Definition LLVMModule.h:274
const CallGraphNode * getCallGraphNode() const
Definition SVFValue.h:363
const SVFFunction * getDefFunForMultipleModule() const
Definition SVFValue.h:404
AddrStmt * addAddrWithHeapSz(NodeID src, NodeID dst, const CallBase *cs)
Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".
void addThreadForkEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Thread fork edge for parameter passing.
AccessPath getAccessPathFromBaseNode(NodeID nodeId)
CopyStmt * addCopyEdge(NodeID src, NodeID dst, CopyStmt::CopyKind kind)
virtual void addComplexConsForExt(Value *D, Value *S, const Value *sz)
SVFTypeLocSetsPair & getTypeLocSetsMap(NodeID argId)
Given an arg NodeId, get its base SVFType* and all its field location sets.
Definition SVFIR.h:245
NodeID addDummyObjNode(const SVFType *type)
Definition SVFIR.h:500
const Function * getProgFunction(const std::string &funName)
Get program entry function from module.
Definition LLVMUtil.cpp:39
const Value * stripConstantCasts(const Value *val)
Strip off the constant casts.
Definition LLVMUtil.cpp:219
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:617
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:633
bool isMemsetExtFun(const SVFFunction *fun)
Definition SVFUtil.h:288
bool isMemcpyExtFun(const SVFFunction *fun)
Definition SVFUtil.h:283
u32_t getHeapAllocHoldingArgPosition(const SVFFunction *fun)
Get the position of argument that holds an allocated heap object.
Definition SVFUtil.h:309
bool isThreadForkCall(const CallICFGNode *inst)
Definition SVFUtil.h:387
const ValVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
Definition SVFUtil.h:435
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:358

◆ handleIndCall()

void SVFIRBuilder::handleIndCall ( CallBase cs)
protected

Handle indirect call.

Indirect call is resolved on-the-fly during pointer analysis

Definition at line 1311 of file SVFIRBuilder.cpp.

1312{
1313 const SVFValue* svfcalledval = llvmModuleSet()->getSVFValue(cs->getCalledOperand());
1314
1317}
void addIndirectCallsites(const CallICFGNode *cs, NodeID funPtr)
Add indirect callsites.
Definition SVFIR.h:558

◆ inferFieldIdxFromByteOffset()

u32_t SVFIRBuilder::inferFieldIdxFromByteOffset ( const llvm::GEPOperator *  gepOp,
DataLayout dl,
AccessPath ap,
APOffset  idx 
)
protected

Infer field index from byteoffset.

Definition at line 413 of file SVFIRBuilder.cpp.

414{
415 return 0;
416}

◆ InitialGlobal()

void SVFIRBuilder::InitialGlobal ( const GlobalVariable gvar,
Constant C,
u32_t  offset 
)
protected

src should not point to anything yet

Definition at line 656 of file SVFIRBuilder.cpp.

658{
659 DBOUT(DPAGBuild, outs() << "global " << llvmModuleSet()->getSVFValue(gvar)->toString() << " constant initializer: " << llvmModuleSet()->getSVFValue(C)->toString() << "\n");
660 if (C->getType()->isSingleValueType())
661 {
662 NodeID src = getValueNode(C);
663 // get the field value if it is available, otherwise we create a dummy field node.
664 setCurrentLocation(gvar, nullptr);
665 NodeID field = getGlobalVarField(gvar, offset, llvmModuleSet()->getSVFType(C->getType()));
666
667 if (SVFUtil::isa<GlobalVariable, Function>(C))
668 {
669 setCurrentLocation(C, nullptr);
670 addStoreEdge(src, field);
671 }
672 else if (SVFUtil::isa<ConstantExpr>(C))
673 {
674 // add gep edge of C1 itself is a constant expression
675 processCE(C);
676 setCurrentLocation(C, nullptr);
677 addStoreEdge(src, field);
678 }
679 else if (SVFUtil::isa<BlockAddress>(C))
680 {
681 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
682 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
683 processCE(C);
684 setCurrentLocation(C, nullptr);
686 }
687 else
688 {
689 setCurrentLocation(C, nullptr);
690 addStoreEdge(src, field);
692 if (C->getType()->isPtrOrPtrVectorTy() && src != pag->getNullPtr())
694 }
695 }
696 else if (SVFUtil::isa<ConstantArray, ConstantStruct>(C))
697 {
699 return;
700 for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
701 {
703 InitialGlobal(gvar, SVFUtil::cast<Constant>(C->getOperand(i)), offset + off);
704 }
705 }
706 else if(ConstantData* data = SVFUtil::dyn_cast<ConstantData>(C))
707 {
709 {
710 if(ConstantDataSequential* seq = SVFUtil::dyn_cast<ConstantDataSequential>(data))
711 {
712 for(u32_t i = 0; i < seq->getNumElements(); i++)
713 {
714 u32_t off = pag->getSymbolInfo()->getFlattenedElemIdx(llvmModuleSet()->getSVFType(C->getType()), i);
715 Constant* ct = seq->getElementAsConstant(i);
717 }
718 }
719 else
720 {
721 assert((SVFUtil::isa<ConstantAggregateZero, UndefValue>(data)) && "Single value type data should have been handled!");
722 }
723 }
724 }
725 else
726 {
727 //TODO:assert(SVFUtil::isa<ConstantVector>(C),"what else do we have");
728 }
729}
NodeID getConstantNode() const
Definition IRGraph.h:165
static const Option< bool > ModelConsts
Definition Options.h:187
static const Option< bool > VtableInSVFIR
Definition Options.h:217
void InitialGlobal(const GlobalVariable *gvar, Constant *C, u32_t offset)
NodeID getGlobalVarField(const GlobalVariable *gvar, u32_t offset, SVFType *tpy)
bool isValVtbl(const Value *val)
Definition CppUtil.cpp:336
llvm::ConstantData ConstantData
Definition BasicTypes.h:116
llvm::Constant Constant
Definition BasicTypes.h:124
llvm::ConstantDataSequential ConstantDataSequential
Definition BasicTypes.h:119

◆ initialiseNodes()

void SVFIRBuilder::initialiseNodes ( )

Initialize nodes and edges.

add address edges for constant nodes.

Definition at line 206 of file SVFIRBuilder.cpp.

207{
208 DBOUT(DPAGBuild, outs() << "Initialise SVFIR Nodes ...\n");
209
211
216
217 // Iterate over all value symbols in the symbol table
218 for (SymbolTableInfo::ValueToIDMapTy::iterator iter =
219 symTable->valSyms().begin(); iter != symTable->valSyms().end();
220 ++iter)
221 {
222 // Debug output for adding value node
223 DBOUT(DPAGBuild, outs() << "add val node " << iter->second << "\n");
224
225 // Skip blackhole and null pointer symbols
226 if(iter->second == symTable->blkPtrSymID() || iter->second == symTable->nullPtrSymID())
227 continue;
228
229 const ICFGNode* icfgNode = nullptr;
230 auto llvmValue = llvmModuleSet()->getLLVMValue(iter->first);
231 if (const Instruction* inst =
232 SVFUtil::dyn_cast<Instruction>(llvmValue))
233 {
234 if (llvmModuleSet()->hasICFGNode(inst))
235 {
236 icfgNode = llvmModuleSet()->getICFGNode(inst);
237 }
238 }
239
240 // Check if the value is a function and get its call graph node
241 if (const Function* func =
242 SVFUtil::dyn_cast<Function>(llvmValue))
243 {
245 // add value node representing the function
246 pag->addFunValNode(cgn, iter->second, icfgNode);
247 }
248 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
249 {
250 pag->addConstantFPValNode(iter->first, fpValue->getValueAPF().convertToDouble(), iter->second, icfgNode);
252 fpValue, pag->getGNode(iter->second));
253 }
254 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
255 {
256 pag->addConstantIntValNode(iter->first, intValue->getSExtValue(), intValue->getZExtValue(), iter->second, icfgNode);
258 intValue, pag->getGNode(iter->second));
259 }
260 else if (auto nullValue = SVFUtil::dyn_cast<ConstantPointerNull>(llvmValue))
261 {
262 pag->addConstantNullPtrValNode(iter->first, iter->second, icfgNode);
264 nullValue, pag->getGNode(iter->second));
265 }
266 else if (auto globalValue = SVFUtil::dyn_cast<GlobalValue>(llvmValue))
267 {
268 pag->addGlobalValueValNode(iter->first, iter->second, icfgNode);
270 globalValue, pag->getGNode(iter->second));
271 }
272 else if (auto dataValue = SVFUtil::dyn_cast<ConstantData>(llvmValue))
273 {
274 pag->addConstantDataValNode(iter->first, iter->second, icfgNode);
276 dataValue, pag->getGNode(iter->second));
277 }
278 else
279 {
280 // Add value node to PAG
281 pag->addValNode(iter->first, iter->second, icfgNode);
282 }
283 }
284
285 // Iterate over all object symbols in the symbol table
286 for (SymbolTableInfo::ValueToIDMapTy::iterator iter =
287 symTable->objSyms().begin(); iter != symTable->objSyms().end();
288 ++iter)
289 {
290 // Debug output for adding object node
291 DBOUT(DPAGBuild, outs() << "add obj node " << iter->second << "\n");
292
293 // Skip blackhole and constant symbols
294 if(iter->second == symTable->blackholeSymID() || iter->second == symTable->constantSymID())
295 continue;
296
297 // Get the LLVM value corresponding to the symbol
298 const Value* llvmValue = llvmModuleSet()->getLLVMValue(iter->first);
299
300 // Check if the value is a function and add a function object node
301 if (const Function* func = SVFUtil::dyn_cast<Function>(llvmValue))
302 {
303 pag->addFunObjNode(llvmModuleSet()->getCallGraphNode(func), iter->second);
304 }
305 // Check if the value is a heap object and add a heap object node
307 {
308 const SVFFunction* f =
309 SVFUtil::cast<SVFInstruction>(iter->first)->getFunction();
310 pag->addHeapObjNode(iter->first, f, iter->second);
312 llvmValue, pag->getGNode(iter->second));
313 }
314 // Check if the value is an alloca instruction and add a stack object node
316 {
317 const SVFFunction* f =
318 SVFUtil::cast<SVFInstruction>(iter->first)->getFunction();
319 pag->addStackObjNode(iter->first, f, iter->second);
321 llvmValue, pag->getGNode(iter->second));
322 }
323 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
324 {
325 pag->addConstantFPObjNode(iter->first, fpValue->getValueAPF().convertToDouble(), iter->second);
327 fpValue, pag->getGNode(iter->second));
328 }
329 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
330 {
331 pag->addConstantIntObjNode(iter->first, intValue->getSExtValue(), intValue->getZExtValue(), iter->second);
333 intValue, pag->getGNode(iter->second));
334 }
335 else if (auto nullValue = SVFUtil::dyn_cast<ConstantPointerNull>(llvmValue))
336 {
337 pag->addConstantNullPtrObjNode(iter->first, iter->second);
339 nullValue, pag->getGNode(iter->second));
340 }
341 else if (auto globalValue = SVFUtil::dyn_cast<GlobalValue>(llvmValue))
342 {
343 pag->addGlobalValueObjNode(iter->first, iter->second);
345 globalValue, pag->getGNode(iter->second));
346 }
347 else if (auto dataValue = SVFUtil::dyn_cast<ConstantData>(llvmValue))
348 {
349 pag->addConstantDataObjNode(iter->first, iter->second);
351 dataValue, pag->getGNode(iter->second));
352 }
353 // Add a generic object node for other types of values
354 else
355 {
356 pag->addObjNode(iter->first, iter->second);
357 }
358 }
359
360 for (SymbolTableInfo::FunToIDMapTy::iterator iter =
361 symTable->retSyms().begin(); iter != symTable->retSyms().end();
362 ++iter)
363 {
364 DBOUT(DPAGBuild, outs() << "add ret node " << iter->second << "\n");
366 llvmModuleSet()->getCallGraphNode(SVFUtil::cast<Function>(
367 llvmModuleSet()->getLLVMValue(iter->first))),
368 iter->second);
369 }
370
371 for (SymbolTableInfo::FunToIDMapTy::iterator iter =
372 symTable->varargSyms().begin();
373 iter != symTable->varargSyms().end(); ++iter)
374 {
375 DBOUT(DPAGBuild, outs() << "add vararg node " << iter->second << "\n");
377 llvmModuleSet()->getCallGraphNode(SVFUtil::cast<Function>(
378 llvmModuleSet()->getLLVMValue(iter->first))),
379 iter->second);
380 }
381
383 for (SymbolTableInfo::ValueToIDMapTy::iterator iter =
384 symTable->objSyms().begin(); iter != symTable->objSyms().end(); ++iter)
385 {
386 DBOUT(DPAGBuild, outs() << "add address edges for constant node " << iter->second << "\n");
387 const SVFValue* val = iter->first;
389 {
391 if(ptr!= pag->getBlkPtr() && ptr!= pag->getNullPtr())
392 {
393 setCurrentLocation(val, nullptr);
394 addAddrEdge(iter->second, ptr);
395 }
396 }
397 }
398
399 assert(pag->getTotalNodeNum() >= symTable->getTotalSymNum()
400 && "not all node have been initialized!!!");
401
402}
const Value * getLLVMValue(const SVFValue *value) const
Definition LLVMModule.h:239
NodeID addNullPtrNode()
Add NullPtr PAGNode.
NodeID addStackObjNode(const SVFValue *val, const SVFFunction *f, NodeID i)
Definition SVFIR.h:637
NodeID addObjNode(const SVFValue *val, NodeID i)
Add a memory obj node.
Definition SVFIR.h:615
NodeID addGlobalValueObjNode(const SVFValue *curInst, const NodeID i)
Definition SVFIR.h:679
NodeID addBlackholePtrNode()
Definition SVFIR.h:746
NodeID addBlackholeObjNode()
Definition SVFIR.h:734
NodeID addGlobalValueValNode(const SVFValue *curInst, const NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:601
NodeID addConstantFPObjNode(const SVFValue *curInst, double dval, const NodeID i)
Definition SVFIR.h:649
NodeID addConstantNullPtrObjNode(const SVFValue *curInst, const NodeID i)
Definition SVFIR.h:670
NodeID addValNode(const SVFValue *val, NodeID i, const ICFGNode *icfgNode)
add node into SVFIR
Definition SVFIR.h:569
NodeID addConstantFPValNode(const SVFValue *curInst, double dval, const NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:581
NodeID addFunValNode(const CallGraphNode *callGraphNode, NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:575
NodeID addConstantIntObjNode(const SVFValue *curInst, s64_t sval, u64_t zval, const NodeID i)
Definition SVFIR.h:659
NodeID addRetNode(const CallGraphNode *callGraphNode, NodeID i)
Add a unique return node for a procedure.
Definition SVFIR.h:698
NodeID addVarargNode(const CallGraphNode *val, NodeID i)
Add a unique vararg node for a procedure.
Definition SVFIR.h:704
NodeID addHeapObjNode(const SVFValue *val, const SVFFunction *f, NodeID i)
Definition SVFIR.h:625
NodeID addConstantDataValNode(const SVFValue *curInst, const NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:607
NodeID addConstantDataObjNode(const SVFValue *curInst, const NodeID i)
Definition SVFIR.h:688
NodeID addFunObjNode(const CallGraphNode *callGraphNode, NodeID id)
Definition SVFIR.cpp:475
NodeID addConstantObjNode()
Definition SVFIR.h:740
bool isHeapObj(const Value *val)
Definition LLVMUtil.cpp:669
bool isStackObj(const Value *val)
Definition LLVMUtil.cpp:691
bool isConstantObjSym(const SVFValue *val)
Check whether this value points-to a constant object.
Definition LLVMUtil.cpp:578

◆ llvmModuleSet()

LLVMModuleSet * SVF::SVFIRBuilder::llvmModuleSet ( )
inlineprivate

Definition at line 511 of file SVFIRBuilder.h.

512 {
514 }

◆ processCE()

void SVFIRBuilder::processCE ( const Value val)
protected

Process constant expression.

Handle constant expression, and connect the gep edge

Definition at line 498 of file SVFIRBuilder.cpp.

499{
500 if (const Constant* ref = SVFUtil::dyn_cast<Constant>(val))
501 {
503 {
504 DBOUT(DPAGBuild, outs() << "handle gep constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
505 const Constant* opnd = gepce->getOperand(0);
506 // handle recursive constant express case (gep (bitcast (gep X 1)) 1)
508 auto &GEPOp = llvm::cast<llvm::GEPOperator>(*gepce);
509 Type *pType = GEPOp.getSourceElementType();
510 AccessPath ap(0, llvmModuleSet()->getSVFType(pType));
511 bool constGep = computeGepOffset(gepce, ap);
512 // must invoke pag methods here, otherwise it will be a dead recursion cycle
513 const SVFValue* cval = getCurrentValue();
514 const SVFBasicBlock* cbb = getCurrentBB();
515 setCurrentLocation(gepce, nullptr);
516 /*
517 * The gep edge created are like constexpr (same edge may appear at multiple callsites)
518 * so bb/inst of this edge may be rewritten several times, we treat it as global here.
519 */
520 addGepEdge(pag->getValueNode(llvmModuleSet()->getSVFValue(opnd)), pag->getValueNode(llvmModuleSet()->getSVFValue(gepce)), ap, constGep);
522 }
523 else if (const ConstantExpr* castce = isCastConstantExpr(ref))
524 {
525 DBOUT(DPAGBuild, outs() << "handle cast constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
526 const Constant* opnd = castce->getOperand(0);
528 const SVFValue* cval = getCurrentValue();
529 const SVFBasicBlock* cbb = getCurrentBB();
530 setCurrentLocation(castce, nullptr);
533 }
535 {
536 DBOUT(DPAGBuild, outs() << "handle select constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
537 const Constant* src1 = selectce->getOperand(1);
538 const Constant* src2 = selectce->getOperand(2);
541 const SVFValue* cval = getCurrentValue();
542 const SVFBasicBlock* cbb = getCurrentBB();
544 NodeID cond = pag->getValueNode(llvmModuleSet()->getSVFValue(selectce->getOperand(0)));
545 NodeID nsrc1 = pag->getValueNode(llvmModuleSet()->getSVFValue(src1));
546 NodeID nsrc2 = pag->getValueNode(llvmModuleSet()->getSVFValue(src2));
547 NodeID nres = pag->getValueNode(llvmModuleSet()->getSVFValue(selectce));
550 }
551 // if we meet a int2ptr, then it points-to black hole
553 {
554 const Constant* opnd = int2Ptrce->getOperand(0);
556 const SVFBasicBlock* cbb = getCurrentBB();
557 const SVFValue* cval = getCurrentValue();
561 }
563 {
564 const Constant* opnd = ptr2Intce->getOperand(0);
566 const SVFBasicBlock* cbb = getCurrentBB();
567 const SVFValue* cval = getCurrentValue();
571 }
573 {
574 // we don't handle trunc and cmp instruction for now
575 const SVFValue* cval = getCurrentValue();
576 const SVFBasicBlock* cbb = getCurrentBB();
577 setCurrentLocation(ref, nullptr);
578 NodeID dst = pag->getValueNode(llvmModuleSet()->getSVFValue(ref));
581 }
582 else if (isBinaryConstantExpr(ref))
583 {
584 // we don't handle binary constant expression like add(x,y) now
585 const SVFValue* cval = getCurrentValue();
586 const SVFBasicBlock* cbb = getCurrentBB();
587 setCurrentLocation(ref, nullptr);
588 NodeID dst = pag->getValueNode(llvmModuleSet()->getSVFValue(ref));
591 }
592 else if (isUnaryConstantExpr(ref))
593 {
594 // we don't handle unary constant expression like fneg(x) now
595 const SVFValue* cval = getCurrentValue();
596 const SVFBasicBlock* cbb = getCurrentBB();
597 setCurrentLocation(ref, nullptr);
598 NodeID dst = pag->getValueNode(llvmModuleSet()->getSVFValue(ref));
601 }
602 else if (SVFUtil::isa<ConstantAggregate>(ref))
603 {
604 // we don't handle constant aggregate like constant vectors
605 }
606 else if (SVFUtil::isa<BlockAddress>(ref))
607 {
608 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
609 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
610 const SVFValue* cval = getCurrentValue();
611 const SVFBasicBlock* cbb = getCurrentBB();
612 setCurrentLocation(ref, nullptr);
613 NodeID dst = pag->getValueNode(llvmModuleSet()->getSVFValue(ref));
616 }
617 else
618 {
619 if(SVFUtil::isa<ConstantExpr>(val))
620 assert(false && "we don't handle all other constant expression for now!");
621 }
622 }
623}
void addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
bool computeGepOffset(const User *V, AccessPath &ap)
Compute offset of a gep instruction or gep constant expression.
const ConstantExpr * isBinaryConstantExpr(const Value *val)
Definition LLVMUtil.h:256
const ConstantExpr * isInt2PtrConstantExpr(const Value *val)
Definition LLVMUtil.h:191
const ConstantExpr * isSelectConstantExpr(const Value *val)
Definition LLVMUtil.h:221
const ConstantExpr * isTruncConstantExpr(const Value *val)
Definition LLVMUtil.h:231
const ConstantExpr * isPtr2IntConstantExpr(const Value *val)
Definition LLVMUtil.h:201
const ConstantExpr * isUnaryConstantExpr(const Value *val)
Definition LLVMUtil.h:267
const ConstantExpr * isCastConstantExpr(const Value *val)
Definition LLVMUtil.h:211
const ConstantExpr * isGepConstantExpr(const Value *val)
Return corresponding constant expression, otherwise return nullptr.
Definition LLVMUtil.h:181
const ConstantExpr * isCmpConstantExpr(const Value *val)
Definition LLVMUtil.h:245
llvm::ConstantExpr ConstantExpr
Definition BasicTypes.h:120

◆ sanityCheck()

void SVFIRBuilder::sanityCheck ( )

Sanity check for SVFIR.

Definition at line 1355 of file SVFIRBuilder.cpp.

1356{
1357 for (SVFIR::iterator nIter = pag->begin(); nIter != pag->end(); ++nIter)
1358 {
1359 (void) pag->getGNode(nIter->first);
1360 //TODO::
1361 // (1) every source(root) node of a pag tree should be object node
1362 // if a node has no incoming edge, but has outgoing edges
1363 // then it has to be an object node.
1364 // (2) make sure every variable should be initialized
1365 // otherwise it causes the a null pointer, the aliasing relation may not be captured
1366 // when loading a pointer value should make sure
1367 // some value has been store into this pointer before
1368 // q = load p, some value should stored into p first like store w p;
1369 // (3) make sure PAGNode should not have a const expr value (pointer should have unique def)
1370 // (4) look closely into addComplexConsForExt, make sure program locations(e.g.,inst bb)
1371 // are set correctly for dummy gepval node
1372 // (5) reduce unnecessary copy edge (const casts) and ensure correctness.
1373 }
1374}
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
Node Iterators.

◆ setCurrentBBAndValueForPAGEdge()

void SVFIRBuilder::setCurrentBBAndValueForPAGEdge ( PAGEdge edge)
protected

We assume every GepValVar and its GepStmt are unique across whole program

We will have one unique function exit ICFGNode for all returns

Definition at line 1429 of file SVFIRBuilder.cpp.

1430{
1432 return;
1433
1434 assert(curVal && "current Val is nullptr?");
1435 edge->setBB(curBB!=nullptr ? curBB : nullptr);
1436 edge->setValue(curVal);
1437 // backmap in valuToEdgeMap
1439 ICFGNode* icfgNode = pag->getICFG()->getGlobalICFGNode();
1441 if (const SVFInstruction* curInst = SVFUtil::dyn_cast<SVFInstruction>(curVal))
1442 {
1443 const SVFFunction* srcFun = edge->getSrcNode()->getFunction();
1444 const SVFFunction* dstFun = edge->getDstNode()->getFunction();
1445 if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && edge->getSrcNode()->hasValue() && !SVFUtil::isa<SVFFunction>(edge->getSrcNode()->getValue()))
1446 {
1447 assert(srcFun==curInst->getFunction() && "SrcNode of the PAGEdge not in the same function?");
1448 }
1449 if(dstFun!=nullptr && !SVFUtil::isa<CallPE>(edge) && !SVFUtil::isa<RetPN>(edge->getDstNode()))
1450 {
1451 assert(dstFun==curInst->getFunction() && "DstNode of the PAGEdge not in the same function?");
1452 }
1453
1455 if (!(SVFUtil::isa<GepStmt>(edge) && SVFUtil::isa<GepValVar>(edge->getDstNode())))
1456 assert(curBB && "instruction does not have a basic block??");
1457
1459 if(curInst->isRetInst())
1460 {
1461 icfgNode = pag->getICFG()->getFunExitICFGNode(curInst->getFunction());
1462 }
1463 else
1464 {
1465 if(SVFUtil::isa<RetPE>(edge))
1466 icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(llvmMS->getLLVMValue(curInst)));
1467 else
1468 icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(llvmMS->getLLVMValue(curInst)));
1469 }
1470 }
1471 else if (const SVFArgument* arg = SVFUtil::dyn_cast<SVFArgument>(curVal))
1472 {
1474 icfgNode = pag->getICFG()->getFunEntryICFGNode(arg->getParent());
1475 }
1476 else if (SVFUtil::isa<SVFConstant>(curVal) ||
1477 SVFUtil::isa<SVFFunction>(curVal) ||
1478 SVFUtil::isa<SVFMetadataAsValue>(curVal))
1479 {
1480 if (!curBB)
1482 else
1483 {
1484 icfgNode = const_cast<ICFGNode*>(curBB->front());
1485 }
1486 }
1487 else
1488 {
1489 assert(false && "what else value can we have?");
1490 }
1491
1492 pag->addToSVFStmtList(icfgNode,edge);
1493 icfgNode->addSVFStmt(edge);
1494 if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1495 {
1496 CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getCallSite());
1497 FunEntryICFGNode* entryNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1499 SVFUtil::cast<CallCFGEdge>(edge)->addCallPE(callPE);
1500 }
1501 else if(const RetPE* retPE = SVFUtil::dyn_cast<RetPE>(edge))
1502 {
1503 RetICFGNode* retNode = const_cast<RetICFGNode*>(retPE->getCallSite()->getRetICFGNode());
1504 FunExitICFGNode* exitNode = const_cast<FunExitICFGNode*>(retPE->getFunExitICFGNode());
1506 SVFUtil::cast<RetCFGEdge>(edge)->addRetPE(retPE);
1507 }
1508}
void addSVFStmt(const SVFStmt *edge)
Definition ICFGNode.h:112
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:268
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:236
void mapValueToEdge(const SVFValue *V, SVFStmt *edge)
Map a value to a set of edges.
Definition IRGraph.h:89
const SVFFunction * getParent() const
Definition SVFValue.h:595
const ICFGNode * front() const
Definition SVFValue.h:605
const SVFBasicBlock * getEntryBlock() const
Definition SVFValue.h:420
void addToSVFStmtList(ICFGNode *inst, SVFStmt *edge)
Add a SVFStmt into instruction map.
Definition SVFIR.h:232
void addGlobalPAGEdge(const SVFStmt *edge)
Add global PAGEdges (not in a procedure)
Definition SVFIR.h:780

◆ setCurrentLocation() [1/2]

void SVF::SVFIRBuilder::setCurrentLocation ( const SVFValue val,
const SVFBasicBlock bb 
)
inlineprotected

Definition at line 246 of file SVFIRBuilder.h.

247 {
248 curBB = bb;
249 curVal = val;
250 }

◆ setCurrentLocation() [2/2]

void SVF::SVFIRBuilder::setCurrentLocation ( const Value val,
const BasicBlock bb 
)
inlineprotected

Set current basic block in order to keep track of control flow information.

Definition at line 241 of file SVFIRBuilder.h.

242 {
243 curBB = (bb == nullptr? nullptr : llvmModuleSet()->getSVFBasicBlock(bb));
244 curVal = (val == nullptr ? nullptr: llvmModuleSet()->getSVFValue(val));
245 }
SVFBasicBlock * getSVFBasicBlock(const BasicBlock *bb) const
Definition LLVMModule.h:267

◆ updateCallGraph()

void SVFIRBuilder::updateCallGraph ( PTACallGraph callgraph)

connect PAG edges based on callgraph

Definition at line 1319 of file SVFIRBuilder.cpp.

1320{
1321 PTACallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
1322 PTACallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
1323 for (; iter != eiter; iter++)
1324 {
1325 const CallICFGNode* callBlock = iter->first;
1326 const CallBase* callbase = SVFUtil::cast<CallBase>(llvmModuleSet()->getLLVMValue(callBlock));
1327 assert(callBlock->isIndirectCall() && "this is not an indirect call?");
1328 const PTACallGraph::FunctionSet& functions = iter->second;
1329 for (PTACallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
1330 {
1331 const Function* callee = SVFUtil::cast<Function>(llvmModuleSet()->getLLVMValue(*func_iter));
1332
1333 if (isExtCall(*func_iter))
1334 {
1335 setCurrentLocation(callee, callee->empty() ? nullptr : &callee->getEntryBlock());
1338 }
1339 else
1340 {
1341 setCurrentLocation(llvmModuleSet()->getSVFValue(llvmModuleSet()->getLLVMValue(callBlock)), callBlock->getBB());
1342 handleDirectCall(const_cast<CallBase*>(callbase), callee);
1343 }
1344 }
1345 }
1346
1347 // dump SVFIR
1349 pag->dump("svfir_final");
1350}
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Set< const SVFFunction * > FunctionSet
void handleDirectCall(CallBase *cs, const Function *F)
Handle direct call.
virtual void handleExtCall(const CallBase *cs, const SVFFunction *svfCallee)
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278
llvm::CallBase CallBase
Definition BasicTypes.h:146

◆ visitAllocaInst()

void SVFIRBuilder::visitAllocaInst ( AllocaInst inst)
virtual

Our visit overrides.

Visit alloca instructions Add edge V (dst) <– O (src), V here is a value node on SVFIR, O is object node on SVFIR

Definition at line 787 of file SVFIRBuilder.cpp.

788{
789
790 // AllocaInst should always be a pointer type
791 assert(SVFUtil::isa<PointerType>(inst.getType()));
792
793 DBOUT(DPAGBuild, outs() << "process alloca " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
794 NodeID dst = getValueNode(&inst);
795
796 NodeID src = getObjectNode(&inst);
797
798 addAddrWithStackArraySz(src, dst, inst);
799
800}
NodeID getObjectNode(const Value *V)
GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.
AddrStmt * addAddrWithStackArraySz(NodeID src, NodeID dst, llvm::AllocaInst &inst)
Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".

◆ visitAtomicCmpXchgInst()

void SVF::SVFIRBuilder::visitAtomicCmpXchgInst ( AtomicCmpXchgInst I)
inline

Definition at line 186 of file SVFIRBuilder.h.

187 {
189 }

◆ visitAtomicRMWInst()

void SVF::SVFIRBuilder::visitAtomicRMWInst ( AtomicRMWInst I)
inline

Definition at line 190 of file SVFIRBuilder.h.

191 {
193 }

◆ visitBinaryOperator()

void SVFIRBuilder::visitBinaryOperator ( BinaryOperator inst)

Visit Binary Operator

Definition at line 902 of file SVFIRBuilder.cpp.

903{
904 NodeID dst = getValueNode(&inst);
905 assert(inst.getNumOperands() == 2 && "not two operands for BinaryOperator?");
906 Value* op1 = inst.getOperand(0);
908 Value* op2 = inst.getOperand(1);
910 u32_t opcode = inst.getOpcode();
911 addBinaryOPEdge(op1Node, op2Node, dst, opcode);
912}
void addBinaryOPEdge(NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
Add Copy edge.

◆ visitBranchInst()

void SVFIRBuilder::visitBranchInst ( BranchInst inst)

Branch and switch instructions are treated as UnaryOP br cmp label if.then, label if.else

set conditional svf var

Definition at line 1082 of file SVFIRBuilder.cpp.

1083{
1084 NodeID brinst = getValueNode(&inst);
1085 NodeID cond;
1086 if (inst.isConditional())
1087 cond = getValueNode(inst.getCondition());
1088 else
1089 cond = pag->getNullPtr();
1090
1091 assert(inst.getNumSuccessors() <= 2 && "if/else has more than two branches?");
1092
1094 std::vector<const Instruction*> nextInsts;
1096 u32_t branchID = 0;
1097 for (const Instruction* succInst : nextInsts)
1098 {
1099 assert(branchID <= 1 && "if/else has more than two branches?");
1100 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1101 successors.push_back(std::make_pair(icfgNode, 1-branchID));
1102 branchID++;
1103 }
1104 addBranchStmt(brinst, cond, successors);
1106 if (inst.isConditional())
1107 {
1108 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1109 {
1110 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1111 {
1112 intraEdge->setConditionVar(pag->getGNode(cond));
1113 }
1114 }
1115 }
1116}
std::vector< std::pair< const ICFGNode *, s32_t > > SuccAndCondPairVec
void addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add Branch statement.
void getNextInsts(const Instruction *curInst, std::vector< const Instruction * > &instList)
Get the next instructions following control flow.
Definition LLVMUtil.cpp:550

◆ visitCallBrInst()

void SVFIRBuilder::visitCallBrInst ( CallBrInst I)

Definition at line 969 of file SVFIRBuilder.cpp.

970{
972}
void visitCallSite(CallBase *cs)

◆ visitCallInst()

void SVFIRBuilder::visitCallInst ( CallInst I)

Definition at line 959 of file SVFIRBuilder.cpp.

960{
962}

◆ visitCallSite()

void SVFIRBuilder::visitCallSite ( CallBase cs)

Collect callsite arguments and returns

Definition at line 977 of file SVFIRBuilder.cpp.

978{
979
980 // skip llvm intrinsics
981 if(isIntrinsicInst(cs))
982 return;
983
985 outs() << "process callsite " << svfcall->valueOnlyToString() << "\n");
986
987
988 CallICFGNode* callBlockNode = llvmModuleSet()->getCallICFGNode(cs);
990
991 pag->addCallSite(callBlockNode);
992
994 for (u32_t i = 0; i < cs->arg_size(); i++)
996 callBlockNode,
997 SVFUtil::cast<ValVar>(pag->getGNode(getValueNode(cs->getArgOperand(i)))));
998
999 if(!cs->getType()->isVoidTy())
1001
1002 if (callBlockNode->isVirtualCall())
1003 {
1004 const Value* value = cppUtil::getVCallVtblPtr(cs);
1005 callBlockNode->setVtablePtr(pag->getGNode(getValueNode(value)));
1006 }
1007 if (const Function *callee = LLVMUtil::getCallee(cs))
1008 {
1010 if (isExtCall(svfcallee))
1011 {
1013 }
1014 else
1015 {
1017 }
1018 }
1019 else
1020 {
1021 //If the callee was not identified as a function (null F), this is indirect.
1022 handleIndCall(cs);
1023 }
1024}
bool isVirtualCall() const
Definition ICFGNode.h:527
void setVtablePtr(SVFVar *v)
Definition ICFGNode.h:532
RetICFGNode * getRetICFGNode(const Instruction *cs)
get a return node
void handleIndCall(CallBase *cs)
Handle indirect call.
void addCallSiteRets(RetICFGNode *retBlockNode, const SVFVar *arg)
Add callsite returns.
Definition SVFIR.h:552
void addCallSiteArgs(CallICFGNode *callBlockNode, const ValVar *arg)
Add callsite arguments.
Definition SVFIR.h:546
void addCallSite(const CallICFGNode *call)
Add callsites.
Definition SVFIR.h:785
bool isIntrinsicInst(const Instruction *inst)
Return true if it is an intrinsic instruction.
Definition LLVMUtil.cpp:203
const Function * getCallee(const CallBase *cs)
Definition LLVMUtil.h:63
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:537

◆ visitCastInst()

void SVFIRBuilder::visitCastInst ( CastInst I)

Definition at line 888 of file SVFIRBuilder.cpp.

889{
890
891 DBOUT(DPAGBuild, outs() << "process cast " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
892 NodeID dst = getValueNode(&inst);
893
894 const Value* opnd = inst.getOperand(0);
895 NodeID src = getValueNode(opnd);
896 addCopyEdge(src, dst, getCopyKind(&inst));
897}
CopyStmt::CopyKind getCopyKind(const Value *val)

◆ visitCmpInst()

void SVFIRBuilder::visitCmpInst ( CmpInst inst)

Visit compare instruction

Definition at line 930 of file SVFIRBuilder.cpp.

931{
932 NodeID dst = getValueNode(&inst);
933 assert(inst.getNumOperands() == 2 && "not two operands for compare instruction?");
934 Value* op1 = inst.getOperand(0);
936 Value* op2 = inst.getOperand(1);
938 u32_t predicate = inst.getPredicate();
939 addCmpEdge(op1Node, op2Node, dst, predicate);
940}
void addCmpEdge(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.

◆ visitExtractElementInst()

void SVFIRBuilder::visitExtractElementInst ( ExtractElementInst inst)

The �extractelement� instruction extracts a single scalar element from a vector at a specified index. TODO: for now we just assume the pointer after extraction points to blackhole The first operand of an �extractelement� instruction is a value of vector type. The second operand is an index indicating the position from which to extract the element.

<result> = extractelement <4 x i32> vec, i32 0 ; yields i32

Definition at line 1072 of file SVFIRBuilder.cpp.

1073{
1074 NodeID dst = getValueNode(&inst);
1076}

◆ visitExtractValueInst()

void SVFIRBuilder::visitExtractValueInst ( ExtractValueInst inst)

visit extract value instructions for structures in registers TODO: for now we just assume the pointer after extraction points to blackhole for example %24 = extractvalue { i32, struct.s_hash* } call34, 0 %24 is a pointer points to first field of a register value call34 however we can not create call34 as an memory object, as it is register value. Is that necessary treat extract value as getelementptr instruction later to get more precise results?

Definition at line 1058 of file SVFIRBuilder.cpp.

1059{
1060 NodeID dst = getValueNode(&inst);
1062}

◆ visitFenceInst()

void SVF::SVFIRBuilder::visitFenceInst ( FenceInst I)
inline

Definition at line 182 of file SVFIRBuilder.h.

183 {
185 }

◆ visitFreezeInst()

void SVFIRBuilder::visitFreezeInst ( FreezeInst inst)

<result> = freeze ty <val> If <val> is undef or poison, ‘freeze’ returns an arbitrary, but fixed value of type ty Otherwise, this instruction is a no-op and returns the input <val>

<result> = freeze ty <val> If <val> is undef or poison, ‘freeze’ returns an arbitrary, but fixed value of type ty Otherwise, this instruction is a no-op and returns the input <val> For now, we assume <val> is never a poison or undef.

Definition at line 1212 of file SVFIRBuilder.cpp.

1213{
1214 NodeID dst = getValueNode(&inst);
1215 for (u32_t i = 0; i < inst.getNumOperands(); i++)
1216 {
1217 Value* opnd = inst.getOperand(i);
1218 NodeID src = getValueNode(opnd);
1219 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1220 }
1221}

◆ visitGetElementPtrInst()

void SVFIRBuilder::visitGetElementPtrInst ( GetElementPtrInst inst)

Visit getelementptr instructions

Definition at line 862 of file SVFIRBuilder.cpp.

863{
864
865 NodeID dst = getValueNode(&inst);
866 // GetElementPtrInst should always be a pointer or a vector contains pointers
867 // for now we don't handle vector type here
868 if(SVFUtil::isa<VectorType>(inst.getType()))
869 {
871 return;
872 }
873
874 assert(SVFUtil::isa<PointerType>(inst.getType()));
875
876 DBOUT(DPAGBuild, outs() << "process gep " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
877
878 NodeID src = getValueNode(inst.getPointerOperand());
879
880 AccessPath ap(0, llvmModuleSet()->getSVFType(inst.getSourceElementType()));
881 bool constGep = computeGepOffset(&inst, ap);
882 addGepEdge(src, dst, ap, constGep);
883}

◆ visitGlobal()

void SVFIRBuilder::visitGlobal ( SVFModule svfModule)
protected

Handle globals including (global variable and functions)

Visit global variables for building SVFIR

initialize global variable

initialize global functions

Definition at line 734 of file SVFIRBuilder.cpp.

735{
736
738 for (Module &M : llvmModuleSet()->getLLVMModules())
739 {
740 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
741 {
742 GlobalVariable *gvar = &*I;
745
746 setCurrentLocation(gvar, nullptr);
748
749 if (gvar->hasInitializer())
750 {
751 Constant *C = gvar->getInitializer();
752 DBOUT(DPAGBuild, outs() << "add global var node " << llvmModuleSet()->getSVFValue(gvar)->toString() << "\n");
753 InitialGlobal(gvar, C, 0);
754 }
755 }
756
757
759 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
760 {
761 const Function* fun = &*I;
762 NodeID idx = getValueNode(fun);
763 NodeID obj = getObjectNode(fun);
764
765 DBOUT(DPAGBuild, outs() << "add global function node " << fun->getName().str() << "\n");
766 setCurrentLocation(fun, nullptr);
768 }
769
770 // Handle global aliases (due to linkage of multiple bc files), e.g., @x = internal alias @y. We need to add a copy from y to x.
771 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; I++)
772 {
773 const GlobalAlias* alias = &*I;
775 NodeID src = pag->getValueNode(llvmModuleSet()->getSVFValue(alias->getAliasee()));
776 processCE(alias->getAliasee());
777 setCurrentLocation(alias, nullptr);
779 }
780 }
781}
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:130
llvm::GlobalAlias GlobalAlias
Definition BasicTypes.h:128

◆ visitInsertElementInst()

void SVF::SVFIRBuilder::visitInsertElementInst ( InsertElementInst I)
inline

Definition at line 162 of file SVFIRBuilder.h.

163 {
165 }

◆ visitInsertValueInst()

void SVF::SVFIRBuilder::visitInsertValueInst ( InsertValueInst I)
inline

Definition at line 136 of file SVFIRBuilder.h.

137 {
139 }

◆ visitInstruction()

void SVF::SVFIRBuilder::visitInstruction ( Instruction )
inline

Provide base case for our instruction visit.

Definition at line 196 of file SVFIRBuilder.h.

197 {
198 // If a new instruction is added to LLVM that we don't handle.
199 // TODO: ignore here:
200 }

◆ visitInvokeInst()

void SVFIRBuilder::visitInvokeInst ( InvokeInst II)

Definition at line 964 of file SVFIRBuilder.cpp.

965{
967}

◆ visitLandingPadInst()

void SVF::SVFIRBuilder::visitLandingPadInst ( LandingPadInst I)
inline

Definition at line 170 of file SVFIRBuilder.h.

171 {
173 }

◆ visitLoadInst()

void SVFIRBuilder::visitLoadInst ( LoadInst I)

Definition at line 830 of file SVFIRBuilder.cpp.

831{
832 DBOUT(DPAGBuild, outs() << "process load " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
833
834 NodeID dst = getValueNode(&inst);
835
836 NodeID src = getValueNode(inst.getPointerOperand());
837
838 addLoadEdge(src, dst);
839}

◆ visitPHINode()

void SVFIRBuilder::visitPHINode ( PHINode inst)

Visit phi instructions

Definition at line 805 of file SVFIRBuilder.cpp.

806{
807
808 DBOUT(DPAGBuild, outs() << "process phi " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
809
810 NodeID dst = getValueNode(&inst);
811
812 for (u32_t i = 0; i < inst.getNumIncomingValues(); ++i)
813 {
814 const Value* val = inst.getIncomingValue(i);
815 const Instruction* incomingInst = SVFUtil::dyn_cast<Instruction>(val);
816 bool matched = (incomingInst == nullptr ||
817 incomingInst->getFunction() == inst.getFunction());
818 (void) matched; // Suppress warning of unused variable under release build
819 assert(matched && "incomingInst's Function incorrect");
820 const Instruction* predInst = &inst.getIncomingBlock(i)->back();
821 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(predInst);
822 NodeID src = getValueNode(val);
823 addPhiStmt(dst,src,icfgNode);
824 }
825}
void addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add Copy edge.

◆ visitResumeInst()

void SVF::SVFIRBuilder::visitResumeInst ( ResumeInst )
inline

Instruction not that often.

Definition at line 176 of file SVFIRBuilder.h.

177 {
178 }

◆ visitReturnInst()

void SVFIRBuilder::visitReturnInst ( ReturnInst inst)

Visit return instructions of a function

Definition at line 1029 of file SVFIRBuilder.cpp.

1030{
1031
1032 // ReturnInst itself should always not be a pointer type
1033 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1034
1035 DBOUT(DPAGBuild, outs() << "process return " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1036
1037 if(Value* src = inst.getReturnValue())
1038 {
1039 const SVFFunction *F = llvmModuleSet()->getSVFFunction(inst.getParent()->getParent());
1040
1042 NodeID vnS = getValueNode(src);
1043 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(&inst);
1044 //vnS may be null if src is a null ptr
1045 addPhiStmt(rnF,vnS,icfgNode);
1046 }
1047}

◆ visitSelectInst()

void SVFIRBuilder::visitSelectInst ( SelectInst inst)

Visit select instructions

Two operands have same incoming basic block, both are the current BB

Definition at line 946 of file SVFIRBuilder.cpp.

947{
948
949 DBOUT(DPAGBuild, outs() << "process select " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
950
951 NodeID dst = getValueNode(&inst);
952 NodeID src1 = getValueNode(inst.getTrueValue());
953 NodeID src2 = getValueNode(inst.getFalseValue());
954 NodeID cond = getValueNode(inst.getCondition());
956 addSelectStmt(dst,src1,src2, cond);
957}

◆ visitShuffleVectorInst()

void SVF::SVFIRBuilder::visitShuffleVectorInst ( ShuffleVectorInst I)
inline

Definition at line 166 of file SVFIRBuilder.h.

167 {
169 }

◆ visitStoreInst()

void SVFIRBuilder::visitStoreInst ( StoreInst inst)

Visit store instructions

Definition at line 844 of file SVFIRBuilder.cpp.

845{
846 // StoreInst itself should always not be a pointer type
847 assert(!SVFUtil::isa<PointerType>(inst.getType()));
848
849 DBOUT(DPAGBuild, outs() << "process store " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
850
851 NodeID dst = getValueNode(inst.getPointerOperand());
852
853 NodeID src = getValueNode(inst.getValueOperand());
854
855 addStoreEdge(src, dst);
856
857}

◆ visitSwitchInst()

void SVFIRBuilder::visitSwitchInst ( SwitchInst inst)

The following implementation follows ICFGBuilder::processFunBody.

See more: https://github.com/SVF-tools/SVF/pull/1191

Given the code:

switch (a) { case 0: printf("0\n"); break; case 1: case 2: case 3: printf("a >=1 && a <= 3\n"); break; case 4: case 6: case 7: printf("a >= 4 && a <=7\n"); break; default: printf("a < 0 || a > 7"); break; }

Generate the IR:

switch i32 %0, label sw.default [ i32 0, label sw.bb i32 1, label sw.bb1 i32 2, label sw.bb1 i32 3, label sw.bb1 i32 4, label sw.bb3 i32 6, label sw.bb3 i32 7, label sw.bb3 ]

We can get every case basic block and related case value: [ {sw.default, -1}, {sw.bb, 0}, {sw.bb1, 1}, {sw.bb1, 2}, {sw.bb1, 3}, {sw.bb3, 4}, {sw.bb3, 6}, {sw.bb3, 7}, ] Note: default case value is nullptr For larger number, we preserve case value just -1 now see more: https://github.com/SVF-tools/SVF/pull/992

branch condition value

default case is set to -1;

set conditional svf var

Definition at line 1164 of file SVFIRBuilder.cpp.

1165{
1166 NodeID brinst = getValueNode(&inst);
1167 NodeID cond = getValueNode(inst.getCondition());
1168
1170 std::vector<const Instruction*> nextInsts;
1172 for (const Instruction* succInst : nextInsts)
1173 {
1175 const ConstantInt* condVal = inst.findCaseDest(const_cast<BasicBlock*>(succInst->getParent()));
1177 s64_t val = -1;
1178 if (condVal && condVal->getBitWidth() <= 64)
1179 val = condVal->getSExtValue();
1180 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1181 successors.push_back(std::make_pair(icfgNode, val));
1182 }
1183 addBranchStmt(brinst, cond, successors);
1185 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1186 {
1187 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1188 {
1189 intraEdge->setConditionVar(pag->getGNode(cond));
1190 }
1191 }
1192}
signed long long s64_t
Definition GeneralType.h:49

◆ visitUnaryOperator()

void SVFIRBuilder::visitUnaryOperator ( UnaryOperator inst)

Visit Unary Operator

Definition at line 917 of file SVFIRBuilder.cpp.

918{
919 NodeID dst = getValueNode(&inst);
920 assert(inst.getNumOperands() == 1 && "not one operand for Unary instruction?");
921 Value* opnd = inst.getOperand(0);
922 NodeID src = getValueNode(opnd);
923 u32_t opcode = inst.getOpcode();
924 addUnaryOPEdge(src, dst, opcode);
925}
void addUnaryOPEdge(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.

◆ visitUnreachableInst()

void SVF::SVFIRBuilder::visitUnreachableInst ( UnreachableInst )
inline

Definition at line 179 of file SVFIRBuilder.h.

180 {
181 }

◆ visitVAArgInst()

void SVFIRBuilder::visitVAArgInst ( VAArgInst inst)

TODO: var arguments need to be handled. https://llvm.org/docs/LangRef.html#id1911

ap = alloca struct.va_list ap2 = bitcast struct.va_list* ap to i8* ; Read a single integer argument from ap2 tmp = va_arg i8* ap2, i32 (VAArgInst) TODO: for now, create a copy edge from ap2 to tmp, we assume here tmp should point to the n-th argument of the var_args

Definition at line 1200 of file SVFIRBuilder.cpp.

1201{
1202 NodeID dst = getValueNode(&inst);
1203 Value* opnd = inst.getPointerOperand();
1204 NodeID src = getValueNode(opnd);
1205 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1206}

◆ visitVACopyInst()

void SVF::SVFIRBuilder::visitVACopyInst ( VACopyInst )
inline

Definition at line 151 of file SVFIRBuilder.h.

151{}

◆ visitVAEndInst()

void SVF::SVFIRBuilder::visitVAEndInst ( VAEndInst )
inline

Definition at line 152 of file SVFIRBuilder.h.

152{}

◆ visitVAStartInst()

void SVF::SVFIRBuilder::visitVAStartInst ( VAStartInst )
inline

Definition at line 153 of file SVFIRBuilder.h.

153{}

Member Data Documentation

◆ curBB

const SVFBasicBlock* SVF::SVFIRBuilder::curBB
private

Current basic block during SVFIR construction when visiting the module.

Definition at line 52 of file SVFIRBuilder.h.

◆ curVal

const SVFValue* SVF::SVFIRBuilder::curVal
private

Current Value during SVFIR construction when visiting the module.

Definition at line 53 of file SVFIRBuilder.h.

◆ pag

SVFIR* SVF::SVFIRBuilder::pag
private

Definition at line 50 of file SVFIRBuilder.h.

◆ svfModule

SVFModule* SVF::SVFIRBuilder::svfModule
private

Definition at line 51 of file SVFIRBuilder.h.


The documentation for this class was generated from the following files: