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

#include <SVFIRBuilder.h>

Inheritance diagram for SVF::SVFIRBuilder:

Public Member Functions

 SVFIRBuilder ()
 Constructor.
 
virtual ~SVFIRBuilder ()
 Destructor.
 
virtual SVFIRbuild ()
 Start building SVFIR here.
 
SVFIRgetPAG () const
 Return SVFIR.
 
void createFunObjVars ()
 
void initFunObjVar ()
 
void initialiseNodes ()
 Initialize nodes and edges.
 
void initialiseBaseObjVars ()
 
void initialiseValVars ()
 
void initSVFBasicBlock (const Function *func)
 
void initDomTree (FunObjVar *func, const Function *f)
 
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 FunObjVar *func)
 getReturnNode - Return the node representing the unique return value of a function.
 
NodeID getVarargNode (const FunObjVar *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 (CallGraph *callgraph)
 connect PAG edges based on callgraph
 

Protected Member Functions

void visitGlobal ()
 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 Function *callee)
 
void setCurrentLocation (const Value *val, const BasicBlock *bb)
 Set current basic block in order to keep track of control flow information.
 
void setCurrentLocation (const Value *val, const SVFBasicBlock *bb)
 
const ValuegetCurrentValue () 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
 
const SVFBasicBlockcurBB
 Current basic block during SVFIR construction when visiting the module.
 
const ValuecurVal
 Current Value during SVFIR construction when visiting the module.
 

Friends

class GraphDBSVFIRBuilder
 

Detailed Description

SVFIR Builder to create SVF variables and statements and PAG

Definition at line 47 of file SVFIRBuilder.h.

Constructor & Destructor Documentation

◆ SVFIRBuilder()

SVF::SVFIRBuilder::SVFIRBuilder ( )
inline

Constructor.

Definition at line 58 of file SVFIRBuilder.h.

58 : pag(SVFIR::getPAG()), curBB(nullptr),curVal(nullptr)
59 {
60 }
const Value * curVal
Current Value during SVFIR construction when visiting the module.
const SVFBasicBlock * curBB
Current basic block 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:118

◆ ~SVFIRBuilder()

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

Destructor.

Definition at line 62 of file SVFIRBuilder.h.

63 {
64 }

Member Function Documentation

◆ addAddrEdge()

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

Add Address edge.

Definition at line 302 of file SVFIRBuilder.h.

303 {
304 if(AddrStmt *edge = pag->addAddrStmt(src, dst))
305 {
307 return edge;
308 }
309 return nullptr;
310 }
void setCurrentBBAndValueForPAGEdge(PAGEdge *edge)
AddrStmt * addAddrStmt(NodeID src, NodeID dst)
Add an edge into SVFIR.
Definition SVFIR.cpp:63
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ 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 324 of file SVFIRBuilder.h.

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

◆ 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 313 of file SVFIRBuilder.h.

314 {
315 AddrStmt* edge = addAddrEdge(src, dst);
316 if (inst.getArraySize())
317 {
318 edge->addArrSize(pag->getGNode(getValueNode(inst.getArraySize())));
319 }
320 return edge;
321 }

◆ addBinaryOPEdge()

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

Add Copy edge.

Definition at line 437 of file SVFIRBuilder.h.

438 {
439 if(BinaryOPStmt *edge = pag->addBinaryOPStmt(op1, op2, dst, opcode))
441 }
BinaryOPStmt * addBinaryOPStmt(NodeID op1, NodeID op2, NodeID dst, u32_t opcode)
Add Copy edge.
Definition SVFIR.cpp:193

◆ addBlackHoleAddrEdge()

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

Definition at line 295 of file SVFIRBuilder.h.

296 {
299 }
SVFStmt * addBlackHoleAddrStmt(NodeID node)
Set a pointer points-to black hole (e.g. int2ptr)
Definition SVFIR.cpp:363
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 449 of file SVFIRBuilder.h.

450 {
451 if(BranchStmt *edge = pag->addBranchStmt(br, cond, succs))
453 }
BranchStmt * addBranchStmt(NodeID br, NodeID cond, const BranchStmt::SuccAndCondPairVec &succs)
Add BranchStmt.
Definition SVFIR.cpp:240

◆ addCallEdge()

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

Add Call edge.

Definition at line 473 of file SVFIRBuilder.h.

474 {
475 if (CallPE* edge = pag->addCallPE(src, dst, cs, entry))
477 }
CallPE * addCallPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Call edge (phi-like: merges actual params from all call sites into formal param)
Definition SVFIR.cpp:310

◆ addCmpEdge()

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

Add Copy edge.

Definition at line 431 of file SVFIRBuilder.h.

432 {
433 if(CmpStmt *edge = pag->addCmpStmt(op1, op2, dst, predict))
435 }
CmpStmt * addCmpStmt(NodeID op1, NodeID op2, NodeID dst, u32_t predict)
Add Copy edge.
Definition SVFIR.cpp:167

◆ 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 82 of file SVFIRExtAPI.cpp.

83{
84 assert(D && S);
86 if(!vnD || !vnS)
87 return;
88
89 std::vector<AccessPath> fields;
90
91 //Get the max possible size of the copy, unless it was provided.
92 std::vector<AccessPath> srcFields;
93 std::vector<AccessPath> dstFields;
96 if(srcFields.size() > dstFields.size())
97 fields = dstFields;
98 else
99 fields = srcFields;
100
102 u32_t sz = fields.size();
103
104 if (fields.size() == 1 && (LLVMUtil::isConstDataOrAggData(D) || LLVMUtil::isConstDataOrAggData(S)))
105 {
109 return;
110 }
111
112 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
113 for (u32_t index = 0; index < sz; index++)
114 {
117 fields[index].getConstantStructFldIdx());
119 fields[index].getConstantStructFldIdx());
125 }
126}
unsigned u32_t
Definition CommandLine.h:18
int index
Definition cJSON.h:170
const SVFType * getFlatternedElemType(const SVFType *baseType, u32_t flatten_idx)
Return the type of a flattened element given a flattened index.
Definition IRGraph.cpp:123
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:131
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 getGepValVar(const Value *val, const AccessPath &ap, const SVFType *elementType)
NodeID addDummyValNode()
Definition SVFIR.h:564
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:368
llvm::Type Type
Definition BasicTypes.h:87
u32_t NodeID
Definition GeneralType.h:56

◆ addCopyEdge()

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

Definition at line 370 of file SVFIRBuilder.h.

371 {
372 if(CopyStmt *edge = pag->addCopyStmt(src, dst, kind))
373 {
375 return edge;
376 }
377 return nullptr;
378 }
CopyStmt * addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type)
Add Copy edge.
Definition SVFIR.cpp:85

◆ 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 485 of file SVFIRBuilder.h.

