Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVFIRExtAPI.cpp
Go to the documentation of this file.
1//===- SVFIRExtAPI.cpp -- External function IR of SVF ---------------------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23/*
24 * SVFIRExtAPI.cpp
25 *
26 * Created on: 18, 5, 2023
27 * Author: Shuangxiang Kan
28 */
29
31#include "Util/SVFUtil.h"
34#include "Graphs/CallGraph.h"
35
36using namespace std;
37using namespace SVF;
38using namespace SVFUtil;
39using namespace LLVMUtil;
40
44const Type* SVFIRBuilder::getBaseTypeAndFlattenedFields(const Value* V, std::vector<AccessPath> &fields, const Value* szValue)
45{
46 assert(V);
47 const Value* value = getBaseValueForExtArg(V);
51 if(szValue && SVFUtil::isa<ConstantInt>(szValue))
52 {
53 auto szIntVal = LLVMUtil::getIntegerValue(SVFUtil::cast<ConstantInt>(szValue));
54 numOfElems = (numOfElems > szIntVal.first) ? szIntVal.first : numOfElems;
55 }
56
58 for(u32_t ei = 0; ei < numOfElems; ei++)
59 {
61 // make a ConstantInt and create char for the content type due to byte-wise copy
62 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
65 {
67 builder.collectSym(offset);
69 }
70 ls.addOffsetVarAndGepTypePair(getPAG()->getGNode(getPAG()->getValueNode(svfOffset)), nullptr);
71 fields.push_back(ls);
72 }
73 return objType;
74}
75
81{
82 assert(D && S);
84 if(!vnD || !vnS)
85 return;
86
87 std::vector<AccessPath> fields;
88
89 //Get the max possible size of the copy, unless it was provided.
90 std::vector<AccessPath> srcFields;
91 std::vector<AccessPath> dstFields;
94 if(srcFields.size() > dstFields.size())
96 else
98
100 u32_t sz = fields.size();
101
103 {
107 return;
108 }
109
110 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
111 for (u32_t index = 0; index < sz; index++)
112 {
115 fields[index].getConstantStructFldIdx());
117 fields[index].getConstantStructFldIdx());
123 }
124}
125
127{
129 const SVFCallInst* svfCall = SVFUtil::cast<SVFCallInst>(svfInst);
131
133 {
137 }
139 {
141 const SVFValue* arg = svfCall->getArgOperand(arg_pos);
142 if (arg->getType()->isPointerTy())
143 {
146 NodeID obj = pag->addDummyObjNode(arg->getType());
147 if (vnArg && dummy && obj)
148 {
151 }
152 }
153 else
154 {
155 writeWrnMsg("Arg receiving new object must be pointer type");
156 }
157 }
158 else if (isMemcpyExtFun(svfCallee))
159 {
160 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
161 // which copies n characters from memory area 'src' to memory area 'dest'.
162 if(svfCallee->getName().find("iconv") != std::string::npos)
163 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
164 else if(svfCallee->getName().find("bcopy") != std::string::npos)
165 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
166 if(svfCall->arg_size() == 3)
167 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
168 else
169 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
170 if(SVFUtil::isa<PointerType>(cs->getType()))
171 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
172 }
173 else if(isMemsetExtFun(svfCallee))
174 {
175 // Side-effects similar to memset(void *str, int c, size_t n)
176 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
177 std::vector<AccessPath> dstFields;
178 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
179 u32_t sz = dstFields.size();
180 //For each field (i), add store edge *(arg0 + i) = arg1
181 for (u32_t index = 0; index < sz; index++)
182 {
185 dstFields[index].getConstantStructFldIdx());
186 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
187 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
188 }
189 if(SVFUtil::isa<PointerType>(cs->getType()))
190 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
191 }
192 else if(svfCallee->getName().compare("dlsym") == 0)
193 {
194 /*
195 Side-effects of void* dlsym( void* handle, const char* funName),
196 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
197 dlsym() example:
198 int main() {
199 // Open the shared library
200 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
201 // Find the function address
202 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
203 // Call the function
204 myFunctionPtr();
205 }
206 */
207 const Value* src = cs->getArgOperand(1);
208 if(const GetElementPtrInst* gep = SVFUtil::dyn_cast<GetElementPtrInst>(src))
209 src = stripConstantCasts(gep->getPointerOperand());
210
211 auto getHookFn = [](const Value* src)->const Function*
212 {
213 if (!SVFUtil::isa<GlobalVariable>(src))
214 return nullptr;
215
216 auto *glob = SVFUtil::cast<GlobalVariable>(src);
217 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
218 return nullptr;
219
220 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
221 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
222 };
223
224 if (const Function *fn = getHookFn(src))
225 {
228 }
229 }
230 else if(svfCallee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
231 {
232 // The purpose of this function is to insert a new node into the red-black tree and then rebalance the tree to ensure that the red-black tree properties are maintained.
233 assert(svfCall->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
234
235 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
236 // Now we calculate the offset from base to vArg3
237 NodeID vnArg3 = pag->getValueNode(svfCall->getArgOperand(3));
240
241 // We get all flattened fields of base
243
244 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
245 // Note that arg0 is aligned with "offset".
246 for (APOffset i = offset + 1; i <= offset + 3; ++i)
247 {
248 if((u32_t)i >= fields.size())
249 break;
251 fields[i].getConstantStructFldIdx());
252 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
253 NodeID vnS = pag->getValueNode(svfCall->getArgOperand(1));
254 if(vnD && vnS)
256 }
257 }
258
260 {
262 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
263 {
269 assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
270 if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
271 {
272 const SVFArgument* formalParm = forkedFun->getArg(0);
274 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
275 {
278 }
279 }
280 }
281 else
282 {
287 }
291 }
292
294}
buffer offset
Definition cJSON.cpp:1113
int index
Definition cJSON.h:170
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:100
const SVFFunction * getFunction() const
Get function of this call node.
Definition CallGraph.h:131
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition ICFG.cpp:234
NodeID getValueNode(const SVFValue *V)
Definition IRGraph.h:137
SymbolTableInfo * getSymbolInfo() const
Definition IRGraph.h:114
NodeID getObjectNode(const SVFValue *V)
Definition IRGraph.h:147
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:122
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
LLVMContext & getContext() const
Definition LLVMModule.h:379
SVFInstruction * getSVFInstruction(const Instruction *inst) const
Definition LLVMModule.h:274
ObjTypeInference * getTypeInference()
SVFValue * getSVFValue(const Value *value)
const Type * inferObjType(const Value *var)
get or infer the type of the object pointed by the value
const CallGraphNode * getCallGraphNode() const
Definition SVFValue.h:363
const SVFFunction * getDefFunForMultipleModule() const
Definition SVFValue.h:404
SVFIR * getPAG() const
Return SVFIR.
void addStoreEdge(NodeID src, NodeID dst)
Add Store edge.
void addLoadEdge(NodeID src, NodeID dst)
Add Load edge.
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)".
LLVMModuleSet * llvmModuleSet()
void addThreadForkEdge(NodeID src, NodeID dst, const CallICFGNode *cs, const FunEntryICFGNode *entry)
Add Thread fork edge for parameter passing.
AccessPath getAccessPathFromBaseNode(NodeID nodeId)
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 void handleExtCall(const CallBase *cs, const SVFFunction *svfCallee)
virtual const Type * getBaseTypeAndFlattenedFields(const Value *V, std::vector< AccessPath > &fields, const Value *szValue)
Handle external call.
CopyStmt * addCopyEdge(NodeID src, NodeID dst, CopyStmt::CopyKind kind)
NodeID getValueNode(const Value *V)
Get different kinds of node.
virtual void addComplexConsForExt(Value *D, Value *S, const Value *sz)
NodeID getGepValVar(const Value *val, const AccessPath &ap, const SVFType *elementType)
NodeID addConstantIntValNode(const SVFValue *curInst, const std::pair< s64_t, u64_t > &intValue, const NodeID i, const ICFGNode *icfgNode)
Definition SVFIR.h:588
ICFG * getICFG() const
Definition SVFIR.h:172
NodeID addDummyValNode()
Definition SVFIR.h:496
SVFTypeLocSetsPair & getTypeLocSetsMap(NodeID argId)
Given an arg NodeId, get its base SVFType* and all its field location sets.
Definition SVFIR.h:245
NodeID addDummyObjNode(const SVFType *type)
Definition SVFIR.h:500
SymID getValSym(const SVFValue *val)
Get different kinds of syms.
const SVFType * getFlatternedElemType(const SVFType *baseType, u32_t flatten_idx)
Return the type of a flattened element given a flattened index.
u32_t getNumOfFlattenElements(const SVFType *T)
Number of flattened elements of an array or struct.
bool hasValSym(const SVFValue *val)
const Function * getProgFunction(const std::string &funName)
Get program entry function from module.
Definition LLVMUtil.cpp:39
const Value * stripConstantCasts(const Value *val)
Strip off the constant casts.
Definition LLVMUtil.cpp:219
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:617
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:362
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:633
bool isMemsetExtFun(const SVFFunction *fun)
Definition SVFUtil.h:288
bool isMemcpyExtFun(const SVFFunction *fun)
Definition SVFUtil.h:283
u32_t getHeapAllocHoldingArgPosition(const SVFFunction *fun)
Get the position of argument that holds an allocated heap object.
Definition SVFUtil.h:309
bool isThreadForkCall(const CallICFGNode *inst)
Definition SVFUtil.h:387
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67
const ValVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
Definition SVFUtil.h:435
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:358
for isBitcode
Definition BasicTypes.h:68
llvm::Type Type
Definition BasicTypes.h:83
llvm::CallBase CallBase
Definition BasicTypes.h:146
u32_t NodeID
Definition GeneralType.h:55
s64_t APOffset
Definition GeneralType.h:60
llvm::Function Function
Definition BasicTypes.h:85
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:82
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:162
unsigned u32_t
Definition GeneralType.h:46
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:125
llvm::LLVMContext LLVMContext
Definition BasicTypes.h:70