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#include "Util/ExtAPI.h"
36#include "Util/Options.h"
37
38using namespace std;
39using namespace SVF;
40using namespace SVFUtil;
41using namespace LLVMUtil;
42
43namespace
44{
45
46struct MemcpyField
47{
48 APOffset byteOffset;
49 AccessPath accessPath;
50 const SVFType* elementType;
51};
52
57bool parseAnnotationArgIndex(const std::string& annotation, const std::string& prefix,
58 u32_t& argIdx, size_t& end)
59{
60 const size_t start = annotation.find(prefix);
61 if (start == std::string::npos)
62 return false;
63
64 end = start + prefix.size();
65 if (end >= annotation.size() || annotation[end] < '0' || annotation[end] > '9')
66 return false;
67
68 argIdx = 0;
69 do
70 {
71 argIdx = argIdx * 10 + static_cast<u32_t>(annotation[end] - '0');
72 ++end;
73 }
74 while (end < annotation.size() && annotation[end] >= '0' && annotation[end] <= '9');
75 return true;
76}
77
81bool parseNondetArgStoreAtExtCall(const std::string& annotation, u32_t& firstArg)
82{
83 size_t end = 0;
84 return parseAnnotationArgIndex(annotation, "STORE_TOP:Arg", firstArg, end) &&
85 end < annotation.size() && annotation[end] == '+';
86}
87
93bool parseScanfFormatArg(const std::string& annotation, u32_t& formatArg)
94{
95 size_t end = 0;
96 return parseAnnotationArgIndex(annotation, "SCANF:FormatArg", formatArg, end);
97}
98
101bool scanfMayStorePointer(const CallBase* cs, u32_t formatArg)
102{
103 // Unknown or writable formats may contain pointer conversions.
104 const GlobalVariable* glob = SVFUtil::dyn_cast<GlobalVariable>(cs->getArgOperand(formatArg));
105 if (!glob || !glob->isConstant() || !glob->hasDefinitiveInitializer())
106 return true;
107 const ConstantDataArray* data = SVFUtil::dyn_cast<ConstantDataArray>(glob->getInitializer());
108 if (!data || !data->isCString())
109 return true;
110
111 auto format = data->getAsCString();
112 auto in = [](const std::string& set, char c)
113 {
114 return set.find(c) != std::string::npos;
115 };
116 // Consume one conversion at a time. For "%*5d %lf %p", %*5d suppresses
117 // assignment, %lf writes a double, and %p makes us return true.
118 // With just "%*5d %lf", no conversion writes a pointer, so we return false.
119 while (!format.empty())
120 {
121 const size_t percent = format.find('%');
122 if (percent == format.npos)
123 break;
124 format = format.drop_front(percent + 1);
125 if (format.consume_front("%")) // %% is a literal percent sign.
126 continue;
127
128 // Split %*5ld into suppression (*), width (5), modifier (l), and type (d).
129 const bool suppressed = format.consume_front("*");
130 format = format.ltrim("0123456789");
131 const auto modifiers = format.take_front(format.find_first_not_of("hljztLqm"));
132 format = format.drop_front(modifiers.size());
133 if (format.empty())
134 return true;
135 const char conversion = format.front();
136 format = format.drop_front();
137 // Keep the pointer model when a conversion is not recognized.
138 if (!in("diouxXaAeEfFgGsScCnp[", conversion))
139 return true;
140
141 // %m and the old GNU %as/%a[ forms allocate a string and store its address.
142 const bool allocatesString = modifiers.contains('m') ||
143 (conversion == 'a' && !format.empty() && in("sS[", format.front()));
144 if (!suppressed && (conversion == 'p' || allocatesString))
145 return true;
146
147 if (conversion == '[')
148 {
149 // Skip the whole character set: %[%p] matches '%' or 'p', not a pointer.
150 // In %[^]p], the first ']' is part of the character set.
151 format.consume_front("^");
152 format.consume_front("]");
153 const size_t end = format.find(']');
154 if (end == format.npos)
155 return true;
156 format = format.drop_front(end + 1);
157 }
158 }
159 return false;
160}
161
162bool hasNondetArgStoreAtExtCall(const CallICFGNode* callICFGNode)
163{
164 const FunObjVar* extFun = callICFGNode->getCalledFunction();
165 if (extFun == nullptr)
166 return false;
167
168 for (const std::string& annotation :
169 ExtAPI::getExtAPI()->getExtFuncAnnotations(extFun))
170 {
171 u32_t firstArg = 0;
172 if (parseNondetArgStoreAtExtCall(annotation, firstArg))
173 return true;
174 }
175 return false;
176}
177
178void collectMemcpyFields(
179 const Type* llvmType,
180 const SVFType* svfType,
181 const DataLayout& dl,
182 IRGraph* pag,
183 std::vector<MemcpyField>& fields,
184 APOffset baseByteOffset = 0,
185 APOffset baseFldIdx = 0)
186{
187 if (llvmType == nullptr || svfType == nullptr)
188 return;
195 const u32_t maxFields = std::max(Options::MaxFieldLimit(), u32_t{1});
196 if (fields.size() >= maxFields)
197 return;
198
199 if (svfType->isPointerTy())
200 {
201 fields.push_back({baseByteOffset, AccessPath(baseFldIdx), svfType});
202 return;
203 }
204
205 // The LLVM and SVF types are walked one level at a time, so each element's SVF type is
206 // taken from its parent SVF type directly. getOriginalElemType() cannot be used here: it
207 // is keyed by flattened field index, and for nested arrays it returns the innermost
208 // element type, which pairs e.g. [8192 x i8] with i8 one level down.
209 if (const auto* structType = SVFUtil::dyn_cast<StructType>(llvmType))
210 {
211 const auto* svfStructType = SVFUtil::dyn_cast<SVFStructType>(svfType);
212 assert(svfStructType && "an LLVM struct type maps to an SVFStructType");
213 const StructLayout* layout = dl.getStructLayout(const_cast<StructType*>(structType));
214 for (u32_t i = 0;
215 i < structType->getNumElements() && fields.size() < maxFields; ++i)
216 {
217 const Type* elemLLVMType = structType->getElementType(i);
218 const SVFType* elemSVFType = svfStructType->getFieldTypes()[i];
219 if (elemSVFType == nullptr)
220 return;
221 APOffset elemByteOffset = baseByteOffset + static_cast<APOffset>(layout->getElementOffset(i));
222 APOffset elemFldIdx = baseFldIdx + pag->getFlattenedElemIdx(svfType, i);
223 collectMemcpyFields(elemLLVMType, elemSVFType, dl, pag, fields, elemByteOffset, elemFldIdx);
224 }
225 return;
226 }
227
228 if (const auto* arrayType = SVFUtil::dyn_cast<ArrayType>(llvmType))
229 {
230 const auto* svfArrayType = SVFUtil::dyn_cast<SVFArrayType>(svfType);
231 assert(svfArrayType && "an LLVM array type maps to an SVFArrayType");
232 const Type* elemLLVMType = arrayType->getElementType();
233 const SVFType* elemSVFType = svfArrayType->getTypeOfElement();
234 if (elemSVFType == nullptr)
235 return;
236 const APOffset elemByteSize = static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(elemLLVMType)));
237 for (u32_t i = 0;
238 i < arrayType->getNumElements() && fields.size() < maxFields; ++i)
239 {
240 APOffset elemByteOffset = baseByteOffset + i * elemByteSize;
241 APOffset elemFldIdx = baseFldIdx + pag->getFlattenedElemIdx(svfType, i);
242 collectMemcpyFields(elemLLVMType, elemSVFType, dl, pag, fields, elemByteOffset, elemFldIdx);
243 }
244 }
245}
246
247std::vector<MemcpyField> getMemcpyFields(const Value* value, const Type* llvmType, const SVFType* svfType)
248{
249 std::vector<MemcpyField> fields;
250 auto* mset = LLVMModuleSet::getLLVMModuleSet();
251 auto* pag = PAG::getPAG();
252 const DataLayout& dl = mset->getMainLLVMModule()->getDataLayout();
253 collectMemcpyFields(llvmType, svfType, dl, pag, fields);
254 return fields;
255}
256
257const Type* getMemcpyLayoutType(const Value* baseValue, const Type* fallbackType)
258{
259 if (const auto* allocaInst = llvm::dyn_cast_or_null<AllocaInst>(baseValue))
260 return allocaInst->getAllocatedType();
261
262 if (const auto* global = llvm::dyn_cast_or_null<GlobalVariable>(baseValue))
263 return global->getValueType();
264
265 return fallbackType;
266}
267
268}
269
273const Type* SVFIRBuilder::getBaseTypeAndFlattenedFields(const Value* V, std::vector<AccessPath> &fields, const Value* szValue)
274{
275 assert(V);
276 const Value* value = getBaseValueForExtArg(V);
278 u32_t numOfElems = pag->getNumOfFlattenElements(LLVMModuleSet::getLLVMModuleSet()->getSVFType(objType));
280 if(szValue && SVFUtil::isa<ConstantInt>(szValue))
281 {
283 numOfElems = (numOfElems > szIntVal.first) ? szIntVal.first : numOfElems;
284 }
291 numOfElems = std::min(numOfElems, std::max(Options::MaxFieldLimit(), u32_t{1}));
292
294 for(u32_t ei = 0; ei < numOfElems; ei++)
295 {
296 AccessPath ls(ei);
297 // make a ConstantInt and create char for the content type due to byte-wise copy
298 const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
299 if (!llvmModuleSet()->hasValueNode(offset))
300 {
301 SymbolTableBuilder builder(pag);
302 builder.collectSym(offset);
304 pag->addConstantIntValNode(id, LLVMUtil::getIntegerValue(offset), nullptr, llvmModuleSet()->getSVFType(offset->getType()));
306 pag->getGNode(id));
307 }
309 fields.push_back(ls);
310 }
311 return objType;
312}
313
319{
320 assert(D && S);
321 NodeID vnD= getValueNode(D), vnS= getValueNode(S);
322 if(!vnD || !vnS)
323 return;
324
325 std::vector<AccessPath> fields;
326
327 //Get the max possible size of the copy, unless it was provided.
328 std::vector<AccessPath> srcFields;
329 std::vector<AccessPath> dstFields;
330 const Type* stype = getBaseTypeAndFlattenedFields(S, srcFields, szValue);
331 const Type* dtype = getBaseTypeAndFlattenedFields(D, dstFields, szValue);
332 if(srcFields.size() > dstFields.size())
333 fields = dstFields;
334 else
335 fields = srcFields;
336
338 u32_t sz = fields.size();
339
340 if (fields.size() == 1 && (LLVMUtil::isConstDataOrAggData(D) || LLVMUtil::isConstDataOrAggData(S)))
341 {
342 NodeID dummy = pag->addDummyValNode();
343 addLoadEdge(vnD,dummy);
344 addStoreEdge(dummy,vnS);
345 return;
346 }
347
348 const Value* dstBase = getBaseValueForExtArg(D);
349 const Value* srcBase = getBaseValueForExtArg(S);
350 Value* dstFieldBase = LLVMUtil::isObject(dstBase) ? const_cast<Value*>(dstBase) : D;
351 Value* srcFieldBase = LLVMUtil::isObject(srcBase) ? const_cast<Value*>(srcBase) : S;
352 const Type* dstLayoutType = getMemcpyLayoutType(dstBase, dtype);
353 const Type* srcLayoutType = getMemcpyLayoutType(srcBase, stype);
354 const bool hasRemappedGlobalBase =
355 (dstFieldBase != D && SVFUtil::isa<GlobalVariable>(dstFieldBase)) ||
356 (srcFieldBase != S && SVFUtil::isa<GlobalVariable>(srcFieldBase));
357 const bool useByteLayoutMemcpy =
358 hasRemappedGlobalBase || (dstLayoutType != dtype) || (srcLayoutType != stype);
359 if (useByteLayoutMemcpy)
360 {
361 const SVFType* dstSVFType = llvmModuleSet()->getSVFType(dstLayoutType);
362 const SVFType* srcSVFType = llvmModuleSet()->getSVFType(srcLayoutType);
363 std::vector<MemcpyField> dstMemcpyFields = getMemcpyFields(D, dstLayoutType, dstSVFType);
364 std::vector<MemcpyField> srcMemcpyFields = getMemcpyFields(S, srcLayoutType, srcSVFType);
365 if (!dstMemcpyFields.empty() && !srcMemcpyFields.empty())
366 {
367 std::unordered_map<APOffset, MemcpyField> srcFieldsByByteOffset;
368 for (const auto& field : srcMemcpyFields)
369 srcFieldsByByteOffset.emplace(field.byteOffset, field);
370
371 const DataLayout& dl = llvmModuleSet()->getMainLLVMModule()->getDataLayout();
372 APOffset copyBytes = std::min<APOffset>(
373 static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(dstLayoutType))),
374 static_cast<APOffset>(dl.getTypeAllocSize(const_cast<Type*>(srcLayoutType))));
375 if (szValue && SVFUtil::isa<ConstantInt>(szValue))
376 {
378 copyBytes = std::min(copyBytes, static_cast<APOffset>(szIntVal.first));
379 }
380
381 for (const auto& dstField : dstMemcpyFields)
382 {
383 if (dstField.byteOffset >= copyBytes)
384 continue;
385 auto it = srcFieldsByByteOffset.find(dstField.byteOffset);
386 if (it == srcFieldsByByteOffset.end())
387 continue;
388
389 NodeID dField = getGepValVar(dstFieldBase, dstField.accessPath, dstField.elementType);
390 NodeID sField = getGepValVar(srcFieldBase, it->second.accessPath, it->second.elementType);
391 NodeID dummy = pag->addDummyValNode();
392 addLoadEdge(sField, dummy);
393 addStoreEdge(dummy, dField);
394 }
395 return;
396 }
397 }
398
399 //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
400 for (u32_t index = 0; index < sz; index++)
401 {
403 const SVFType* dElementType = pag->getFlatternedElemType(llvmmodule->getSVFType(dtype),
404 fields[index].getConstantStructFldIdx());
405 const SVFType* sElementType = pag->getFlatternedElemType(llvmmodule->getSVFType(stype),
406 fields[index].getConstantStructFldIdx());
407 NodeID dField = getGepValVar(D,fields[index],dElementType);
408 NodeID sField = getGepValVar(S,fields[index],sElementType);
409 NodeID dummy = pag->addDummyValNode();
410 addLoadEdge(sField,dummy);
411 addStoreEdge(dummy,dField);
412 }
413}
414
416{
417 Set<u32_t> storeTopArgs;
418 NodeID src = pag->getBlkPtr();
419 const FunObjVar* extFun = callICFGNode->getCalledFunction();
420 if (extFun)
421 {
422 for (const std::string& annotation :
423 ExtAPI::getExtAPI()->getExtFuncAnnotations(extFun))
424 {
425 u32_t annotatedFormatArg = 0;
426 if (parseScanfFormatArg(annotation, annotatedFormatArg))
427 {
428 if (annotatedFormatArg < cs->arg_size())
429 {
430 src = pag->getBlkPtr();
431 if (!scanfMayStorePointer(cs, annotatedFormatArg))
432 {
433 // scanf("%d", &n) writes a number, not a pointer. Copy BlkPtr
434 // into a non-pointer variable so AE still sees an unknown value.
435 src = pag->addValNode(NodeIDAllocator::get()->allocateValueId(), SVFType::getSVFInt8Type(), callICFGNode);
436 // Keep the call's LLVM value available when printing this variable.
437 llvmModuleSet()->addToSVFVar2LLVMValueMap(cs, pag->getGNode(src));
438 addCopyEdge(pag->getBlkPtr(), src, CopyStmt::COPYVAL);
439 }
440 }
441 continue;
442 }
443
444 u32_t firstArg = 0;
445 if (!parseNondetArgStoreAtExtCall(annotation, firstArg))
446 continue;
447 if (firstArg >= cs->arg_size())
448 continue;
449
450 for (u32_t argIdx = firstArg; argIdx < cs->arg_size(); ++argIdx)
451 storeTopArgs.insert(argIdx);
452 }
453 }
454
455 for (u32_t argIdx : storeTopArgs)
456 {
457 const Value* arg = cs->getArgOperand(argIdx);
458 if (!arg->getType()->isPointerTy())
459 continue;
460
461 const Type* storedType =
463 NodeID dst = getValueNode(arg);
464 if (NodeID fieldZero = getDirectAccessFieldZeroValVar(arg, storedType))
465 dst = fieldZero;
466 if (src && dst)
467 addStoreEdge(src, dst);
468 }
469}
470
471void SVFIRBuilder::handleExtCall(const CallBase* cs, const Function* callee)
472{
473 const CallICFGNode *callICFGNode = llvmModuleSet()->getCallICFGNode(cs);
474
475 if (hasNondetArgStoreAtExtCall(callICFGNode))
476 {
477 handleNondetArgStoreAtExtCall(cs, callICFGNode);
478 }
479 else if (isHeapAllocExtCallViaRet(callICFGNode))
480 {
481 NodeID val = llvmModuleSet()->getValueNode(cs);
483 addAddrWithHeapSz(obj, val, cs);
484 }
485 else if (isHeapAllocExtCallViaArg(callICFGNode))
486 {
488 Value* arg = cs->getArgOperand(arg_pos);
489 if (cs->getArgOperand(arg_pos)->getType()->isPointerTy())
490 {
491 NodeID vnArg = llvmModuleSet()->getValueNode(arg);
492 NodeID dummy = pag->addDummyValNode();
493 NodeID obj = pag->addDummyObjNode(llvmModuleSet()->getSVFType(cs->getArgOperand(arg_pos)->getType()));
494 if (vnArg && dummy && obj)
495 {
496 addAddrWithHeapSz(obj, dummy, cs);
497 addStoreEdge(dummy, vnArg);
498 }
499 }
500 else
501 {
502 writeWrnMsg("Arg receiving new object must be pointer type");
503 }
504 }
505 else if (LLVMUtil::isMemcpyExtFun(callee))
506 {
507 // Side-effects similar to void *memcpy(void *dest, const void * src, size_t n)
508 // which copies n characters from memory area 'src' to memory area 'dest'.
509 if(callee->getName().find("iconv") != std::string::npos)
510 addComplexConsForExt(cs->getArgOperand(3), cs->getArgOperand(1), nullptr);
511 else if(callee->getName().find("bcopy") != std::string::npos)
512 addComplexConsForExt(cs->getArgOperand(1), cs->getArgOperand(0), cs->getArgOperand(2));
513 if(cs->arg_size() == 3)
514 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), cs->getArgOperand(2));
515 else
516 addComplexConsForExt(cs->getArgOperand(0), cs->getArgOperand(1), nullptr);
517 if(SVFUtil::isa<PointerType>(cs->getType()))
518 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
519 }
520 else if (llvmModuleSet()->hasExtFuncAnnotation(callee, "STRLEN"))
521 {
522 // strlen(p) and wcslen(p) read characters, not just p's address.
523 // For char s[4]="ABC", represent reads of s[0..3] so a write
524 // to s[1] in a callee can reach this call through the SVFG.
525 std::vector<AccessPath> fields;
526 const Value* arg = cs->getArgOperand(0);
527 const Type* type = getBaseTypeAndFlattenedFields(arg, fields, nullptr);
528 for (const AccessPath& field : fields)
529 {
530 const SVFType* elementType = pag->getFlatternedElemType(
531 llvmModuleSet()->getSVFType(type),
532 field.getConstantStructFldIdx());
533 NodeID address = getGepValVar(arg, field, elementType);
534 addLoadEdge(address, pag->addDummyValNode());
535 }
536 }
537 else if(LLVMUtil::isMemsetExtFun(callee))
538 {
539 // Side-effects similar to memset(void *str, int c, size_t n)
540 // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
541 std::vector<AccessPath> dstFields;
542 const Type *dtype = getBaseTypeAndFlattenedFields(cs->getArgOperand(0), dstFields, cs->getArgOperand(2));
543 u32_t sz = dstFields.size();
544 //For each field (i), add store edge *(arg0 + i) = arg1
545 for (u32_t index = 0; index < sz; index++)
546 {
548 const SVFType* dElementType = pag->getFlatternedElemType(llvmmodule->getSVFType(dtype),
549 dstFields[index].getConstantStructFldIdx());
550 NodeID dField = getGepValVar(cs->getArgOperand(0), dstFields[index], dElementType);
551 addStoreEdge(getValueNode(cs->getArgOperand(1)),dField);
552 }
553 if(SVFUtil::isa<PointerType>(cs->getType()))
554 addCopyEdge(getValueNode(cs->getArgOperand(0)), getValueNode(cs), CopyStmt::COPYVAL);
555 }
556 else if(callee->getName().compare("dlsym") == 0)
557 {
558 /*
559 Side-effects of void* dlsym( void* handle, const char* funName),
560 Locate the function with the name "funName," then add a "copy" edge between the callsite and that function.
561 dlsym() example:
562 int main() {
563 // Open the shared library
564 void* handle = dlopen("./my_shared_library.so", RTLD_LAZY);
565 // Find the function address
566 void (*myFunctionPtr)() = (void (*)())dlsym(handle, "myFunction");
567 // Call the function
568 myFunctionPtr();
569 }
570 */
571 const Value* src = cs->getArgOperand(1);
573 src = stripConstantCasts(gep->getPointerOperand());
574
575 auto getHookFn = [](const Value* src)->const Function*
576 {
578 return nullptr;
579
580 auto *glob = SVFUtil::cast<GlobalVariable>(src);
581 if (!glob->hasInitializer() || !SVFUtil::isa<ConstantDataArray>(glob->getInitializer()))
582 return nullptr;
583
584 auto *constarray = SVFUtil::cast<ConstantDataArray>(glob->getInitializer());
585 return LLVMUtil::getProgFunction(constarray->getAsCString().str());
586 };
587
588 if (const Function *fn = getHookFn(src))
589 {
590 NodeID srcNode = getValueNode(fn);
592 }
593 }
594 else if(callee->getName().find("_ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_") != std::string::npos)
595 {
596 // 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.
597 assert(cs->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
598
599 // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
600 // Now we calculate the offset from base to vArg3
601 NodeID vnArg3 = llvmModuleSet()->getValueNode(cs->getArgOperand(3));
604
605 // We get all flattened fields of base
606 vector<AccessPath> fields = pag->getTypeLocSetsMap(vnArg3).second;
607
608 // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
609 // Note that arg0 is aligned with "offset".
610 for (APOffset i = offset + 1; i <= offset + 3; ++i)
611 {
612 if((u32_t)i >= fields.size())
613 break;
614 const SVFType* elementType = pag->getFlatternedElemType(pag->getTypeLocSetsMap(vnArg3).first,
615 fields[i].getConstantStructFldIdx());
616 NodeID vnD = getGepValVar(cs->getArgOperand(3), fields[i], elementType);
617 NodeID vnS = llvmModuleSet()->getValueNode(cs->getArgOperand(1));
618 if(vnD && vnS)
619 addStoreEdge(vnS,vnD);
620 }
621 }
622
623 if (isThreadForkCall(callICFGNode))
624 {
625 const ValVar* valVar = getForkedFun(callICFGNode);
626 if (const FunValVar* funcValVar = SVFUtil::dyn_cast<FunValVar>(valVar))
627 {
628 const FunObjVar* forkedFun = funcValVar->getFunction()->getDefFunForMultipleModule();
629 const SVFVar* actualParm = getActualParmAtForkSite(callICFGNode);
632 assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
633 if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
634 {
635 const ArgValVar* formalParm = forkedFun->getArg(0);
637 if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
638 {
639 FunEntryICFGNode *entry = pag->getICFG()->getFunEntryICFGNode(forkedFun);
640 addThreadForkEdge(actualParm->getId(), formalParm->getId(), callICFGNode, entry);
641 }
642 }
643 }
644 else
645 {
650 }
654 }
655
657}
unsigned u32_t
Definition CommandLine.h:18
newitem type
Definition cJSON.cpp:2739
buffer offset
Definition cJSON.cpp:1113
char const int const cJSON_bool format
Definition cJSON.h:163
int index
Definition cJSON.h:170
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:102
bool addOffsetVarAndGepTypePair(const ValVar *var, const SVFType *gepIterType)
Class representing a function argument variable in the SVFIR.
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:501
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:43
const ArgValVar * getArg(u32_t idx) const
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
u32_t arg_size() const
const FunObjVar * getDefFunForMultipleModule() const
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:148
NodeID getValueNode(const Value *V)
Module * getMainLLVMModule() const
Definition LLVMModule.h:373
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:137
void addToSVFVar2LLVMValueMap(const Value *val, SVFValue *svfBaseNode)
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
NodeID getObjectNode(const Value *V)
LLVMContext & getContext() const
Definition LLVMModule.h:393
ObjTypeInference * getTypeInference()
static NodeIDAllocator * get(void)
Return (singleton) allocator.
const Type * inferObjType(const Value *var)
get or infer the type of the object pointed by the value
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34
SVFIR * getPAG() const
Return SVFIR.
void addStoreEdge(NodeID src, NodeID dst)
Add Store edge.
void addLoadEdge(NodeID src, NodeID dst)
Add Load edge.
virtual void handleExtCall(const CallBase *cs, const Function *callee)
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 handleNondetArgStoreAtExtCall(const CallBase *cs, const CallICFGNode *callICFGNode)
NodeID getDirectAccessFieldZeroValVar(const Value *ptr, const Type *accessTy)
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)
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:121
bool isPointerTy() const
Definition SVFType.h:292
static SVFType * getSVFInt8Type()
Definition SVFType.h:222
NodeID getId() const
Get ID.
Definition SVFValue.h:158
virtual const SVFType * getType() const
Definition SVFValue.h:169
virtual bool isPointer() const
Check if this variable represents a pointer.
void collectSym(const Value *val)
const Function * getProgFunction(const std::string &funName)
Get program entry function from module.
Definition LLVMUtil.cpp:41
const Value * stripConstantCasts(const Value *val)
Strip off the constant casts.
Definition LLVMUtil.cpp:220
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition LLVMUtil.cpp:645
bool isMemcpyExtFun(const Function *fun)
Definition LLVMUtil.cpp:390
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:95
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:397
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition LLVMUtil.cpp:660
bool isMemsetExtFun(const Function *fun)
Definition LLVMUtil.cpp:396
bool isObject(const Value *ref)
Return true if this value refers to a object.
Definition LLVMUtil.cpp:61
u32_t getHeapAllocHoldingArgPosition(const Function *fun)
Definition LLVMUtil.cpp:402
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
bool isThreadForkCall(const CallICFGNode *inst)
Definition SVFUtil.h:365
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:88
const ValVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
Definition SVFUtil.h:413
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:336
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
for isBitcode
Definition BasicTypes.h:70
llvm::DataLayout DataLayout
Definition BasicTypes.h:106
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:131
llvm::Type Type
Definition BasicTypes.h:81
llvm::CallBase CallBase
Definition BasicTypes.h:147
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:92
u32_t NodeID
Definition GeneralType.h:76
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition GeneralType.h:51
llvm::StructLayout StructLayout
Definition BasicTypes.h:103
s64_t APOffset
Definition GeneralType.h:80
llvm::Function Function
Definition BasicTypes.h:83
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:80
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:163
unsigned u32_t
Definition GeneralType.h:67
llvm::ConstantDataArray ConstantDataArray
Definition BasicTypes.h:119
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:123
llvm::LLVMContext LLVMContext
Definition BasicTypes.h:72