Static Value-Flow Analysis
Loading...
Searching...
No Matches
CppUtil.cpp
Go to the documentation of this file.
1//===- CPPUtil.cpp -- Base class of pointer analyses -------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <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 * CPPUtil.cpp
25 *
26 * Created on: Apr 13, 2016
27 * Author: Xiaokang Fan
28 */
29
30#include "SVF-LLVM/CppUtil.h"
31#include "SVF-LLVM/BasicTypes.h"
32#include "SVF-LLVM/LLVMUtil.h"
33#include "Util/Casting.h"
34#include "Util/SVFUtil.h"
35#include "SVF-LLVM/LLVMModule.h"
37
38#include "llvm/Demangle/Demangle.h"
39
40using namespace SVF;
41
42// label for global vtbl value before demangle
43const std::string vtblLabelAfterDemangle = "vtable for ";
44
45// label for multi inheritance virtual function
46const std::string NVThunkFunLabel = "non-virtual thunk to ";
47const std::string VThunkFuncLabel = "virtual thunk to ";
48
49// label for global vtbl value before demangle
50const std::string vtblLabelBeforeDemangle = "_ZTV";
51
52// label for virtual functions
53const std::string vfunPreLabel = "_Z";
54
55const std::string clsName = "class.";
56const std::string structName = "struct.";
57const std::string vtableType = "(...)**";
58
59const std::string znwm = "_Znwm";
60const std::string zn1Label = "_ZN1"; // c++ constructor
61const std::string znstLabel = "_ZNSt";
62const std::string znst5Label = "_ZNSt5"; // _ZNSt5dequeIPK1ASaIS2_EE5frontEv -> std::deque<A const*, std::allocator<A const*> >::front()
63const std::string znst12Label = "_ZNSt12"; // _ZNSt12forward_listIPK1ASaIS2_EEC2Ev -> std::forward_list<A const*, std::allocator<A const*> >::forward_list()
64const std::string znst6Label = "_ZNSt6"; // _ZNSt6vectorIP1ASaIS1_EEC2Ev -> std::vector<A*, std::allocator<A*> >::vector()
65const std::string znst7Label = "_ZNSt7"; // _ZNSt7__cxx114listIPK1ASaIS3_EEC2Ev -> std::__cxx11::list<A const*, std::allocator<A const*> >::list()
66const std::string znst14Label = "_ZNSt14"; // _ZNSt14_Fwd_list_baseI1ASaIS0_EEC2Ev -> std::_Fwd_list_base<A, std::allocator<A> >::_Fwd_list_base()
67
68
69const std::string znkstLabel = "_ZNKSt";
70const std::string znkst5Label = "_ZNKSt15_"; // _ZNKSt15_Deque_iteratorIPK1ARS2_PS2_EdeEv -> std::_Deque_iterator<A const*, A const*&, A const**>::operator*() const
71const std::string znkst20Label = "_ZNKSt20_"; // _ZNKSt20_List_const_iteratorIPK1AEdeEv -> std::_List_const_iterator<A const*>::operator*() const
72
73const std::string znkst23Label = "_ZNKSt23_"; // _ZNKSt23_Rb_tree_const_iteratorISt4pairIKi1AEEptEv -> std::_List_const_iterator<A const*>::operator*() const
74
75
76const std::string znkLabel = "_ZNK";
77const std::string znk9Label = "_ZNK9"; // _ZNK9__gnu_cxx17__normal_iteratorIPK1ASt6vectorIS1_SaIS1_EEEdeEv -> __gnu_cxx::__normal_iterator<A const*, std::vector<A, std::allocator<A> > >::operator*() const
78
79const std::string ztilabel = "_ZTI";
80const std::string ztiprefix = "typeinfo for ";
81const std::string dyncast = "__dynamic_cast";
82
83
84static bool isOperOverload(const std::string& name)
85{
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)
91 {
92 subname = subname.substr(leftpos + 1);
93 leftpos = subname.find('<');
94 leftnum++;
95 }
96 subname = name;
97 rightpos = subname.find('>');
98 while (rightpos != std::string::npos)
99 {
100 subname = subname.substr(rightpos + 1);
101 rightpos = subname.find('>');
102 rightnum++;
103 }
104 return leftnum != rightnum;
105}
106
107static std::string getBeforeParenthesis(const std::string& name)
108{
109 size_t lastRightParen = name.rfind(')');
111
112 s32_t paren_num = 1, pos;
113 for (pos = lastRightParen - 1; pos >= 0; pos--)
114 {
115 if (name[pos] == ')')
116 paren_num++;
117 if (name[pos] == '(')
118 paren_num--;
119 if (paren_num == 0)
120 break;
121 }
122 return name.substr(0, pos);
123}
124
127std::string cppUtil::getBeforeBrackets(const std::string& name)
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}
145
147{
148 // when handling multi-inheritance,
149 // the compiler may generate thunk functions
150 // to perform `this` pointer adjustment
151 // they are indicated with `virtual thunk to `
152 // and `nun-virtual thunk to`.
153 // if the classname starts with part of a
154 // demangled name starts with
155 // these prefixes, we need to remove the prefix
156 // to get the real class name
157
158 static std::vector<std::string> thunkPrefixes = {VThunkFuncLabel,
160 };
161 for (unsigned i = 0; i < thunkPrefixes.size(); i++)
162 {
163 auto prefix = thunkPrefixes[i];
164 if (dname.className.size() > prefix.size() &&
165 dname.className.compare(0, prefix.size(), prefix) == 0)
166 {
167 dname.className = dname.className.substr(prefix.size());
168 dname.isThunkFunc = true;
169 return;
170 }
171 }
172}
173
174/*
175 * input: _ZN****
176 * after abi::__cxa_demangle:
177 * namespace::A<...::...>::f<...::...>(...)
178 * ^
179 * delimiter
180 *
181 * step1: getBeforeParenthesis
182 * namespace::A<...::...>::f<...::...>
183 *
184 * step2: getBeforeBrackets
185 * namespace::A<...::...>::f
186 *
187 * step3: find delimiter
188 * namespace::A<...::...>::
189 * ^
190 *
191 * className: namespace::A<...::...>
192 * functionName: f<...::...>
193 */
194
195struct cppUtil::DemangledName cppUtil::demangle(const std::string& name)
196{
197 return getCXXABI()->demangle(name);
198}
199
200// Extract class name in parameters
201// e.g., given "WithSemaphore::WithSemaphore(AP_HAL::Semaphore&)", return "AP_HAL::Semaphore"
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);
250 res.insert(param);
251 }
252 }
253 return res;
254}
255
256std::string cppUtil::getClassNameFromVtblObj(const std::string& vtblName)
257{
259}
260
262{
263 const ConstantStruct *vtblStruct = SVFUtil::dyn_cast<ConstantStruct>(vtbl->getOperand(0));
264 assert(vtblStruct && "Initializer of a vtable not a struct?");
265
266 if (vtblStruct->getNumOperands() == 2 &&
267 SVFUtil::isa<ConstantStruct>(vtblStruct->getOperand(0)) &&
268 vtblStruct->getOperand(1)->getType()->isArrayTy())
269 return SVFUtil::cast<ConstantStruct>(vtblStruct->getOperand(0));
270
271 return vtblStruct;
272}
273
275{
276 if (!SVFUtil::isa<GlobalVariable>(val))
277 return false;
278 std::string valName = val->getName().str();
279 return getCXXABI(val)->isVtable(valName);
280}
281
282/*
283 * a virtual callsite follows the following instruction sequence pattern:
284 * %vtable = load this
285 * %vfn = getelementptr %vtable, idx
286 * %x = load %vfn
287 * call %x (this)
288 */
290{
291 // the callsite must be an indirect one with at least one argument (this
292 // ptr)
293 if (cs->getCalledFunction() != nullptr || cs->arg_empty())
294 return false;
295
296 // the first argument (this pointer) must be a pointer type and must be a
297 // class name
298 if (cs->getArgOperand(0)->getType()->isPointerTy() == false)
299 return false;
300
301 const Value* vfunc = cs->getCalledOperand();
302 if (const LoadInst* vfuncloadinst = SVFUtil::dyn_cast<LoadInst>(vfunc))
303 {
304 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
306 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr))
307 {
308 if (vfuncptrgepinst->getNumIndices() != 1)
309 return false;
310 const Value* vtbl = vfuncptrgepinst->getPointerOperand();
311 if (SVFUtil::isa<LoadInst>(vtbl))
312 {
313 return true;
314 }
315 }
316 }
317 return false;
318}
319
321{
322 cppUtil::DemangledName dname = cppUtil::demangle(F->getName().str());
323 return dname.isThunkFunc;
324}
325
327{
328 const Function* ret = nullptr;
329
330 for (auto& bb : *F)
331 {
332 for (auto& inst : bb)
333 {
334 if (const CallBase* callbase = SVFUtil::dyn_cast<CallBase>(&inst))
335 {
336 // assert(cs.getCalledFunction() &&
337 // "Indirect call detected in thunk func");
338 // assert(ret == nullptr && "multiple callsites in thunk func");
339
340 ret = callbase->getCalledFunction();
341 }
342 }
343 }
344
345 return ret;
346}
347
349{
350 if (cs->paramHasAttr(0, llvm::Attribute::StructRet))
351 {
352 return cs->getArgOperand(1);
353 }
354 else
355 {
356 return cs->getArgOperand(0);
357 }
358}
359
362static bool isDerivedFromThisPtr(const Argument* thisPtr, const Value* V)
363{
364 V = V->stripPointerCasts();
365 if (V == thisPtr)
366 return true;
367
368 if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(V))
369 {
370 if (const AllocaInst* alloca =
371 SVFUtil::dyn_cast<AllocaInst>(load->getPointerOperand()))
372 {
373 for (const User* U : alloca->users())
374 {
375 if (const StoreInst* store = SVFUtil::dyn_cast<StoreInst>(U))
376 {
377 if (store->getPointerOperand() == alloca &&
378 store->getValueOperand()->stripPointerCasts() == thisPtr)
379 return true;
380 }
381 }
382 }
383 }
384 return false;
385}
386
422 const Value* thisPtr2)
423{
424 if (thisPtr1 == thisPtr2)
425 return true;
426
427 const Value* stripped = thisPtr2->stripPointerCasts();
428 if (stripped == thisPtr1)
429 return true;
430
431 // === Opaque pointer: Load from this.addr (Case 2: primary base at O0) ===
433 return true;
434
435 // === Opaque pointer: GEP check (Case 3 & 4) ===
436 if (const GetElementPtrInst* GEP = SVFUtil::dyn_cast<GetElementPtrInst>(stripped))
437 {
438 if (!isDerivedFromThisPtr(thisPtr1, GEP->getPointerOperand()))
439 return false;
440 // i8 GEP = non-primary base class (Case 3)
441 // struct GEP = member field (Case 4)
442 return GEP->getSourceElementType()->isIntegerTy(8);
443 }
444
445 // === Typed pointer (legacy): store -> load -> bitcast ===
446 for (const Value* thisU : thisPtr1->users())
447 {
448 if (const StoreInst* store = SVFUtil::dyn_cast<StoreInst>(thisU))
449 {
450 for (const Value* storeU : store->getPointerOperand()->users())
451 {
452 if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(storeU))
453 {
454 if (load->getNextNode() &&
455 SVFUtil::isa<CastInst>(load->getNextNode()))
456 return SVFUtil::cast<CastInst>(load->getNextNode()) ==
457 (thisPtr2->stripPointerCasts());
458 }
459 }
460 }
461 }
462 return false;
463}
464
466{
467 assert((isConstructor(fun) || isDestructor(fun)) &&
468 "not a constructor?");
469 // We always need at least one argument to return something meaningful.
470 assert(fun->arg_size() >= 1 && "expected at least one argument");
471
472 // If param 0 is sret, 'this' is typically param 1, but be defensive.
473 const bool isStructRet = fun->hasParamAttribute(0, llvm::Attribute::StructRet);
474
475 // Prefer arg1 when sret is present and available; otherwise fall back to arg0.
476 const u32_t thisIdx = (isStructRet && fun->arg_size() >= 2) ? 1 : 0;
477 const Argument* thisPtr = fun->getArg(thisIdx);
478
479 return thisPtr;
480}
481
485{
486 dname.funcName = cppUtil::getBeforeBrackets(dname.funcName);
487 dname.className = cppUtil::getBeforeBrackets(dname.className);
488 size_t colon = dname.className.rfind("::");
489 if (colon == std::string::npos)
490 {
491 dname.className = cppUtil::getBeforeBrackets(dname.className);
492 }
493 else
494 {
495 // strip off namespace
496 dname.className =
497 cppUtil::getBeforeBrackets(dname.className.substr(colon + 2));
498 }
499}
500
502{
503 if (F->isDeclaration())
504 return false;
505 std::string funcName = F->getName().str();
506 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
507 {
508 return false;
509 }
511 if (dname.className.size() == 0)
512 {
513 return false;
514 }
517 return dname.className.size() > 0 &&
518 dname.className.compare(dname.funcName) == 0;
519}
520
522{
523 if (F->isDeclaration())
524 return false;
525 std::string funcName = F->getName().str();
526 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
527 {
528 return false;
529 }
531 if (dname.className.size() == 0)
532 {
533 return false;
534 }
536 return (dname.className.size() > 0 && dname.funcName.size() > 0 &&
537 dname.className.size() + 1 == dname.funcName.size() &&
538 dname.funcName.compare(0, 1, "~") == 0 &&
539 dname.className.compare(dname.funcName.substr(1)) == 0);
540}
541
542/*
543 * get the ptr "vtable" for a given virtual callsite:
544 * %vtable = load ...
545 * %vfn = getelementptr %vtable, idx
546 * %x = load %vfn
547 * call %x (...)
548 */
550{
551 const LoadInst* loadInst =
552 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
553 assert(loadInst != nullptr);
554 const Value* vfuncptr = loadInst->getPointerOperand();
556 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr);
557 assert(gepInst != nullptr);
558 const Value* vtbl = gepInst->getPointerOperand();
559 return vtbl;
560}
561
562/*
563 * Is this virtual call inside its own constructor or destructor?
564 */
566{
568 const Function* func = cs->getCaller();
569 for (const auto &classNameOfThisPtr: classNameOfThisPtrs)
570 {
572 {
574 if (classNameOfThisPtr.compare(dname.className) == 0)
575 return true;
576 }
577 }
578 return false;
579}
580
582{
583 if(getClassNameFromType(ty).empty()==false)
584 {
585 for(auto it = ty->element_begin(); it!=ty->element_end(); it++)
586 {
587 const std::string& str = LLVMUtil::dumpType(*it);
588 if (str.find(vtableType) != std::string::npos)
589 return true;
590 }
591 }
592 return false;
593}
594
596{
597 std::string className = "";
598 if (!((SVFUtil::cast<StructType>(ty))->isLiteral()))
599 {
600 std::string elemTypeName = ty->getStructName().str();
601 if (elemTypeName.compare(0, clsName.size(), clsName) == 0)
602 {
603 className = elemTypeName.substr(clsName.size());
604 }
605 else if (elemTypeName.compare(0, structName.size(), structName) == 0)
606 {
607 className = elemTypeName.substr(structName.size());
608 }
609 }
610 return className;
611}
612
614{
616 std::string thisPtrClassName = "";
617 if (const MDNode* N = inst->getMetadata("VCallPtrType"))
618 {
619 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
620 thisPtrClassName = mdstr->getString().str();
621 }
622 if (thisPtrClassName.size() == 0)
623 {
624 const Value* thisPtr = getVCallThisPtr(inst);
626 thisPtrNames.insert(names.begin(), names.end());
627 }
628
630 std::transform(thisPtrNames.begin(), thisPtrNames.end(), std::inserter(ans, ans.begin()),
631 [](const std::string &thisPtrName) -> std::string
632 {
633 size_t found = thisPtrName.find_last_not_of("0123456789");
634 if (found != std::string::npos)
635 {
636 if (found != thisPtrName.size() - 1 &&
637 thisPtrName[found] == '.')
638 {
639 return thisPtrName.substr(0, found);
640 }
641 }
642 return thisPtrName;
643 });
644 return ans;
645}
646
648{
649 std::string funName;
650 if (const MDNode* N = inst->getMetadata("VCallFunName"))
651 {
652 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
653 funName = mdstr->getString().str();
654 }
655 return funName;
656}
657
659{
660 const LoadInst* vfuncloadinst =
661 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
662 assert(vfuncloadinst != nullptr);
663 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
665 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr);
666 User::const_op_iterator oi = vfuncptrgepinst->idx_begin();
667 const ConstantInt* idx = SVFUtil::dyn_cast<ConstantInt>(oi->get());
669 if (idx == nullptr)
670 {
671 SVFUtil::errs() << "vcall gep idx not constantint\n";
672 idx_value = 0;
673 }
674 else
675 {
677 }
678 return idx_value;
679}
680
685{
686 if (const GlobalVariable* v = SVFUtil::dyn_cast<GlobalVariable>(val))
687 {
689 return false;
690 else if (!v->hasInitializer())
691 {
692 return !v->isExternalLinkage(v->getLinkage());
693 }
694 else
695 {
696 StInfo *stInfo = LLVMModuleSet::getLLVMModuleSet()->getSVFType(v->getInitializer()->getType())->getTypeInfo();
697 const std::vector<const SVFType*> &fields = stInfo->getFlattenFieldTypes();
698 for (std::vector<const SVFType*>::const_iterator it = fields.begin(), eit = fields.end(); it != eit; ++it)
699 {
700 const SVFType* elemTy = *it;
701 assert(!SVFUtil::isa<SVFFunctionType>(elemTy) && "Initializer of a global is a function?");
702 if (SVFUtil::isa<SVFPointerType>(elemTy))
703 return false;
704 }
705
706 return v->isConstant();
707 }
708 }
710}
711
719{
720 const std::string &name = foo->getName().str();
722 {
723 // c++ constructor or destructor
727 clsNameInBrackets.insert(demangledName.className);
728 return clsNameInBrackets;
729 }
730 else if (isTemplateFunc(foo))
731 {
732 // array index
734 assert(!classNames.empty() && "empty class names?");
735 return classNames;
736 }
737 return {};
738}
739
746std::vector<std::string> findInnermostBrackets(const std::string &input)
747{
748 typedef std::pair<u32_t, u32_t> StEdIdxPair;
749 std::stack<int> stack;
750 std::vector<StEdIdxPair> innerMostPairs;
751 std::vector<bool> used(input.length(), false);
752
753 for (u32_t i = 0; i < input.length(); ++i)
754 {
755 if (input[i] == '<')
756 {
757 stack.push(i);
758 }
759 else if (input[i] == '>' && i > 0 && input[i - 1] != '-')
760 {
761 if (!stack.empty())
762 {
763 int openIndex = stack.top();
764 stack.pop();
765
766 // Check if this pair is innermost
767 bool isInnermost = true;
768 for (u32_t j = openIndex + 1; j < i && isInnermost; ++j)
769 {
770 if (used[j])
771 {
772 isInnermost = false;
773 }
774 }
775
776 if (isInnermost)
777 {
778 innerMostPairs.emplace_back(openIndex, i);
779 used[openIndex] = used[i] = true; // Mark these indices as used
780 }
781 }
782 }
783 }
784 std::vector<std::string> ans(innerMostPairs.size());
785 std::transform(innerMostPairs.begin(), innerMostPairs.end(), ans.begin(), [&input](StEdIdxPair &p) -> std::string
786 {
787 return input.substr(p.first + 1, p.second - p.first - 1);
788 });
789 return ans;
790}
791
797std::string stripWhitespaces(const std::string &str)
798{
799 auto start = std::find_if(str.begin(), str.end(), [](unsigned char ch)
800 {
801 return !std::isspace(ch);
802 });
803 auto end = std::find_if(str.rbegin(), str.rend(), [](unsigned char ch)
804 {
805 return !std::isspace(ch);
806 }).base();
807
808 return (start < end) ? std::string(start, end) : std::string();
809}
810
811std::vector<std::string> splitAndStrip(const std::string &input, char delimiter)
812{
813 std::vector<std::string> tokens;
814 size_t start = 0, end = 0;
815
816 while ((end = input.find(delimiter, start)) != std::string::npos)
817 {
818 tokens.push_back(stripWhitespaces(input.substr(start, end - start)));
819 start = end + 1;
820 }
821
822 tokens.push_back(stripWhitespaces(input.substr(start)));
823
824 return tokens;
825}
826
833{
834 // "std::array<A const*, 2ul>" -> A
835 // "std::queue<A*, std::deque<A*, std::allocator<A*> > >" -> A
836 // __gnu_cxx::__aligned_membuf<std::pair<int const, A> >::_M_ptr() const -> A
838 std::string demangleName = llvm::demangle(oname);
839 std::vector<std::string> innermosts = findInnermostBrackets(demangleName);
840 for (const auto &innermost: innermosts)
841 {
842 const std::vector<std::string> &allstrs = splitAndStrip(innermost, ',');
843 for (const auto &str: allstrs)
844 {
845 size_t spacePos = str.find(' ');
846 if (spacePos != std::string::npos)
847 {
848 // A const* -> A
849 ans.insert(str.substr(0, spacePos));
850 }
851 else
852 {
853 size_t starPos = str.find('*');
854 if (starPos != std::string::npos)
855 // A* -> A
856 ans.insert(str.substr(0, starPos));
857 else
858 ans.insert(str);
859 }
860 }
861 }
862 return ans;
863}
864
865
873{
874 if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(val))
875 {
876 const Function *foo = callBase->getCalledFunction();
877 // indirect call
878 if(!foo) return false;
880 }
881 else if (const auto *func = SVFUtil::dyn_cast<Function>(val))
882 {
884 }
885 return false;
886}
887
894bool cppUtil::matchesLabel(const std::string &foo, const std::string &label)
895{
896 return foo.compare(0, label.size(), label) == 0;
897}
898
906{
907 const std::string &name = foo->getName().str();
910 // we exclude "_ZNK6cArray3dupEv" -> cArray::dup() const
911 const std::string &demangledName = llvm::demangle(name);
912 return matchedLabel && demangledName.find('<') != std::string::npos && demangledName.find('>') != std::string::npos;
913}
914
921{
922 return foo->getName().str() == dyncast;
923}
924
931{
932 Value *tgtCast = callBase->getArgOperand(2);
933 const std::string &valueStr = LLVMUtil::dumpValue(tgtCast);
935 assert(leftPos != (u32_t) std::string::npos && "does not find ZTI for dyncast?");
937 while (rightPos < valueStr.size() && valueStr[rightPos] != ' ') rightPos++;
938 const std::string &substr = valueStr.substr(leftPos, rightPos - leftPos);
939 std::string demangleName = llvm::demangle(substr);
940 const std::string &realName = demangleName.substr(ztiprefix.size(),
941 demangleName.size() - ztiprefix.size());
942 assert(realName != "" && "real name for dyncast empty?");
943 return realName;
944}
945
946const Type *cppUtil::cppClsNameToType(const std::string &className)
947{
948 StructType *classTy = StructType::getTypeByName(LLVMModuleSet::getLLVMModuleSet()->getContext(),
951}
952
953namespace SVF
954{
955namespace cppUtil
956{
957
959{
960 if (M)
961 {
962 llvm::Triple triple(M->getTargetTriple());
963 if (triple.isKnownWindowsMSVCEnvironment() ||
964 triple.isOSBinFormatCOFF())
965 {
966 static MSVCABI msvcabi;
967 return &msvcabi;
968 }
969 }
970 static ItaniumABI itaniumabi;
971 return &itaniumabi;
972}
973
975{
976 if (val)
977 {
978 if (const GlobalValue* GV = SVFUtil::dyn_cast<GlobalValue>(val))
979 {
980 return getCXXABI(GV->getParent());
981 }
982 if (const Instruction* I = SVFUtil::dyn_cast<Instruction>(val))
983 {
984 return getCXXABI(I->getFunction()->getParent());
985 }
986 if (const Argument* Arg = SVFUtil::dyn_cast<Argument>(val))
987 {
988 return getCXXABI(Arg->getParent()->getParent());
989 }
990 }
991 return getCXXABI();
992}
993
995{
998 {
999 return getCXXABI(
1000 LLVMModuleSet::getLLVMModuleSet()->getMainLLVMModule());
1001 }
1002 static ItaniumABI itaniumabi;
1003 return &itaniumabi;
1004}
1005
1006bool ItaniumABI::isVtable(const std::string& name)
1007{
1008 return name.compare(0, vtblLabelBeforeDemangle.size(),
1010}
1011
1012bool ItaniumABI::isTypeInfo(const std::string& name)
1013{
1014 return name.compare(0, ztilabel.size(), ztilabel) == 0;
1015}
1016
1017bool ItaniumABI::isConstructor(const std::string& name)
1018{
1019 if (name.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
1020 {
1021 return false;
1022 }
1024 if (dname.className.size() == 0)
1025 {
1026 return false;
1027 }
1029 return dname.className.size() > 0 && dname.className == dname.funcName;
1030}
1031
1032bool ItaniumABI::isDestructor(const std::string& name)
1033{
1034 if (name.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
1035 {
1036 return false;
1037 }
1039 if (dname.className.size() == 0)
1040 {
1041 return false;
1042 }
1044 return (dname.className.size() > 0 && dname.funcName.size() > 0 &&
1045 dname.className.size() + 1 == dname.funcName.size() &&
1046 dname.funcName.compare(0, 1, "~") == 0 &&
1047 dname.className.compare(dname.funcName.substr(1)) == 0);
1048}
1049
1050std::string ItaniumABI::extractClassName(const std::string& name)
1051{
1052 std::string className = "";
1053 std::string realnameStr = llvm::demangle(name);
1054 if (realnameStr != name)
1055 {
1056 if (realnameStr.compare(0, vtblLabelAfterDemangle.size(),
1058 {
1059 className = realnameStr.substr(vtblLabelAfterDemangle.size());
1060 }
1061 }
1062 return className;
1063}
1064
1066{
1068 dname.isThunkFunc = false;
1069
1070 std::string realnameStr = llvm::demangle(name);
1071 if (realnameStr == name)
1072 {
1073 dname.className = "";
1074 dname.funcName = "";
1075 }
1076 else
1077 {
1079 if (beforeParenthesis.find("::") == std::string::npos ||
1081 {
1082 dname.className = "";
1083 dname.funcName = "";
1084 }
1085 else
1086 {
1088 size_t colon = beforeBracket.rfind("::");
1089 if (colon == std::string::npos)
1090 {
1091 dname.className = "";
1092 dname.funcName = "";
1093 }
1094 else
1095 {
1096 dname.className = beforeParenthesis.substr(0, colon);
1097 dname.funcName = beforeParenthesis.substr(colon + 2);
1098 }
1099 }
1100 }
1101
1103
1104 return dname;
1105}
1106
1107bool MSVCABI::isVtable(const std::string& name)
1108{
1109 return name.compare(0, 4, "??_7") == 0 || name.compare(0, 4, "??_8") == 0;
1110}
1111
1112bool MSVCABI::isTypeInfo(const std::string& name)
1113{
1114 return name.compare(0, 4, "??_R") == 0;
1115}
1116
1117bool MSVCABI::isConstructor(const std::string& name)
1118{
1119 return name.compare(0, 3, "??0") == 0;
1120}
1121
1122bool MSVCABI::isDestructor(const std::string& name)
1123{
1124 return name.compare(0, 3, "??1") == 0;
1125}
1126
1127std::string MSVCABI::extractClassName(const std::string& name)
1128{
1129 std::string className = "";
1130 std::string realnameStr = llvm::demangle(name);
1131 size_t pos = realnameStr.rfind("::`vftable'");
1132 if (pos == std::string::npos)
1133 {
1134 pos = realnameStr.rfind("::`vbtable'");
1135 }
1136 if (pos != std::string::npos)
1137 {
1138 className = realnameStr.substr(0, pos);
1139 if (className.compare(0, 6, "const ") == 0)
1140 {
1141 className = className.substr(6);
1142 }
1143 }
1144 return className;
1145}
1146
1148{
1150 dname.isThunkFunc = false;
1151
1152 std::string realnameStr = llvm::demangle(name);
1153 if (realnameStr == name)
1154 {
1155 dname.className = "";
1156 dname.funcName = "";
1157 return dname;
1158 }
1159
1160 if (realnameStr.find("[thunk]") != std::string::npos ||
1161 realnameStr.find("`vcall'") != std::string::npos ||
1162 realnameStr.find("`adjustor'") != std::string::npos)
1163 {
1164 dname.isThunkFunc = true;
1165 }
1166
1168 if (beforeParenthesis.find("::") == std::string::npos ||
1170 {
1171 dname.className = "";
1172 dname.funcName = "";
1173 }
1174 else
1175 {
1177 size_t colon = beforeBracket.rfind("::");
1178 if (colon == std::string::npos)
1179 {
1180 dname.className = "";
1181 dname.funcName = "";
1182 }
1183 else
1184 {
1185 std::string classNamePart = beforeParenthesis.substr(0, colon);
1186 dname.funcName = beforeParenthesis.substr(colon + 2);
1187
1188 int i = classNamePart.size() - 1;
1189 int bracketDepth = 0;
1190 while (i >= 0)
1191 {
1192 char c = classNamePart[i];
1193 if (c == '>')
1194 {
1195 bracketDepth++;
1196 }
1197 else if (c == '<')
1198 {
1199 bracketDepth--;
1200 }
1201
1202 if (bracketDepth > 0)
1203 {
1204 i--;
1205 }
1206 else
1207 {
1208 if (std::isalnum(c) || c == '_' || c == ':' || c == '<' ||
1209 c == '>')
1210 {
1211 i--;
1212 }
1213 else
1214 {
1215 break;
1216 }
1217 }
1218 }
1219 dname.className = classNamePart.substr(i + 1);
1220 }
1221 }
1222
1223 return dname;
1224}
1225
1226} // namespace cppUtil
1227} // namespace SVF
PRIVATE Xlinker stack
unsigned u32_t
Definition CommandLine.h:18
const std::string znst6Label
Definition CppUtil.cpp:64
const std::string znkst23Label
Definition CppUtil.cpp:73
const std::string vtblLabelBeforeDemangle
Definition CppUtil.cpp:50
static void handleThunkFunction(cppUtil::DemangledName &dname)
Definition CppUtil.cpp:146
static bool isOperOverload(const std::string &name)
Definition CppUtil.cpp:84
const std::string VThunkFuncLabel
Definition CppUtil.cpp:47
static std::string getBeforeParenthesis(const std::string &name)
Definition CppUtil.cpp:107
const std::string znkst20Label
Definition CppUtil.cpp:71
const std::string znst5Label
Definition CppUtil.cpp:62
const std::string vtblLabelAfterDemangle
Definition CppUtil.cpp:43
static bool isDerivedFromThisPtr(const Argument *thisPtr, const Value *V)
Definition CppUtil.cpp:362
const std::string clsName
Definition CppUtil.cpp:55
const std::string structName
Definition CppUtil.cpp:56
const std::string znstLabel
Definition CppUtil.cpp:61
std::string stripWhitespaces(const std::string &str)
Definition CppUtil.cpp:797
const std::string zn1Label
Definition CppUtil.cpp:60
std::vector< std::string > findInnermostBrackets(const std::string &input)
Definition CppUtil.cpp:746
const std::string znkstLabel
Definition CppUtil.cpp:69
const std::string znst7Label
Definition CppUtil.cpp:65
const std::string dyncast
Definition CppUtil.cpp:81
const std::string znst12Label
Definition CppUtil.cpp:63
const std::string znwm
Definition CppUtil.cpp:59
const std::string NVThunkFunLabel
Definition CppUtil.cpp:46
const std::string znkLabel
Definition CppUtil.cpp:76
const std::string vtableType
Definition CppUtil.cpp:57
const std::string ztilabel
Definition CppUtil.cpp:79
std::vector< std::string > splitAndStrip(const std::string &input, char delimiter)
Definition CppUtil.cpp:811
const std::string znst14Label
Definition CppUtil.cpp:66
const std::string znk9Label
Definition CppUtil.cpp:77
const std::string znkst5Label
Definition CppUtil.cpp:70
void stripBracketsAndNamespace(cppUtil::DemangledName &dname)
Definition CppUtil.cpp:484
const std::string ztiprefix
Definition CppUtil.cpp:80
const std::string vfunPreLabel
Definition CppUtil.cpp:53
cJSON * p
Definition cJSON.cpp:2559
const char *const name
Definition cJSON.h:264
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:137
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
StInfo * getTypeInfo()
Definition SVFType.h:273
std::vector< const SVFType * > & getFlattenFieldTypes()
Definition SVFType.h:131
virtual DemangledName demangle(const std::string &name)=0
virtual std::string extractClassName(const std::string &name)=0
virtual bool isVtable(const std::string &name)=0
std::string extractClassName(const std::string &name) override
Definition CppUtil.cpp:1050
bool isVtable(const std::string &name) override
Definition CppUtil.cpp:1006
bool isDestructor(const std::string &name) override
Definition CppUtil.cpp:1032
bool isConstructor(const std::string &name) override
Definition CppUtil.cpp:1017
DemangledName demangle(const std::string &name) override
Definition CppUtil.cpp:1065
bool isTypeInfo(const std::string &name) override
Definition CppUtil.cpp:1012
bool isTypeInfo(const std::string &name) override
Definition CppUtil.cpp:1112
DemangledName demangle(const std::string &name) override
Definition CppUtil.cpp:1147
bool isDestructor(const std::string &name) override
Definition CppUtil.cpp:1122
bool isVtable(const std::string &name) override
Definition CppUtil.cpp:1107
bool isConstructor(const std::string &name) override
Definition CppUtil.cpp:1117
std::string extractClassName(const std::string &name) override
Definition CppUtil.cpp:1127
bool isConstantObjSym(const Value *val)
Check whether this value points-to a constant object.
Definition CppUtil.cpp:684
std::string dumpType(const Type *type)
Definition LLVMUtil.cpp:627
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:99
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:415
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:616
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64
std::string getFunNameOfVCallSite(const CallBase *cs)
Definition CppUtil.cpp:647
std::string getBeforeBrackets(const std::string &name)
Definition CppUtil.cpp:127
const Argument * getConstructorThisPtr(const Function *fun)
Definition CppUtil.cpp:465
std::string extractClsNameFromDynCast(const CallBase *callBase)
extract class name from cpp dyncast function
Definition CppUtil.cpp:930
s32_t getVCallIdx(const CallBase *cs)
Definition CppUtil.cpp:658
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:549
bool isTemplateFunc(const Function *foo)
whether foo is a cpp template function
Definition CppUtil.cpp:905
bool classTyHasVTable(const StructType *ty)
Definition CppUtil.cpp:581
bool isSameThisPtrInConstructor(const Argument *thisPtr1, const Value *thisPtr2)
Definition CppUtil.cpp:421
Set< std::string > getClsNamesInBrackets(const std::string &name)
Definition CppUtil.cpp:202
const Value * getVCallThisPtr(const CallBase *cs)
Definition CppUtil.cpp:348
bool matchesLabel(const std::string &foo, const std::string &label)
whether foo matches the mangler label
Definition CppUtil.cpp:894
std::string getClassNameFromType(const StructType *ty)
Definition CppUtil.cpp:595
struct DemangledName demangle(const std::string &name)
Definition CppUtil.cpp:195
Set< std::string > getClassNameOfThisPtr(const CallBase *cs)
Definition CppUtil.cpp:613
bool isCPPThunkFunction(const Function *F)
Definition CppUtil.cpp:320
bool VCallInCtorOrDtor(const CallBase *cs)
Definition CppUtil.cpp:565
bool isClsNameSource(const Value *val)
Definition CppUtil.cpp:872
CXXABI * getCXXABI()
Definition CppUtil.cpp:994
Set< std::string > extractClsNamesFromTemplate(const std::string &oname)
extract class names from template functions
Definition CppUtil.cpp:832
bool isVirtualCallSite(const CallBase *cs)
Definition CppUtil.cpp:289
const Type * cppClsNameToType(const std::string &className)
Definition CppUtil.cpp:946
const Function * getThunkTarget(const Function *F)
Definition CppUtil.cpp:326
const ConstantStruct * getVtblStruct(const GlobalValue *vtbl)
Definition CppUtil.cpp:261
bool isConstructor(const Function *F)
Definition CppUtil.cpp:501
std::string getClassNameFromVtblObj(const std::string &vtblName)
Definition CppUtil.cpp:256
Set< std::string > extractClsNamesFromFunc(const Function *foo)
extract class name from the c++ function name, e.g., constructor/destructors
Definition CppUtil.cpp:718
bool isValVtbl(const Value *val)
A carefully crafted input such as FakeVTable _ZTV1A = {{nullptr, nullptr}}; can forge a vtable; detec...
Definition CppUtil.cpp:274
bool isDestructor(const Function *F)
Definition CppUtil.cpp:521
bool isDynCast(const Function *foo)
whether foo is a cpp dyncast function
Definition CppUtil.cpp:920
for isBitcode
Definition BasicTypes.h:70
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:137
llvm::Type Type
Definition BasicTypes.h:87
llvm::CallBase CallBase
Definition BasicTypes.h:153
llvm::MDString MDString
Definition BasicTypes.h:105
llvm::ConstantStruct ConstantStruct
Definition BasicTypes.h:110
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:98
llvm::AllocaInst AllocaInst
Definition BasicTypes.h:157
llvm::Argument Argument
Definition BasicTypes.h:152
llvm::LoadInst LoadInst
Definition BasicTypes.h:156
llvm::Function Function
Definition BasicTypes.h:89
llvm::GlobalValue GlobalValue
Definition BasicTypes.h:92
llvm::Instruction Instruction
Definition BasicTypes.h:91
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:86
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
signed s32_t
Definition GeneralType.h:68
llvm::Module Module
Definition BasicTypes.h:88
llvm::StoreInst StoreInst
Definition BasicTypes.h:155
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:169
llvm::MDNode MDNode
Definition BasicTypes.h:116
unsigned u32_t
Definition GeneralType.h:67
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:129
llvm::User User
Definition BasicTypes.h:149