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 handleNondetArgStoreAtExtCall (const CallBase *cs, const CallICFGNode *callICFGNode)
 
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)
 
NodeID getDirectAccessFieldZeroValVar (const Value *ptr, const Type *accessTy)
 
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 305 of file SVFIRBuilder.h.

306 {
307 if(AddrStmt *edge = pag->addAddrStmt(src, dst))
308 {
310 return edge;
311 }
312 return nullptr;
313 }
void setCurrentBBAndValueForPAGEdge(PAGEdge *edge)
AddrStmt * addAddrStmt(NodeID src, NodeID dst)
Add an edge into SVFIR.
Definition SVFIR.cpp:64
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 327 of file SVFIRBuilder.h.

328 {
329 // get name of called function
330 AddrStmt* edge = addAddrEdge(src, dst);
331
332 llvm::Function* calledFunc = cs->getCalledFunction();
333 std::string functionName;
334 if (calledFunc)
335 {
336 functionName = calledFunc->getName().str();
337 }
338 else
339 {
340 SVFUtil::writeWrnMsg("not support indirect call to add AddrStmt.\n");
341 }
342 if (functionName == "malloc")
343 {
344 if (cs->arg_size() > 0)
345 {
346 const llvm::Value* val = cs->getArgOperand(0);
347 edge->addArrSize(pag->getGNode(getValueNode(val)));
348 }
349 }
350 // Check if the function called is 'calloc' and process its arguments.
351 // e.g. "%5 = call i8* @calloc(1, 8)", edge should add two SVFValue (1 and 8)
352 else if (functionName == "calloc")
353 {
354 if (cs->arg_size() > 1)
355 {
356 edge->addArrSize(
357 pag->getGNode(getValueNode(cs->getArgOperand(0))));
358 edge->addArrSize(
359 pag->getGNode(getValueNode(cs->getArgOperand(1))));
360 }
361 }
362 else
363 {
364 if (cs->arg_size() > 0)
365 {
366 const llvm::Value* val = cs->getArgOperand(0);
367 edge->addArrSize(pag->getGNode(getValueNode(val)));
368 }
369 }
370 return edge;
371 }
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.
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:72

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

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

◆ addBinaryOPEdge()

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

Add Copy edge.

Definition at line 440 of file SVFIRBuilder.h.

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

◆ addBlackHoleAddrEdge()

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

Definition at line 298 of file SVFIRBuilder.h.

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

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

◆ addCallEdge()

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

Add Call edge.

Definition at line 476 of file SVFIRBuilder.h.

477 {
478 if (CallPE* edge = pag->addCallPE(src, dst, cs, entry))
480 }
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:311

◆ addCmpEdge()

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

Add Copy edge.

Definition at line 434 of file SVFIRBuilder.h.

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

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

205{
206 assert(D && S);
208 if(!vnD || !vnS)
209 return;
210
211 std::vector<AccessPath> fields;
212
213 //Get the max possible size of the copy, unless it was provided.
214 std::vector<AccessPath> srcFields;
215 std::vector<AccessPath> dstFields;
218 if(srcFields.size() > dstFields.size())
219 fields = dstFields;
220 else
221 fields = srcFields;
222
224 u32_t sz = fields.size();
225
226 if (fields.size() == 1 && (LLVMUtil::isConstDataOrAggData(D) || LLVMUtil::isConstDataOrAggData(S)))
227 {
231 return;
232 }
233
240 const bool hasRemappedGlobalBase =
241 (dstFieldBase != D && SVFUtil::isa<GlobalVariable>(dstFieldBase)) ||
242 (srcFieldBase != S && SVFUtil::isa<GlobalVariable>(srcFieldBase));
243 const bool useByteLayoutMemcpy =
246 {
249 std::vector<MemcpyField> dstMemcpyFields = getMemcpyFields(D, dstLayoutType, dstSVFType);
250 std::vector<MemcpyField> srcMemcpyFields = getMemcpyFields(S, srcLayoutType, srcSVFType);
251 if (!dstMemcpyFields.empty() && !srcMemcpyFields.empty())
252 {
253 std::unordered_map<APOffset, MemcpyField> srcFieldsByByteOffset;
254 for (const auto& field : srcMemcpyFields)
256
257 const DataLayout& dl = llvmModuleSet()->getMainLLVMModule()->getDataLayout();
258 APOffset copyBytes = std::min<APOffset>(
259 static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(dstLayoutType))),
260 static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(srcLayoutType))));
261 if (szValue && SVFUtil::isa<ConstantInt>(szValue))
262 {
263 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
264 copyBytes = std::min(copyBytes, static_cast<APOffset>(szIntVal.first));
265 }
266
267 for (const auto& dstField : dstMemcpyFields)
268 {
269 if (dstField.byteOffset >= copyBytes)
270 continue;
271 auto it = srcFieldsByByteOffset.find(dstField.byteOffset);
272 if (it == srcFieldsByByteOffset.end())
273 continue;
274
275 NodeID dField = getGepValVar(dstFieldBase, dstField.accessPath, dstField.elementType);
276 NodeID sField = getGepValVar(srcFieldBase, it->second.accessPath, it->second.elementType);
280 }
281 return;
282 }
283 }
284
285 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
286 for (u32_t index = 0; index < sz; index++)
287 {
290 fields[index].getConstantStructFldIdx());
292 fields[index].getConstantStructFldIdx());
298 }
299}
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
Module * getMainLLVMModule() const
Definition LLVMModule.h:369
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:133
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
void addStoreEdge(NodeID src, NodeID dst)
Add Store edge.
void addLoadEdge(NodeID src, NodeID dst)
Add Load edge.
LLVMModuleSet * llvmModuleSet()
const Value * getBaseValueForExtArg(const Value *V)
Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst,...
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
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:83
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:376
bool isObject(const Value *ref)
Return true if this value refers to a object.
Definition LLVMUtil.cpp:60
llvm::DataLayout DataLayout
Definition BasicTypes.h:112
llvm::Type Type
Definition BasicTypes.h:87
u32_t NodeID
Definition GeneralType.h:56
s64_t APOffset
Definition GeneralType.h:60
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:86

◆ addCopyEdge()

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

Definition at line 373 of file SVFIRBuilder.h.

374 {
375 if(CopyStmt *edge = pag->addCopyStmt(src, dst, kind))
376 {
378 return edge;
379 }
380 return nullptr;
381 }
CopyStmt * addCopyStmt(NodeID src, NodeID dst, CopyStmt::CopyKind type)
Add Copy edge.
Definition SVFIR.cpp:86

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

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

◆ addGlobalBlackHoleAddrEdge()

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

Add global black hole Address edge.

Definition at line 271 of file SVFIRBuilder.h.

272 {
273 const Value* cval = getCurrentValue();
274 const SVFBasicBlock* cbb = getCurrentBB();
275 setCurrentLocation(int2Ptrce,(SVFBasicBlock*) nullptr);
278 }
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

◆ addLoadEdge()

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

Add Load edge.

Definition at line 458 of file SVFIRBuilder.h.

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

◆ addNormalGepEdge()

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

Add Offset(Gep) edge.

Definition at line 494 of file SVFIRBuilder.h.

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

◆ addNullPtrNode()

NodeID SVF::SVFIRBuilder::addNullPtrNode ( )
inlineprotected

Add NullPtr PAGNode.

Definition at line 281 of file SVFIRBuilder.h.

282 {
284 ConstantPointerNull* constNull = ConstantPointerNull::get(PointerType::getUnqual(cxt));
285 NodeID nullPtr = pag->addConstantNullPtrValNode(pag->getNullPtr(), nullptr, llvmModuleSet()->getSVFType(constNull->getType()));
287 setCurrentLocation(constNull, (SVFBasicBlock*) nullptr);
289 return nullPtr;
290 }
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:384
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 421 of file SVFIRBuilder.h.

422 {
424 if(PhiStmt *edge = pag->addPhiStmt(res,opnd,pred))
426 }
PhiStmt * addPhiStmt(NodeID res, NodeID opnd, const ICFGNode *pred)
Add phi node information.
Definition SVFIR.cpp:109

◆ addRetEdge()

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

Add Return edge.

Definition at line 482 of file SVFIRBuilder.h.

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

◆ addSelectStmt()

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

Add SelectStmt.

Definition at line 428 of file SVFIRBuilder.h.

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

◆ addStoreEdge()

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

Add Store edge.

Definition at line 464 of file SVFIRBuilder.h.

465 {
466 ICFGNode* node;
467 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
468 node = llvmModuleSet()->getICFGNode(
469 SVFUtil::cast<Instruction>(inst));
470 else
471 node = nullptr;
472 if (StoreStmt* edge = pag->addStoreStmt(src, dst, node))
474 }
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:288
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 506 of file SVFIRBuilder.h.

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

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

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

◆ addUnaryOPEdge()

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

Add Unary edge.

Definition at line 446 of file SVFIRBuilder.h.

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

◆ addVariantGepEdge()

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

Add Variant(Gep) edge.

Definition at line 500 of file SVFIRBuilder.h.

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

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