486 {
487 if (GepStmt* edge = pag->addGepStmt(src, dst, ap, constGep))
489 }
GepStmt * addGepStmt(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
Definition SVFIR.cpp:418

◆ addGlobalBlackHoleAddrEdge()

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

Add global black hole Address edge.

Definition at line 270 of file SVFIRBuilder.h.

271 {
272 const Value* cval = getCurrentValue();
273 const SVFBasicBlock* cbb = getCurrentBB();
274 setCurrentLocation(int2Ptrce,(SVFBasicBlock*) nullptr);
277 }
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 SVFBasicBlock * getCurrentBB() const
const Value * getCurrentValue() const
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:86

◆ addLoadEdge()

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

Add Load edge.

Definition at line 455 of file SVFIRBuilder.h.

456 {
457 if(LoadStmt *edge = pag->addLoadStmt(src, dst))
459 }
LoadStmt * addLoadStmt(NodeID src, NodeID dst)
Add Load edge.
Definition SVFIR.cpp:263

◆ addNormalGepEdge()

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

Add Offset(Gep) edge.

Definition at line 491 of file SVFIRBuilder.h.

492 {
493 if (GepStmt* edge = pag->addNormalGepStmt(src, dst, ap))
495 }
GepStmt * addNormalGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Offset(Gep) edge.
Definition SVFIR.cpp:437

◆ addNullPtrNode()

NodeID SVF::SVFIRBuilder::addNullPtrNode ( )
inlineprotected

Add NullPtr PAGNode.

Definition at line 280 of file SVFIRBuilder.h.

281 {
283 ConstantPointerNull* constNull = ConstantPointerNull::get(PointerType::getUnqual(cxt));
284 NodeID nullPtr = pag->addConstantNullPtrValNode(pag->getNullPtr(), nullptr, llvmModuleSet()->getSVFType(constNull->getType()));
286 setCurrentLocation(constNull, (SVFBasicBlock*) nullptr);
288 return nullPtr;
289 }
NodeID getBlkPtr() const
Definition IRGraph.h:255
NodeID getNullPtr() const
Definition IRGraph.h:259
void addToSVFVar2LLVMValueMap(const Value *val, SVFValue *svfBaseNode)
LLVMContext & getContext() const
Definition LLVMModule.h:381
LLVMModuleSet * llvmModuleSet()
NodeID addConstantNullPtrValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:696
llvm::ConstantPointerNull ConstantPointerNull
Definition BasicTypes.h:131
llvm::LLVMContext LLVMContext
Definition BasicTypes.h:72

◆ 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 418 of file SVFIRBuilder.h.

419 {
421 if(PhiStmt *edge = pag->addPhiStmt(res,opnd,pred))
423 }
PhiStmt * addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add phi node information.
Definition SVFIR.cpp:108

◆ addRetEdge()

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

Add Return edge.

Definition at line 479 of file SVFIRBuilder.h.

480 {
481 if (RetPE* edge = pag->addRetPE(src, dst, cs, exit))
483 }
RetPE * addRetPE(NodeID src, NodeID dst, const CallICFGNode *cs, const FunExitICFGNode *exit)
Add Return edge.
Definition SVFIR.cpp:340

◆ addSelectStmt()

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

Add SelectStmt.

Definition at line 425 of file SVFIRBuilder.h.

426 {
427 if(SelectStmt *edge = pag->addSelectStmt(res,op1,op2,cond))
429 }
SelectStmt * addSelectStmt(NodeID res, NodeID op1, NodeID op2, NodeID cond)
Add SelectStmt.
Definition SVFIR.cpp:141

◆ addStoreEdge()

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

Add Store edge.

Definition at line 461 of file SVFIRBuilder.h.

462 {
463 ICFGNode* node;
464 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
465 node = llvmModuleSet()->getICFGNode(
466 SVFUtil::cast<Instruction>(inst));
467 else
468 node = nullptr;
469 if (StoreStmt* edge = pag->addStoreStmt(src, dst, node))
471 }
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:287
llvm::Instruction Instruction
Definition BasicTypes.h:91

◆ 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 503 of file SVFIRBuilder.h.

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

◆ 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 509 of file SVFIRBuilder.h.

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

◆ addUnaryOPEdge()

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

Add Unary edge.

Definition at line 443 of file SVFIRBuilder.h.

444 {
445 if(UnaryOPStmt *edge = pag->addUnaryOPStmt(src, dst, opcode))
447 }
UnaryOPStmt * addUnaryOPStmt(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.
Definition SVFIR.cpp:217

◆ addVariantGepEdge()

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

Add Variant(Gep) edge.

Definition at line 497 of file SVFIRBuilder.h.

498 {
499 if (GepStmt* edge = pag->addVariantGepStmt(src, dst, ap))
501 }
GepStmt * addVariantGepStmt(NodeID src, NodeID dst, const AccessPath &ap)
Add Variant(Gep) edge.
Definition SVFIR.cpp:464

◆ build()

SVFIR * SVFIRBuilder::build ( )
virtual

Start building SVFIR here.

Start building SVFIR here

build icfg

initial external library information initial SVFIR nodes

initial SVFIR edges: // handle globals

build callgraph

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 54 of file SVFIRBuilder.cpp.

55{
56 double startTime = SVFStat::getClk(true);
57
58 DBOUT(DGENERAL, outs() << pasMsg("\t Building SVFIR ...\n"));
59
60 // If the SVFIR has been built before, then we return the unique SVFIR of the program
62 return pag;
63
64
66
69 pag->icfg = icfgbuilder.build();
70
78
79
80
83 std::vector<const FunObjVar*> funset;
84 for (const auto& item: llvmModuleSet()->getFunctionSet())
85 {
87 }
88 pag->callGraph = callGraphBuilder.buildSVFIRCallGraph(funset);
89
90 CHGraph* chg = new CHGraph();
92 chgbuilder.buildCHG();
93 pag->setCHG(chg);
94
96 for (Module& M : llvmModuleSet()->getLLVMModules())
97 {
98 for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
99 {
100 const Function& fun = *F;
101 const FunObjVar* svffun = llvmModuleSet()->getFunObjVar(&fun);
103 if(!fun.isDeclaration())
104 {
110 if (fun.doesNotReturn() == false &&
111 fun.getReturnType()->isVoidTy() == false)
112 {
115 }
116
119 for (Function::const_arg_iterator I = fun.arg_begin(), E = fun.arg_end();
120 I != E; ++I)
121 {
122 setCurrentLocation(&*I,&fun.getEntryBlock());
124 // if this is the function does not have caller (e.g. main)
125 // or a dead function, shall we create a black hole address edge for it?
126 // it is (1) too conservative, and (2) make FormalParmVFGNode defined at blackhole address PAGEdge.
127 // if(SVFUtil::ArgInNoCallerFunction(&*I)) {
128 // if(I->getType()->isPointerTy())
129 // addBlackHoleAddrEdge(argValNodeId);
130 //}
132 }
133 }
134 for (Function::const_iterator bit = fun.begin(), ebit = fun.end();
135 bit != ebit; ++bit)
136 {
137 const BasicBlock& bb = *bit;
138 for (BasicBlock::const_iterator it = bb.begin(), eit = bb.end();
139 it != eit; ++it)
140 {
141 const Instruction& inst = *it;
142 setCurrentLocation(&inst,&bb);
143 visit(const_cast<Instruction&>(inst));
144 }
145 }
146 }
147 }
148
149 sanityCheck();
150
152
154
155 // dump SVFIR
157 pag->dump("svfir_initial");
158
159 // print to command line of the SVFIR graph
160 if (Options::PAGPrint())
161 pag->print();
162
163 // dump ICFG
164 if (Options::DumpICFG())
165 pag->getICFG()->dump("icfg_initial");
166
168 {
171 }
172
173 // dump SVFIR as JSON
174 if (!Options::DumpJson().empty())
175 {
176 assert(false && "please implement SVFIRWriter::writeJsonToPath");
177 }
178
179 double endTime = SVFStat::getClk(true);
180 SVFStat::timeOfBuildingSVFIR = (endTime - startTime) / TIMEINTERVAL;
181
182 return pag;
183}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:593
#define TIMEINTERVAL
Definition SVFType.h:621
#define DGENERAL
Definition SVFType.h:599
cJSON * item
Definition cJSON.h:222
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:411
u32_t getNodeNumAfterPAGBuild() const
Definition IRGraph.h:322
void dump(std::string name)
Dump SVFIR.
Definition IRGraph.cpp:316
NodeID getReturnNode(const FunObjVar *func) const
GetReturnNode - Return the unique node representing the return value of a function.
Definition IRGraph.cpp:60
void setNodeNumAfterPAGBuild(u32_t num)
Definition IRGraph.h:326
virtual void build(ICFG *icfg)
Start from here.
NodeID getValueNode(const Value *V)
const FunObjVar * getFunObjVar(const Function *fun) const
Definition LLVMModule.h:267
static const Option< bool > PAGDotGraph
Definition Options.h:118
static const Option< std::string > DumpJson
Definition Options.h:121
static const Option< bool > PAGPrint
Definition Options.h:124
static const Option< bool > LoopAnalysis
Definition Options.h:239
static const Option< bool > DumpICFG
Definition Options.h:120
void sanityCheck()
Sanity check for SVFIR.
void visitGlobal()
Handle globals including (global variable and functions)
void initialiseNodes()
Initialize nodes and edges.
void addFunArgs(const FunObjVar *fun, const ValVar *arg)
Get/set method for function/callsite arguments and returns.
Definition SVFIR.h:616
void print()
Print SVFIR.
Definition SVFIR.cpp:646
void addFunRet(const FunObjVar *fun, const ValVar *ret)
Add function returns.
Definition SVFIR.h:628
CallGraph * callGraph
all the callsites of a program
Definition SVFIR.h:101
ICFG * getICFG() const
Definition SVFIR.h:229
void setCHG(CommonCHGraph *c)
Set/Get CHG.
Definition SVFIR.h:235
ICFG * icfg
Definition SVFIR.h:98
const ValVar * getValVar(NodeID id) const
Definition SVFIR.h:137
void initialiseCandidatePointers()
Initialize candidate pointers.
Definition SVFIR.cpp:731
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
static double timeOfBuildingSVFIR
Definition SVFStat.h:95
const FunObjVar * getFunObjVar(const std::string &name)
Definition LLVMUtil.cpp:435
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:101
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
llvm::BasicBlock BasicBlock
Definition BasicTypes.h:90
llvm::Function Function
Definition BasicTypes.h:89
llvm::Module Module
Definition BasicTypes.h:88

◆ 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 643 of file SVFIRBuilder.cpp.

644{
645 assert(V);
646
647 const llvm::GEPOperator *gepOp = SVFUtil::dyn_cast<const llvm::GEPOperator>(V);
648 DataLayout * dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
649 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gepOp->getPointerAddressSpace()),0,true);
650 if(gepOp && dataLayout && gepOp->accumulateConstantOffset(*dataLayout,byteOffset))
651 {
652 //s32_t bo = byteOffset.getSExtValue();
653 }
654
655 bool isConst = true;
656
657 bool prevPtrOperand = false;
659 gi != ge; ++gi)
660 {
661 const Type* gepTy = *gi;
663
664 assert((prevPtrOperand && svfGepTy->isPointerTy()) == false &&
665 "Expect no more than one gep operand to be of a pointer type");
666 if(!prevPtrOperand && svfGepTy->isPointerTy()) prevPtrOperand = true;
667 const Value* offsetVal = gi.getOperand();
668 assert(gepTy != offsetVal->getType() && "iteration and operand have the same type?");
670
671 //The int value of the current index operand
672 const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(offsetVal);
673
674 // if Options::ModelConsts() is disabled. We will treat whole array as one,
675 // but we can distinguish different field of an array of struct, e.g. s[1].f1 is different from s[0].f2
676 if(const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(gepTy))
677 {
678 if(!op || (arrTy->getArrayNumElements() <= (u32_t)LLVMUtil::getIntegerValue(op).first))
679 continue;
683 }
684 else if (const StructType *ST = SVFUtil::dyn_cast<StructType>(gepTy))
685 {
686 assert(op && "non-const offset accessing a struct");
687 // guard against negative or out-of-bounds struct indices
688 // (e.g. rust hashbrown bucket back-offset: gep { ... }, ptr %p, i64 -1)
689 // a negative i64 wraps to a huge uint64_t that overflows u32_t,
690 // creating an invalid field index that severs points-to tracking
692 if (rawIdx >= ST->getNumElements())
693 {
694 isConst = false;
695 continue;
696 }
700 }
701 else if (gepTy->isSingleValueType())
702 {
703 // If it's a non-constant offset access
704 // If its point-to target is struct or array, it's likely an array accessing (%result = gep %struct.A* %a, i32 %non-const-index)
705 // If its point-to target is single value (pointer arithmetic), then it's a variant gep (%result = gep i8* %p, i32 %non-const-index)
706 if(!op && gepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
707 {
708 isConst = false;
709 }
710
711 // The actual index
712 //s32_t idx = op->getSExtValue();
713
714 // For pointer arithmetic we ignore the byte offset
715 // consider using inferFieldIdxFromByteOffset(geopOp,dataLayout,ap,idx)?
716 // ap.setFldIdx(ap.getConstantFieldIdx() + inferFieldIdxFromByteOffset(geopOp,idx));
717 }
718 }
719 return isConst;
720}
buffer offset
Definition cJSON.cpp:1113
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:98
void setFldIdx(APOffset idx)
Definition AccessPath.h:102
bool addOffsetVarAndGepTypePair(const ValVar *var, const SVFType *gepIterType)
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:144
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
SVFIR * getPAG() const
Return SVFIR.
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:82
static DataLayout * getDataLayout(Module *mod)
Definition LLVMUtil.h:313
llvm::DataLayout DataLayout
Definition BasicTypes.h:112
llvm::ArrayType ArrayType
Definition BasicTypes.h:99
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:98
s64_t APOffset
Definition GeneralType.h:60
unsigned u32_t
Definition GeneralType.h:47
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:129
bridge_gep_iterator bridge_gep_end(const User *GEP)
bridge_gep_iterator bridge_gep_begin(const User *GEP)

◆ createFunObjVars()

void SVFIRBuilder::createFunObjVars ( )

set fun in bb

Definition at line 328 of file SVFIRBuilder.cpp.

