Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVF::cppUtil Namespace Reference

Classes

struct  DemangledName
class  CXXABI
class  ItaniumABI
class  MSVCABI

Functions

CXXABI * getCXXABI ()
CXXABI * getCXXABI (const Module *M)
CXXABI * getCXXABI (const Value *val)
struct DemangledName demangle (const std::string &name)
Set< std::string > getClsNamesInBrackets (const std::string &name)
std::string getBeforeBrackets (const std::string &name)
std::string getClassNameFromVtblObj (const std::string &vtblName)
const ConstantStruct * getVtblStruct (const GlobalValue *vtbl)
bool isValVtbl (const Value *val)
 A carefully crafted input such as FakeVTable _ZTV1A = {{nullptr, nullptr}}; can forge a vtable; detection is approximate and heuristic.
bool isVirtualCallSite (const CallBase *cs)
bool isConstructor (const Function *F)
bool isDestructor (const Function *F)
bool isCPPThunkFunction (const Function *F)
const Function * getThunkTarget (const Function *F)
const Argument * getConstructorThisPtr (const Function *fun)
const Value * getVCallThisPtr (const CallBase *cs)
const Value * getVCallVtblPtr (const CallBase *cs)
s32_t getVCallIdx (const CallBase *cs)
bool classTyHasVTable (const StructType *ty)
std::string getClassNameFromType (const StructType *ty)
Set< std::string > getClassNameOfThisPtr (const CallBase *cs)
std::string getFunNameOfVCallSite (const CallBase *cs)
bool VCallInCtorOrDtor (const CallBase *cs)
bool isSameThisPtrInConstructor (const Argument *thisPtr1, const Value *thisPtr2)
Set< std::string > extractClsNamesFromFunc (const Function *foo)
 extract class name from the c++ function name, e.g., constructor/destructors
Set< std::string > extractClsNamesFromTemplate (const std::string &oname)
 extract class names from template functions
bool isClsNameSource (const Value *val)
bool matchesLabel (const std::string &foo, const std::string &label)
 whether foo matches the mangler label
bool isTemplateFunc (const Function *foo)
 whether foo is a cpp template function
bool isDynCast (const Function *foo)
 whether foo is a cpp dyncast function
std::string extractClsNameFromDynCast (const CallBase *callBase)
 extract class name from cpp dyncast function
const Type * cppClsNameToType (const std::string &className)

Function Documentation

◆ classTyHasVTable()

bool SVF::cppUtil::classTyHasVTable ( const StructType * ty)

Definition at line 602 of file CppUtil.cpp.

603{
604 if(getClassNameFromType(ty).empty()==false)
605 {
606 for(auto it = ty->element_begin(); it!=ty->element_end(); it++)
607 {
608 const std::string& str = LLVMUtil::dumpType(*it);
609 if (str.find(vtableType) != std::string::npos)
610 return true;
611 }
612 }
613 return false;
614}
const std::string vtableType
Definition CppUtil.cpp:57
std::string dumpType(const Type *type)
Definition LLVMUtil.cpp:623
std::string getClassNameFromType(const StructType *ty)
Definition CppUtil.cpp:616

◆ cppClsNameToType()

const Type * SVF::cppUtil::cppClsNameToType ( const std::string & className)

Definition at line 967 of file CppUtil.cpp.

968{
969 StructType *classTy = StructType::getTypeByName(LLVMModuleSet::getLLVMModuleSet()->getContext(),
970 clsName + className);
971 return classTy ? classTy : LLVMModuleSet::getLLVMModuleSet()->getTypeInference()->ptrType();
972}
const std::string clsName
Definition CppUtil.cpp:55
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:137
ObjTypeInference * getTypeInference()
const Type * ptrType()
pointer type
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:92

◆ demangle()

struct cppUtil::DemangledName SVF::cppUtil::demangle ( const std::string & name)

Definition at line 195 of file CppUtil.cpp.