56{
57 double startTime = SVFStat::getClk(true);
58
59 DBOUT(DGENERAL, outs() << pasMsg("\t Building SVFIR ...\n"));
60
61 // If the SVFIR has been built before, then we return the unique SVFIR of the program
63 return pag;
64
65
67
70 pag->icfg = icfgbuilder.build();
71
79
80
81
84 std::vector<const FunObjVar*> funset;
85 for (const auto& item: llvmModuleSet()->getFunctionSet())
86 {
88 }
89 pag->callGraph = callGraphBuilder.buildSVFIRCallGraph(funset);
90
91 CHGraph* chg = new CHGraph();
93 chgbuilder.buildCHG();
94 pag->setCHG(chg);
95
97 for (Module& M : llvmModuleSet()->getLLVMModules())
98 {
99 for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
100 {
101 const Function& fun = *F;
102 const FunObjVar* svffun = llvmModuleSet()->getFunObjVar(&fun);
104 if(!fun.isDeclaration())
105 {
111 if (fun.doesNotReturn() == false &&
112 fun.getReturnType()->isVoidTy() == false)
113 {
116 }
117
120 for (Function::const_arg_iterator I = fun.arg_begin(), E = fun.arg_end();
121 I != E; ++I)
122 {
123 setCurrentLocation(&*I,&fun.getEntryBlock());
125 // if this is the function does not have caller (e.g. main)
126 // or a dead function, shall we create a black hole address edge for it?
127 // it is (1) too conservative, and (2) make FormalParmVFGNode defined at blackhole address PAGEdge.
128 // if(SVFUtil::ArgInNoCallerFunction(&*I)) {
129 // if(I->getType()->isPointerTy())
130 // addBlackHoleAddrEdge(argValNodeId);
131 //}
133 }
134 }
135 for (Function::const_iterator bit = fun.begin(), ebit = fun.end();
136 bit != ebit; ++bit)
137 {
138 const BasicBlock& bb = *bit;
139 for (BasicBlock::const_iterator it = bb.begin(), eit = bb.end();
140 it != eit; ++it)
141 {
142 const Instruction& inst = *it;
143 setCurrentLocation(&inst,&bb);
144 visit(const_cast<Instruction&>(inst));
145 }
146 }
147 }
148 }
149
150 sanityCheck();
151
153
155
156 // dump SVFIR
158 pag->dump("svfir_initial");
159
160 // print to command line of the SVFIR graph
161 if (Options::PAGPrint())
162 pag->print();
163
164 // dump ICFG
165 if (Options::DumpICFG())
166 pag->getICFG()->dump("icfg_initial");
167
169 {
172 }
173
174 // dump SVFIR as JSON
175 if (!Options::DumpJson().empty())
176 {
177 assert(false && "please implement SVFIRWriter::writeJsonToPath");
178 }
179
180 double endTime = SVFStat::getClk(true);
181 SVFStat::timeOfBuildingSVFIR = (endTime - startTime) / TIMEINTERVAL;
182
183 return pag;
184}
#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:321
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:325
virtual void build(ICFG *icfg)
Start from here.
NodeID getValueNode(const Value *V)
const FunObjVar * getFunObjVar(const Function *fun) const
Definition LLVMModule.h:270
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:236
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:649
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:734
static double getClk(bool mark=false)
Definition SVFStat.cpp:51
static double timeOfBuildingSVFIR
Definition SVFStat.h:97
const FunObjVar * getFunObjVar(const std::string &name)
Definition LLVMUtil.cpp:436
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:105
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 640 of file SVFIRBuilder.cpp.

641{
642 assert(V);
643
644 const llvm::GEPOperator *gepOp = SVFUtil::dyn_cast<const llvm::GEPOperator>(V);
645 DataLayout * dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
646 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gepOp->getPointerAddressSpace()),0,true);
647 if(gepOp && dataLayout && gepOp->accumulateConstantOffset(*dataLayout,byteOffset))
648 {
649 //s32_t bo = byteOffset.getSExtValue();
650 }
651
652 bool isConst = true;
653
654 bool prevPtrOperand = false;
656 gi != ge; ++gi)
657 {
658 const Type* gepTy = *gi;
660
661 assert((prevPtrOperand && svfGepTy->isPointerTy()) == false &&
662 "Expect no more than one gep operand to be of a pointer type");
663 if(!prevPtrOperand && svfGepTy->isPointerTy()) prevPtrOperand = true;
664 const Value* offsetVal = gi.getOperand();
665 assert(gepTy != offsetVal->getType() && "iteration and operand have the same type?");
666
667 const ArrayType* inferredPtrArrayTy = nullptr;
668 const SVFType* idxGepTy = svfGepTy;
669 if (svfGepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
670 {
671 const Type* baseObjType =
673 if (const auto* arrTy = SVFUtil::dyn_cast<ArrayType>(baseObjType))
674 {
675 if (arrTy->getElementType()->isPointerTy())
676 {
679 }
680 }
681 }
682
684
685 //The int value of the current index operand
686 const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(offsetVal);
687
688 // if Options::ModelConsts() is disabled. We will treat whole array as one,
689 // but we can distinguish different field of an array of struct, e.g. s[1].f1 is different from s[0].f2
690 if(const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(gepTy))
691 {
692 if (!Options::ModelArrays() && arrTy->getElementType()->isPointerTy())
693 continue;
694 if(!op || (arrTy->getArrayNumElements() <= (u32_t)LLVMUtil::getIntegerValue(op).first))
695 continue;
699 }
700 else if (const StructType *ST = SVFUtil::dyn_cast<StructType>(gepTy))
701 {
702 assert(op && "non-const offset accessing a struct");
703 // guard against negative or out-of-bounds struct indices
704 // (e.g. rust hashbrown bucket back-offset: gep { ... }, ptr %p, i64 -1)
705 // a negative i64 wraps to a huge uint64_t that overflows u32_t,
706 // creating an invalid field index that severs points-to tracking
708 if (rawIdx >= ST->getNumElements())
709 {
710 isConst = false;
711 continue;
712 }
716 }
717 else if (gepTy->isSingleValueType())
718 {
720 {
721 if (!op || (inferredPtrArrayTy->getArrayNumElements() <= (u32_t)LLVMUtil::getIntegerValue(op).first))
722 continue;
726 continue;
727 }
728 // If it's a non-constant offset access
729 // If its point-to target is struct or array, it's likely an array accessing (%result = gep %struct.A* %a, i32 %non-const-index)
730 // If its point-to target is single value (pointer arithmetic), then it's a variant gep (%result = gep i8* %p, i32 %non-const-index)
731 if(!op && gepTy->isPointerTy() && gepOp->getSourceElementType()->isSingleValueType())
732 {
733 isConst = false;
734 }
735
736 // The actual index
737 //s32_t idx = op->getSExtValue();
738
739 // For pointer arithmetic we ignore the byte offset
740 // consider using inferFieldIdxFromByteOffset(geopOp,dataLayout,ap,idx)?
741 // ap.setFldIdx(ap.getConstantFieldIdx() + inferFieldIdxFromByteOffset(geopOp,idx));
742 }
743 }
744 return isConst;
745}
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
ObjTypeInference * getTypeInference()
const Type * inferObjType(const Value *var)
get or infer the type of the object pointed by the value
static Option< bool > ModelArrays
Definition Options.h:182
SVFIR * getPAG() const
Return SVFIR.
static DataLayout * getDataLayout(Module *mod)
Definition LLVMUtil.h:317
llvm::ArrayType ArrayType
Definition BasicTypes.h:99
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:98
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 329 of file SVFIRBuilder.cpp.

330{
331 std::vector<FunObjVar*> funset;
332 // Iterate over all object symbols in the symbol table
333 for (const auto* fun: llvmModuleSet()->getFunctionSet())
334 {
335 u32_t id = llvmModuleSet()->objSyms()[fun];
336 // Debug output for adding object node
337 DBOUT(DPAGBuild, outs() << "add obj node " << id << "\n");
338
339 // Check if the value is a function and add a function object node
340 pag->addFunObjNode(id, pag->getObjTypeInfo(id), nullptr);
342
343 FunObjVar *funObjVar = SVFUtil::cast<FunObjVar>(pag->getGNode(id));
344 funset.push_back(funObjVar);
345
346 funObjVar->initFunObjVar(fun->isDeclaration(), LLVMUtil::isIntrinsicFun(fun), fun->hasAddressTaken(),
348 SVFUtil::cast<SVFFunctionType>(llvmModuleSet()->getSVFType(fun->getFunctionType())),
349 new SVFLoopAndDomInfo, nullptr, nullptr,
350 {}, nullptr);
351 BasicBlockGraph* bbGraph = new BasicBlockGraph();
352 funObjVar->setBasicBlockGraph(bbGraph);
353
354
355 for (const BasicBlock& bb : *fun)
356 {
357 llvmModuleSet()->addBasicBlock(funObjVar, &bb);
358 }
359
361 for (auto& bb: *funObjVar->bbGraph)
362 {
363 bb.second->setFun(funObjVar);
364 }
366 }
367
369}
#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:101
ValueToIDMapTy & objSyms()
Definition LLVMModule.h:215
void addBasicBlock(FunObjVar *fun, const BasicBlock *bb)
Definition LLVMModule.h:235
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:158
bool isIntrinsicFun(const Function *func)
Definition LLVMUtil.cpp:190
bool functionDoesNotRet(const Function *fun)
Definition LLVMUtil.cpp:123

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