329{
330 std::vector<FunObjVar*> funset;
331 // Iterate over all object symbols in the symbol table
332 for (const auto* fun: llvmModuleSet()->getFunctionSet())
333 {
334 u32_t id = llvmModuleSet()->objSyms()[fun];
335 // Debug output for adding object node
336 DBOUT(DPAGBuild, outs() << "add obj node " << id << "\n");
337
338 // Check if the value is a function and add a function object node
339 pag->addFunObjNode(id, pag->getObjTypeInfo(id), nullptr);
341
342 FunObjVar *funObjVar = SVFUtil::cast<FunObjVar>(pag->getGNode(id));
343 funset.push_back(funObjVar);
344
345 funObjVar->initFunObjVar(fun->isDeclaration(), LLVMUtil::isIntrinsicFun(fun), fun->hasAddressTaken(),
347 SVFUtil::cast<SVFFunctionType>(llvmModuleSet()->getSVFType(fun->getFunctionType())),
348 new SVFLoopAndDomInfo, nullptr, nullptr,
349 {}, nullptr);
350 BasicBlockGraph* bbGraph = new BasicBlockGraph();
351 funObjVar->setBasicBlockGraph(bbGraph);
352
353
354 for (const BasicBlock& bb : *fun)
355 {
356 llvmModuleSet()->addBasicBlock(funObjVar, &bb);
357 }
358
360 for (auto& bb: *funObjVar->bbGraph)
361 {
362 bb.second->setFun(funObjVar);
363 }
365 }
366
368}
#define DPAGBuild
Definition SVFType.h:601
void setBasicBlockGraph(BasicBlockGraph *graph)
void initFunObjVar(bool decl, bool intrinc, bool addr, bool uncalled, bool notret, bool vararg, const SVFFunctionType *ft, SVFLoopAndDomInfo *ld, const FunObjVar *real, BasicBlockGraph *bbg, const std::vector< const ArgValVar * > &allarg, const SVFBasicBlock *exit)
ObjTypeInfo * getObjTypeInfo(NodeID id) const
Definition IRGraph.h:234
LLVMFun2FunObjVarMap LLVMFun2FunObjVar
Map an LLVM Function to an SVF Funobjvar.
Definition LLVMModule.h:99
ValueToIDMapTy & objSyms()
Definition LLVMModule.h:212
void addBasicBlock(FunObjVar *fun, const BasicBlock *bb)
Definition LLVMModule.h:232
NodeID addFunObjNode(NodeID id, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:745
bool isUncalledFunction(const Function *fun)
whether this is a function without any possible caller?
Definition LLVMUtil.cpp:157
bool isIntrinsicFun(const Function *func)
Definition LLVMUtil.cpp:189
bool functionDoesNotRet(const Function *fun)
Definition LLVMUtil.cpp:122

◆ 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 1836 of file SVFIRBuilder.cpp.

1837{
1838 SVFVar* node = pag->getGNode(nodeId);
1841 if(geps.empty())
1842 return AccessPath(0);
1843
1844 assert(geps.size()==1 && "one node can only be connected by at most one gep edge!");
1845 SVFVar::iterator it = geps.begin();
1846 const GepStmt* gepEdge = SVFUtil::cast<GepStmt>(*it);
1847 if(gepEdge->isVariantFieldGep())
1848 return AccessPath(0);
1849 else
1850 return gepEdge->getAccessPath();
1851}
GEdgeSetTy::iterator iterator
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
SVFStmt::SVFStmtSetTy & getIncomingEdges(SVFStmt::PEDGEK kind)
Edge accessors and checkers.

◆ 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 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
54 numOfElems = (numOfElems > szIntVal.first) ? szIntVal.first : numOfElems;
55 }
56
58 for(u32_t ei = 0; ei < numOfElems; ei++)
59 {
61 // make a ConstantInt and create char for the content type due to byte-wise copy
62 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
63 if (!llvmModuleSet()->hasValueNode(offset))
64 {
66 builder.collectSym(offset);
68 pag->addConstantIntValNode(id, LLVMUtil::getIntegerValue(offset), nullptr, llvmModuleSet()->getSVFType(offset->getType()));
70 pag->getGNode(id));
71 }
72 ls.addOffsetVarAndGepTypePair(getPAG()->getValVar(llvmModuleSet()->getValueNode(offset)), nullptr);
73 fields.push_back(ls);
74 }
75 return objType;
76}
u32_t getNumOfFlattenElements(const SVFType *T)
Definition IRGraph.cpp:169
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(NodeID i, const std::pair< s64_t, u64_t > &intValue, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:689

◆ 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))

Example 1:

%0 = getelementptr inbounds struct.outer, struct.inner base, i32 0, i32 0 call void @llvm.memcpy(ptr inner, ptr %0, i64 24, i1 false) The base value for %0 is base. Note: the base is recognized as the base value if the offset (field index) is 0

Example 2: https://github.com/SVF-tools/SVF/issues/1650 https://github.com/SVF-tools/SVF/pull/1652

@i1 = dso_local global struct.inner { i32 0, ptr @f1, ptr @f2 } @n1 = dso_local global struct.outer { i32 0, ptr @i1 }

inner = alloca struct.inner %0 = load ptr, ptr getelementptr inbounds (struct.outer, ptr @n1, i32 0, i32 1) call void @llvm.memcpy(ptr inner, ptr %0, i64 24, i1 false)

The base value for %0 is @i1

Example 3:

@conststruct = internal global <{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }> <{ [40 x i8] undef, [4 x i8] zeroinitializer, [4 x i8] undef, [2512 x i8] zeroinitializer }>, align 8

%0 = load ptr, ptr getelementptr inbounds (<{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>, ptr @conststruct, i64 0, i32 0, i64 16)

The base value for %0 is still %0

Definition at line 1547 of file SVFIRBuilder.cpp.

1548{
1549 const Value* value = stripAllCasts(V);
1550 assert(value && "null ptr?");
1551 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(value))
1552 {
1553 APOffset totalidx = 0;
1555 {
1556 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
1558 }
1559 if(totalidx == 0 && !SVFUtil::isa<StructType>(value->getType()))
1560 value = gep->getPointerOperand();
1561 }
1562 else if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(value))
1563 {
1564 const Value* loadP = load->getPointerOperand();
1565 if (const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(loadP))
1566 {
1567 APOffset totalidx = 0;
1569 {
1570 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
1572 }
1573 const Value * pointer_operand = gep->getPointerOperand();
1574 if (auto *glob = SVFUtil::dyn_cast<GlobalVariable>(pointer_operand))
1575 {
1576 if (glob->hasInitializer())
1577 {
1578 if (auto *initializer = SVFUtil::dyn_cast<
1579 ConstantStruct>(glob->getInitializer()))
1580 {
1581 /*
1582 *@conststruct = internal global <{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>
1583 <{ [40 x i8] undef, [4 x i8] zeroinitializer, [4 x i8] undef, [2512 x i8] zeroinitializer }>, align 8
1584
1585 %0 = load ptr, ptr getelementptr inbounds (<{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>,
1586 ptr @conststruct, i64 0, i32 0, i64 16)
1587 in this case, totalidx is 16 while initializer->getNumOperands() is 4, so we return value as the base
1588 */
1589 if (totalidx >= initializer->getNumOperands()) return value;
1590 auto *ptrField = initializer->getOperand(totalidx);
1591 if (auto *ptrValue = SVFUtil::dyn_cast<llvm::GlobalVariable>(ptrField))
1592 {
1593 return ptrValue;
1594 }
1595 }
1596 }
1597 }
1598 }
1599 }
1600
1601 return value;
1602}
const Value * stripAllCasts(const Value *val)
Strip off the all casts.
Definition LLVMUtil.cpp:249
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
llvm::ConstantStruct ConstantStruct
Definition BasicTypes.h:110
llvm::LoadInst LoadInst
Definition BasicTypes.h:156
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:169

◆ getCopyKind()

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

Definition at line 380 of file SVFIRBuilder.h.

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

◆ getCurrentBB()

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

Definition at line 264 of file SVFIRBuilder.h.

265 {
266 return curBB;
267 }

◆ getCurrentValue()

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

Definition at line 260 of file SVFIRBuilder.h.

261 {
262 return curVal;
263 }

◆ 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 1676 of file SVFIRBuilder.cpp.

1677{
1678 NodeID base = getValueNode(val);
1680 if (gepval==UINT_MAX)
1681 {
1682 assert(((int) UINT_MAX)==-1 && "maximum limit of unsigned int is not -1?");
1683 /*
1684 * getGepValVar can only be called from two places:
1685 * 1. SVFIRBuilder::addComplexConsForExt to handle external calls
1686 * 2. SVFIRBuilder::getGlobalVarField to initialize global variable
1687 * so curVal can only be
1688 * 1. Instruction
1689 * 2. GlobalVariable
1690 */
1691 assert(
1692 (SVFUtil::isa<Instruction>(curVal) || SVFUtil::isa<GlobalVariable>(curVal)) && "curVal not an instruction or a globalvariable?");
1693
1694 // We assume every GepValNode and its GepEdge to the baseNode are unique across the whole program
1695 // We preserve the current BB information to restore it after creating the gepNode
1696 const Value* cval = getCurrentValue();
1697 const SVFBasicBlock* cbb = getCurrentBB();
1700 const ICFGNode* node = nullptr;
1701 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
1702 {
1703 if (llvmmodule->hasICFGNode(inst))
1704 {
1705 node = llvmmodule->getICFGNode(inst);
1706 }
1707 }
1708 else if (SVFUtil::isa<GlobalVariable>(curVal))
1709 {
1710 // GEP on a global variable: the resulting GepValVar belongs to the global ICFG node.
1711 node = pag->getICFG()->getGlobalICFGNode();
1712 }
1714 NodeIDAllocator::get()->allocateValueId(),
1715 llvmmodule->getSVFType(PointerType::getUnqual(llvmmodule->getContext())), node);
1716 addGepEdge(base, gepNode, ap, true);
1718 return gepNode;
1719 }
1720 else
1721 return gepval;
1722}
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:244
static NodeIDAllocator * get(void)
Return (singleton) allocator.
void addGepEdge(NodeID src, NodeID dst, const AccessPath &ap, bool constGep)
Add Gep edge.
NodeID getGepValVar(NodeID curInst, NodeID base, const AccessPath &ap) const
Due to constraint expression, curInst is used to distinguish different instructions (e....
Definition SVFIR.cpp:611
NodeID addGepValNode(NodeID curInst, const ValVar *base, const AccessPath &ap, NodeID i, const SVFType *type, const ICFGNode *node)
Add a temp field value node, this method can only invoked by getGepValVar.
Definition SVFIR.cpp:485

◆ 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 856 of file SVFIRBuilder.cpp.

857{
858
859 // if the global variable do not have any field needs to be initialized
860 if (offset == 0 && gvar->getInitializer()->getType()->isSingleValueType())
861 {
862 return getValueNode(gvar);
863 }
866 else
867 {
869 }
870}

◆ 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 108 of file SVFIRBuilder.h.

109 {
110 return llvmModuleSet()->getObjectNode(V);
111 }
NodeID getObjectNode(const Value *V)

◆ getPAG()

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

Return SVFIR.

Definition at line 70 of file SVFIRBuilder.h.

71 {
72 return pag;
73 }

◆ getReturnNode()

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

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

Definition at line 114 of file SVFIRBuilder.h.

115 {
116 return pag->getReturnNode(func);
117 }

◆ getValueNode()

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

Get different kinds of node.

Definition at line 98 of file SVFIRBuilder.h.

99 {
100 // first handle gep edge if val if a constant expression
101 processCE(V);
102
103 // strip off the constant cast and return the value node
104 return llvmModuleSet()->getValueNode(V);
105 }
void processCE(const Value *val)
Process constant expression.

◆ getVarargNode()

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

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

Definition at line 120 of file SVFIRBuilder.h.

121 {
122 return pag->getVarargNode(func);
123 }
NodeID getVarargNode(const FunObjVar *func) const
getVarargNode - Return the unique node representing the variadic argument of a variadic function.
Definition IRGraph.cpp:67

◆ 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 1453 of file SVFIRBuilder.cpp.

1454{
1455
1456 assert(F);
1460 outs() << "handle direct call " << LLVMUtil::dumpValue(cs) << " callee " << F->getName().str() << "\n");
1461
1462 //Only handle the ret.val. if it's used as a ptr.
1464 //Does it actually return a ptr?
1465 if (!cs->getType()->isVoidTy())
1466 {
1470 }
1471 //Iterators for the actual and formal parameters
1472 u32_t itA = 0, ieA = cs->arg_size();
1473 Function::const_arg_iterator itF = F->arg_begin(), ieF = F->arg_end();
1474 //Go through the fixed parameters.
1475 DBOUT(DPAGBuild, outs() << " args:");
1476 for (; itF != ieF; ++itA, ++itF)
1477 {
1478 //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
1479 if (itA == ieA)
1480 {
1481 DBOUT(DPAGBuild, outs() << " !! not enough args\n");
1482 break;
1483 }
1484 const Value* AA = cs->getArgOperand(itA), *FA = &*itF; //current actual/formal arg
1485
1486 DBOUT(DPAGBuild, outs() << "process actual parm " << llvmModuleSet()->getSVFValue(AA)->toString() << " \n");
1487
1492 }
1493 //Any remaining actual args must be varargs.
1494 if (F->isVarArg())
1495 {
1497 DBOUT(DPAGBuild, outs() << "\n varargs:");
1498 for (; itA != ieA; ++itA)
1499 {
1500 const Value* AA = cs->getArgOperand(itA);
1504 }
1505 }
1506 if(itA != ieA)
1507 {
1510 writeWrnMsg("too many args to non-vararg func.");
1511 writeWrnMsg("(" + callICFGNode->getSourceLoc() + ")");
1512
1513 }
1514}
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:249
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:242
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
NodeID getVarargNode(const FunObjVar *func)
getVarargNode - Return the node representing the unique variadic argument of a function.
NodeID getReturnNode(const FunObjVar *func)
getReturnNode - Return the node representing the unique return value 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.
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:604
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:68