196{
197 return getCXXABI()->demangle(name);
198}
const char *const name
Definition cJSON.h:264
virtual DemangledName demangle(const std::string &name)=0
CXXABI * getCXXABI()
Definition CppUtil.cpp:1015

◆ extractClsNameFromDynCast()

std::string SVF::cppUtil::extractClsNameFromDynCast ( const CallBase * callBase)

extract class name from cpp dyncast function

extract class name from cpp dyncast function

Parameters
callBase
Returns

Definition at line 951 of file CppUtil.cpp.

952{
953 Value *tgtCast = callBase->getArgOperand(2);
954 const std::string &valueStr = LLVMUtil::dumpValue(tgtCast);
955 u32_t leftPos = valueStr.find(ztilabel);
956 assert(leftPos != (u32_t) std::string::npos && "does not find ZTI for dyncast?");
957 u32_t rightPos = leftPos;
958 while (rightPos < valueStr.size() && valueStr[rightPos] != ' ') rightPos++;
959 const std::string &substr = valueStr.substr(leftPos, rightPos - leftPos);
960 std::string demangleName = llvm::demangle(substr);
961 const std::string &realName = demangleName.substr(ztiprefix.size(),
962 demangleName.size() - ztiprefix.size());
963 assert(realName != "" && "real name for dyncast empty?");
964 return realName;
965}
const std::string ztilabel
Definition CppUtil.cpp:79
const std::string ztiprefix
Definition CppUtil.cpp:80
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:612
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:80
unsigned u32_t
Definition GeneralType.h:67

◆ extractClsNamesFromFunc()

Set< std::string > SVF::cppUtil::extractClsNamesFromFunc ( const Function * foo)

extract class name from the c++ function name, e.g., constructor/destructors

extract class name from the c++ function name, e.g., constructor/destructors

Parameters
foo
Returns

Definition at line 739 of file CppUtil.cpp.

740{
741 const std::string &name = foo->getName().str();
742 if (isConstructor(foo) || isDestructor(foo))
743 {
744 // c++ constructor or destructor
745 DemangledName demangledName = cppUtil::demangle(name);
746 Set<std::string> clsNameInBrackets =
748 clsNameInBrackets.insert(demangledName.className);
749 return clsNameInBrackets;
750 }
751 else if (isTemplateFunc(foo))
752 {
753 // array index
755 assert(!classNames.empty() && "empty class names?");
756 return classNames;
757 }
758 return {};
759}
bool isTemplateFunc(const Function *foo)
whether foo is a cpp template function
Definition CppUtil.cpp:926
Set< std::string > getClsNamesInBrackets(const std::string &name)
Definition CppUtil.cpp:202
struct DemangledName demangle(const std::string &name)
Definition CppUtil.cpp:195
Set< std::string > extractClsNamesFromTemplate(const std::string &oname)
extract class names from template functions
Definition CppUtil.cpp:853
bool isConstructor(const Function *F)
Definition CppUtil.cpp:522
bool isDestructor(const Function *F)
Definition CppUtil.cpp:542
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition GeneralType.h:51

◆ extractClsNamesFromTemplate()

Set< std::string > SVF::cppUtil::extractClsNamesFromTemplate ( const std::string & oname)

extract class names from template functions

extract class names from template functions

Parameters
oname
Returns

Definition at line 853 of file CppUtil.cpp.