1975{
1976 SVFVar* node = pag->getGNode(nodeId);
1979 if(geps.empty())
1980 return AccessPath(0);
1981
1982 assert(geps.size()==1 && "one node can only be connected by at most one gep edge!");
1983 SVFVar::iterator it = geps.begin();
1984 const GepStmt* gepEdge = SVFUtil::cast<GepStmt>(*it);
1985 if(gepEdge->isVariantFieldGep())
1986 return AccessPath(0);
1987 else
1988 return gepEdge->getAccessPath();
1989}
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 166 of file SVFIRExtAPI.cpp.

167{
168 assert(V);
169 const Value* value = getBaseValueForExtArg(V);
173 if(szValue && SVFUtil::isa<ConstantInt>(szValue))
174 {
175 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
176 numOfElems = (numOfElems > szIntVal.first) ? szIntVal.first : numOfElems;
177 }
178
180 for(u32_t ei = 0; ei < numOfElems; ei++)
181 {
183 // make a ConstantInt and create char for the content type due to byte-wise copy
184 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
185 if (!llvmModuleSet()->hasValueNode(offset))
186 {
188 builder.collectSym(offset);
190 pag->addConstantIntValNode(id, LLVMUtil::getIntegerValue(offset), nullptr, llvmModuleSet()->getSVFType(offset->getType()));
192 pag->getGNode(id));
193 }
194 ls.addOffsetVarAndGepTypePair(getPAG()->getValVar(llvmModuleSet()->getValueNode(offset)), nullptr);
195 fields.push_back(ls);
196 }
197 return objType;
198}
u32_t getNumOfFlattenElements(const SVFType *T)
Definition IRGraph.cpp:169
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 1605 of file SVFIRBuilder.cpp.

1606{
1607 const Value* value = stripAllCasts(V);
1608 assert(value && "null ptr?");
1610 [this](const GlobalVariable* glob, int64_t byteOffset) -> const Value*
1611 {
1612 if (!glob || !glob->hasInitializer())
1613 return nullptr;
1614
1615 auto* initializer = SVFUtil::dyn_cast<ConstantStruct>(glob->getInitializer());
1616 auto* structType = SVFUtil::dyn_cast<StructType>(glob->getValueType());
1617 if (!initializer || !structType)
1618 return nullptr;
1619
1620 DataLayout* dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
1621 const StructLayout* layout =
1622 dataLayout->getStructLayout(const_cast<StructType*>(structType));
1623 for (u32_t fieldIdx = 0; fieldIdx < initializer->getNumOperands(); ++fieldIdx)
1624 {
1625 if (layout->getElementOffset(fieldIdx) != static_cast<uint64_t>(byteOffset))
1626 continue;
1627 if (auto* ptrValue =
1628 SVFUtil::dyn_cast<llvm::GlobalVariable>(initializer->getOperand(fieldIdx)))
1629 return ptrValue;
1630 return nullptr;
1631 }
1632 return nullptr;
1633 };
1634
1635 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(value))
1636 {
1637 APOffset totalidx = 0;
1639 {
1640 if(const ConstantInt* op = SVFUtil::dyn_cast<ConstantInt>(gi.getOperand()))
1642 }
1643 if(totalidx == 0 && !SVFUtil::isa<StructType>(value->getType()))
1644 value = gep->getPointerOperand();
1645 }
1646 else if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(value))
1647 {
1648 const Value* loadP = load->getPointerOperand();
1649 if (const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(loadP))
1650 {
1651 DataLayout* dataLayout = getDataLayout(llvmModuleSet()->getMainLLVMModule());
1652 llvm::APInt byteOffset(dataLayout->getIndexSizeInBits(gep->getPointerAddressSpace()), 0, true);
1653 const bool hasByteOffset = dataLayout && gep->accumulateConstantOffset(*dataLayout, byteOffset);
1654
1655 const Value * pointer_operand = gep->getPointerOperand();
1656 if (auto *glob = SVFUtil::dyn_cast<GlobalVariable>(pointer_operand))
1657 {
1658 if (hasByteOffset)
1659 {
1660 if (const Value* ptrValue = getGlobalFieldFromByteOffset(glob, byteOffset.getSExtValue()))
1661 return ptrValue;
1662 }
1663 }
1664 else if (hasByteOffset && !byteOffset.isNegative() &&
1665 SVFUtil::isa<AllocaInst>(pointer_operand) && load->getType()->isPointerTy())
1666 {
1667 const u64_t offset = byteOffset.getZExtValue();
1668 const u64_t accessBytes = dataLayout->getPointerSize(gep->getPointerAddressSpace());
1669
1670 auto isCoveredByMemcpy = [offset, accessBytes](const CallBase* cs) -> bool
1671 {
1672 if (cs->arg_size() < 3)
1673 return false;
1674
1675 const auto* copySize = SVFUtil::dyn_cast<ConstantInt>(cs->getArgOperand(2));
1676 if (!copySize)
1677 return false;
1678
1679 const u64_t copyBytes = copySize->getZExtValue();
1681 };
1682
1683 auto hasInterveningWrite = [load](const Instruction* from) -> bool
1684 {
1685 if (from->getParent() != load->getParent() || !from->comesBefore(load))
1686 return true;
1687
1688 auto it = from->getIterator();
1689 const auto end = load->getIterator();
1690 while (++it != end)
1691 {
1692 if (it->mayWriteToMemory())
1693 return true;
1694 }
1695 return false;
1696 };
1697
1698 for (const auto& use : pointer_operand->users())
1699 {
1700 const auto* cs = SVFUtil::dyn_cast<CallBase>(use);
1701 if (!cs || cs->getParent() != load->getParent() ||
1702 cs->arg_size() < 1 ||
1703 stripAllCasts(cs->getArgOperand(0)) != pointer_operand)
1704 continue;
1705
1706 const Function* calledFun = cs->getCalledFunction();
1709 continue;
1710
1711 const Value* copiedFrom = getBaseValueForExtArg(cs->getArgOperand(1));
1712 if (const auto* copiedGlob = SVFUtil::dyn_cast<GlobalVariable>(copiedFrom))
1713 {
1714 if (const Value* ptrValue =
1715 getGlobalFieldFromByteOffset(copiedGlob, byteOffset.getSExtValue()))
1716 return ptrValue;
1717 }
1718 }
1719 }
1720 }
1721 }
1722
1723 return value;
1724}
const Value * stripAllCasts(const Value *val)
Strip off the all casts.
Definition LLVMUtil.cpp:250
bool isMemcpyExtFun(const Function *fun)
Definition LLVMUtil.cpp:389
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:137
llvm::CallBase CallBase
Definition BasicTypes.h:153
unsigned long long u64_t
Definition GeneralType.h:49
llvm::StructLayout StructLayout
Definition BasicTypes.h:109
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 383 of file SVFIRBuilder.h.

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

◆ getCurrentBB()

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

Definition at line 265 of file SVFIRBuilder.h.

266 {
267 return curBB;
268 }

◆ getCurrentValue()

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

Definition at line 261 of file SVFIRBuilder.h.

262 {
263 return curVal;
264 }

◆ getDirectAccessFieldZeroValVar()

NodeID SVFIRBuilder::getDirectAccessFieldZeroValVar ( const Value ptr,
const Type accessTy 
)
protected

Definition at line 1846 of file SVFIRBuilder.cpp.

1847{
1848 if (!Options::ModelArrays() || SVFUtil::isa<llvm::GEPOperator>(ptr))
1849 return 0;
1850
1851 const Type* objTy =
1853 const ArrayType* arrTy = SVFUtil::dyn_cast<ArrayType>(objTy);
1854 if (!arrTy || !arrTy->getElementType()->isPointerTy() ||
1855 arrTy->getElementType() != accessTy)
1856 return 0;
1857
1858 AccessPath ap(0, llvmModuleSet()->getSVFType(arrTy));
1859 return getGepValVar(ptr, ap, llvmModuleSet()->getSVFType(accessTy));
1860}

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

1799{
1800 NodeID base = getValueNode(val);
1802 if (gepval==UINT_MAX)
1803 {
1804 assert(((int) UINT_MAX)==-1 && "maximum limit of unsigned int is not -1?");
1805 /*
1806 * getGepValVar can only be called from two places:
1807 * 1. SVFIRBuilder::addComplexConsForExt to handle external calls
1808 * 2. SVFIRBuilder::getGlobalVarField to initialize global variable
1809 * so curVal can only be
1810 * 1. Instruction
1811 * 2. GlobalVariable
1812 */
1813 assert(
1814 (SVFUtil::isa<Instruction>(curVal) || SVFUtil::isa<GlobalVariable>(curVal)) && "curVal not an instruction or a globalvariable?");
1815
1816 // We assume every GepValNode and its GepEdge to the baseNode are unique across the whole program
1817 // We preserve the current BB information to restore it after creating the gepNode
1818 const Value* cval = getCurrentValue();
1819 const SVFBasicBlock* cbb = getCurrentBB();
1822 const ICFGNode* node = nullptr;
1823 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(curVal))
1824 {
1825 if (llvmmodule->hasICFGNode(inst))
1826 {
1827 node = llvmmodule->getICFGNode(inst);
1828 }
1829 }
1830 else if (SVFUtil::isa<GlobalVariable>(curVal))
1831 {
1832 // GEP on a global variable: the resulting GepValVar belongs to the global ICFG node.
1833 node = pag->getICFG()->getGlobalICFGNode();
1834 }
1836 NodeIDAllocator::get()->allocateValueId(),
1837 llvmmodule->getSVFType(PointerType::getUnqual(llvmmodule->getContext())), node);
1838 addGepEdge(base, gepNode, ap, true);
1840 return gepNode;
1841 }
1842 else
1843 return gepval;
1844}
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:614
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:486

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