◆ handleExtCall()

void SVFIRBuilder::handleExtCall ( const CallBase cs,
const Function callee 
)
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 128 of file SVFIRExtAPI.cpp.

129{
131
133 {
137 }
139 {
141 Value* arg = cs->getArgOperand(arg_pos);
142 if (cs->getArgOperand(arg_pos)->getType()->isPointerTy())
143 {
146 NodeID obj = pag->addDummyObjNode(llvmModuleSet()->getSVFType(cs->getArgOperand(arg_pos)->getType()));
147 if (vnArg && dummy && obj)
148 {
151 }
152 }
153 else
154 {
155 writeWrnMsg("Arg receiving new object must be pointer type");
156 }
157 }
159 {
160 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
161 // which copies n characters from memory area 'src' to memory area 'dest'.
162 if(callee->getName().find("iconv") != std::string::npos)
163 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
164 else if(callee->getName().find("bcopy") != std::string::npos)
165 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
166 if(cs->arg_size() == 3)
167 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
168 else
169 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
170 if(SVFUtil::isa<PointerType>(cs->getType()))
171 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
172 }
174 {
175 // Side-effects similar to memset(void *str, int c, size_t n)
176 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
177 std::vector<AccessPath> dstFields;
178 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
179 u32_t sz = dstFields.size();
180 //For each field (i), add store edge *(arg0 + i) = arg1
181 for (u32_t index = 0; index < sz; index++)
182 {
185 dstFields[index].getConstantStructFldIdx());
186 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
187 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
188 }
189 if(SVFUtil::isa<PointerType>(cs->getType()))
190 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
191 }
192 else if(callee->getName().compare("dlsym") == 0)
193 {
194 /*
195 Side-effects of void* dlsym( void* handle, const char* funName),
196 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
197 dlsym() example:
198 int main() {
199 // Open the shared library
200 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
201 // Find the function address
202 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
203 // Call the function
204 myFunctionPtr();
205 }
206 */
207 const Value* src = cs->getArgOperand(1);
208 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(src))
209 src = stripConstantCasts(gep->getPointerOperand());
210
211 auto getHookFn = [](const Value* src)->const Function*
212 {
213 if (!SVFUtil::isa<GlobalVariable>(src))
214 return nullptr;
215
216 auto *glob = SVFUtil::cast<GlobalVariable>(src);
217 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
218 return nullptr;
219
220 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
221 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
222 };
223
224 if (const Function *fn = getHookFn(src))
225 {
228 }
229 }
230 else if(callee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
231 {
232 // 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.
233 assert(cs->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
234
235 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
236 // Now we calculate the offset from base to vArg3
237 NodeID vnArg3 = llvmModuleSet()->getValueNode(cs->getArgOperand(3));
240
241 // We get all flattened fields of base
243
244 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
245 // Note that arg0 is aligned with "offset".
246 for (APOffset i = offset + 1; i <= offset + 3; ++i)
247 {
248 if((u32_t)i >= fields.size())
249 break;
251 fields[i].getConstantStructFldIdx());
252 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
253 NodeID vnS = llvmModuleSet()->getValueNode(cs->getArgOperand(1));
254 if(vnD && vnS)
256 }
257 }
258
260 {
262 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
263 {
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 ArgValVar* formalParm = forkedFun->getArg(0);
273 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
274 {
276 addThreadForkEdge(actualParm->getId(), formalParm->getId(), callICFGNode, entry);
277 }
278 }
279 }
280 else
281 {
286 }
290 }
291
293}
Class representing a function argument variable in the SVFIR.
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const FunObjVar * getDefFunForMultipleModule() const
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:339
NodeID addDummyObjNode(const SVFType *type)
Definition SVFIR.h:568
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:218
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:637
bool isMemcpyExtFun(const Function *fun)
Definition LLVMUtil.cpp:388
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:652
bool isMemsetExtFun(const Function *fun)
Definition LLVMUtil.cpp:394
u32_t getHeapAllocHoldingArgPosition(const Function *fun)
Definition LLVMUtil.cpp:400
bool isThreadForkCall(const CallICFGNode *inst)
Definition SVFUtil.h:360
const ValVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
Definition SVFUtil.h:408
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:331

◆ handleIndCall()

void SVFIRBuilder::handleIndCall ( CallBase cs)
protected

Handle indirect call.

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

Definition at line 1607 of file SVFIRBuilder.cpp.

1608{
1610 NodeID indFunPtrId = llvmModuleSet()->getValueNode(cs->getCalledOperand());
1611 const_cast<CallICFGNode*>(cbn)->setIndFunPtr(pag->getGNode(indFunPtrId));
1613}
void addIndirectCallsites(const CallICFGNode *cs, NodeID funPtr)
Add indirect callsites.
Definition SVFIR.h:652

◆ inferFieldIdxFromByteOffset()

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

Infer field index from byteoffset.

Definition at line 632 of file SVFIRBuilder.cpp.

633{
634 return 0;
635}

◆ initDomTree()

void SVFIRBuilder::initDomTree ( FunObjVar func,
const Function f 
)

Definition at line 256 of file SVFIRBuilder.cpp.

257{
258 if (fun->isDeclaration())
259 return;
260 //process and stored dt & df
263 df.analyze(dt);
265 PostDominatorTree pdt = PostDominatorTree(const_cast<Function&>(*fun));
266 SVFLoopAndDomInfo* ld = svffun->getLoopAndDomInfo();
267
269 for (DominanceFrontierBase::const_iterator dfIter = df.begin(), eDfIter = df.end(); dfIter != eDfIter; dfIter++)
270 {
271 const BasicBlock* keyBB = dfIter->first;
272#if LLVM_VERSION_MAJOR > 16
273 const llvm::SetVector<llvm::BasicBlock* >& domSet = dfIter->second;
274#else
275 const std::set<BasicBlock* >& domSet = dfIter->second;
276#endif
278 for (const BasicBlock* bbValue:domSet)
279 {
280 valueBasicBlocks.insert(llvmModuleSet()->getSVFBasicBlock(bbValue));
281 }
282 }
283 std::vector<const SVFBasicBlock*> reachableBBs;
284 LLVMUtil::getFunReachableBBs(fun, reachableBBs);
285 ld->setReachableBBs(reachableBBs);
286
287 for (Function::const_iterator bit = fun->begin(), beit = fun->end(); bit!=beit; ++bit)
288 {
289 const BasicBlock &bb = *bit;
291 if (DomTreeNode* dtNode = dt.getNode(&bb))
292 {
293 SVFLoopAndDomInfo::BBSet& bbSet = ld->getDomTreeMap()[svfBB];
294 for (const auto domBB : *dtNode)
295 {
296 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
297 bbSet.insert(domSVFBB);
298 }
299 }
300
301 if (DomTreeNode* pdtNode = pdt.getNode(&bb))
302 {
303 u32_t level = pdtNode->getLevel();
304 ld->getBBPDomLevel()[svfBB] = level;
305 BasicBlock* idomBB = pdtNode->getIDom()->getBlock();
307 ld->getBB2PIdom()[svfBB] = idom;
308
309 SVFLoopAndDomInfo::BBSet& bbSet = ld->getPostDomTreeMap()[svfBB];
310 for (const auto domBB : *pdtNode)
311 {
312 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
313 bbSet.insert(domSVFBB);
314 }
315 }
316
317 if (const Loop* loop = loopInfo.getLoopFor(&bb))
318 {
319 for (const BasicBlock* loopBlock : loop->getBlocks())
320 {
322 ld->addToBB2LoopMap(svfBB, loopbb);
323 }
324 }
325 }
326}
SVFBasicBlock * getSVFBasicBlock(const BasicBlock *bb)
Definition LLVMModule.h:298
DominatorTree & getDomTree(const Function *fun)
const Map< const SVFBasicBlock *, BBSet > & getDomFrontierMap() const
Set< const SVFBasicBlock * > BBSet
#define NULL
Definition extapi.c:5
void getFunReachableBBs(const Function *svfFun, std::vector< const SVFBasicBlock * > &bbs)
Get reachable basic block from function entry.
Definition LLVMUtil.cpp:74
llvm::LoopInfo LoopInfo
Definition BasicTypes.h:148
llvm::DomTreeNode DomTreeNode
Definition BasicTypes.h:141
llvm::PostDominatorTree PostDominatorTree
Definition BasicTypes.h:143
llvm::DominanceFrontier DominanceFrontier
Definition BasicTypes.h:142
llvm::Loop Loop
LLVM Loop.
Definition BasicTypes.h:147
llvm::DominatorTree DominatorTree
LLVM Dominators.
Definition BasicTypes.h:140

◆ initFunObjVar()

void SVFIRBuilder::initFunObjVar ( )

Function

set realDefFun for all functions

Definition at line 185 of file SVFIRBuilder.cpp.

186{
187 for (Module& mod : llvmModuleSet()->getLLVMModules())
188 {
190 for (const Function& f : mod.functions())
191 {
194
195 if (!LLVMUtil::isExtCall(&f))
196 {
198 }
201 svffun->setRelDefFun(realfun == nullptr ? nullptr : llvmModuleSet()->getFunObjVar(realfun));
202 }
203 }
204
205 // Store annotations of functions in extapi.bc
206 for (const auto& pair : llvmModuleSet()->ExtFun2Annotations)
207 {
209 }
210
211}
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:44
void setExtFuncAnnotations(const FunObjVar *fun, const std::vector< std::string > &funcAnnotations)
Definition ExtAPI.cpp:223
const Function * getRealDefFun(const Function *fun) const
Definition LLVMModule.h:185
void initSVFBasicBlock(const Function *func)
void initDomTree(FunObjVar *func, const Function *f)
bool isExtCall(const Function *fun)
Definition LLVMUtil.cpp:383

◆ InitialGlobal()

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

src should not point to anything yet

Definition at line 883 of file SVFIRBuilder.cpp.