854{
855 // "std::array<A const*, 2ul>" -> A
856 // "std::queue<A*, std::deque<A*, std::allocator<A*> > >" -> A
857 // __gnu_cxx::__aligned_membuf<std::pair<int const, A> >::_M_ptr() const -> A
859 std::string demangleName = llvm::demangle(oname);
860 std::vector<std::string> innermosts = findInnermostBrackets(demangleName);
861 for (const auto &innermost: innermosts)
862 {
863 const std::vector<std::string> &allstrs = splitAndStrip(innermost, ',');
864 for (const auto &str: allstrs)
865 {
866 size_t spacePos = str.find(' ');
867 if (spacePos != std::string::npos)
868 {
869 // A const* -> A
870 ans.insert(str.substr(0, spacePos));
871 }
872 else
873 {
874 size_t starPos = str.find('*');
875 if (starPos != std::string::npos)
876 // A* -> A
877 ans.insert(str.substr(0, starPos));
878 else
879 ans.insert(str);
880 }
881 }
882 }
883 return ans;
884}
std::vector< std::string > findInnermostBrackets(const std::string &input)
Definition CppUtil.cpp:767
std::vector< std::string > splitAndStrip(const std::string &input, char delimiter)
Definition CppUtil.cpp:832

◆ getBeforeBrackets()

std::string SVF::cppUtil::getBeforeBrackets ( const std::string & name)

get class name before brackets e.g., for namespace::A<...::...>::f', we get namespace::A'

Definition at line 127 of file CppUtil.cpp.

128{
129 if (name.empty() || name[name.size() - 1] != '>')
130 {
131 return name;
132 }
133 s32_t bracket_num = 1, pos;
134 for (pos = name.size() - 2; pos >= 0; pos--)
135 {
136 if (name[pos] == '>')
137 bracket_num++;
138 if (name[pos] == '<')
139 bracket_num--;
140 if (bracket_num == 0)
141 break;
142 }
143 return name.substr(0, pos);
144}
signed s32_t
Definition GeneralType.h:68

◆ getClassNameFromType()

std::string SVF::cppUtil::getClassNameFromType ( const StructType * ty)

Definition at line 616 of file CppUtil.cpp.

617{
618 std::string className = "";
619 if (!((SVFUtil::cast<StructType>(ty))->isLiteral()))
620 {
621 std::string elemTypeName = ty->getStructName().str();
622 if (elemTypeName.compare(0, clsName.size(), clsName) == 0)
623 {
624 className = elemTypeName.substr(clsName.size());
625 }
626 else if (elemTypeName.compare(0, structName.size(), structName) == 0)
627 {
628 className = elemTypeName.substr(structName.size());
629 }
630 }
631 return className;
632}
const std::string structName
Definition CppUtil.cpp:56
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

◆ getClassNameFromVtblObj()

std::string SVF::cppUtil::getClassNameFromVtblObj ( const std::string & vtblName)

Definition at line 256 of file CppUtil.cpp.

257{
258 return getCXXABI()->extractClassName(vtblName);
259}
virtual std::string extractClassName(const std::string &name)=0

◆ getClassNameOfThisPtr()

Set< std::string > SVF::cppUtil::getClassNameOfThisPtr ( const CallBase * cs)

Definition at line 634 of file CppUtil.cpp.

635{
636 Set<std::string> thisPtrNames;
637 std::string thisPtrClassName = "";
638 if (const MDNode* N = inst->getMetadata("VCallPtrType"))
639 {
640 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
641 thisPtrClassName = mdstr->getString().str();
642 }
643 if (thisPtrClassName.size() == 0)
644 {
645 const Value* thisPtr = getVCallThisPtr(inst);
647 thisPtrNames.insert(names.begin(), names.end());
648 }
649
651 std::transform(thisPtrNames.begin(), thisPtrNames.end(), std::inserter(ans, ans.begin()),
652 [](const std::string &thisPtrName) -> std::string
653 {
654 size_t found = thisPtrName.find_last_not_of("0123456789");
655 if (found != std::string::npos)
656 {
657 if (found != thisPtrName.size() - 1 &&
658 thisPtrName[found] == '.')
659 {
660 return thisPtrName.substr(0, found);
661 }
662 }
663 return thisPtrName;
664 });
665 return ans;
666}
Set< std::string > & inferThisPtrClsName(const Value *thisPtr)
get or infer the class names of thisptr
const Value * getVCallThisPtr(const CallBase *cs)
Definition CppUtil.cpp:369
llvm::MDString MDString
Definition BasicTypes.h:99
llvm::MDNode MDNode
Definition BasicTypes.h:110