885{
886
887 // if the global variable do not have any field needs to be initialized
888 if (offset == 0 && gvar->getInitializer()->getType()->isSingleValueType())
889 {
890 return getValueNode(gvar);
891 }
894 else
895 {
897 }
898}

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

1511{
1512
1513 assert(F);
1516 DBOUT(DPAGBuild, outs() << "handle direct call " << LLVMUtil::dumpValue(cs)
1517 << " callee " << F->getName().str() << "\n");
1518
1519 //Only handle the ret.val. if it's used as a ptr.
1521 //Does it actually return a ptr?
1522 if (!cs->getType()->isVoidTy())
1523 {
1527 }
1528 //Iterators for the actual and formal parameters
1529 u32_t itA = 0, ieA = cs->arg_size();
1530 Function::const_arg_iterator itF = F->arg_begin(), ieF = F->arg_end();
1531 //Go through the fixed parameters.
1532 DBOUT(DPAGBuild, outs() << " args:");
1533 for (; itF != ieF; ++itA, ++itF)
1534 {
1535 //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
1536 if (itA == ieA)
1537 {
1538 DBOUT(DPAGBuild, outs() << " !! not enough args\n");
1539 break;
1540 }
1541 const Value* AA = cs->getArgOperand(itA), *FA = &*itF; //current actual/formal arg
1542
1543 DBOUT(DPAGBuild, outs() << "process actual parm "
1544 << LLVMUtil::dumpValue(AA) << "\n");
1545
1550 }
1551 //Any remaining actual args must be varargs.
1552 if (F->isVarArg())
1553 {
1555 DBOUT(DPAGBuild, outs() << "\n varargs:");
1556 for (; itA != ieA; ++itA)
1557 {
1558 const Value* AA = cs->getArgOperand(itA);
1562 }
1563 }
1564 if(itA != ieA)
1565 {
1568 writeWrnMsg("too many args to non-vararg func.");
1569 writeWrnMsg("(" + callICFGNode->getSourceLoc() + ")");
1570
1571 }
1572}
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:605

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

339{
341
343 {
345 }
347 {
351 }
353 {
355 Value* arg = cs->getArgOperand(arg_pos);
356 if (cs->getArgOperand(arg_pos)->getType()->isPointerTy())
357 {
360 NodeID obj = pag->addDummyObjNode(llvmModuleSet()->getSVFType(cs->getArgOperand(arg_pos)->getType()));
361 if (vnArg && dummy && obj)
362 {
365 }
366 }
367 else
368 {
369 writeWrnMsg("Arg receiving new object must be pointer type");
370 }
371 }
373 {
374 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
375 // which copies n characters from memory area 'src' to memory area 'dest'.
376 if(callee->getName().find("iconv") != std::string::npos)
377 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
378 else if(callee->getName().find("bcopy") != std::string::npos)
379 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
380 if(cs->arg_size() == 3)
381 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
382 else
383 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
384 if(SVFUtil::isa<PointerType>(cs->getType()))
385 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
386 }
388 {
389 // Side-effects similar to memset(void *str, int c, size_t n)
390 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
391 std::vector<AccessPath> dstFields;
392 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
393 u32_t sz = dstFields.size();
394 //For each field (i), add store edge *(arg0 + i) = arg1
395 for (u32_t index = 0; index < sz; index++)
396 {
399 dstFields[index].getConstantStructFldIdx());
400 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
401 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
402 }
403 if(SVFUtil::isa<PointerType>(cs->getType()))
404 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
405 }
406 else if(callee->getName().compare("dlsym") == 0)
407 {
408 /*
409 Side-effects of void* dlsym( void* handle, const char* funName),
410 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
411 dlsym() example:
412 int main() {
413 // Open the shared library
414 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
415 // Find the function address
416 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
417 // Call the function
418 myFunctionPtr();
419 }
420 */
421 const Value* src = cs->getArgOperand(1);
422 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(src))
423 src = stripConstantCasts(gep->getPointerOperand());
424
425 auto getHookFn = [](const Value* src)->const Function*
426 {
427 if (!SVFUtil::isa<GlobalVariable>(src))
428 return nullptr;
429
430 auto *glob = SVFUtil::cast<GlobalVariable>(src);
431 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
432 return nullptr;
433
434 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
435 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
436 };
437
438 if (const Function *fn = getHookFn(src))
439 {
442 }
443 }
444 else if(callee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
445 {
446 // 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.
447 assert(cs->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
448
449 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
450 // Now we calculate the offset from base to vArg3
451 NodeID vnArg3 = llvmModuleSet()->getValueNode(cs->getArgOperand(3));
454
455 // We get all flattened fields of base
457
458 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
459 // Note that arg0 is aligned with "offset".
460 for (APOffset i = offset + 1; i <= offset + 3; ++i)
461 {
462 if((u32_t)i >= fields.size())
463 break;
464 const SVFType* elementType = pag->getFlatternedElemType(pag->getTypeLocSetsMap(vnArg3).first,
465 fields[i].getConstantStructFldIdx());
466 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
467 NodeID vnS = llvmModuleSet()->getValueNode(cs->getArgOperand(1));
468 if(vnD && vnS)
470 }
471 }
472
474 {
476 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
477 {
482 assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
483 if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
484 {
485 const ArgValVar* formalParm = forkedFun->getArg(0);
487 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
488 {
490 addThreadForkEdge(actualParm->getId(), formalParm->getId(), callICFGNode, entry);
491 }
492 }
493 }
494 else
495 {
500 }
504 }
505
507}
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)
virtual void handleNondetArgStoreAtExtCall(const CallBase *cs, const CallICFGNode *callICFGNode)
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:40
const Value * stripConstantCasts(const Value *val)
Strip off the constant casts.
Definition LLVMUtil.cpp:219
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:638
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:653
bool isMemsetExtFun(const Function *fun)
Definition LLVMUtil.cpp:395
u32_t getHeapAllocHoldingArgPosition(const Function *fun)
Definition LLVMUtil.cpp:401
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 1729 of file SVFIRBuilder.cpp.

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

◆ handleNondetArgStoreAtExtCall()

void SVFIRBuilder::handleNondetArgStoreAtExtCall ( const CallBase cs,
const CallICFGNode callICFGNode 
)
protectedvirtual

Definition at line 301 of file SVFIRExtAPI.cpp.

302{
304 const FunObjVar* extFun = callICFGNode->getCalledFunction();
305 if (extFun)
306 {
307 for (const std::string& annotation :
308 ExtAPI::getExtAPI()->getExtFuncAnnotations(extFun))
309 {
310 u32_t firstArg = 0;
312 continue;
313 if (firstArg >= cs->arg_size())
314 continue;
315
316 for (u32_t argIdx = firstArg; argIdx < cs->arg_size(); ++argIdx)
317 storeTopArgs.insert(argIdx);
318 }
319 }
320
322 {
323 const Value* arg = cs->getArgOperand(argIdx);
324 if (!arg->getType()->isPointerTy())
325 continue;
326
327 const Type* storedType =
329 NodeID src = pag->getBlkPtr();
330 NodeID dst = getValueNode(arg);
332 dst = fieldZero;
333 if (src && dst)
334 addStoreEdge(src, dst);
335 }
336}
NodeID getDirectAccessFieldZeroValVar(const Value *ptr, const Type *accessTy)

◆ inferFieldIdxFromByteOffset()

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

Infer field index from byteoffset.

Definition at line 629 of file SVFIRBuilder.cpp.

630{
631 return 0;
632}

◆ initDomTree()

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

Definition at line 257 of file SVFIRBuilder.cpp.