885{
886 DBOUT(DPAGBuild, outs() << "global " << llvmModuleSet()->getSVFValue(gvar)->toString() << " constant initializer: " << llvmModuleSet()->getSVFValue(C)->toString() << "\n");
887 if (C->getType()->isSingleValueType())
888 {
889 NodeID src = getValueNode(C);
890 // get the field value if it is available, otherwise we create a dummy field node.
892 NodeID field = getGlobalVarField(gvar, offset, llvmModuleSet()->getSVFType(C->getType()));
893
894 if (SVFUtil::isa<GlobalVariable, Function>(C))
895 {
897 addStoreEdge(src, field);
898 }
899 else if (SVFUtil::isa<ConstantExpr>(C))
900 {
901 // add gep edge of C1 itself is a constant expression
902 processCE(C);
904 addStoreEdge(src, field);
905 }
906 else if (SVFUtil::isa<BlockAddress>(C))
907 {
908 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
909 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
910 processCE(C);
913 }
914 else
915 {
917 addStoreEdge(src, field);
919 if (C->getType()->isPtrOrPtrVectorTy() && src != pag->getNullPtr())
921 }
922 }
923 else if (SVFUtil::isa<ConstantArray, ConstantStruct>(C))
924 {
926 return;
927 for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
928 {
930 InitialGlobal(gvar, SVFUtil::cast<Constant>(C->getOperand(i)), offset + off);
931 }
932 }
933 else if(ConstantData* data = SVFUtil::dyn_cast<ConstantData>(C))
934 {
936 {
937 if(ConstantDataSequential* seq = SVFUtil::dyn_cast<ConstantDataSequential>(data))
938 {
939 for(u32_t i = 0; i < seq->getNumElements(); i++)
940 {
941 u32_t off = pag->getFlattenedElemIdx(llvmModuleSet()->getSVFType(C->getType()), i);
942 Constant* ct = seq->getElementAsConstant(i);
944 }
945 }
946 else
947 {
948 assert((SVFUtil::isa<ConstantAggregateZero, UndefValue>(data)) && "Single value type data should have been handled!");
949 }
950 }
951 }
952 else
953 {
954 //TODO:assert(SVFUtil::isa<ConstantVector>(C),"what else do we have");
955 }
956}
NodeID getConstantNode() const
Definition IRGraph.h:251
static Option< bool > ModelConsts
Definition Options.h:184
static const Option< bool > VtableInSVFIR
Definition Options.h:214
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:120
llvm::Constant Constant
Definition BasicTypes.h:128
llvm::ConstantDataSequential ConstantDataSequential
Definition BasicTypes.h:123

◆ initialiseBaseObjVars()

void SVFIRBuilder::initialiseBaseObjVars ( )

Definition at line 370 of file SVFIRBuilder.cpp.

371{
372 // Iterate over all object symbols in the symbol table
373 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
374 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end();
375 ++iter)
376 {
377 // Debug output for adding object node
378 DBOUT(DPAGBuild, outs() << "add obj node " << iter->second << "\n");
379
380 // Skip blackhole and constant symbols
381 if(iter->second == pag->blackholeSymID() || iter->second == pag->constantSymID())
382 continue;
383
384 // Get the LLVM value corresponding to the symbol
385 const Value* llvmValue = iter->first;
386
387 const ICFGNode* icfgNode = nullptr;
388 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
389 {
390 if(llvmModuleSet()->hasICFGNode(inst))
391 icfgNode = llvmModuleSet()->getICFGNode(inst);
392 }
393
394 // Check if the value is a function and add a function object node
395 if (SVFUtil::dyn_cast<Function>(llvmValue))
396 {
397 // already one
398 }
399 // Check if the value is a heap object and add a heap object node
401 {
402 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
403 pag->addHeapObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
404 }
405 // Check if the value is an alloca instruction and add a stack object node
407 {
408 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
409 pag->addStackObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
410 }
411 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
412 {
413 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
415 }
416 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
417 {
418 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
420 }
421 else if (SVFUtil::isa<ConstantPointerNull>(llvmValue))
422 {
423 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
424 pag->addConstantNullPtrObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
425 }
426 else if (SVFUtil::isa<GlobalValue>(llvmValue))
427 {
428 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
429 pag->addGlobalObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
430 }
431 else if (SVFUtil::isa<ConstantData, ConstantExpr, MetadataAsValue, BlockAddress>(llvmValue))
432 {
433 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
434 pag->addConstantDataObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
435 }
436 else if (SVFUtil::isa<ConstantAggregate>(llvmValue))
437 {
438 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
439 pag->addConstantAggObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
440 }
441 // Add a generic object node for other types of values
442 else
443 {
444 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
445 pag->addObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
446 }
448 }
449
450}
NodeID constantSymID() const
Definition IRGraph.h:188
NodeID blackholeSymID() const
Definition IRGraph.h:193
NodeID addConstantAggObjNode(const NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:778
NodeID addGlobalObjNode(const NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:773
NodeID addConstantDataObjNode(const NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:783
NodeID addConstantFPObjNode(NodeID i, ObjTypeInfo *ti, double dval, const ICFGNode *node)
Definition SVFIR.h:752
NodeID addObjNode(NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Add a memory obj node.
Definition SVFIR.h:722
NodeID addHeapObjNode(NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:730
NodeID addConstantNullPtrObjNode(const NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:767
NodeID addStackObjNode(NodeID i, ObjTypeInfo *ti, const ICFGNode *node)
Definition SVFIR.h:739
NodeID addConstantIntObjNode(NodeID i, ObjTypeInfo *ti, const std::pair< s64_t, u64_t > &intValue, const ICFGNode *node)
Definition SVFIR.h:759
double getDoubleValue(const ConstantFP *fpValue)
Definition LLVMUtil.h:54
bool isHeapObj(const Value *val)
Definition LLVMUtil.cpp:686
bool isStackObj(const Value *val)
Definition LLVMUtil.cpp:708

◆ initialiseNodes()

void SVFIRBuilder::initialiseNodes ( )

Initialize nodes and edges.

add address edges for constant nodes.

add argvalvar for svffunctions

Definition at line 542 of file SVFIRBuilder.cpp.

543{
544 DBOUT(DPAGBuild, outs() << "Initialise SVFIR Nodes ...\n");
545
546
551
554
555 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
556 llvmModuleSet()->retSyms().begin(); iter != llvmModuleSet()->retSyms().end();
557 ++iter)
558 {
559 const Value* llvmValue = iter->first;
560 // retSyms keys are Function*, not Instruction, so dyn_cast<Instruction> always fails.
561 // RetValPN represents the callee's return value, defined at FunExitICFGNode.
562 // External functions have no exit node, so keep nullptr.
563 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
564 const ICFGNode* icfgNode = funObjVar->isDeclaration() ? nullptr : pag->getICFG()->getFunExitICFGNode(funObjVar);
565 DBOUT(DPAGBuild, outs() << "add ret node " << iter->second << "\n");
566 pag->addRetNode(iter->second,
567 funObjVar,
568 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
570 pag->returnFunObjSymMap[funObjVar] = iter->second;
571 }
572
573 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
574 llvmModuleSet()->varargSyms().begin();
575 iter != llvmModuleSet()->varargSyms().end(); ++iter)
576 {
577 const Value* llvmValue = iter->first;
578 // varargSyms keys are Function*, not Instruction.
579 // Variadic arguments are received at the function entry point.
580 // External functions have no entry node, so keep nullptr.
581 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
582 const ICFGNode* icfgNode = funObjVar->isDeclaration() ? nullptr : pag->getICFG()->getFunEntryICFGNode(funObjVar);
583 DBOUT(DPAGBuild, outs() << "add vararg node " << iter->second << "\n");
584 pag->addVarargNode(iter->second,
585 funObjVar,
586 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
588 pag->varargFunObjSymMap[funObjVar] = iter->second;
589 }
590
592 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
593 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end(); ++iter)
594 {
595 DBOUT(DPAGBuild, outs() << "add address edges for constant node " << iter->second << "\n");
596 const Value* val = iter->first;
598 {
600 if(ptr!= pag->getBlkPtr() && ptr!= pag->getNullPtr())
601 {
603 addAddrEdge(iter->second, ptr);
604 }
605 }
606 }
607
609 && "not all node have been initialized!!!");
610
612 for (auto& fun: llvmModuleSet()->getFunctionSet())
613 {
614 for (const Argument& arg : fun->args())
615 {
616 const_cast<FunObjVar*>(llvmModuleSet()->getFunObjVar(fun))->addArgument(SVFUtil::cast<ArgValVar>(
618 }
619 }
620
621}
bool isDeclaration() const
u32_t getTotalSymNum() const
Statistics.
Definition IRGraph.h:200
FunObjVarToIDMapTy varargFunObjSymMap
vararg map
Definition IRGraph.h:86
FunObjVarToIDMapTy returnFunObjSymMap
return map
Definition IRGraph.h:85
FunToIDMapTy & retSyms()
Definition LLVMModule.h:274
FunToIDMapTy & varargSyms()
Definition LLVMModule.h:279
NodeID addNullPtrNode()
Add NullPtr PAGNode.
NodeID addBlackholePtrNode()
Definition SVFIR.h:844
NodeID addBlackholeObjNode()
Definition SVFIR.h:836
NodeID addVarargNode(NodeID i, const FunObjVar *val, const SVFType *type, const ICFGNode *n)
Add a unique vararg node for a procedure.
Definition SVFIR.h:796
NodeID addRetNode(NodeID i, const FunObjVar *callGraphNode, const SVFType *type, const ICFGNode *icn)
Add a unique return node for a procedure.
Definition SVFIR.h:790
NodeID addConstantObjNode()
Definition SVFIR.h:840
bool isConstantObjSym(const Value *val)
Check whether this value points-to a constant object.
Definition CppUtil.cpp:747
llvm::Argument Argument
Definition BasicTypes.h:152

◆ initialiseValVars()

void SVFIRBuilder::initialiseValVars ( )

Definition at line 452 of file SVFIRBuilder.cpp.

453{
454 // Iterate over all value symbols in the symbol table
455 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
456 llvmModuleSet()->valSyms().begin(); iter != llvmModuleSet()->valSyms().end();
457 ++iter)
458 {
459 // Debug output for adding value node
460 DBOUT(DPAGBuild, outs() << "add val node " << iter->second << "\n");
461
462 // Skip blackhole and null pointer symbols
463 if(iter->second == pag->blkPtrSymID() || iter->second == pag->nullPtrSymID())
464 continue;
465
466 const ICFGNode* icfgNode = nullptr;
467 auto llvmValue = iter->first;
468
469 // Check if the value is a function and get its call graph node
470 if (const Function* func = SVFUtil::dyn_cast<Function>(llvmValue))
471 {
472 pag->addFunValNode(iter->second, icfgNode, llvmModuleSet()->getFunObjVar(func), llvmModuleSet()->getSVFType(llvmValue->getType()));
473 }
474 else if (auto argval = SVFUtil::dyn_cast<Argument>(llvmValue))
475 {
476 // Formal params are defined at FunEntryICFGNode (where CallPE copies actual args).
477 // External (declaration-only) functions have no entry node, so keep nullptr.
478 const FunObjVar* funObj = llvmModuleSet()->getFunObjVar(argval->getParent());
479 const ICFGNode* entryNode = funObj->isDeclaration() ? nullptr : pag->getICFG()->getFunEntryICFGNode(funObj);
481 iter->second, argval->getArgNo(), entryNode,
482 funObj, llvmModuleSet()->getSVFType(llvmValue->getType()));
483 if (!argval->hasName())
484 pag->getGNode(iter->second)->setName("arg_" + std::to_string(argval->getArgNo()));
485 }
486 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
487 {
488 pag->addConstantFPValNode(iter->second, LLVMUtil::getDoubleValue(fpValue), icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
489 }
490 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
491 {
492 pag->addConstantIntValNode(iter->second, LLVMUtil::getIntegerValue(intValue), icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
493 }
494 else if (SVFUtil::isa<ConstantPointerNull>(llvmValue))
495 {
496 pag->addConstantNullPtrValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
497 }
498 else if (SVFUtil::isa<GlobalValue>(llvmValue))
499 {
500 // Global variables are defined at the global ICFG node.
502 llvmModuleSet()->getSVFType(llvmValue->getType()));
503 }
504 else if (SVFUtil::isa<ConstantData, ConstantExpr, MetadataAsValue, BlockAddress>(llvmValue))
505 {
506 pag->addConstantDataValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
507 }
508 else if (SVFUtil::isa<ConstantAggregate>(llvmValue))
509 {
510 pag->addConstantAggValNode(iter->second, icfgNode, llvmModuleSet()->getSVFType(llvmValue->getType()));
511 }
512 else if (SVFUtil::isa<BasicBlock>(llvmValue))
513 {
514 pag->addBasicBlockValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()));
515 }
516 else if (SVFUtil::isa<InlineAsm>(llvmValue) ||
517 SVFUtil::isa<DSOLocalEquivalent>(llvmValue) ||
518 SVFUtil::isa<NoCFIValue>(llvmValue))
519 {
520 pag->addAsmPCValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()));
521 }
522 else if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
523 {
525 pag->addIntrinsicValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()));
526 else
527 {
528 assert(llvmModuleSet()->hasICFGNode(inst) && "LLVM instruction is not associated with an ICFGNode");
529 icfgNode = llvmModuleSet()->getICFGNode(inst);
530 pag->addValNode(iter->second, llvmModuleSet()->getSVFType(llvmValue->getType()), icfgNode);
531 }
532 }
534 pag->getGNode(iter->second));
535 }
536}
NodeID blkPtrSymID() const
Definition IRGraph.h:178
NodeID nullPtrSymID() const
Definition IRGraph.h:183
ValueToIDMapTy & valSyms()
Definition LLVMModule.h:207
NodeID addGlobalValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *svfType)
Definition SVFIR.h:702
NodeID addBasicBlockValNode(NodeID i, const SVFType *type)
Definition SVFIR.h:852
NodeID addConstantDataValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:714
NodeID addIntrinsicValNode(NodeID i, const SVFType *type)
Definition SVFIR.h:848
NodeID addFunValNode(NodeID i, const ICFGNode *icfgNode, const FunObjVar *funObjVar, const SVFType *type)
Definition SVFIR.h:669
NodeID addConstantFPValNode(const NodeID i, double dval, const ICFGNode *icfgNode, const SVFType *type)
Definition SVFIR.h:682
NodeID addConstantAggValNode(const NodeID i, const ICFGNode *icfgNode, const SVFType *svfType)
Definition SVFIR.h:708
NodeID addValNode(NodeID i, const SVFType *type, const ICFGNode *icfgNode)
add node into SVFIR
Definition SVFIR.h:663
NodeID addAsmPCValNode(NodeID i, const SVFType *type)
Definition SVFIR.h:856
NodeID addArgValNode(NodeID i, u32_t argNo, const ICFGNode *icfgNode, const FunObjVar *callGraphNode, const SVFType *type)
Definition SVFIR.h:675
virtual void setName(const std::string &nameInfo)
Definition SVFValue.h:179
bool isIntrinsicInst(const Instruction *inst)
Return true if it is an intrinsic instruction.
Definition LLVMUtil.cpp:202