◆ getClsNamesInBrackets()

Set< std::string > SVF::cppUtil::getClsNamesInBrackets ( const std::string & name)

Definition at line 202 of file CppUtil.cpp.

203{
205 // Lambda to trim whitespace from both ends of a string
206 auto trim = [](std::string& s)
207 {
208 size_t first = s.find_first_not_of(' ');
209 size_t last = s.find_last_not_of(' ');
210 if (first != std::string::npos && last != std::string::npos)
211 {
212 s = s.substr(first, (last - first + 1));
213 }
214 else
215 {
216 s.clear();
217 }
218 };
219
220 // Lambda to remove trailing '*' and '&' characters
221 auto removePointerAndReference = [](std::string& s)
222 {
223 while (!s.empty() && (s.back() == '*' || s.back() == '&'))
224 {
225 s.pop_back();
226 }
227 };
228
229 const std::string realnameStr = llvm::demangle(name);
230 if (realnameStr != name && !realnameStr.empty())
231 {
232 // Find the start and end of the parameter list
233 size_t start = realnameStr.find('(');
234 size_t end = realnameStr.find(')');
235 if (start == std::string::npos || end == std::string::npos || start >= end)
236 {
237 return res; // Return empty set if the format is incorrect
238 }
239
240 // Extract the parameter list
241 std::string paramList = realnameStr.substr(start + 1, end - start - 1);
242
243 // Split the parameter list by commas
244 std::istringstream ss(paramList);
245 std::string param;
246 while (std::getline(ss, param, ','))
247 {
248 trim(param);
249 removePointerAndReference(param);
250 res.insert(param);
251 }
252 }
253 return res;
254}

◆ getConstructorThisPtr()

const Argument * SVF::cppUtil::getConstructorThisPtr ( const Function * fun)

Definition at line 486 of file CppUtil.cpp.

487{
488 assert((isConstructor(fun) || isDestructor(fun)) &&
489 "not a constructor?");
490 // We always need at least one argument to return something meaningful.
491 assert(fun->arg_size() >= 1 && "expected at least one argument");
492
493 // If param 0 is sret, 'this' is typically param 1, but be defensive.
494 const bool isStructRet = fun->hasParamAttribute(0, llvm::Attribute::StructRet);
495
496 // Prefer arg1 when sret is present and available; otherwise fall back to arg0.
497 const u32_t thisIdx = (isStructRet && fun->arg_size() >= 2) ? 1 : 0;
498 const Argument* thisPtr = fun->getArg(thisIdx);
499
500 return thisPtr;
501}
llvm::Argument Argument
Definition BasicTypes.h:146

◆ getCXXABI() [1/3]

CXXABI * SVF::cppUtil::getCXXABI ( )

Definition at line 1015 of file CppUtil.cpp.

1016{
1019 {
1020 return getCXXABI(
1021 LLVMModuleSet::getLLVMModuleSet()->getMainLLVMModule());
1022 }
1023 static ItaniumABI itaniumabi;
1024 return &itaniumabi;
1025}

◆ getCXXABI() [2/3]

CXXABI * SVF::cppUtil::getCXXABI ( const Module * M)

Definition at line 979 of file CppUtil.cpp.

980{
981 if (M)
982 {
983 llvm::Triple triple(M->getTargetTriple());
984 if (triple.isKnownWindowsMSVCEnvironment() ||
985 triple.isOSBinFormatCOFF())
986 {
987 static MSVCABI msvcabi;
988 return &msvcabi;
989 }
990 }
991 static ItaniumABI itaniumabi;
992 return &itaniumabi;
993}

◆ getCXXABI() [3/3]

CXXABI * SVF::cppUtil::getCXXABI ( const Value * val)

Definition at line 995 of file CppUtil.cpp.