258{
259 if (fun->isDeclaration())
260 return;
261 //process and stored dt & df
264 df.analyze(dt);
266 PostDominatorTree pdt = PostDominatorTree(const_cast<Function&>(*fun));
267 SVFLoopAndDomInfo* ld = svffun->getLoopAndDomInfo();
268
270 for (DominanceFrontierBase::const_iterator dfIter = df.begin(), eDfIter = df.end(); dfIter != eDfIter; dfIter++)
271 {
272 const BasicBlock* keyBB = dfIter->first;
273#if LLVM_VERSION_MAJOR > 16
274 const llvm::SetVector<llvm::BasicBlock* >& domSet = dfIter->second;
275#else
276 const std::set<BasicBlock* >& domSet = dfIter->second;
277#endif
279 for (const BasicBlock* bbValue:domSet)
280 {
281 valueBasicBlocks.insert(llvmModuleSet()->getSVFBasicBlock(bbValue));
282 }
283 }
284 std::vector<const SVFBasicBlock*> reachableBBs;
285 LLVMUtil::getFunReachableBBs(fun, reachableBBs);
286 ld->setReachableBBs(reachableBBs);
287
288 for (Function::const_iterator bit = fun->begin(), beit = fun->end(); bit!=beit; ++bit)
289 {
290 const BasicBlock &bb = *bit;
292 if (DomTreeNode* dtNode = dt.getNode(&bb))
293 {
294 SVFLoopAndDomInfo::BBSet& bbSet = ld->getDomTreeMap()[svfBB];
295 for (const auto domBB : *dtNode)
296 {
297 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
298 bbSet.insert(domSVFBB);
299 }
300 }
301
302 if (DomTreeNode* pdtNode = pdt.getNode(&bb))
303 {
304 u32_t level = pdtNode->getLevel();
305 ld->getBBPDomLevel()[svfBB] = level;
306 BasicBlock* idomBB = pdtNode->getIDom()->getBlock();
308 ld->getBB2PIdom()[svfBB] = idom;
309
310 SVFLoopAndDomInfo::BBSet& bbSet = ld->getPostDomTreeMap()[svfBB];
311 for (const auto domBB : *pdtNode)
312 {
313 const auto* domSVFBB = llvmModuleSet()->getSVFBasicBlock(domBB->getBlock());
314 bbSet.insert(domSVFBB);
315 }
316 }
317
318 if (const Loop* loop = loopInfo.getLoopFor(&bb))
319 {
320 for (const BasicBlock* loopBlock : loop->getBlocks())
321 {
323 ld->addToBB2LoopMap(svfBB, loopbb);
324 }
325 }
326 }
327}
SVFBasicBlock * getSVFBasicBlock(const BasicBlock *bb)
Definition LLVMModule.h:301
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:75
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 186 of file SVFIRBuilder.cpp.

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

◆ InitialGlobal()

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

src should not point to anything yet

Definition at line 911 of file SVFIRBuilder.cpp.

913{
914 DBOUT(DPAGBuild, outs() << "global " << LLVMUtil::dumpValue(gvar)
915 << " constant initializer: "
916 << LLVMUtil::dumpValue(C) << "\n");
917 if (C->getType()->isSingleValueType())
918 {
919 NodeID src = getValueNode(C);
920 // get the field value if it is available, otherwise we create a dummy field node.
922 NodeID field = getGlobalVarField(gvar, offset, llvmModuleSet()->getSVFType(C->getType()));
923
924 if (SVFUtil::isa<GlobalVariable, Function>(C))
925 {
927 addStoreEdge(src, field);
928 }
929 else if (SVFUtil::isa<ConstantExpr>(C))
930 {
931 // add gep edge of C1 itself is a constant expression
932 processCE(C);
934 addStoreEdge(src, field);
935 }
936 else if (SVFUtil::isa<BlockAddress>(C))
937 {
938 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
939 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
940 processCE(C);
943 }
944 else
945 {
947 addStoreEdge(src, field);
949 if (C->getType()->isPtrOrPtrVectorTy() && src != pag->getNullPtr())
951 }
952 }
953 else if (SVFUtil::isa<ConstantArray, ConstantStruct>(C))
954 {
956 return;
957 for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
958 {
960 InitialGlobal(gvar, SVFUtil::cast<Constant>(C->getOperand(i)), offset + off);
961 }
962 }
963 else if(ConstantData* data = SVFUtil::dyn_cast<ConstantData>(C))
964 {
966 {
967 if(ConstantDataSequential* seq = SVFUtil::dyn_cast<ConstantDataSequential>(data))
968 {
969 for(u32_t i = 0; i < seq->getNumElements(); i++)
970 {
971 u32_t off = pag->getFlattenedElemIdx(llvmModuleSet()->getSVFType(C->getType()), i);
972 Constant* ct = seq->getElementAsConstant(i);
974 }
975 }
976 else
977 {
978 assert((SVFUtil::isa<ConstantAggregateZero, UndefValue>(data)) && "Single value type data should have been handled!");
979 }
980 }
981 }
982 else
983 {
984 //TODO:assert(SVFUtil::isa<ConstantVector>(C),"what else do we have");
985 }
986}
NodeID getConstantNode() const
Definition IRGraph.h:251
static Option< bool > ModelConsts
Definition Options.h:181
static const Option< bool > VtableInSVFIR
Definition Options.h:211
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 371 of file SVFIRBuilder.cpp.

372{
373 // Iterate over all object symbols in the symbol table
374 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
375 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end();
376 ++iter)
377 {
378 // Debug output for adding object node
379 DBOUT(DPAGBuild, outs() << "add obj node " << iter->second << "\n");
380
381 // Skip blackhole and constant symbols
382 if(iter->second == pag->blackholeSymID() || iter->second == pag->constantSymID())
383 continue;
384
385 // Get the LLVM value corresponding to the symbol
386 const Value* llvmValue = iter->first;
387
388 const ICFGNode* icfgNode = nullptr;
389 if (const Instruction* inst = SVFUtil::dyn_cast<Instruction>(llvmValue))
390 {
391 if(llvmModuleSet()->hasICFGNode(inst))
392 icfgNode = llvmModuleSet()->getICFGNode(inst);
393 }
394
395 // Check if the value is a function and add a function object node
396 if (SVFUtil::dyn_cast<Function>(llvmValue))
397 {
398 // already one
399 }
400 // Check if the value is a heap object and add a heap object node
402 {
403 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
404 pag->addHeapObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
405 }
406 // Check if the value is an alloca instruction and add a stack object node
408 {
409 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
410 pag->addStackObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
411 }
412 else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
413 {
414 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
416 }
417 else if (auto intValue = SVFUtil::dyn_cast<ConstantInt>(llvmValue))
418 {
419 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
421 }
422 else if (SVFUtil::isa<ConstantPointerNull>(llvmValue))
423 {
424 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
425 pag->addConstantNullPtrObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
426 }
427 else if (SVFUtil::isa<GlobalValue>(llvmValue))
428 {
429 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
430 pag->addGlobalObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
431 }
432 else if (SVFUtil::isa<ConstantData, ConstantExpr, MetadataAsValue, BlockAddress>(llvmValue))
433 {
434 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
435 pag->addConstantDataObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
436 }
437 else if (SVFUtil::isa<ConstantAggregate>(llvmValue))
438 {
439 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
440 pag->addConstantAggObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
441 }
442 // Add a generic object node for other types of values
443 else
444 {
445 NodeID id = llvmModuleSet()->getObjectNode(iter->first);
446 pag->addObjNode(iter->second, pag->getObjTypeInfo(id), icfgNode);
447 }
449 }
450
451}
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:55
bool isHeapObj(const Value *val)
Definition LLVMUtil.cpp:687
bool isStackObj(const Value *val)
Definition LLVMUtil.cpp:709

◆ initialiseNodes()

void SVFIRBuilder::initialiseNodes ( )

Initialize nodes and edges.

add address edges for constant nodes.

add argvalvar for svffunctions

Definition at line 539 of file SVFIRBuilder.cpp.

