38#include "llvm/Demangle/Demangle.h"
59const std::string
znwm =
"_Znwm";
81const std::string
dyncast =
"__dynamic_cast";
86 u32_t leftnum = 0, rightnum = 0;
87 std::string subname =
name;
88 size_t leftpos, rightpos;
89 leftpos = subname.find(
'<');
90 while (leftpos != std::string::npos)
92 subname = subname.substr(leftpos + 1);
93 leftpos = subname.find(
'<');
97 rightpos = subname.find(
'>');
98 while (rightpos != std::string::npos)
100 subname = subname.substr(rightpos + 1);
101 rightpos = subname.find(
'>');
104 return leftnum != rightnum;
109 size_t lastRightParen =
name.rfind(
')');
110 assert(lastRightParen > 0);
112 s32_t paren_num = 1, pos;
113 for (pos = lastRightParen - 1; pos >= 0; pos--)
115 if (
name[pos] ==
')')
117 if (
name[pos] ==
'(')
122 return name.substr(0, pos);
133 s32_t bracket_num = 1, pos;
134 for (pos =
name.size() - 2; pos >= 0; pos--)
136 if (
name[pos] ==
'>')
138 if (
name[pos] ==
'<')
140 if (bracket_num == 0)
143 return name.substr(0, pos);
161 for (
unsigned i = 0; i < thunkPrefixes.size(); i++)
163 auto prefix = thunkPrefixes[i];
164 if (dname.
className.size() > prefix.size() &&
165 dname.
className.compare(0, prefix.size(), prefix) == 0)
206 auto trim = [](std::string& s)
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)
212 s = s.substr(first, (last - first + 1));
221 auto removePointerAndReference = [](std::string& s)
223 while (!s.empty() && (s.back() ==
'*' || s.back() ==
'&'))
229 const std::string realnameStr = llvm::demangle(
name);
230 if (realnameStr !=
name && !realnameStr.empty())
233 size_t start = realnameStr.find(
'(');
234 size_t end = realnameStr.find(
')');
235 if (start == std::string::npos || end == std::string::npos || start >= end)
241 std::string paramList = realnameStr.substr(start + 1, end - start - 1);
244 std::istringstream ss(paramList);
246 while (std::getline(ss, param,
','))
249 removePointerAndReference(param);
258 return getCXXABI()->extractClassName(vtblName);
264 if (!global || !global->hasInitializer())
272 if (!array->getType()->getElementType()->isPointerTy())
275 ConstantStruct::getAnon(vtbl->getContext(), {array}));
280 if (vtblStruct->getNumOperands() == 2 &&
282 vtblStruct->getOperand(1)->getType()->isArrayTy())
285 for (
unsigned i = 0; i < vtblStruct->getNumOperands(); ++i)
288 if (!array || !array->getType()->getElementType()->isPointerTy())
299 std::string valName = val->getName().str();
300 return getCXXABI(val)->isVtable(valName);
314 if (cs->getCalledFunction() !=
nullptr || cs->arg_empty())
319 if (cs->getArgOperand(0)->getType()->isPointerTy() ==
false)
322 const Value* vfunc = cs->getCalledOperand();
325 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
329 if (vfuncptrgepinst->getNumIndices() != 1)
331 const Value* vtbl = vfuncptrgepinst->getPointerOperand();
353 for (
auto& inst : bb)
361 ret = callbase->getCalledFunction();
371 if (cs->paramHasAttr(0, llvm::Attribute::StructRet))
373 return cs->getArgOperand(1);
377 return cs->getArgOperand(0);
385 V = V->stripPointerCasts();
394 for (
const User* U : alloca->users())
398 if (store->getPointerOperand() == alloca &&
399 store->getValueOperand()->stripPointerCasts() == thisPtr)
443 const Value* thisPtr2)
445 if (thisPtr1 == thisPtr2)
448 const Value* stripped = thisPtr2->stripPointerCasts();
449 if (stripped == thisPtr1)
463 return GEP->getSourceElementType()->isIntegerTy(8);
467 for (
const Value* thisU : thisPtr1->users())
471 for (
const Value* storeU : store->getPointerOperand()->users())
475 if (load->getNextNode() &&
478 (thisPtr2->stripPointerCasts());
489 "not a constructor?");
491 assert(fun->arg_size() >= 1 &&
"expected at least one argument");
494 const bool isStructRet = fun->hasParamAttribute(0, llvm::Attribute::StructRet);
497 const u32_t thisIdx = (isStructRet && fun->arg_size() >= 2) ? 1 : 0;
498 const Argument* thisPtr = fun->getArg(thisIdx);
509 size_t colon = dname.
className.rfind(
"::");
510 if (colon == std::string::npos)
524 if (F->isDeclaration())
526 std::string funcName = F->getName().str();
544 if (F->isDeclaration())
546 std::string
funcName = F->getName().str();
559 dname.
funcName.compare(0, 1,
"~") == 0 &&
574 assert(loadInst !=
nullptr);
575 const Value* vfuncptr = loadInst->getPointerOperand();
578 assert(gepInst !=
nullptr);
579 const Value* vtbl = gepInst->getPointerOperand();
589 const Function* func = cs->getCaller();
590 for (
const auto &classNameOfThisPtr: classNameOfThisPtrs)
595 if (classNameOfThisPtr.compare(dname.
className) == 0)
606 for(
auto it = ty->element_begin(); it!=ty->element_end(); it++)
609 if (str.find(
vtableType) != std::string::npos)
621 std::string elemTypeName = ty->getStructName().str();
637 std::string thisPtrClassName =
"";
638 if (
const MDNode* N = inst->getMetadata(
"VCallPtrType"))
641 thisPtrClassName = mdstr->getString().str();
643 if (thisPtrClassName.size() == 0)
647 thisPtrNames.insert(names.begin(), names.end());
651 std::transform(thisPtrNames.begin(), thisPtrNames.end(), std::inserter(ans, ans.begin()),
652 [](
const std::string &thisPtrName) -> std::string
654 size_t found = thisPtrName.find_last_not_of(
"0123456789");
655 if (found != std::string::npos)
657 if (found != thisPtrName.size() - 1 &&
658 thisPtrName[found] ==
'.')
660 return thisPtrName.substr(0, found);
671 if (
const MDNode* N = inst->getMetadata(
"VCallFunName"))
674 funName = mdstr->getString().str();
683 assert(vfuncloadinst !=
nullptr);
684 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
687 User::const_op_iterator oi = vfuncptrgepinst->idx_begin();
711 else if (!v->hasInitializer())
713 return !v->isExternalLinkage(v->getLinkage());
719 for (std::vector<const SVFType*>::const_iterator it = fields.begin(), eit = fields.end(); it != eit; ++it)
727 return v->isConstant();
741 const std::string &
name = foo->getName().str();
748 clsNameInBrackets.insert(demangledName.
className);
749 return clsNameInBrackets;
755 assert(!classNames.empty() &&
"empty class names?");
769 typedef std::pair<u32_t, u32_t> StEdIdxPair;
770 std::stack<int>
stack;
771 std::vector<StEdIdxPair> innerMostPairs;
772 std::vector<bool> used(input.length(),
false);
774 for (
u32_t i = 0; i < input.length(); ++i)
780 else if (input[i] ==
'>' && i > 0 && input[i - 1] !=
'-')
784 int openIndex =
stack.top();
788 bool isInnermost =
true;
789 for (
u32_t j = openIndex + 1; j < i && isInnermost; ++j)
799 innerMostPairs.emplace_back(openIndex, i);
800 used[openIndex] = used[i] =
true;
805 std::vector<std::string> ans(innerMostPairs.size());
806 std::transform(innerMostPairs.begin(), innerMostPairs.end(), ans.begin(), [&input](StEdIdxPair &
p) -> std::string
808 return input.substr(p.first + 1, p.second - p.first - 1);
820 auto start = std::find_if(str.begin(), str.end(), [](
unsigned char ch)
822 return !std::isspace(ch);
824 auto end = std::find_if(str.rbegin(), str.rend(), [](
unsigned char ch)
826 return !std::isspace(ch);
829 return (start < end) ? std::string(start, end) : std::string();
832std::vector<std::string>
splitAndStrip(
const std::string &input,
char delimiter)
834 std::vector<std::string> tokens;
835 size_t start = 0, end = 0;
837 while ((end = input.find(delimiter, start)) != std::string::npos)
859 std::string demangleName = llvm::demangle(oname);
861 for (
const auto &innermost: innermosts)
863 const std::vector<std::string> &allstrs =
splitAndStrip(innermost,
',');
864 for (
const auto &str: allstrs)
866 size_t spacePos = str.find(
' ');
867 if (spacePos != std::string::npos)
870 ans.insert(str.substr(0, spacePos));
874 size_t starPos = str.find(
'*');
875 if (starPos != std::string::npos)
877 ans.insert(str.substr(0, starPos));
897 const Function *foo = callBase->getCalledFunction();
899 if(!foo)
return false;
917 return foo.compare(0, label.size(), label) == 0;
928 const std::string &
name = foo->getName().str();
932 const std::string &demangledName = llvm::demangle(
name);
933 return matchedLabel && demangledName.find(
'<') != std::string::npos && demangledName.find(
'>') != std::string::npos;
943 return foo->getName().str() ==
dyncast;
953 Value *tgtCast = callBase->getArgOperand(2);
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(),
963 assert(realName !=
"" &&
"real name for dyncast empty?");
983 llvm::Triple triple(M->getTargetTriple());
984 if (triple.isKnownWindowsMSVCEnvironment() ||
985 triple.isOSBinFormatCOFF())
1005 return getCXXABI(I->getFunction()->getParent());
1009 return getCXXABI(Arg->getParent()->getParent());
1067 dname.
funcName.compare(0, 1,
"~") == 0 &&
1073 std::string className =
"";
1074 std::string realnameStr = llvm::demangle(
name);
1075 if (realnameStr !=
name)
1091 std::string realnameStr = llvm::demangle(
name);
1092 if (realnameStr ==
name)
1100 if (beforeParenthesis.find(
"::") == std::string::npos ||
1109 size_t colon = beforeBracket.rfind(
"::");
1110 if (colon == std::string::npos)
1117 dname.
className = beforeParenthesis.substr(0, colon);
1118 dname.
funcName = beforeParenthesis.substr(colon + 2);
1130 return name.compare(0, 4,
"??_7") == 0 ||
name.compare(0, 4,
"??_8") == 0;
1135 return name.compare(0, 4,
"??_R") == 0;
1140 return name.compare(0, 3,
"??0") == 0;
1145 return name.compare(0, 3,
"??1") == 0;
1150 std::string className =
"";
1151 std::string realnameStr = llvm::demangle(
name);
1152 size_t pos = realnameStr.rfind(
"::`vftable'");
1153 if (pos == std::string::npos)
1155 pos = realnameStr.rfind(
"::`vbtable'");
1157 if (pos != std::string::npos)
1159 className = realnameStr.substr(0, pos);
1160 if (className.compare(0, 6,
"const ") == 0)
1162 className = className.substr(6);
1173 std::string realnameStr = llvm::demangle(
name);
1174 if (realnameStr ==
name)
1181 if (realnameStr.find(
"[thunk]") != std::string::npos ||
1182 realnameStr.find(
"`vcall'") != std::string::npos ||
1183 realnameStr.find(
"`adjustor'") != std::string::npos)
1189 if (beforeParenthesis.find(
"::") == std::string::npos ||
1198 size_t colon = beforeBracket.rfind(
"::");
1199 if (colon == std::string::npos)
1206 std::string classNamePart = beforeParenthesis.substr(0, colon);
1207 dname.
funcName = beforeParenthesis.substr(colon + 2);
1209 int i = classNamePart.size() - 1;
1210 int bracketDepth = 0;
1213 char c = classNamePart[i];
1223 if (bracketDepth > 0)
1229 if (std::isalnum(c) || c ==
'_' || c ==
':' || c ==
'<' ||
1240 dname.
className = classNamePart.substr(i + 1);
const std::string znst6Label
const std::string znkst23Label
const std::string vtblLabelBeforeDemangle
static void handleThunkFunction(cppUtil::DemangledName &dname)
static bool isOperOverload(const std::string &name)
const std::string VThunkFuncLabel
static std::string getBeforeParenthesis(const std::string &name)
const std::string znkst20Label
const std::string znst5Label
const std::string vtblLabelAfterDemangle
static bool isDerivedFromThisPtr(const Argument *thisPtr, const Value *V)
const std::string clsName
const std::string structName
const std::string znstLabel
std::string stripWhitespaces(const std::string &str)
const std::string zn1Label
std::vector< std::string > findInnermostBrackets(const std::string &input)
const std::string znkstLabel
const std::string znst7Label
const std::string dyncast
const std::string znst12Label
const std::string NVThunkFunLabel
const std::string znkLabel
const std::string vtableType
const std::string ztilabel
std::vector< std::string > splitAndStrip(const std::string &input, char delimiter)
const std::string znst14Label
const std::string znk9Label
const std::string znkst5Label
void stripBracketsAndNamespace(cppUtil::DemangledName &dname)
const std::string ztiprefix
const std::string vfunPreLabel
static LLVMModuleSet * getLLVMModuleSet()
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
ObjTypeInference * getTypeInference()
Set< std::string > & inferThisPtrClsName(const Value *thisPtr)
get or infer the class names of thisptr
const Type * ptrType()
pointer type
std::vector< const SVFType * > & getFlattenFieldTypes()
virtual DemangledName demangle(const std::string &name)=0
std::string extractClassName(const std::string &name) override
bool isVtable(const std::string &name) override
bool isDestructor(const std::string &name) override
bool isConstructor(const std::string &name) override
DemangledName demangle(const std::string &name) override
bool isTypeInfo(const std::string &name) override
bool isTypeInfo(const std::string &name) override
DemangledName demangle(const std::string &name) override
bool isDestructor(const std::string &name) override
bool isVtable(const std::string &name) override
bool isConstructor(const std::string &name) override
std::string extractClassName(const std::string &name) override
bool isConstantObjSym(const Value *val)
Check whether this value points-to a constant object.
std::string dumpType(const Type *type)
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
std::string dumpValue(const Value *val)
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
LLVM_NODISCARD bool isa(const Y &Val)
std::ostream & errs()
Overwrite llvm::errs().
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
std::string getFunNameOfVCallSite(const CallBase *cs)
std::string getBeforeBrackets(const std::string &name)
const Argument * getConstructorThisPtr(const Function *fun)
std::string extractClsNameFromDynCast(const CallBase *callBase)
extract class name from cpp dyncast function
s32_t getVCallIdx(const CallBase *cs)
const Value * getVCallVtblPtr(const CallBase *cs)
bool isTemplateFunc(const Function *foo)
whether foo is a cpp template function
bool classTyHasVTable(const StructType *ty)
bool isSameThisPtrInConstructor(const Argument *thisPtr1, const Value *thisPtr2)
Set< std::string > getClsNamesInBrackets(const std::string &name)
const Value * getVCallThisPtr(const CallBase *cs)
bool matchesLabel(const std::string &foo, const std::string &label)
whether foo matches the mangler label
std::string getClassNameFromType(const StructType *ty)
struct DemangledName demangle(const std::string &name)
Set< std::string > getClassNameOfThisPtr(const CallBase *cs)
bool isCPPThunkFunction(const Function *F)
bool VCallInCtorOrDtor(const CallBase *cs)
bool isClsNameSource(const Value *val)
Set< std::string > extractClsNamesFromTemplate(const std::string &oname)
extract class names from template functions
bool isVirtualCallSite(const CallBase *cs)
const Type * cppClsNameToType(const std::string &className)
const Function * getThunkTarget(const Function *F)
const ConstantStruct * getVtblStruct(const GlobalValue *vtbl)
bool isConstructor(const Function *F)
std::string getClassNameFromVtblObj(const std::string &vtblName)
Set< std::string > extractClsNamesFromFunc(const Function *foo)
extract class name from the c++ function name, e.g., constructor/destructors
bool isValVtbl(const Value *val)
A carefully crafted input such as FakeVTable _ZTV1A = {{nullptr, nullptr}}; can forge a vtable; detec...
bool isDestructor(const Function *F)
bool isDynCast(const Function *foo)
whether foo is a cpp dyncast function
llvm::GlobalVariable GlobalVariable
llvm::ConstantStruct ConstantStruct
llvm::StructType StructType
LLVM types.
llvm::AllocaInst AllocaInst
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
llvm::ConstantArray ConstantArray
llvm::GlobalValue GlobalValue
llvm::Instruction Instruction
llvm::Value Value
LLVM Basic classes.
llvm::StoreInst StoreInst
llvm::GetElementPtrInst GetElementPtrInst
llvm::ConstantInt ConstantInt