996{
997 if (val)
998 {
999 if (const GlobalValue* GV = SVFUtil::dyn_cast<GlobalValue>(val))
1000 {
1001 return getCXXABI(GV->getParent());
1002 }
1003 if (const Instruction* I = SVFUtil::dyn_cast<Instruction>(val))
1004 {
1005 return getCXXABI(I->getFunction()->getParent());
1006 }
1007 if (const Argument* Arg = SVFUtil::dyn_cast<Argument>(val))
1008 {
1009 return getCXXABI(Arg->getParent()->getParent());
1010 }
1011 }
1012 return getCXXABI();
1013}
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
llvm::GlobalValue GlobalValue
Definition BasicTypes.h:86
llvm::Instruction Instruction
Definition BasicTypes.h:85

◆ getFunNameOfVCallSite()

std::string SVF::cppUtil::getFunNameOfVCallSite ( const CallBase * cs)

Definition at line 668 of file CppUtil.cpp.

669{
670 std::string funName;
671 if (const MDNode* N = inst->getMetadata("VCallFunName"))
672 {
673 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
674 funName = mdstr->getString().str();
675 }
676 return funName;
677}

◆ getThunkTarget()

const Function * SVF::cppUtil::getThunkTarget ( const Function * F)

Definition at line 347 of file CppUtil.cpp.

348{
349 const Function* ret = nullptr;
350
351 for (auto& bb : *F)
352 {
353 for (auto& inst : bb)
354 {
355 if (const CallBase* callbase = SVFUtil::dyn_cast<CallBase>(&inst))
356 {
357 // assert(cs.getCalledFunction() &&
358 // "Indirect call detected in thunk func");
359 // assert(ret == nullptr && "multiple callsites in thunk func");
360
361 ret = callbase->getCalledFunction();
362 }
363 }
364 }
365
366 return ret;
367}
llvm::CallBase CallBase
Definition BasicTypes.h:147
llvm::Function Function
Definition BasicTypes.h:83

◆ getVCallIdx()

s32_t SVF::cppUtil::getVCallIdx ( const CallBase * cs)

Definition at line 679 of file CppUtil.cpp.

680{
681 const LoadInst* vfuncloadinst =
682 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
683 assert(vfuncloadinst != nullptr);
684 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
685 const GetElementPtrInst* vfuncptrgepinst =
687 User::const_op_iterator oi = vfuncptrgepinst->idx_begin();
688 const ConstantInt* idx = SVFUtil::dyn_cast<ConstantInt>(oi->get());
689 s32_t idx_value;
690 if (idx == nullptr)
691 {
692 SVFUtil::errs() << "vcall gep idx not constantint\n";
693 idx_value = 0;
694 }
695 else
696 {
697 idx_value = LLVMUtil::getIntegerValue(idx).first;
698 }
699 return idx_value;
700}
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:95
std::ostream & errs()
Overwrite llvm::errs().
Definition SVFUtil.h:64
llvm::LoadInst LoadInst
Definition BasicTypes.h:150
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:163
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:123

◆ getVCallThisPtr()

const Value * SVF::cppUtil::getVCallThisPtr ( const CallBase * cs)

Definition at line 369 of file CppUtil.cpp.

370{
371 if (cs->paramHasAttr(0, llvm::Attribute::StructRet))
372 {
373 return cs->getArgOperand(1);
374 }
375 else
376 {
377 return cs->getArgOperand(0);
378 }
379}

◆ getVCallVtblPtr()

const Value * SVF::cppUtil::getVCallVtblPtr ( const CallBase * cs)

Definition at line 570 of file CppUtil.cpp.

571{
572 const LoadInst* loadInst =
573 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
574 assert(loadInst != nullptr);
575 const Value* vfuncptr = loadInst->getPointerOperand();
576 const GetElementPtrInst* gepInst =
578 assert(gepInst != nullptr);
579 const Value* vtbl = gepInst->getPointerOperand();
580 return vtbl;
581}

◆ getVtblStruct()

const ConstantStruct * SVF::cppUtil::getVtblStruct ( const GlobalValue * vtbl)