540{
541 DBOUT(DPAGBuild, outs() << "Initialise SVFIR Nodes ...\n");
542
543
548
551
552 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
553 llvmModuleSet()->retSyms().begin(); iter != llvmModuleSet()->retSyms().end();
554 ++iter)
555 {
556 const Value* llvmValue = iter->first;
557 // retSyms keys are Function*, not Instruction, so dyn_cast<Instruction> always fails.
558 // RetValPN represents the callee's return value, defined at FunExitICFGNode.
559 // External functions have no exit node, so keep nullptr.
560 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
561 const ICFGNode* icfgNode = funObjVar->isDeclaration() ? nullptr : pag->getICFG()->getFunExitICFGNode(funObjVar);
562 DBOUT(DPAGBuild, outs() << "add ret node " << iter->second << "\n");
563 pag->addRetNode(iter->second,
564 funObjVar,
565 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
567 pag->returnFunObjSymMap[funObjVar] = iter->second;
568 }
569
570 for (LLVMModuleSet::FunToIDMapTy::iterator iter =
571 llvmModuleSet()->varargSyms().begin();
572 iter != llvmModuleSet()->varargSyms().end(); ++iter)
573 {
574 const Value* llvmValue = iter->first;
575 // varargSyms keys are Function*, not Instruction.
576 // Variadic arguments are received at the function entry point.
577 // External functions have no entry node, so keep nullptr.
578 const FunObjVar* funObjVar = llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(llvmValue));
579 const ICFGNode* icfgNode = funObjVar->isDeclaration() ? nullptr : pag->getICFG()->getFunEntryICFGNode(funObjVar);
580 DBOUT(DPAGBuild, outs() << "add vararg node " << iter->second << "\n");
581 pag->addVarargNode(iter->second,
582 funObjVar,
583 llvmModuleSet()->getSVFType(iter->first->getType()), icfgNode);
585 pag->varargFunObjSymMap[funObjVar] = iter->second;
586 }
587
589 for (LLVMModuleSet::ValueToIDMapTy::iterator iter =
590 llvmModuleSet()->objSyms().begin(); iter != llvmModuleSet()->objSyms().end(); ++iter)
591 {
592 DBOUT(DPAGBuild, outs() << "add address edges for constant node " << iter->second << "\n");
593 const Value* val = iter->first;
595 {
597 if(ptr!= pag->getBlkPtr() && ptr!= pag->getNullPtr())
598 {
600 addAddrEdge(iter->second, ptr);
601 }
602 }
603 }
604
606 && "not all node have been initialized!!!");
607
609 for (auto& fun: llvmModuleSet()->getFunctionSet())
610 {
611 for (const Argument& arg : fun->args())
612 {
613 const_cast<FunObjVar*>(llvmModuleSet()->getFunObjVar(fun))->addArgument(SVFUtil::cast<ArgValVar>(
615 }
616 }
617
618}
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:277
FunToIDMapTy & varargSyms()
Definition LLVMModule.h:282
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 453 of file SVFIRBuilder.cpp.

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

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

215{
217 for (Function::const_iterator bit = func->begin(), ebit = func->end(); bit != ebit; ++bit)
218 {
219 const BasicBlock* bb = &*bit;
222 {
225 }
227 {
230 }
231
233 if (svfbb->getSuccessors().empty())
234 {
236 {
238 SVFUtil::isa<ReturnInst>(bb->back())) &&
239 "last inst must be return inst");
240 svfFun->setExitBlock(svfbb);
241 }
242 }
243 }
244 // For no return functions, we set the last block as exit BB
245 // This ensures that each function that has definition must have an exit BB
246 if (svfFun->hasBasicBlock() && svfFun->exitBlock == nullptr)
247 {
248 SVFBasicBlock* retBB = const_cast<SVFBasicBlock*>(svfFun->back());
250 SVFUtil::isa<ReturnInst>(&func->back().back())) &&
251 "last inst must be return inst");
252 svfFun->setExitBlock(retBB);
253 }
254}
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:109
llvm::succ_const_iterator succ_const_iterator
LLVM Iterators.
Definition BasicTypes.h:287
llvm::const_pred_iterator const_pred_iterator
Definition BasicTypes.h:265

◆ llvmModuleSet()

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

Definition at line 522 of file SVFIRBuilder.h.

523 {
525 }

◆ processCE()

void SVFIRBuilder::processCE ( const Value val)
protected

Process constant expression.

Handle constant expression, and connect the gep edge

Definition at line 750 of file SVFIRBuilder.cpp.

751{
752 if (const Constant* ref = SVFUtil::dyn_cast<Constant>(val))
753 {
755 {
756 DBOUT(DPAGBuild, outs() << "handle gep constant expression "
757 << LLVMUtil::dumpValue(ref) << "\n");
758 const Constant* opnd = gepce->getOperand(0);
759 // handle recursive constant express case (gep (bitcast (gep X 1)) 1)
761 auto &GEPOp = llvm::cast<llvm::GEPOperator>(*gepce);
762 Type *pType = GEPOp.getSourceElementType();
763 AccessPath ap(0, llvmModuleSet()->getSVFType(pType));
764 bool constGep = computeGepOffset(gepce, ap);
765 // must invoke pag methods here, otherwise it will be a dead recursion cycle
766 const Value* cval = getCurrentValue();
767 const SVFBasicBlock* cbb = getCurrentBB();
769 /*
770 * The gep edge created are like constexpr (same edge may appear at multiple callsites)
771 * so bb/inst of this edge may be rewritten several times, we treat it as global here.
772 */
775 }
776 else if (const ConstantExpr* castce = isCastConstantExpr(ref))
777 {
778 DBOUT(DPAGBuild, outs() << "handle cast constant expression "
779 << LLVMUtil::dumpValue(ref) << "\n");
780 const Constant* opnd = castce->getOperand(0);
782 const Value* cval = getCurrentValue();
783 const SVFBasicBlock* cbb = getCurrentBB();
787 }
789 {
790 DBOUT(DPAGBuild, outs() << "handle select constant expression "
791 << LLVMUtil::dumpValue(ref) << "\n");
792 const Constant* src1 = selectce->getOperand(1);
793 const Constant* src2 = selectce->getOperand(2);
796 const Value* cval = getCurrentValue();
797 const SVFBasicBlock* cbb = getCurrentBB();
799 NodeID cond = llvmModuleSet()->getValueNode(selectce->getOperand(0));
805 }
806 // if we meet a int2ptr, then it points-to black hole
808 {
809 const Constant* opnd = int2Ptrce->getOperand(0);
811 const SVFBasicBlock* cbb = getCurrentBB();
812 const Value* cval = getCurrentValue();
816 }
818 {
819 const Constant* opnd = ptr2Intce->getOperand(0);
821 const SVFBasicBlock* cbb = getCurrentBB();
822 const Value* cval = getCurrentValue();
826 }
828 {
829 // we don't handle trunc and cmp instruction for now
830 const Value* cval = getCurrentValue();
831 const SVFBasicBlock* cbb = getCurrentBB();
836 }
837 else if (isBinaryConstantExpr(ref))
838 {
839 // we don't handle binary constant expression like add(x,y) now
840 const Value* cval = getCurrentValue();
841 const SVFBasicBlock* cbb = getCurrentBB();
846 }
847 else if (isUnaryConstantExpr(ref))
848 {
849 // we don't handle unary constant expression like fneg(x) now
850 const Value* cval = getCurrentValue();
851 const SVFBasicBlock* cbb = getCurrentBB();
856 }
857 else if (SVFUtil::isa<ConstantAggregate>(ref))
858 {
859 // we don't handle constant aggregate like constant vectors
860 }
861 else if (SVFUtil::isa<BlockAddress>(ref))
862 {
863 // blockaddress instruction (e.g. i8* blockaddress(@run_vm, %182))
864 // is treated as constant data object for now, see LLVMUtil.h:397, SymbolTableInfo.cpp:674 and SVFIRBuilder.cpp:183-194
865 const Value* cval = getCurrentValue();
866 const SVFBasicBlock* cbb = getCurrentBB();
871 }
872 else
873 {
874 if(SVFUtil::isa<ConstantExpr>(val))
875 assert(false && "we don't handle all other constant expression for now!");
876 }
877 }
878}
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:294
const ConstantExpr * isInt2PtrConstantExpr(const Value *val)
Definition LLVMUtil.h:229
const ConstantExpr * isSelectConstantExpr(const Value *val)
Definition LLVMUtil.h:259
const ConstantExpr * isTruncConstantExpr(const Value *val)
Definition LLVMUtil.h:269
const ConstantExpr * isPtr2IntConstantExpr(const Value *val)
Definition LLVMUtil.h:239
const ConstantExpr * isUnaryConstantExpr(const Value *val)
Definition LLVMUtil.h:305
const ConstantExpr * isCastConstantExpr(const Value *val)
Definition LLVMUtil.h:249
const ConstantExpr * isGepConstantExpr(const Value *val)
Return corresponding constant expression, otherwise return nullptr.
Definition LLVMUtil.h:219
const ConstantExpr * isCmpConstantExpr(const Value *val)
Definition LLVMUtil.h:283
llvm::ConstantExpr ConstantExpr
Definition BasicTypes.h:124

◆ sanityCheck()

void SVFIRBuilder::sanityCheck ( )

Sanity check for SVFIR.

Definition at line 1772 of file SVFIRBuilder.cpp.

1773{
1774 for (SVFIR::iterator nIter = pag->begin(); nIter != pag->end(); ++nIter)
1775 {
1776 (void) pag->getGNode(nIter->first);
1777 //TODO::
1778 // (1) every source(root) node of a pag tree should be object node
1779 // if a node has no incoming edge, but has outgoing edges
1780 // then it has to be an object node.
1781 // (2) make sure every variable should be initialized
1782 // otherwise it causes the a null pointer, the aliasing relation may not be captured
1783 // when loading a pointer value should make sure
1784 // some value has been store into this pointer before
1785 // q = load p, some value should stored into p first like store w p;
1786 // (3) make sure PAGNode should not have a const expr value (pointer should have unique def)
1787 // (4) look closely into addComplexConsForExt, make sure program locations(e.g.,inst bb)
1788 // are set correctly for dummy gepval node
1789 // (5) reduce unnecessary copy edge (const casts) and ensure correctness.
1790 }
1791}
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 1876 of file SVFIRBuilder.cpp.