◆ initSVFBasicBlock()

void SVFIRBuilder::initSVFBasicBlock ( const Function func)

set exit block: exit basic block must have no successors and have a return instruction

Definition at line 213 of file SVFIRBuilder.cpp.

214{
216 for (Function::const_iterator bit = func->begin(), ebit = func->end(); bit != ebit; ++bit)
217 {
218 const BasicBlock* bb = &*bit;
221 {
224 }
226 {
229 }
230
232 if (svfbb->getSuccessors().empty())
233 {
235 {
237 SVFUtil::isa<ReturnInst>(bb->back())) &&
238 "last inst must be return inst");
239 svfFun->setExitBlock(svfbb);
240 }
241 }
242 }
243 // For no return functions, we set the last block as exit BB
244 // This ensures that each function that has definition must have an exit BB
245 if (svfFun->hasBasicBlock() && svfFun->exitBlock == nullptr)
246 {
247 SVFBasicBlock* retBB = const_cast<SVFBasicBlock*>(svfFun->back());
249 SVFUtil::isa<ReturnInst>(&func->back().back())) &&
250 "last inst must be return inst");
251 svfFun->setExitBlock(retBB);
252 }
253}
void addPredBasicBlock(const SVFBasicBlock *pred2)
void addSuccBasicBlock(const SVFBasicBlock *succ2)
bool basicBlockHasRetInst(const BasicBlock *bb)
Return true if the function has a return instruction.
Definition LLVMUtil.cpp:108
llvm::succ_const_iterator succ_const_iterator
LLVM Iterators.
Definition BasicTypes.h:283
llvm::const_pred_iterator const_pred_iterator
Definition BasicTypes.h:261

◆ llvmModuleSet()

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

Definition at line 519 of file SVFIRBuilder.h.

520 {
522 }

◆ processCE()

void SVFIRBuilder::processCE ( const Value val)
protected

Process constant expression.

Handle constant expression, and connect the gep edge

Definition at line 725 of file SVFIRBuilder.cpp.

726{
727 if (const Constant* ref = SVFUtil::dyn_cast<Constant>(val))
728 {
730 {
731 DBOUT(DPAGBuild, outs() << "handle gep constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
732 const Constant* opnd = gepce->getOperand(0);
733 // handle recursive constant express case (gep (bitcast (gep X 1)) 1)
735 auto &GEPOp = llvm::cast<llvm::GEPOperator>(*gepce);
736 Type *pType = GEPOp.getSourceElementType();
737 AccessPath ap(0, llvmModuleSet()->getSVFType(pType));
738 bool constGep = computeGepOffset(gepce, ap);
739 // must invoke pag methods here, otherwise it will be a dead recursion cycle
740 const Value* cval = getCurrentValue();
741 const SVFBasicBlock* cbb = getCurrentBB();
743 /*
744 * The gep edge created are like constexpr (same edge may appear at multiple callsites)
745 * so bb/inst of this edge may be rewritten several times, we treat it as global here.
746 */
749 }
750 else if (const ConstantExpr* castce = isCastConstantExpr(ref))
751 {
752 DBOUT(DPAGBuild, outs() << "handle cast constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
753 const Constant* opnd = castce->getOperand(0);
755 const Value* cval = getCurrentValue();
756 const SVFBasicBlock* cbb = getCurrentBB();
760 }
762 {
763 DBOUT(DPAGBuild, outs() << "handle select constant expression " << llvmModuleSet()->getSVFValue(ref)->toString() << "\n");
764 const Constant* src1 = selectce->getOperand(1);
765 const Constant* src2 = selectce->getOperand(2);
768 const Value* cval = getCurrentValue();
769 const SVFBasicBlock* cbb = getCurrentBB();
771 NodeID cond = llvmModuleSet()->getValueNode(selectce->getOperand(0));
777 }
778 // if we meet a int2ptr, then it points-to black hole
780 {
781 const Constant* opnd = int2Ptrce->getOperand(0);
783 const SVFBasicBlock* cbb = getCurrentBB();
784 const Value* cval = getCurrentValue();
788 }
790 {
791 const Constant* opnd = ptr2Intce->getOperand(0);
793 const SVFBasicBlock* cbb = getCurrentBB();
794 const Value* cval = getCurrentValue();
798 }
800 {
801 // we don't handle trunc and cmp instruction for now
802 const Value* cval = getCurrentValue();
803 const SVFBasicBlock* cbb = getCurrentBB();
808 }
809 else if (isBinaryConstantExpr(ref))
810 {
811 // we don't handle binary constant expression like add(x,y) now
812 const Value* cval = getCurrentValue();
813 const SVFBasicBlock* cbb = getCurrentBB();
818 }
819 else if (isUnaryConstantExpr(ref))
820 {
821 // we don't handle unary constant expression like fneg(x) now
822 const Value* cval = getCurrentValue();
823 const SVFBasicBlock* cbb = getCurrentBB();
828 }
829 else if (SVFUtil::isa<ConstantAggregate>(ref))
830 {
831 // we don't handle constant aggregate like constant vectors
832 }
833 else if (SVFUtil::isa<BlockAddress>(ref))
834 {
835 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
836 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
837 const Value* cval = getCurrentValue();
838 const SVFBasicBlock* cbb = getCurrentBB();
843 }
844 else
845 {
846 if(SVFUtil::isa<ConstantExpr>(val))
847 assert(false && "we don't handle all other constant expression for now!");
848 }
849 }
850}
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:290
const ConstantExpr * isInt2PtrConstantExpr(const Value *val)
Definition LLVMUtil.h:225
const ConstantExpr * isSelectConstantExpr(const Value *val)
Definition LLVMUtil.h:255
const ConstantExpr * isTruncConstantExpr(const Value *val)
Definition LLVMUtil.h:265
const ConstantExpr * isPtr2IntConstantExpr(const Value *val)
Definition LLVMUtil.h:235
const ConstantExpr * isUnaryConstantExpr(const Value *val)
Definition LLVMUtil.h:301
const ConstantExpr * isCastConstantExpr(const Value *val)
Definition LLVMUtil.h:245
const ConstantExpr * isGepConstantExpr(const Value *val)
Return corresponding constant expression, otherwise return nullptr.
Definition LLVMUtil.h:215
const ConstantExpr * isCmpConstantExpr(const Value *val)
Definition LLVMUtil.h:279
llvm::ConstantExpr ConstantExpr
Definition BasicTypes.h:124

◆ sanityCheck()

void SVFIRBuilder::sanityCheck ( )

Sanity check for SVFIR.

Definition at line 1650 of file SVFIRBuilder.cpp.

1651{
1652 for (SVFIR::iterator nIter = pag->begin(); nIter != pag->end(); ++nIter)
1653 {
1654 (void) pag->getGNode(nIter->first);
1655 //TODO::
1656 // (1) every source(root) node of a pag tree should be object node
1657 // if a node has no incoming edge, but has outgoing edges
1658 // then it has to be an object node.
1659 // (2) make sure every variable should be initialized
1660 // otherwise it causes the a null pointer, the aliasing relation may not be captured
1661 // when loading a pointer value should make sure
1662 // some value has been store into this pointer before
1663 // q = load p, some value should stored into p first like store w p;
1664 // (3) make sure PAGNode should not have a const expr value (pointer should have unique def)
1665 // (4) look closely into addComplexConsForExt, make sure program locations(e.g.,inst bb)
1666 // are set correctly for dummy gepval node
1667 // (5) reduce unnecessary copy edge (const casts) and ensure correctness.
1668 }
1669}
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

CallPE is placed at FunEntryICFGNode (phi-like merging of actual params)

CallPE is phi-like at FunEntryICFGNode. Collect it on each CallCFGEdge whose call site appears as an operand, so the edge knows which params are passed.

Definition at line 1738 of file SVFIRBuilder.cpp.

1739{
1741 return;
1742
1743 assert(curVal && "current Val is nullptr?");
1744 edge->setBB(curBB!=nullptr ? curBB : nullptr);
1746 ICFGNode* icfgNode = pag->getICFG()->getGlobalICFGNode();
1748 if (const Instruction* curInst = SVFUtil::dyn_cast<Instruction>(curVal))
1749 {
1750 const FunObjVar* srcFun = edge->getSrcNode()->getFunction();
1751 const FunObjVar* dstFun = edge->getDstNode()->getFunction();
1752 if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && !SVFUtil::isa<FunValVar>(edge->getSrcNode()) && !SVFUtil::isa<FunObjVar>(edge->getSrcNode()))
1753 {
1754 assert(srcFun==llvmMS->getFunObjVar(curInst->getFunction()) && "SrcNode of the PAGEdge not in the same function?");
1755 }
1756 if(dstFun!=nullptr && !SVFUtil::isa<CallPE>(edge) && !SVFUtil::isa<RetValPN>(edge->getDstNode()))
1757 {
1758 assert(dstFun==llvmMS->getFunObjVar(curInst->getFunction()) && "DstNode of the PAGEdge not in the same function?");
1759 }
1760
1762 if (!(SVFUtil::isa<GepStmt>(edge) && SVFUtil::isa<GepValVar>(edge->getDstNode())))
1763 assert(curBB && "instruction does not have a basic block??");
1764
1766 if(SVFUtil::isa<ReturnInst>(curInst))
1767 {
1768 icfgNode = pag->getICFG()->getFunExitICFGNode(llvmMS->getFunObjVar(curInst->getFunction()));
1769 }
1770 else if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1771 {
1773 icfgNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1774 }
1775 else if(SVFUtil::isa<RetPE>(edge))
1776 {
1777 icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(curInst));
1778 }
1779 else
1780 {
1781 icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(curInst));
1782 }
1783 }
1784 else if (const Argument* arg = SVFUtil::dyn_cast<Argument>(curVal))
1785 {
1787 icfgNode = pag->getICFG()->getFunEntryICFGNode(
1788 llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(arg->getParent())));
1789 }
1790 else if (SVFUtil::isa<Constant>(curVal) ||
1791 SVFUtil::isa<Function>(curVal) ||
1792 SVFUtil::isa<MetadataAsValue>(curVal))
1793 {
1794 if (!curBB)
1796 else
1797 {
1798 icfgNode = const_cast<ICFGNode*>(curBB->front());
1799 }
1800 }
1801 else
1802 {
1803 assert(false && "what else value can we have?");
1804 }
1805
1806 pag->addToSVFStmtList(icfgNode,edge);
1807 icfgNode->addSVFStmt(edge);
1808 if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1809 {
1812 FunEntryICFGNode* entryNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1813 for(u32_t i = 0; i < callPE->getOpVarNum(); i++)
1814 {
1815 CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getOpCallICFGNode(i));
1817 SVFUtil::cast<CallCFGEdge>(icfgEdge)->addCallPE(callPE);
1818 }
1819 }
1820 else if(const RetPE* retPE = SVFUtil::dyn_cast<RetPE>(edge))
1821 {
1822 RetICFGNode* retNode = const_cast<RetICFGNode*>(retPE->getCallSite()->getRetICFGNode());
1823 FunExitICFGNode* exitNode = const_cast<FunExitICFGNode*>(retPE->getFunExitICFGNode());
1825 SVFUtil::cast<RetCFGEdge>(edge)->addRetPE(retPE);
1826 }
1827}
const SVFBasicBlock * getEntryBlock() const
void addSVFStmt(const SVFStmt *edge)
Definition ICFGNode.h:110
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:276
const FunObjVar * getParent() const
const ICFGNode * front() const
static bool pagReadFromTXT()
Definition SVFIR.h:278
void addToSVFStmtList(ICFGNode *inst, SVFStmt *edge)
Add a SVFStmt into instruction map.
Definition SVFIR.h:326
void addGlobalPAGEdge(const SVFStmt *edge)
Add global PAGEdges (not in a procedure)
Definition SVFIR.h:878