Definition at line 261 of file CppUtil.cpp.

262{
264 if (!global || !global->hasInitializer())
265 return nullptr;
266
267 Constant *initializer = SVFUtil::cast<Constant>(global->getOperand(0));
268 const ConstantStruct *vtblStruct = SVFUtil::dyn_cast<ConstantStruct>(initializer);
269 // cir2c emits a flat array rather than Clang's struct of arrays.
270 if (auto *array = SVFUtil::dyn_cast<ConstantArray>(initializer))
271 {
272 if (!array->getType()->getElementType()->isPointerTy())
273 return nullptr;
275 ConstantStruct::getAnon(vtbl->getContext(), {array}));
276 }
277 if (!vtblStruct)
278 return nullptr;
279
280 if (vtblStruct->getNumOperands() == 2 &&
281 SVFUtil::isa<ConstantStruct>(vtblStruct->getOperand(0)) &&
282 vtblStruct->getOperand(1)->getType()->isArrayTy())
283 vtblStruct = SVFUtil::cast<ConstantStruct>(vtblStruct->getOperand(0));
284
285 for (unsigned i = 0; i < vtblStruct->getNumOperands(); ++i)
286 {
287 const ConstantArray *array = SVFUtil::dyn_cast<ConstantArray>(vtblStruct->getOperand(i));
288 if (!array || !array->getType()->getElementType()->isPointerTy())
289 return nullptr;
290 }
291
292 return vtblStruct;
293}
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:131
llvm::ConstantStruct ConstantStruct
Definition BasicTypes.h:104
llvm::ConstantArray ConstantArray
Definition BasicTypes.h:121
llvm::Constant Constant
Definition BasicTypes.h:122

◆ isClsNameSource()

bool SVF::cppUtil::isClsNameSource ( const Value * val)

class sources can be heap allocation or functions where we can extract the class name (constructors/destructors or template functions)

class sources are functions where we can extract the class name (constructors/destructors or template functions)

Parameters
val
Returns

Definition at line 893 of file CppUtil.cpp.

894{
895 if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(val))
896 {
897 const Function *foo = callBase->getCalledFunction();
898 // indirect call
899 if(!foo) return false;
900 return isConstructor(foo) || isDestructor(foo) || isTemplateFunc(foo) || isDynCast(foo);
901 }
902 else if (const auto *func = SVFUtil::dyn_cast<Function>(val))
903 {
904 return isConstructor(func) || isDestructor(func) || isTemplateFunc(func);
905 }
906 return false;
907}
bool isDynCast(const Function *foo)
whether foo is a cpp dyncast function
Definition CppUtil.cpp:941

◆ isConstructor()

bool SVF::cppUtil::isConstructor ( const Function * F)

TODO: on mac os function name is an empty string after demangling

Definition at line 522 of file CppUtil.cpp.

523{
524 if (F->isDeclaration())
525 return false;
526 std::string funcName = F->getName().str();
527 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
528 {
529 return false;
530 }
531 struct cppUtil::DemangledName dname = cppUtil::demangle(funcName.c_str());
532 if (dname.className.size() == 0)
533 {
534 return false;
535 }
538 return dname.className.size() > 0 &&
539 dname.className.compare(dname.funcName) == 0;
540}
void stripBracketsAndNamespace(cppUtil::DemangledName &dname)
Definition CppUtil.cpp:505
const std::string vfunPreLabel
Definition CppUtil.cpp:53

◆ isCPPThunkFunction()

bool SVF::cppUtil::isCPPThunkFunction ( const Function * F)

Definition at line 341 of file CppUtil.cpp.

342{
343 cppUtil::DemangledName dname = cppUtil::demangle(F->getName().str());
344 return dname.isThunkFunc;
345}

◆ isDestructor()

bool SVF::cppUtil::isDestructor ( const Function * F)

Definition at line 542 of file CppUtil.cpp.