1877{
1879 return;
1880
1881 assert(curVal && "current Val is nullptr?");
1882 edge->setBB(curBB!=nullptr ? curBB : nullptr);
1884 ICFGNode* icfgNode = pag->getICFG()->getGlobalICFGNode();
1886 if (const Instruction* curInst = SVFUtil::dyn_cast<Instruction>(curVal))
1887 {
1888 const FunObjVar* srcFun = edge->getSrcNode()->getFunction();
1889 const FunObjVar* dstFun = edge->getDstNode()->getFunction();
1890 if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && !SVFUtil::isa<FunValVar>(edge->getSrcNode()) && !SVFUtil::isa<FunObjVar>(edge->getSrcNode()))
1891 {
1892 assert(srcFun==llvmMS->getFunObjVar(curInst->getFunction()) && "SrcNode of the PAGEdge not in the same function?");
1893 }
1894 if(dstFun!=nullptr && !SVFUtil::isa<CallPE>(edge) && !SVFUtil::isa<RetValPN>(edge->getDstNode()))
1895 {
1896 assert(dstFun==llvmMS->getFunObjVar(curInst->getFunction()) && "DstNode of the PAGEdge not in the same function?");
1897 }
1898
1900 if (!(SVFUtil::isa<GepStmt>(edge) && SVFUtil::isa<GepValVar>(edge->getDstNode())))
1901 assert(curBB && "instruction does not have a basic block??");
1902
1904 if(SVFUtil::isa<ReturnInst>(curInst))
1905 {
1906 icfgNode = pag->getICFG()->getFunExitICFGNode(llvmMS->getFunObjVar(curInst->getFunction()));
1907 }
1908 else if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1909 {
1911 icfgNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1912 }
1913 else if(SVFUtil::isa<RetPE>(edge))
1914 {
1915 icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(curInst));
1916 }
1917 else
1918 {
1919 icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(curInst));
1920 }
1921 }
1922 else if (const Argument* arg = SVFUtil::dyn_cast<Argument>(curVal))
1923 {
1925 icfgNode = pag->getICFG()->getFunEntryICFGNode(
1926 llvmModuleSet()->getFunObjVar(SVFUtil::cast<Function>(arg->getParent())));
1927 }
1928 else if (SVFUtil::isa<Constant>(curVal) ||
1929 SVFUtil::isa<Function>(curVal) ||
1930 SVFUtil::isa<MetadataAsValue>(curVal))
1931 {
1932 if (!curBB)
1934 else
1935 {
1936 icfgNode = const_cast<ICFGNode*>(curBB->front());
1937 }
1938 }
1939 else
1940 {
1941 assert(false && "what else value can we have?");
1942 }
1943
1944 pag->addToSVFStmtList(icfgNode,edge);
1945 icfgNode->addSVFStmt(edge);
1946 if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1947 {
1950 FunEntryICFGNode* entryNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1951 for(u32_t i = 0; i < callPE->getOpVarNum(); i++)
1952 {
1953 CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getOpCallICFGNode(i));
1955 SVFUtil::cast<CallCFGEdge>(icfgEdge)->addCallPE(callPE);
1956 }
1957 }
1958 else if(const RetPE* retPE = SVFUtil::dyn_cast<RetPE>(edge))
1959 {
1960 RetICFGNode* retNode = const_cast<RetICFGNode*>(retPE->getCallSite()->getRetICFGNode());
1961 FunExitICFGNode* exitNode = const_cast<FunExitICFGNode*>(retPE->getFunExitICFGNode());
1963 SVFUtil::cast<RetCFGEdge>(edge)->addRetPE(retPE);
1964 }
1965}
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:874

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

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

◆ setCurrentLocation() [2/2]

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

Definition at line 256 of file SVFIRBuilder.h.

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

◆ updateCallGraph()

void SVFIRBuilder::updateCallGraph ( CallGraph callgraph)

connect PAG edges based on callgraph

Definition at line 1737 of file SVFIRBuilder.cpp.

1738{
1739 CallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
1740 CallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
1741 for (; iter != eiter; iter++)
1742 {
1743 const CallICFGNode* callBlock = iter->first;
1744 const CallBase* callbase = SVFUtil::cast<CallBase>(llvmModuleSet()->getLLVMValue(callBlock));
1745 assert(callBlock->isIndirectCall() && "this is not an indirect call?");
1746 const CallGraph::FunctionSet& functions = iter->second;
1747 for (CallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
1748 {
1749 const Function* callee = SVFUtil::cast<Function>(llvmModuleSet()->getLLVMValue(*func_iter));
1750
1751 if (isExtCall(*func_iter))
1752 {
1753 setCurrentLocation(callee, callee->empty() ? nullptr : &callee->getEntryBlock());
1755 }
1756 else
1757 {
1758 setCurrentLocation(llvmModuleSet()->getLLVMValue(callBlock), callBlock->getBB());
1759 handleDirectCall(const_cast<CallBase*>(callbase), callee);
1760 }
1761 }
1762 }
1763
1764 // dump SVFIR
1766 pag->dump("svfir_final");
1767}
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)

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

1046{
1047
1048 // AllocaInst should always be a pointer type
1049 assert(SVFUtil::isa<PointerType>(inst.getType()));
1050
1052 outs() << "process alloca " << LLVMUtil::dumpValue(&inst) << "\n");
1053 NodeID dst = getValueNode(&inst);
1054
1055 NodeID src = getObjectNode(&inst);
1056
1057 addAddrWithStackArraySz(src, dst, inst);
1058
1059}
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 1185 of file SVFIRBuilder.cpp.

1186{
1187 NodeID dst = getValueNode(&inst);
1188 assert(inst.getNumOperands() == 2 && "not two operands for BinaryOperator?");
1189 Value* op1 = inst.getOperand(0);
1191 Value* op2 = inst.getOperand(1);
1193 u32_t opcode = inst.getOpcode();
1194 addBinaryOPEdge(op1Node, op2Node, dst, opcode);
1195}
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 1365 of file SVFIRBuilder.cpp.

1366{
1367 NodeID brinst = getValueNode(&inst);
1368 NodeID cond;
1369 if (inst.isConditional())
1370 cond = getValueNode(inst.getCondition());
1371 else
1372 cond = pag->getNullPtr();
1373
1374 assert(inst.getNumSuccessors() <= 2 && "if/else has more than two branches?");
1375
1377 std::vector<const Instruction*> nextInsts;
1379 u32_t branchID = 0;
1380 for (const Instruction* succInst : nextInsts)
1381 {
1382 assert(branchID <= 1 && "if/else has more than two branches?");
1383 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1384 successors.push_back(std::make_pair(icfgNode, 1-branchID));
1385 branchID++;
1386 }
1387 addBranchStmt(brinst, cond, successors);
1389 if (inst.isConditional())
1390 {
1391 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1392 {
1393 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1394 {
1395 intraEdge->setConditionVar(pag->getGNode(cond));
1396 }
1397 }
1398 }
1399}
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:578

◆ visitCallBrInst()

void SVFIRBuilder::visitCallBrInst ( CallBrInst I)

Definition at line 1253 of file SVFIRBuilder.cpp.

1254{
1255 visitCallSite(&i);
1256}
void visitCallSite(CallBase *cs)

◆ visitCallInst()

void SVFIRBuilder::visitCallInst ( CallInst I)

Definition at line 1243 of file SVFIRBuilder.cpp.

1244{
1245 visitCallSite(&i);
1246}

◆ visitCallSite()

void SVFIRBuilder::visitCallSite ( CallBase cs)

Collect callsite arguments and returns

Definition at line 1261 of file SVFIRBuilder.cpp.

1262{
1263
1264 // skip llvm intrinsics
1265 if(isIntrinsicInst(cs))
1266 return;
1267
1269 outs() << "process callsite " << LLVMUtil::dumpValue(cs) << "\n");
1270
1271 CallICFGNode* callBlockNode = llvmModuleSet()->getCallICFGNode(cs);
1273
1274 pag->addCallSite(callBlockNode);
1275
1277 for (u32_t i = 0; i < cs->arg_size(); i++)
1279 callBlockNode,
1280 pag->getValVar(getValueNode(cs->getArgOperand(i))));
1281
1282 if(!cs->getType()->isVoidTy())
1284
1285 if (callBlockNode->isVirtualCall())
1286 {
1287 const Value* value = cppUtil::getVCallVtblPtr(cs);
1288 callBlockNode->setVtablePtr(pag->getGNode(getValueNode(value)));
1289 }
1290 if (const Function *callee = LLVMUtil::getCallee(cs))
1291 {
1293 {
1294 handleExtCall(cs, callee);
1295 }
1296 else
1297 {
1299 }
1300 }
1301 else
1302 {
1303 //If the callee was not identified as a function (null F), this is indirect.
1304 handleIndCall(cs);
1305 }
1306}
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:879
void addCallSiteRets(RetICFGNode *retBlockNode, const ValVar *arg)
Add callsite returns.
Definition SVFIR.h:646
const Function * getCallee(const CallBase *cs)
Definition LLVMUtil.h:98
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:612

◆ visitCastInst()

void SVFIRBuilder::visitCastInst ( CastInst I)

Definition at line 1170 of file SVFIRBuilder.cpp.

1171{
1172
1174 outs() << "process cast " << LLVMUtil::dumpValue(&inst) << "\n");
1175 NodeID dst = getValueNode(&inst);
1176
1177 const Value* opnd = inst.getOperand(0);
1178 NodeID src = getValueNode(opnd);
1179 addCopyEdge(src, dst, getCopyKind(&inst));
1180}
CopyStmt::CopyKind getCopyKind(const Value *val)

◆ visitCmpInst()

void SVFIRBuilder::visitCmpInst ( CmpInst inst)

Visit compare instruction

Definition at line 1213 of file SVFIRBuilder.cpp.