◆ setCurrentLocation() [1/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 250 of file SVFIRBuilder.h.

251 {
252 curBB = (bb == nullptr? nullptr : llvmModuleSet()->getSVFBasicBlock(bb));
253 curVal = (val == nullptr ? nullptr: val);
254 }

◆ setCurrentLocation() [2/2]

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

Definition at line 255 of file SVFIRBuilder.h.

256 {
257 curBB = bb;
258 curVal = val;
259 }

◆ updateCallGraph()

void SVFIRBuilder::updateCallGraph ( CallGraph callgraph)

connect PAG edges based on callgraph

Definition at line 1615 of file SVFIRBuilder.cpp.

1616{
1617 CallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
1618 CallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
1619 for (; iter != eiter; iter++)
1620 {
1621 const CallICFGNode* callBlock = iter->first;
1622 const CallBase* callbase = SVFUtil::cast<CallBase>(llvmModuleSet()->getLLVMValue(callBlock));
1623 assert(callBlock->isIndirectCall() && "this is not an indirect call?");
1624 const CallGraph::FunctionSet& functions = iter->second;
1625 for (CallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
1626 {
1627 const Function* callee = SVFUtil::cast<Function>(llvmModuleSet()->getLLVMValue(*func_iter));
1628
1629 if (isExtCall(*func_iter))
1630 {
1631 setCurrentLocation(callee, callee->empty() ? nullptr : &callee->getEntryBlock());
1633 }
1634 else
1635 {
1636 setCurrentLocation(llvmModuleSet()->getLLVMValue(callBlock), callBlock->getBB());
1637 handleDirectCall(const_cast<CallBase*>(callbase), callee);
1638 }
1639 }
1640 }
1641
1642 // dump SVFIR
1644 pag->dump("svfir_final");
1645}
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition CallGraph.h:331
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
void handleDirectCall(CallBase *cs, const Function *F)
Handle direct call.
virtual void handleExtCall(const CallBase *cs, const Function *callee)
llvm::CallBase CallBase
Definition BasicTypes.h:153

◆ 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 1014 of file SVFIRBuilder.cpp.

1015{
1016
1017 // AllocaInst should always be a pointer type
1018 assert(SVFUtil::isa<PointerType>(inst.getType()));
1019
1020 DBOUT(DPAGBuild, outs() << "process alloca " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1021 NodeID dst = getValueNode(&inst);
1022
1023 NodeID src = getObjectNode(&inst);
1024
1025 addAddrWithStackArraySz(src, dst, inst);
1026
1027}
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 195 of file SVFIRBuilder.h.

196 {
198 }

◆ visitAtomicRMWInst()

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

Definition at line 199 of file SVFIRBuilder.h.

200 {
202 }

◆ visitBinaryOperator()

void SVFIRBuilder::visitBinaryOperator ( BinaryOperator inst)

Visit Binary Operator

Definition at line 1129 of file SVFIRBuilder.cpp.

1130{
1131 NodeID dst = getValueNode(&inst);
1132 assert(inst.getNumOperands() == 2 && "not two operands for BinaryOperator?");
1133 Value* op1 = inst.getOperand(0);
1135 Value* op2 = inst.getOperand(1);
1137 u32_t opcode = inst.getOpcode();
1138 addBinaryOPEdge(op1Node, op2Node, dst, opcode);
1139}
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 1308 of file SVFIRBuilder.cpp.

1309{
1310 NodeID brinst = getValueNode(&inst);
1311 NodeID cond;
1312 if (inst.isConditional())
1313 cond = getValueNode(inst.getCondition());
1314 else
1315 cond = pag->getNullPtr();
1316
1317 assert(inst.getNumSuccessors() <= 2 && "if/else has more than two branches?");
1318
1320 std::vector<const Instruction*> nextInsts;
1322 u32_t branchID = 0;
1323 for (const Instruction* succInst : nextInsts)
1324 {
1325 assert(branchID <= 1 && "if/else has more than two branches?");
1326 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1327 successors.push_back(std::make_pair(icfgNode, 1-branchID));
1328 branchID++;
1329 }
1330 addBranchStmt(brinst, cond, successors);
1332 if (inst.isConditional())
1333 {
1334 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1335 {
1336 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1337 {
1338 intraEdge->setConditionVar(pag->getGNode(cond));
1339 }
1340 }
1341 }
1342}
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:577

◆ visitCallBrInst()

void SVFIRBuilder::visitCallBrInst ( CallBrInst I)

Definition at line 1196 of file SVFIRBuilder.cpp.

1197{
1198 visitCallSite(&i);
1199}
void visitCallSite(CallBase *cs)

◆ visitCallInst()

void SVFIRBuilder::visitCallInst ( CallInst I)

Definition at line 1186 of file SVFIRBuilder.cpp.

1187{
1188 visitCallSite(&i);
1189}

◆ visitCallSite()

void SVFIRBuilder::visitCallSite ( CallBase cs)

Collect callsite arguments and returns

Definition at line 1204 of file SVFIRBuilder.cpp.

1205{
1206
1207 // skip llvm intrinsics
1208 if(isIntrinsicInst(cs))
1209 return;
1210
1212 outs() << "process callsite " << svfcall->valueOnlyToString() << "\n");
1213
1214
1215 CallICFGNode* callBlockNode = llvmModuleSet()->getCallICFGNode(cs);
1217
1218 pag->addCallSite(callBlockNode);
1219
1221 for (u32_t i = 0; i < cs->arg_size(); i++)
1223 callBlockNode,
1224 pag->getValVar(getValueNode(cs->getArgOperand(i))));
1225
1226 if(!cs->getType()->isVoidTy())
1228
1229 if (callBlockNode->isVirtualCall())
1230 {
1231 const Value* value = cppUtil::getVCallVtblPtr(cs);
1232 callBlockNode->setVtablePtr(pag->getGNode(getValueNode(value)));
1233 }
1234 if (const Function *callee = LLVMUtil::getCallee(cs))
1235 {
1237 {
1238 handleExtCall(cs, callee);
1239 }
1240 else
1241 {
1243 }
1244 }
1245 else
1246 {
1247 //If the callee was not identified as a function (null F), this is indirect.
1248 handleIndCall(cs);
1249 }
1250}
bool isVirtualCall() const
Definition ICFGNode.h:509
void setVtablePtr(SVFVar *v)
Definition ICFGNode.h:514
RetICFGNode * getRetICFGNode(const Instruction *cs)
get a return node
void handleIndCall(CallBase *cs)
Handle indirect call.
void addCallSiteArgs(CallICFGNode *callBlockNode, const ValVar *arg)
Add callsite arguments.
Definition SVFIR.h:640
void addCallSite(const CallICFGNode *call)
Add callsites.
Definition SVFIR.h:883
void addCallSiteRets(RetICFGNode *retBlockNode, const ValVar *arg)
Add callsite returns.
Definition SVFIR.h:646
const Function * getCallee(const CallBase *cs)
Definition LLVMUtil.h:97
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:612

◆ visitCastInst()

void SVFIRBuilder::visitCastInst ( CastInst I)

Definition at line 1115 of file SVFIRBuilder.cpp.

1116{
1117
1118 DBOUT(DPAGBuild, outs() << "process cast " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1119 NodeID dst = getValueNode(&inst);
1120
1121 const Value* opnd = inst.getOperand(0);
1122 NodeID src = getValueNode(opnd);
1123 addCopyEdge(src, dst, getCopyKind(&inst));
1124}
CopyStmt::CopyKind getCopyKind(const Value *val)

◆ visitCmpInst()

void SVFIRBuilder::visitCmpInst ( CmpInst inst)

Visit compare instruction

Definition at line 1157 of file SVFIRBuilder.cpp.

1158{
1159 NodeID dst = getValueNode(&inst);
1160 assert(inst.getNumOperands() == 2 && "not two operands for compare instruction?");
1161 Value* op1 = inst.getOperand(0);
1163 Value* op2 = inst.getOperand(1);
1165 u32_t predicate = inst.getPredicate();
1166 addCmpEdge(op1Node, op2Node, dst, predicate);
1167}
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 1298 of file SVFIRBuilder.cpp.

1299{
1300 NodeID dst = getValueNode(&inst);
1302}

◆ 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 1284 of file SVFIRBuilder.cpp.

1285{
1286 NodeID dst = getValueNode(&inst);
1288}

◆ visitFenceInst()

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

Definition at line 191 of file SVFIRBuilder.h.

192 {
194 }

◆ 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 1438 of file SVFIRBuilder.cpp.

1439{
1440 NodeID dst = getValueNode(&inst);
1441 for (u32_t i = 0; i < inst.getNumOperands(); i++)
1442 {
1443 Value* opnd = inst.getOperand(i);
1444 NodeID src = getValueNode(opnd);
1445 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1446 }
1447}

◆ visitGetElementPtrInst()

void SVFIRBuilder::visitGetElementPtrInst ( GetElementPtrInst inst)

Visit getelementptr instructions

Definition at line 1089 of file SVFIRBuilder.cpp.

1090{
1091
1092 NodeID dst = getValueNode(&inst);
1093 // GetElementPtrInst should always be a pointer or a vector contains pointers
1094 // for now we don't handle vector type here
1095 if(SVFUtil::isa<VectorType>(inst.getType()))
1096 {
1098 return;
1099 }
1100
1101 assert(SVFUtil::isa<PointerType>(inst.getType()));
1102
1103 DBOUT(DPAGBuild, outs() << "process gep " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1104
1105 NodeID src = getValueNode(inst.getPointerOperand());
1106
1107 AccessPath ap(0, llvmModuleSet()->getSVFType(inst.getSourceElementType()));
1108 bool constGep = computeGepOffset(&inst, ap);
1109 addGepEdge(src, dst, ap, constGep);
1110}

◆ visitGlobal()

void SVFIRBuilder::visitGlobal ( )
protected

Handle globals including (global variable and functions)

Visit global variables for building SVFIR

initialize global variable

initialize global functions

Definition at line 961 of file SVFIRBuilder.cpp.

962{
963
965 for (Module &M : llvmModuleSet()->getLLVMModules())
966 {
967 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
968 {
969 GlobalVariable *gvar = &*I;
972
975
976 if (gvar->hasInitializer())
977 {
978 Constant *C = gvar->getInitializer();
979 DBOUT(DPAGBuild, outs() << "add global var node " << llvmModuleSet()->getSVFValue(gvar)->toString() << "\n");
980 InitialGlobal(gvar, C, 0);
981 }
982 }
983
984
986 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
987 {
988 const Function* fun = &*I;
989 NodeID idx = getValueNode(fun);
990 NodeID obj = getObjectNode(fun);
991
992 DBOUT(DPAGBuild, outs() << "add global function node " << fun->getName().str() << "\n");
993 setCurrentLocation(fun, (SVFBasicBlock*) nullptr);
995 }
996
997 // 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.
998 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; I++)
999 {
1000 const GlobalAlias* alias = &*I;
1001 NodeID dst = llvmModuleSet()->getValueNode(alias);
1002 NodeID src = llvmModuleSet()->getValueNode(alias->getAliasee());
1003 processCE(alias->getAliasee());
1004 setCurrentLocation(alias, (SVFBasicBlock*) nullptr);
1005 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1006 }
1007 }
1008}
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:137
llvm::GlobalAlias GlobalAlias
Definition BasicTypes.h:135

◆ visitInsertElementInst()

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

Definition at line 171 of file SVFIRBuilder.h.

172 {
174 }

◆ visitInsertValueInst()

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

Definition at line 145 of file SVFIRBuilder.h.

146 {
148 }

◆ visitInstruction()

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

Provide base case for our instruction visit.

Definition at line 205 of file SVFIRBuilder.h.

206 {
207 // If a new instruction is added to LLVM that we don't handle.
208 // TODO: ignore here:
209 }

◆ visitInvokeInst()

void SVFIRBuilder::visitInvokeInst ( InvokeInst II)

Definition at line 1191 of file SVFIRBuilder.cpp.

1192{
1193 visitCallSite(&i);
1194}

◆ visitLandingPadInst()

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

Definition at line 179 of file SVFIRBuilder.h.

180 {
182 }

◆ visitLoadInst()

void SVFIRBuilder::visitLoadInst ( LoadInst I)

Definition at line 1057 of file SVFIRBuilder.cpp.

1058{
1059 DBOUT(DPAGBuild, outs() << "process load " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1060
1061 NodeID dst = getValueNode(&inst);
1062
1063 NodeID src = getValueNode(inst.getPointerOperand());
1064
1065 addLoadEdge(src, dst);
1066}

◆ visitPHINode()

void SVFIRBuilder::visitPHINode ( PHINode inst)

Visit phi instructions

Definition at line 1032 of file SVFIRBuilder.cpp.

1033{
1034
1035 DBOUT(DPAGBuild, outs() << "process phi " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1036
1037 NodeID dst = getValueNode(&inst);
1038
1039 for (u32_t i = 0; i < inst.getNumIncomingValues(); ++i)
1040 {
1041 const Value* val = inst.getIncomingValue(i);
1042 const Instruction* incomingInst = SVFUtil::dyn_cast<Instruction>(val);
1043 bool matched = (incomingInst == nullptr ||
1044 incomingInst->getFunction() == inst.getFunction());
1045 (void) matched; // Suppress warning of unused variable under release build
1046 assert(matched && "incomingInst's Function incorrect");
1047 const Instruction* predInst = &inst.getIncomingBlock(i)->back();
1048 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(predInst);
1049 NodeID src = getValueNode(val);
1050 addPhiStmt(dst,src,icfgNode);
1051 }
1052}
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 185 of file SVFIRBuilder.h.

186 {
187 }

◆ visitReturnInst()

void SVFIRBuilder::visitReturnInst ( ReturnInst inst)

Visit return instructions of a function

Definition at line 1255 of file SVFIRBuilder.cpp.

1256{
1257
1258 // ReturnInst itself should always not be a pointer type
1259 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1260
1261 DBOUT(DPAGBuild, outs() << "process return " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1262
1263 if(Value* src = inst.getReturnValue())
1264 {
1265 const FunObjVar *F = llvmModuleSet()->getFunObjVar(inst.getParent()->getParent());
1266
1268 NodeID vnS = getValueNode(src);
1269 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(&inst);
1270 //vnS may be null if src is a null ptr
1271 addPhiStmt(rnF,vnS,icfgNode);
1272 }
1273}

◆ visitSelectInst()

void SVFIRBuilder::visitSelectInst ( SelectInst inst)

Visit select instructions

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

Definition at line 1173 of file SVFIRBuilder.cpp.

1174{
1175
1176 DBOUT(DPAGBuild, outs() << "process select " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1177
1178 NodeID dst = getValueNode(&inst);
1179 NodeID src1 = getValueNode(inst.getTrueValue());
1180 NodeID src2 = getValueNode(inst.getFalseValue());
1181 NodeID cond = getValueNode(inst.getCondition());
1183 addSelectStmt(dst,src1,src2, cond);
1184}

◆ visitShuffleVectorInst()

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

Definition at line 175 of file SVFIRBuilder.h.

176 {
178 }

◆ visitStoreInst()

void SVFIRBuilder::visitStoreInst ( StoreInst inst)

Visit store instructions

Definition at line 1071 of file SVFIRBuilder.cpp.

1072{
1073 // StoreInst itself should always not be a pointer type
1074 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1075
1076 DBOUT(DPAGBuild, outs() << "process store " << llvmModuleSet()->getSVFValue(&inst)->toString() << " \n");
1077
1078 NodeID dst = getValueNode(inst.getPointerOperand());
1079
1080 NodeID src = getValueNode(inst.getValueOperand());
1081
1082 addStoreEdge(src, dst);
1083
1084}

◆ 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 1390 of file SVFIRBuilder.cpp.

1391{
1392 NodeID brinst = getValueNode(&inst);
1393 NodeID cond = getValueNode(inst.getCondition());
1394
1396 std::vector<const Instruction*> nextInsts;
1398 for (const Instruction* succInst : nextInsts)
1399 {
1401 const ConstantInt* condVal = inst.findCaseDest(const_cast<BasicBlock*>(succInst->getParent()));
1403 s64_t val = -1;
1404 if (condVal && condVal->getBitWidth() <= 64)
1406 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1407 successors.push_back(std::make_pair(icfgNode, val));
1408 }
1409 addBranchStmt(brinst, cond, successors);
1411 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1412 {
1413 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1414 {
1415 intraEdge->setConditionVar(pag->getGNode(cond));
1416 }
1417 }
1418}
signed long long s64_t
Definition GeneralType.h:50

◆ visitUnaryOperator()

void SVFIRBuilder::visitUnaryOperator ( UnaryOperator inst)

Visit Unary Operator

Definition at line 1144 of file SVFIRBuilder.cpp.

1145{
1146 NodeID dst = getValueNode(&inst);
1147 assert(inst.getNumOperands() == 1 && "not one operand for Unary instruction?");
1148 Value* opnd = inst.getOperand(0);
1149 NodeID src = getValueNode(opnd);
1150 u32_t opcode = inst.getOpcode();
1151 addUnaryOPEdge(src, dst, opcode);
1152}
void addUnaryOPEdge(NodeID src, NodeID dst, u32_t opcode)
Add Unary edge.

◆ visitUnreachableInst()

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

Definition at line 188 of file SVFIRBuilder.h.

189 {
190 }

◆ 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 1426 of file SVFIRBuilder.cpp.

1427{
1428 NodeID dst = getValueNode(&inst);
1429 Value* opnd = inst.getPointerOperand();
1430 NodeID src = getValueNode(opnd);
1431 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1432}

◆ visitVACopyInst()

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

Definition at line 160 of file SVFIRBuilder.h.

160{}

◆ visitVAEndInst()

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

Definition at line 161 of file SVFIRBuilder.h.

161{}

◆ visitVAStartInst()

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

Definition at line 162 of file SVFIRBuilder.h.

162{}

Friends And Related Symbol Documentation

◆ GraphDBSVFIRBuilder

friend class GraphDBSVFIRBuilder
friend

Definition at line 49 of file SVFIRBuilder.h.

Member Data Documentation

◆ curBB

const SVFBasicBlock* SVF::SVFIRBuilder::curBB
private

Current basic block during SVFIR construction when visiting the module.

Definition at line 53 of file SVFIRBuilder.h.

◆ curVal

const Value* SVF::SVFIRBuilder::curVal
private

Current Value during SVFIR construction when visiting the module.

Definition at line 54 of file SVFIRBuilder.h.

◆ pag

SVFIR* SVF::SVFIRBuilder::pag
private

Definition at line 52 of file SVFIRBuilder.h.


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