543{
544 if (F->isDeclaration())
545 return false;
546 std::string funcName = F->getName().str();
547 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
548 {
549 return false;
550 }
551 struct cppUtil::DemangledName dname = cppUtil::demangle(funcName.c_str());
552 if (dname.className.size() == 0)
553 {
554 return false;
555 }
557 return (dname.className.size() > 0 && dname.funcName.size() > 0 &&
558 dname.className.size() + 1 == dname.funcName.size() &&
559 dname.funcName.compare(0, 1, "~") == 0 &&
560 dname.className.compare(dname.funcName.substr(1)) == 0);
561}

◆ isDynCast()

bool SVF::cppUtil::isDynCast ( const Function * foo)

whether foo is a cpp dyncast function

whether foo is a cpp dyncast function

Parameters
foo
Returns

Definition at line 941 of file CppUtil.cpp.

942{
943 return foo->getName().str() == dyncast;
944}
const std::string dyncast
Definition CppUtil.cpp:81

◆ isSameThisPtrInConstructor()

bool SVF::cppUtil::isSameThisPtrInConstructor ( const Argument * thisPtr1,
const Value * thisPtr2 )

Given an inheritance relation B is a child of A We assume B::B(thisPtr1){ A::A(thisPtr2) } such that thisPtr1 == thisPtr2

=== Typed pointer mode === this.addr = alloca class.B1* store class.B1* this, class.B1** this.addr this1 = load class.B1*, class.B1** this.addr %0 = bitcast class.B1* this1 to class.A* call void @A::A()(class.A* %0)

=== Opaque pointer mode ===

Case 1: Primary base class (offset 0) at O1+ call ptr @Base::Base(ptr this) → thisPtr2 == thisPtr1, return true

Case 2: Primary base class (offset 0) at O0 this.addr = alloca ptr store ptr this, ptr this.addr this1 = load ptr, ptr this.addr call void @Base::Base(ptr this1) → thisPtr2 is LoadInst from alloca storing thisPtr1, return true

Case 3: Non-primary base class (multiple inheritance, offset > 0) %0 = getelementptr inbounds i8, ptr this1, i64 4 call void @Base2::Base2(ptr %0) → i8 GEP from this, return true

Case 4: Member field initialization (NOT base class) mem = getelementptr inbounds struct.Derived, ptr this1, i32 0, i32 1 call void @Member::Member(ptr mem) → struct GEP from this, return false

Definition at line 442 of file CppUtil.cpp.

444{
445 if (thisPtr1 == thisPtr2)
446 return true;
447
448 const Value* stripped = thisPtr2->stripPointerCasts();
449 if (stripped == thisPtr1)
450 return true;
451
452 // === Opaque pointer: Load from this.addr (Case 2: primary base at O0) ===
453 if (isDerivedFromThisPtr(thisPtr1, stripped))
454 return true;
455
456 // === Opaque pointer: GEP check (Case 3 & 4) ===
458 {
459 if (!isDerivedFromThisPtr(thisPtr1, GEP->getPointerOperand()))
460 return false;
461 // i8 GEP = non-primary base class (Case 3)
462 // struct GEP = member field (Case 4)
463 return GEP->getSourceElementType()->isIntegerTy(8);
464 }
465
466 // === Typed pointer (legacy): store -> load -> bitcast ===
467 for (const Value* thisU : thisPtr1->users())
468 {
469 if (const StoreInst* store = SVFUtil::dyn_cast<StoreInst>(thisU))
470 {
471 for (const Value* storeU : store->getPointerOperand()->users())
472 {
473 if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(storeU))
474 {
475 if (load->getNextNode() &&
476 SVFUtil::isa<CastInst>(load->getNextNode()))
477 return SVFUtil::cast<CastInst>(load->getNextNode()) ==
478 (thisPtr2->stripPointerCasts());
479 }
480 }
481 }
482 }
483 return false;
484}
static bool isDerivedFromThisPtr(const Argument *thisPtr, const Value *V)
Definition CppUtil.cpp:383
llvm::StoreInst StoreInst
Definition BasicTypes.h:149