1214{
1215 NodeID dst = getValueNode(&inst);
1216 assert(inst.getNumOperands() == 2 && "not two operands for compare instruction?");
1217 Value* op1 = inst.getOperand(0);
1219 Value* op2 = inst.getOperand(1);
1221 u32_t predicate = inst.getPredicate();
1222 addCmpEdge(op1Node, op2Node, dst, predicate);
1223}
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 1355 of file SVFIRBuilder.cpp.

1356{
1357 NodeID dst = getValueNode(&inst);
1359}

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

1342{
1343 NodeID dst = getValueNode(&inst);
1345}

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

1496{
1497 NodeID dst = getValueNode(&inst);
1498 for (u32_t i = 0; i < inst.getNumOperands(); i++)
1499 {
1500 Value* opnd = inst.getOperand(i);
1501 NodeID src = getValueNode(opnd);
1502 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1503 }
1504}

◆ visitGetElementPtrInst()

void SVFIRBuilder::visitGetElementPtrInst ( GetElementPtrInst inst)

Visit getelementptr instructions

Definition at line 1130 of file SVFIRBuilder.cpp.

1131{
1132
1133 NodeID dst = getValueNode(&inst);
1134 // GetElementPtrInst should always be a pointer or a vector contains pointers
1135 // for now we don't handle vector type here
1136 if(SVFUtil::isa<VectorType>(inst.getType()))
1137 {
1139 return;
1140 }
1141
1142 assert(SVFUtil::isa<PointerType>(inst.getType()));
1143
1145 outs() << "process gep " << LLVMUtil::dumpValue(&inst) << "\n");
1146
1147 NodeID src = getValueNode(inst.getPointerOperand());
1148
1149 AccessPath ap(0, llvmModuleSet()->getSVFType(inst.getSourceElementType()));
1150 bool constGep = computeGepOffset(&inst, ap);
1151 if (constGep && ap.getConstantStructFldIdx() == 0 && !Options::ModelArrays())
1152 {
1153 const Type* baseObjType =
1154 LLVMModuleSet::getLLVMModuleSet()->getTypeInference()->inferObjType(inst.getPointerOperand());
1155 if (const auto* arrTy = SVFUtil::dyn_cast<ArrayType>(baseObjType))
1156 {
1157 if (arrTy->getElementType()->isPointerTy())
1158 {
1159 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1160 return;
1161 }
1162 }
1163 }
1164 addGepEdge(src, dst, ap, constGep);
1165}

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

992{
993
995 for (Module &M : llvmModuleSet()->getLLVMModules())
996 {
997 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
998 {
999 GlobalVariable *gvar = &*I;
1002
1005
1006 if (gvar->hasInitializer())
1007 {
1008 Constant *C = gvar->getInitializer();
1009 DBOUT(DPAGBuild, outs() << "add global var node "
1010 << LLVMUtil::dumpValue(gvar) << "\n");
1011 InitialGlobal(gvar, C, 0);
1012 }
1013 }
1014
1015
1017 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
1018 {
1019 const Function* fun = &*I;
1020 NodeID idx = getValueNode(fun);
1021 NodeID obj = getObjectNode(fun);
1022
1023 DBOUT(DPAGBuild, outs() << "add global function node " << fun->getName().str() << "\n");
1024 setCurrentLocation(fun, (SVFBasicBlock*) nullptr);
1026 }
1027
1028 // 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.
1029 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; I++)
1030 {
1031 const GlobalAlias* alias = &*I;
1032 NodeID dst = llvmModuleSet()->getValueNode(alias);
1033 NodeID src = llvmModuleSet()->getValueNode(alias->getAliasee());
1034 processCE(alias->getAliasee());
1035 setCurrentLocation(alias, (SVFBasicBlock*) nullptr);
1036 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1037 }
1038 }
1039}
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 1248 of file SVFIRBuilder.cpp.

1249{
1250 visitCallSite(&i);
1251}

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

1091{
1093 outs() << "process load " << LLVMUtil::dumpValue(&inst) << "\n");
1094
1095 NodeID dst = getValueNode(&inst);
1096
1097 NodeID src = getValueNode(inst.getPointerOperand());
1098 const Type* loadedTy = inst.getType();
1099 if (NodeID fieldZero = getDirectAccessFieldZeroValVar(inst.getPointerOperand(), loadedTy))
1100 src = fieldZero;
1101
1102 addLoadEdge(src, dst);
1103}

◆ visitPHINode()

void SVFIRBuilder::visitPHINode ( PHINode inst)

Visit phi instructions

Definition at line 1064 of file SVFIRBuilder.cpp.

1065{
1066
1068 outs() << "process phi " << LLVMUtil::dumpValue(&inst) << "\n");
1069
1070 NodeID dst = getValueNode(&inst);
1071
1072 for (u32_t i = 0; i < inst.getNumIncomingValues(); ++i)
1073 {
1074 const Value* val = inst.getIncomingValue(i);
1075 const Instruction* incomingInst = SVFUtil::dyn_cast<Instruction>(val);
1076 bool matched = (incomingInst == nullptr ||
1077 incomingInst->getFunction() == inst.getFunction());
1078 (void) matched; // Suppress warning of unused variable under release build
1079 assert(matched && "incomingInst's Function incorrect");
1080 const Instruction* predInst = &inst.getIncomingBlock(i)->back();
1081 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(predInst);
1082 NodeID src = getValueNode(val);
1083 addPhiStmt(dst,src,icfgNode);
1084 }
1085}
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 1311 of file SVFIRBuilder.cpp.

1312{
1313
1314 // ReturnInst itself should always not be a pointer type
1315 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1316
1318 outs() << "process return " << LLVMUtil::dumpValue(&inst) << "\n");
1319
1320 if(Value* src = inst.getReturnValue())
1321 {
1322 const FunObjVar *F = llvmModuleSet()->getFunObjVar(inst.getParent()->getParent());
1323
1325 NodeID vnS = getValueNode(src);
1326 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(&inst);
1327 //vnS may be null if src is a null ptr
1328 addPhiStmt(rnF,vnS,icfgNode);
1329 }
1330}

◆ visitSelectInst()

void SVFIRBuilder::visitSelectInst ( SelectInst inst)

Visit select instructions

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

Definition at line 1229 of file SVFIRBuilder.cpp.

1230{
1231
1233 outs() << "process select " << LLVMUtil::dumpValue(&inst) << "\n");
1234
1235 NodeID dst = getValueNode(&inst);
1236 NodeID src1 = getValueNode(inst.getTrueValue());
1237 NodeID src2 = getValueNode(inst.getFalseValue());
1238 NodeID cond = getValueNode(inst.getCondition());
1240 addSelectStmt(dst,src1,src2, cond);
1241}

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

1109{
1110 // StoreInst itself should always not be a pointer type
1111 assert(!SVFUtil::isa<PointerType>(inst.getType()));
1112
1114 outs() << "process store " << LLVMUtil::dumpValue(&inst) << "\n");
1115
1116 NodeID dst = getValueNode(inst.getPointerOperand());
1117 const Type* storedTy = inst.getValueOperand()->getType();
1118 if (NodeID fieldZero = getDirectAccessFieldZeroValVar(inst.getPointerOperand(), storedTy))
1119 dst = fieldZero;
1120
1121 NodeID src = getValueNode(inst.getValueOperand());
1122
1123 addStoreEdge(src, dst);
1124
1125}

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

1448{
1449 NodeID brinst = getValueNode(&inst);
1450 NodeID cond = getValueNode(inst.getCondition());
1451
1453 std::vector<const Instruction*> nextInsts;
1455 for (const Instruction* succInst : nextInsts)
1456 {
1458 const ConstantInt* condVal = inst.findCaseDest(const_cast<BasicBlock*>(succInst->getParent()));
1460 s64_t val = -1;
1461 if (condVal && condVal->getBitWidth() <= 64)
1463 const ICFGNode* icfgNode = llvmModuleSet()->getICFGNode(succInst);
1464 successors.push_back(std::make_pair(icfgNode, val));
1465 }
1466 addBranchStmt(brinst, cond, successors);
1468 for (auto& edge : llvmModuleSet()->getICFGNode(&inst)->getOutEdges())
1469 {
1470 if (IntraCFGEdge* intraEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge))
1471 {
1472 intraEdge->setConditionVar(pag->getGNode(cond));
1473 }
1474 }
1475}
signed long long s64_t
Definition GeneralType.h:50

◆ visitUnaryOperator()

void SVFIRBuilder::visitUnaryOperator ( UnaryOperator inst)

Visit Unary Operator

Definition at line 1200 of file SVFIRBuilder.cpp.

1201{
1202 NodeID dst = getValueNode(&inst);
1203 assert(inst.getNumOperands() == 1 && "not one operand for Unary instruction?");
1204 Value* opnd = inst.getOperand(0);
1205 NodeID src = getValueNode(opnd);
1206 u32_t opcode = inst.getOpcode();
1207 addUnaryOPEdge(src, dst, opcode);
1208}
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 1483 of file SVFIRBuilder.cpp.

1484{
1485 NodeID dst = getValueNode(&inst);
1486 Value* opnd = inst.getPointerOperand();
1487 NodeID src = getValueNode(opnd);
1488 addCopyEdge(src, dst, CopyStmt::COPYVAL);
1489}

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