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 <cxxabi.h> // for demangling
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{
198 dname.isThunkFunc = false;
199
201 char* realname = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
202 if (realname == nullptr)
203 {
204 dname.className = "";
205 dname.funcName = "";
206 }
207 else
208 {
209 std::string realnameStr = std::string(realname);
211 if (beforeParenthesis.find("::") == std::string::npos ||
213 {
214 dname.className = "";
215 dname.funcName = "";
216 }
217 else
218 {
220 size_t colon = beforeBracket.rfind("::");
221 if (colon == std::string::npos)
222 {
223 dname.className = "";
224 dname.funcName = "";
225 }
226 else
227 {
228 dname.className = beforeParenthesis.substr(0, colon);
229 dname.funcName = beforeParenthesis.substr(colon + 2);
230 }
231 }
232 std::free(realname);
233 }
234
236
237 return dname;
238}
239
240// Extract class name in parameters
241// e.g., given "WithSemaphore::WithSemaphore(AP_HAL::Semaphore&)", return "AP_HAL::Semaphore"
243{
245 // Lambda to trim whitespace from both ends of a string
246 auto trim = [](std::string& s)
247 {
248 size_t first = s.find_first_not_of(' ');
249 size_t last = s.find_last_not_of(' ');
250 if (first != std::string::npos && last != std::string::npos)
251 {
252 s = s.substr(first, (last - first + 1));
253 }
254 else
255 {
256 s.clear();
257 }
258 };
259
260 // Lambda to remove trailing '*' and '&' characters
261 auto removePointerAndReference = [](std::string& s)
262 {
263 while (!s.empty() && (s.back() == '*' || s.back() == '&'))
264 {
265 s.pop_back();
266 }
267 };
268
270 char* realname = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
271 if (realname == nullptr)
272 {
273 // do nothing
274 }
275 else
276 {
277 std::string realnameStr = std::string(realname);
278
279 // Find the start and end of the parameter list
280 size_t start = realnameStr.find('(');
281 size_t end = realnameStr.find(')');
282 if (start == std::string::npos || end == std::string::npos || start >= end)
283 {
284 return res; // Return empty set if the format is incorrect
285 }
286
287 // Extract the parameter list
288 std::string paramList = realnameStr.substr(start + 1, end - start - 1);
289
290 // Split the parameter list by commas
291 std::istringstream ss(paramList);
292 std::string param;
293 while (std::getline(ss, param, ','))
294 {
295 trim(param);
297 res.insert(param);
298 }
299 std::free(realname);
300 }
301 return res;
302}
303
304std::string cppUtil::getClassNameFromVtblObj(const std::string& vtblName)
305{
306 std::string className = "";
307
309 char* realname = abi::__cxa_demangle(vtblName.c_str(), 0, 0, &status);
310 if (realname != nullptr)
311 {
312 std::string realnameStr = std::string(realname);
313 if (realnameStr.compare(0, vtblLabelAfterDemangle.size(),
315 {
317 }
318 std::free(realname);
319 }
320 return className;
321}
322
324{
325 const ConstantStruct *vtblStruct = SVFUtil::dyn_cast<ConstantStruct>(vtbl->getOperand(0));
326 assert(vtblStruct && "Initializer of a vtable not a struct?");
327
328 if (vtblStruct->getNumOperands() == 2 &&
329 SVFUtil::isa<ConstantStruct>(vtblStruct->getOperand(0)) &&
330 vtblStruct->getOperand(1)->getType()->isArrayTy())
331 return SVFUtil::cast<ConstantStruct>(vtblStruct->getOperand(0));
332
333 return vtblStruct;
334}
335
337{
338 if (!SVFUtil::isa<GlobalVariable>(val))
339 return false;
340 std::string valName = val->getName().str();
341 return valName.compare(0, vtblLabelBeforeDemangle.size(),
343}
344
345/*
346 * a virtual callsite follows the following instruction sequence pattern:
347 * %vtable = load this
348 * %vfn = getelementptr %vtable, idx
349 * %x = load %vfn
350 * call %x (this)
351 */
353{
354 // the callsite must be an indirect one with at least one argument (this
355 // ptr)
356 if (cs->getCalledFunction() != nullptr || cs->arg_empty())
357 return false;
358
359 // the first argument (this pointer) must be a pointer type and must be a
360 // class name
361 if (cs->getArgOperand(0)->getType()->isPointerTy() == false)
362 return false;
363
364 const Value* vfunc = cs->getCalledOperand();
365 if (const LoadInst* vfuncloadinst = SVFUtil::dyn_cast<LoadInst>(vfunc))
366 {
367 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
369 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr))
370 {
371 if (vfuncptrgepinst->getNumIndices() != 1)
372 return false;
373 const Value* vtbl = vfuncptrgepinst->getPointerOperand();
374 if (SVFUtil::isa<LoadInst>(vtbl))
375 {
376 return true;
377 }
378 }
379 }
380 return false;
381}
382
384{
385 cppUtil::DemangledName dname = cppUtil::demangle(F->getName().str());
386 return dname.isThunkFunc;
387}
388
390{
391 const Function* ret = nullptr;
392
393 for (auto& bb : *F)
394 {
395 for (auto& inst : bb)
396 {
397 if (const CallBase* callbase = SVFUtil::dyn_cast<CallBase>(&inst))
398 {
399 // assert(cs.getCalledFunction() &&
400 // "Indirect call detected in thunk func");
401 // assert(ret == nullptr && "multiple callsites in thunk func");
402
403 ret = callbase->getCalledFunction();
404 }
405 }
406 }
407
408 return ret;
409}
410
412{
413 if (cs->paramHasAttr(0, llvm::Attribute::StructRet))
414 {
415 return cs->getArgOperand(1);
416 }
417 else
418 {
419 return cs->getArgOperand(0);
420 }
421}
422
425static bool isDerivedFromThisPtr(const Argument* thisPtr, const Value* V)
426{
427 V = V->stripPointerCasts();
428 if (V == thisPtr)
429 return true;
430
431 if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(V))
432 {
433 if (const AllocaInst* alloca =
434 SVFUtil::dyn_cast<AllocaInst>(load->getPointerOperand()))
435 {
436 for (const User* U : alloca->users())
437 {
438 if (const StoreInst* store = SVFUtil::dyn_cast<StoreInst>(U))
439 {
440 if (store->getPointerOperand() == alloca &&
441 store->getValueOperand()->stripPointerCasts() == thisPtr)
442 return true;
443 }
444 }
445 }
446 }
447 return false;
448}
449
485 const Value* thisPtr2)
486{
487 if (thisPtr1 == thisPtr2)
488 return true;
489
490 const Value* stripped = thisPtr2->stripPointerCasts();
491 if (stripped == thisPtr1)
492 return true;
493
494 // === Opaque pointer: Load from this.addr (Case 2: primary base at O0) ===
496 return true;
497
498 // === Opaque pointer: GEP check (Case 3 & 4) ===
499 if (const GetElementPtrInst* GEP = SVFUtil::dyn_cast<GetElementPtrInst>(stripped))
500 {
501 if (!isDerivedFromThisPtr(thisPtr1, GEP->getPointerOperand()))
502 return false;
503 // i8 GEP = non-primary base class (Case 3)
504 // struct GEP = member field (Case 4)
505 return GEP->getSourceElementType()->isIntegerTy(8);
506 }
507
508 // === Typed pointer (legacy): store -> load -> bitcast ===
509 for (const Value* thisU : thisPtr1->users())
510 {
511 if (const StoreInst* store = SVFUtil::dyn_cast<StoreInst>(thisU))
512 {
513 for (const Value* storeU : store->getPointerOperand()->users())
514 {
515 if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(storeU))
516 {
517 if (load->getNextNode() &&
518 SVFUtil::isa<CastInst>(load->getNextNode()))
519 return SVFUtil::cast<CastInst>(load->getNextNode()) ==
520 (thisPtr2->stripPointerCasts());
521 }
522 }
523 }
524 }
525 return false;
526}
527
529{
530 assert((isConstructor(fun) || isDestructor(fun)) &&
531 "not a constructor?");
532 assert(fun->arg_size() >= 1 && "argument size >= 1?");
533 const bool isStructRet = fun->hasParamAttribute(0, llvm::Attribute::StructRet);
534 assert((isStructRet ? fun->arg_size() >= 2 : true) &&
535 "argument size for struct ret constructor >= 2?");
536 const Argument* thisPtr = isStructRet ?
537 fun->getArg(1) : fun->getArg(0);
538 return thisPtr;
539}
540
544{
545 dname.funcName = cppUtil::getBeforeBrackets(dname.funcName);
546 dname.className = cppUtil::getBeforeBrackets(dname.className);
547 size_t colon = dname.className.rfind("::");
548 if (colon == std::string::npos)
549 {
550 dname.className = cppUtil::getBeforeBrackets(dname.className);
551 }
552 else
553 {
554 // strip off namespace
555 dname.className =
556 cppUtil::getBeforeBrackets(dname.className.substr(colon + 2));
557 }
558}
559
561{
562 if (F->isDeclaration())
563 return false;
564 std::string funcName = F->getName().str();
565 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
566 {
567 return false;
568 }
570 if (dname.className.size() == 0)
571 {
572 return false;
573 }
576 return dname.className.size() > 0 &&
577 dname.className.compare(dname.funcName) == 0;
578}
579
581{
582 if (F->isDeclaration())
583 return false;
584 std::string funcName = F->getName().str();
585 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
586 {
587 return false;
588 }
590 if (dname.className.size() == 0)
591 {
592 return false;
593 }
595 return (dname.className.size() > 0 && dname.funcName.size() > 0 &&
596 dname.className.size() + 1 == dname.funcName.size() &&
597 dname.funcName.compare(0, 1, "~") == 0 &&
598 dname.className.compare(dname.funcName.substr(1)) == 0);
599}
600
601/*
602 * get the ptr "vtable" for a given virtual callsite:
603 * %vtable = load ...
604 * %vfn = getelementptr %vtable, idx
605 * %x = load %vfn
606 * call %x (...)
607 */
609{
610 const LoadInst* loadInst =
611 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
612 assert(loadInst != nullptr);
613 const Value* vfuncptr = loadInst->getPointerOperand();
615 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr);
616 assert(gepInst != nullptr);
617 const Value* vtbl = gepInst->getPointerOperand();
618 return vtbl;
619}
620
621/*
622 * Is this virtual call inside its own constructor or destructor?
623 */
625{
627 const Function* func = cs->getCaller();
628 for (const auto &classNameOfThisPtr: classNameOfThisPtrs)
629 {
631 {
633 if (classNameOfThisPtr.compare(dname.className) == 0)
634 return true;
635 }
636 }
637 return false;
638}
639
641{
642 if(getClassNameFromType(ty).empty()==false)
643 {
644 for(auto it = ty->element_begin(); it!=ty->element_end(); it++)
645 {
646 const std::string& str = LLVMUtil::dumpType(*it);
647 if (str.find(vtableType) != std::string::npos)
648 return true;
649 }
650 }
651 return false;
652}
653
655{
656 std::string className = "";
657 if (!((SVFUtil::cast<StructType>(ty))->isLiteral()))
658 {
659 std::string elemTypeName = ty->getStructName().str();
660 if (elemTypeName.compare(0, clsName.size(), clsName) == 0)
661 {
662 className = elemTypeName.substr(clsName.size());
663 }
664 else if (elemTypeName.compare(0, structName.size(), structName) == 0)
665 {
666 className = elemTypeName.substr(structName.size());
667 }
668 }
669 return className;
670}
671
673{
675 std::string thisPtrClassName = "";
676 if (const MDNode* N = inst->getMetadata("VCallPtrType"))
677 {
678 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
679 thisPtrClassName = mdstr->getString().str();
680 }
681 if (thisPtrClassName.size() == 0)
682 {
683 const Value* thisPtr = getVCallThisPtr(inst);
685 thisPtrNames.insert(names.begin(), names.end());
686 }
687
689 std::transform(thisPtrNames.begin(), thisPtrNames.end(), std::inserter(ans, ans.begin()),
690 [](const std::string &thisPtrName) -> std::string
691 {
692 size_t found = thisPtrName.find_last_not_of("0123456789");
693 if (found != std::string::npos)
694 {
695 if (found != thisPtrName.size() - 1 &&
696 thisPtrName[found] == '.')
697 {
698 return thisPtrName.substr(0, found);
699 }
700 }
701 return thisPtrName;
702 });
703 return ans;
704}
705
707{
708 std::string funName;
709 if (const MDNode* N = inst->getMetadata("VCallFunName"))
710 {
711 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
712 funName = mdstr->getString().str();
713 }
714 return funName;
715}
716
718{
719 const LoadInst* vfuncloadinst =
720 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
721 assert(vfuncloadinst != nullptr);
722 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
724 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr);
725 User::const_op_iterator oi = vfuncptrgepinst->idx_begin();
726 const ConstantInt* idx = SVFUtil::dyn_cast<ConstantInt>(oi->get());
728 if (idx == nullptr)
729 {
730 SVFUtil::errs() << "vcall gep idx not constantint\n";
731 idx_value = 0;
732 }
733 else
734 {
736 }
737 return idx_value;
738}
739
744{
745 if (const GlobalVariable* v = SVFUtil::dyn_cast<GlobalVariable>(val))
746 {
748 return false;
749 else if (!v->hasInitializer())
750 {
751 return !v->isExternalLinkage(v->getLinkage());
752 }
753 else
754 {
755 StInfo *stInfo = LLVMModuleSet::getLLVMModuleSet()->getSVFType(v->getInitializer()->getType())->getTypeInfo();
756 const std::vector<const SVFType*> &fields = stInfo->getFlattenFieldTypes();
757 for (std::vector<const SVFType*>::const_iterator it = fields.begin(), eit = fields.end(); it != eit; ++it)
758 {
759 const SVFType* elemTy = *it;
760 assert(!SVFUtil::isa<SVFFunctionType>(elemTy) && "Initializer of a global is a function?");
761 if (SVFUtil::isa<SVFPointerType>(elemTy))
762 return false;
763 }
764
765 return v->isConstant();
766 }
767 }
769}
770
778{
779 const std::string &name = foo->getName().str();
781 {
782 // c++ constructor or destructor
786 clsNameInBrackets.insert(demangledName.className);
787 return clsNameInBrackets;
788 }
789 else if (isTemplateFunc(foo))
790 {
791 // array index
793 assert(!classNames.empty() && "empty class names?");
794 return classNames;
795 }
796 return {};
797}
798
805std::vector<std::string> findInnermostBrackets(const std::string &input)
806{
807 typedef std::pair<u32_t, u32_t> StEdIdxPair;
808 std::stack<int> stack;
809 std::vector<StEdIdxPair> innerMostPairs;
810 std::vector<bool> used(input.length(), false);
811
812 for (u32_t i = 0; i < input.length(); ++i)
813 {
814 if (input[i] == '<')
815 {
816 stack.push(i);
817 }
818 else if (input[i] == '>' && i > 0 && input[i - 1] != '-')
819 {
820 if (!stack.empty())
821 {
822 int openIndex = stack.top();
823 stack.pop();
824
825 // Check if this pair is innermost
826 bool isInnermost = true;
827 for (u32_t j = openIndex + 1; j < i && isInnermost; ++j)
828 {
829 if (used[j])
830 {
831 isInnermost = false;
832 }
833 }
834
835 if (isInnermost)
836 {
837 innerMostPairs.emplace_back(openIndex, i);
838 used[openIndex] = used[i] = true; // Mark these indices as used
839 }
840 }
841 }
842 }
843 std::vector<std::string> ans(innerMostPairs.size());
844 std::transform(innerMostPairs.begin(), innerMostPairs.end(), ans.begin(), [&input](StEdIdxPair &p) -> std::string
845 {
846 return input.substr(p.first + 1, p.second - p.first - 1);
847 });
848 return ans;
849}
850
856std::string stripWhitespaces(const std::string &str)
857{
858 auto start = std::find_if(str.begin(), str.end(), [](unsigned char ch)
859 {
860 return !std::isspace(ch);
861 });
862 auto end = std::find_if(str.rbegin(), str.rend(), [](unsigned char ch)
863 {
864 return !std::isspace(ch);
865 }).base();
866
867 return (start < end) ? std::string(start, end) : std::string();
868}
869
870std::vector<std::string> splitAndStrip(const std::string &input, char delimiter)
871{
872 std::vector<std::string> tokens;
873 size_t start = 0, end = 0;
874
875 while ((end = input.find(delimiter, start)) != std::string::npos)
876 {
877 tokens.push_back(stripWhitespaces(input.substr(start, end - start)));
878 start = end + 1;
879 }
880
881 tokens.push_back(stripWhitespaces(input.substr(start)));
882
883 return tokens;
884}
885
892{
893 // "std::array<A const*, 2ul>" -> A
894 // "std::queue<A*, std::deque<A*, std::allocator<A*> > >" -> A
895 // __gnu_cxx::__aligned_membuf<std::pair<int const, A> >::_M_ptr() const -> A
897 std::string demangleName = llvm::demangle(oname);
898 std::vector<std::string> innermosts = findInnermostBrackets(demangleName);
899 for (const auto &innermost: innermosts)
900 {
901 const std::vector<std::string> &allstrs = splitAndStrip(innermost, ',');
902 for (const auto &str: allstrs)
903 {
904 size_t spacePos = str.find(' ');
905 if (spacePos != std::string::npos)
906 {
907 // A const* -> A
908 ans.insert(str.substr(0, spacePos));
909 }
910 else
911 {
912 size_t starPos = str.find('*');
913 if (starPos != std::string::npos)
914 // A* -> A
915 ans.insert(str.substr(0, starPos));
916 else
917 ans.insert(str);
918 }
919 }
920 }
921 return ans;
922}
923
924
932{
933 if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(val))
934 {
935 const Function *foo = callBase->getCalledFunction();
936 // indirect call
937 if(!foo) return false;
939 }
940 else if (const auto *func = SVFUtil::dyn_cast<Function>(val))
941 {
943 }
944 return false;
945}
946
953bool cppUtil::matchesLabel(const std::string &foo, const std::string &label)
954{
955 return foo.compare(0, label.size(), label) == 0;
956}
957
965{
966 const std::string &name = foo->getName().str();
969 // we exclude "_ZNK6cArray3dupEv" -> cArray::dup() const
970 const std::string &demangledName = llvm::demangle(name);
971 return matchedLabel && demangledName.find('<') != std::string::npos && demangledName.find('>') != std::string::npos;
972}
973
980{
981 return foo->getName().str() == dyncast;
982}
983
990{
991 Value *tgtCast = callBase->getArgOperand(2);
992 const std::string &valueStr = LLVMUtil::dumpValue(tgtCast);
994 assert(leftPos != (u32_t) std::string::npos && "does not find ZTI for dyncast?");
996 while (rightPos < valueStr.size() && valueStr[rightPos] != ' ') rightPos++;
997 const std::string &substr = valueStr.substr(leftPos, rightPos - leftPos);
998 std::string demangleName = llvm::demangle(substr);
999 const std::string &realName = demangleName.substr(ztiprefix.size(),
1000 demangleName.size() - ztiprefix.size());
1001 assert(realName != "" && "real name for dyncast empty?");
1002 return realName;
1003}
1004
1005const Type *cppUtil::cppClsNameToType(const std::string &className)
1006{
1007 StructType *classTy = StructType::getTypeByName(LLVMModuleSet::getLLVMModuleSet()->getContext(),
1008 clsName + className);
1010}
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:425
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:856
const std::string zn1Label
Definition CppUtil.cpp:60
std::vector< std::string > findInnermostBrackets(const std::string &input)
Definition CppUtil.cpp:805
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:870
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:543
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:131
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:232
std::vector< const SVFType * > & getFlattenFieldTypes()
Definition SVFType.h:104
bool isConstantObjSym(const Value *val)
Check whether this value points-to a constant object.
Definition CppUtil.cpp:743
std::string dumpType(const Type *type)
Definition LLVMUtil.cpp:611
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:82
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:368
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:600
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
std::string getFunNameOfVCallSite(const CallBase *cs)
Definition CppUtil.cpp:706
std::string getBeforeBrackets(const std::string &name)
Definition CppUtil.cpp:127
const Argument * getConstructorThisPtr(const Function *fun)
Definition CppUtil.cpp:528
std::string extractClsNameFromDynCast(const CallBase *callBase)
extract class name from cpp dyncast function
Definition CppUtil.cpp:989
s32_t getVCallIdx(const CallBase *cs)
Definition CppUtil.cpp:717
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:608
bool isTemplateFunc(const Function *foo)
whether foo is a cpp template function
Definition CppUtil.cpp:964
bool classTyHasVTable(const StructType *ty)
Definition CppUtil.cpp:640
bool isSameThisPtrInConstructor(const Argument *thisPtr1, const Value *thisPtr2)
Definition CppUtil.cpp:484
Set< std::string > getClsNamesInBrackets(const std::string &name)
Definition CppUtil.cpp:242
const Value * getVCallThisPtr(const CallBase *cs)
Definition CppUtil.cpp:411
bool matchesLabel(const std::string &foo, const std::string &label)
whether foo matches the mangler label
Definition CppUtil.cpp:953
std::string getClassNameFromType(const StructType *ty)
Definition CppUtil.cpp:654
struct DemangledName demangle(const std::string &name)
Definition CppUtil.cpp:195
Set< std::string > getClassNameOfThisPtr(const CallBase *cs)
Definition CppUtil.cpp:672
bool isCPPThunkFunction(const Function *F)
Definition CppUtil.cpp:383
bool VCallInCtorOrDtor(const CallBase *cs)
Definition CppUtil.cpp:624
bool isClsNameSource(const Value *val)
Definition CppUtil.cpp:931
Set< std::string > extractClsNamesFromTemplate(const std::string &oname)
extract class names from template functions
Definition CppUtil.cpp:891
bool isVirtualCallSite(const CallBase *cs)
Definition CppUtil.cpp:352
const Type * cppClsNameToType(const std::string &className)
Definition CppUtil.cpp:1005
const Function * getThunkTarget(const Function *F)
Definition CppUtil.cpp:389
const ConstantStruct * getVtblStruct(const GlobalValue *vtbl)
Definition CppUtil.cpp:323
bool isConstructor(const Function *F)
Definition CppUtil.cpp:560
std::string getClassNameFromVtblObj(const std::string &vtblName)
Definition CppUtil.cpp:304
Set< std::string > extractClsNamesFromFunc(const Function *foo)
extract class name from the c++ function name, e.g., constructor/destructors
Definition CppUtil.cpp:777
bool isValVtbl(const Value *val)
Definition CppUtil.cpp:336
bool isDestructor(const Function *F)
Definition CppUtil.cpp:580
bool isDynCast(const Function *foo)
whether foo is a cpp dyncast function
Definition CppUtil.cpp:979
for isBitcode
Definition BasicTypes.h:68
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:130
llvm::Type Type
Definition BasicTypes.h:83
llvm::CallBase CallBase
Definition BasicTypes.h:146
llvm::MDString MDString
Definition BasicTypes.h:101
llvm::ConstantStruct ConstantStruct
Definition BasicTypes.h:106
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:94
llvm::AllocaInst AllocaInst
Definition BasicTypes.h:150
llvm::Argument Argument
Definition BasicTypes.h:145
llvm::LoadInst LoadInst
Definition BasicTypes.h:149
llvm::Function Function
Definition BasicTypes.h:85
llvm::GlobalValue GlobalValue
Definition BasicTypes.h:88
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:82
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
signed s32_t
Definition GeneralType.h:48
llvm::StoreInst StoreInst
Definition BasicTypes.h:148
llvm::GetElementPtrInst GetElementPtrInst
Definition BasicTypes.h:162
llvm::MDNode MDNode
Definition BasicTypes.h:112
unsigned u32_t
Definition GeneralType.h:47
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:125
llvm::User User
Definition BasicTypes.h:142