◆ isTemplateFunc()

bool SVF::cppUtil::isTemplateFunc ( const Function * foo)

whether foo is a cpp template function

whether foo is a cpp template function TODO: we only consider limited label for now (see the very beginning of CppUtil.cpp)

Parameters
foo
Returns

Definition at line 926 of file CppUtil.cpp.

927{
928 const std::string &name = foo->getName().str();
929 bool matchedLabel = matchesLabel(name, znstLabel) || matchesLabel(name, znkstLabel) ||
931 // we exclude "_ZNK6cArray3dupEv" -> cArray::dup() const
932 const std::string &demangledName = llvm::demangle(name);
933 return matchedLabel && demangledName.find('<') != std::string::npos && demangledName.find('>') != std::string::npos;
934}
const std::string znstLabel
Definition CppUtil.cpp:61
const std::string znkstLabel
Definition CppUtil.cpp:69
const std::string znkLabel
Definition CppUtil.cpp:76
bool matchesLabel(const std::string &foo, const std::string &label)
whether foo matches the mangler label
Definition CppUtil.cpp:915

◆ isValVtbl()

bool SVF::cppUtil::isValVtbl ( const Value * val)

A carefully crafted input such as FakeVTable _ZTV1A = {{nullptr, nullptr}}; can forge a vtable; detection is approximate and heuristic.

Definition at line 295 of file CppUtil.cpp.

296{
298 return false;
299 std::string valName = val->getName().str();
300 return getCXXABI(val)->isVtable(valName);
301}
virtual bool isVtable(const std::string &name)=0

◆ isVirtualCallSite()

bool SVF::cppUtil::isVirtualCallSite ( const CallBase * cs)

Definition at line 310 of file CppUtil.cpp.

311{
312 // the callsite must be an indirect one with at least one argument (this
313 // ptr)
314 if (cs->getCalledFunction() != nullptr || cs->arg_empty())
315 return false;
316
317 // the first argument (this pointer) must be a pointer type and must be a
318 // class name
319 if (cs->getArgOperand(0)->getType()->isPointerTy() == false)
320 return false;
321
322 const Value* vfunc = cs->getCalledOperand();
323 if (const LoadInst* vfuncloadinst = SVFUtil::dyn_cast<LoadInst>(vfunc))
324 {
325 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
326 if (const GetElementPtrInst* vfuncptrgepinst =
328 {
329 if (vfuncptrgepinst->getNumIndices() != 1)
330 return false;
331 const Value* vtbl = vfuncptrgepinst->getPointerOperand();
332 if (SVFUtil::isa<LoadInst>(vtbl))
333 {
334 return true;
335 }
336 }
337 }
338 return false;
339}

◆ matchesLabel()

bool SVF::cppUtil::matchesLabel ( const std::string & foo,
const std::string & label )

whether foo matches the mangler label

whether fooName matches the mangler label

Parameters
foo
label
Returns

Definition at line 915 of file CppUtil.cpp.

916{
917 return foo.compare(0, label.size(), label) == 0;
918}

◆ VCallInCtorOrDtor()

bool SVF::cppUtil::VCallInCtorOrDtor ( const CallBase * cs)

Definition at line 586 of file CppUtil.cpp.

587{
588 Set<std::string> classNameOfThisPtrs = cppUtil::getClassNameOfThisPtr(cs);
589 const Function* func = cs->getCaller();
590 for (const auto &classNameOfThisPtr: classNameOfThisPtrs)
591 {
593 {
594 cppUtil::DemangledName dname = cppUtil::demangle(func->getName().str());
595 if (classNameOfThisPtr.compare(dname.className) == 0)
596 return true;
597 }
598 }
599 return false;
600}
Set< std::string > getClassNameOfThisPtr(const CallBase *cs)
Definition CppUtil.cpp:634