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{
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
438 const Value* thisPtr2)
439{
440 if (thisPtr1 == thisPtr2)
441 return true;
442 for (const Value* thisU : thisPtr1->users())
443 {
444 if (const StoreInst* store = SVFUtil::dyn_cast<StoreInst>(thisU))
445 {
446 for (const Value* storeU : store->getPointerOperand()->users())
447 {
448 if (const LoadInst* load = SVFUtil::dyn_cast<LoadInst>(storeU))
449 {
450 if (load->getNextNode() &&
451 SVFUtil::isa<CastInst>(load->getNextNode()))
452 return SVFUtil::cast<CastInst>(load->getNextNode()) ==
453 (thisPtr2->stripPointerCasts());
454 }
455 }
456 }
457 }
458 return false;
459}
460
462{
463 assert((isConstructor(fun) || isDestructor(fun)) &&
464 "not a constructor?");
465 assert(fun->arg_size() >= 1 && "argument size >= 1?");
466 const Argument* thisPtr = &*(fun->arg_begin());
467 return thisPtr;
468}
469
473{
474 dname.funcName = cppUtil::getBeforeBrackets(dname.funcName);
475 dname.className = cppUtil::getBeforeBrackets(dname.className);
476 size_t colon = dname.className.rfind("::");
477 if (colon == std::string::npos)
478 {
479 dname.className = cppUtil::getBeforeBrackets(dname.className);
480 }
481 else
482 {
483 // strip off namespace
484 dname.className =
485 cppUtil::getBeforeBrackets(dname.className.substr(colon + 2));
486 }
487}
488
490{
491 if (F->isDeclaration())
492 return false;
493 std::string funcName = F->getName().str();
494 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
495 {
496 return false;
497 }
499 if (dname.className.size() == 0)
500 {
501 return false;
502 }
505 return dname.className.size() > 0 &&
506 dname.className.compare(dname.funcName) == 0;
507}
508
510{
511 if (F->isDeclaration())
512 return false;
513 std::string funcName = F->getName().str();
514 if (funcName.compare(0, vfunPreLabel.size(), vfunPreLabel) != 0)
515 {
516 return false;
517 }
519 if (dname.className.size() == 0)
520 {
521 return false;
522 }
524 return (dname.className.size() > 0 && dname.funcName.size() > 0 &&
525 dname.className.size() + 1 == dname.funcName.size() &&
526 dname.funcName.compare(0, 1, "~") == 0 &&
527 dname.className.compare(dname.funcName.substr(1)) == 0);
528}
529
530/*
531 * get the ptr "vtable" for a given virtual callsite:
532 * %vtable = load ...
533 * %vfn = getelementptr %vtable, idx
534 * %x = load %vfn
535 * call %x (...)
536 */
538{
539 const LoadInst* loadInst =
540 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
541 assert(loadInst != nullptr);
542 const Value* vfuncptr = loadInst->getPointerOperand();
544 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr);
545 assert(gepInst != nullptr);
546 const Value* vtbl = gepInst->getPointerOperand();
547 return vtbl;
548}
549
550/*
551 * Is this virtual call inside its own constructor or destructor?
552 */
554{
556 const Function* func = cs->getCaller();
557 for (const auto &classNameOfThisPtr: classNameOfThisPtrs)
558 {
560 {
561 cppUtil::DemangledName dname = cppUtil::demangle(func->getName().str());
562 if (classNameOfThisPtr.compare(dname.className) == 0)
563 return true;
564 }
565 }
566 return false;
567}
568
570{
571 if(getClassNameFromType(ty).empty()==false)
572 {
573 for(auto it = ty->element_begin(); it!=ty->element_end(); it++)
574 {
575 const std::string& str = LLVMUtil::dumpType(*it);
576 if (str.find(vtableType) != std::string::npos)
577 return true;
578 }
579 }
580 return false;
581}
582
584{
585 std::string className = "";
586 if (!((SVFUtil::cast<StructType>(ty))->isLiteral()))
587 {
588 std::string elemTypeName = ty->getStructName().str();
589 if (elemTypeName.compare(0, clsName.size(), clsName) == 0)
590 {
591 className = elemTypeName.substr(clsName.size());
592 }
593 else if (elemTypeName.compare(0, structName.size(), structName) == 0)
594 {
595 className = elemTypeName.substr(structName.size());
596 }
597 }
598 return className;
599}
600
602{
604 std::string thisPtrClassName = "";
605 if (const MDNode* N = inst->getMetadata("VCallPtrType"))
606 {
607 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
608 thisPtrClassName = mdstr->getString().str();
609 }
610 if (thisPtrClassName.size() == 0)
611 {
612 const Value* thisPtr = getVCallThisPtr(inst);
614 thisPtrNames.insert(names.begin(), names.end());
615 }
616
618 std::transform(thisPtrNames.begin(), thisPtrNames.end(), std::inserter(ans, ans.begin()),
619 [](const std::string &thisPtrName) -> std::string
620 {
621 size_t found = thisPtrName.find_last_not_of("0123456789");
622 if (found != std::string::npos)
623 {
624 if (found != thisPtrName.size() - 1 &&
625 thisPtrName[found] == '.')
626 {
627 return thisPtrName.substr(0, found);
628 }
629 }
630 return thisPtrName;
631 });
632 return ans;
633}
634
636{
637 std::string funName;
638 if (const MDNode* N = inst->getMetadata("VCallFunName"))
639 {
640 const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
641 funName = mdstr->getString().str();
642 }
643 return funName;
644}
645
647{
648 const LoadInst* vfuncloadinst =
649 SVFUtil::dyn_cast<LoadInst>(cs->getCalledOperand());
650 assert(vfuncloadinst != nullptr);
651 const Value* vfuncptr = vfuncloadinst->getPointerOperand();
653 SVFUtil::dyn_cast<GetElementPtrInst>(vfuncptr);
654 User::const_op_iterator oi = vfuncptrgepinst->idx_begin();
655 const ConstantInt* idx = SVFUtil::dyn_cast<ConstantInt>(oi->get());
657 if (idx == nullptr)
658 {
659 SVFUtil::errs() << "vcall gep idx not constantint\n";
660 idx_value = 0;
661 }
662 else
663 {
664 idx_value = (s32_t)idx->getSExtValue();
665 }
666 return idx_value;
667}
668
673{
674 if (const GlobalVariable* v = SVFUtil::dyn_cast<GlobalVariable>(val))
675 {
677 return false;
678 else if (!v->hasInitializer())
679 {
680 return !v->isExternalLinkage(v->getLinkage());
681 }
682 else
683 {
684 StInfo *stInfo = LLVMModuleSet::getLLVMModuleSet()->getSVFType(v->getInitializer()->getType())->getTypeInfo();
685 const std::vector<const SVFType*> &fields = stInfo->getFlattenFieldTypes();
686 for (std::vector<const SVFType*>::const_iterator it = fields.begin(), eit = fields.end(); it != eit; ++it)
687 {
688 const SVFType* elemTy = *it;
689 assert(!SVFUtil::isa<SVFFunctionType>(elemTy) && "Initializer of a global is a function?");
690 if (SVFUtil::isa<SVFPointerType>(elemTy))
691 return false;
692 }
693
694 return v->isConstant();
695 }
696 }
698}
699
707{
708 const std::string &name = foo->getName().str();
710 {
711 // c++ constructor or destructor
715 clsNameInBrackets.insert(demangledName.className);
716 return clsNameInBrackets;
717 }
718 else if (isTemplateFunc(foo))
719 {
720 // array index
722 assert(!classNames.empty() && "empty class names?");
723 return classNames;
724 }
725 return {};
726}
727
734std::vector<std::string> findInnermostBrackets(const std::string &input)
735{
736 typedef std::pair<u32_t, u32_t> StEdIdxPair;
737 std::stack<int> stack;
738 std::vector<StEdIdxPair> innerMostPairs;
739 std::vector<bool> used(input.length(), false);
740
741 for (u32_t i = 0; i < input.length(); ++i)
742 {
743 if (input[i] == '<')
744 {
745 stack.push(i);
746 }
747 else if (input[i] == '>' && i > 0 && input[i - 1] != '-')
748 {
749 if (!stack.empty())
750 {
751 int openIndex = stack.top();
752 stack.pop();
753
754 // Check if this pair is innermost
755 bool isInnermost = true;
756 for (u32_t j = openIndex + 1; j < i && isInnermost; ++j)
757 {
758 if (used[j])
759 {
760 isInnermost = false;
761 }
762 }
763
764 if (isInnermost)
765 {
766 innerMostPairs.emplace_back(openIndex, i);
767 used[openIndex] = used[i] = true; // Mark these indices as used
768 }
769 }
770 }
771 }
772 std::vector<std::string> ans(innerMostPairs.size());
773 std::transform(innerMostPairs.begin(), innerMostPairs.end(), ans.begin(), [&input](StEdIdxPair &p) -> std::string
774 {
775 return input.substr(p.first + 1, p.second - p.first - 1);
776 });
777 return ans;
778}
779
785std::string stripWhitespaces(const std::string &str)
786{
787 auto start = std::find_if(str.begin(), str.end(), [](unsigned char ch)
788 {
789 return !std::isspace(ch);
790 });
791 auto end = std::find_if(str.rbegin(), str.rend(), [](unsigned char ch)
792 {
793 return !std::isspace(ch);
794 }).base();
795
796 return (start < end) ? std::string(start, end) : std::string();
797}
798
799std::vector<std::string> splitAndStrip(const std::string &input, char delimiter)
800{
801 std::vector<std::string> tokens;
802 size_t start = 0, end = 0;
803
804 while ((end = input.find(delimiter, start)) != std::string::npos)
805 {
806 tokens.push_back(stripWhitespaces(input.substr(start, end - start)));
807 start = end + 1;
808 }
809
810 tokens.push_back(stripWhitespaces(input.substr(start)));
811
812 return tokens;
813}
814
821{
822 // "std::array<A const*, 2ul>" -> A
823 // "std::queue<A*, std::deque<A*, std::allocator<A*> > >" -> A
824 // __gnu_cxx::__aligned_membuf<std::pair<int const, A> >::_M_ptr() const -> A
826 std::string demangleName = llvm::demangle(oname);
827 std::vector<std::string> innermosts = findInnermostBrackets(demangleName);
828 for (const auto &innermost: innermosts)
829 {
830 const std::vector<std::string> &allstrs = splitAndStrip(innermost, ',');
831 for (const auto &str: allstrs)
832 {
833 size_t spacePos = str.find(' ');
834 if (spacePos != std::string::npos)
835 {
836 // A const* -> A
837 ans.insert(str.substr(0, spacePos));
838 }
839 else
840 {
841 size_t starPos = str.find('*');
842 if (starPos != std::string::npos)
843 // A* -> A
844 ans.insert(str.substr(0, starPos));
845 else
846 ans.insert(str);
847 }
848 }
849 }
850 return ans;
851}
852
853
861{
862 if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(val))
863 {
864 const Function *foo = callBase->getCalledFunction();
865 // indirect call
866 if(!foo) return false;
868 }
869 else if (const auto *func = SVFUtil::dyn_cast<Function>(val))
870 {
871 return isConstructor(func) || isDestructor(func) || isTemplateFunc(func);
872 }
873 return false;
874}
875
882bool cppUtil::matchesLabel(const std::string &foo, const std::string &label)
883{
884 return foo.compare(0, label.size(), label) == 0;
885}
886
894{
895 const std::string &name = foo->getName().str();
898 // we exclude "_ZNK6cArray3dupEv" -> cArray::dup() const
899 const std::string &demangledName = llvm::demangle(name);
900 return matchedLabel && demangledName.find('<') != std::string::npos && demangledName.find('>') != std::string::npos;
901}
902
909{
910 return foo->getName().str() == dyncast;
911}
912
919{
920 Value *tgtCast = callBase->getArgOperand(2);
921 const std::string &valueStr = LLVMUtil::dumpValue(tgtCast);
923 assert(leftPos != (u32_t) std::string::npos && "does not find ZTI for dyncast?");
925 while (rightPos < valueStr.size() && valueStr[rightPos] != ' ') rightPos++;
926 const std::string &substr = valueStr.substr(leftPos, rightPos - leftPos);
927 std::string demangleName = llvm::demangle(substr);
928 const std::string &realName = demangleName.substr(ztiprefix.size(),
929 demangleName.size() - ztiprefix.size());
930 assert(realName != "" && "real name for dyncast empty?");
931 return realName;
932}
933
934const Type *cppUtil::cppClsNameToType(const std::string &className)
935{
936 StructType *classTy = StructType::getTypeByName(LLVMModuleSet::getLLVMModuleSet()->getContext(),
939}
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
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:785
const std::string zn1Label
Definition CppUtil.cpp:60
std::vector< std::string > findInnermostBrackets(const std::string &input)
Definition CppUtil.cpp:734
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:799
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:472
const std::string ztiprefix
Definition CppUtil.cpp:80
const std::string vfunPreLabel
Definition CppUtil.cpp:53
#define F(f)
cJSON * p
Definition cJSON.cpp:2559
const char *const name
Definition cJSON.h:264
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:122
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:230
std::vector< const SVFType * > & getFlattenFieldTypes()
Definition SVFType.h:106
std::string dumpType(const Type *type)
Definition LLVMUtil.cpp:595
bool isConstDataOrAggData(const Value *val)
Return true if the value refers to constant data, e.g., i32 0.
Definition LLVMUtil.h:327
bool isConstantObjSym(const SVFValue *val)
Check whether this value points-to a constant object.
Definition LLVMUtil.cpp:578
std::string dumpValue(const Value *val)
Definition LLVMUtil.cpp:584
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
std::string getFunNameOfVCallSite(const CallBase *cs)
Definition CppUtil.cpp:635
std::string getBeforeBrackets(const std::string &name)
Definition CppUtil.cpp:127
const Argument * getConstructorThisPtr(const Function *fun)
Definition CppUtil.cpp:461
std::string extractClsNameFromDynCast(const CallBase *callBase)
extract class name from cpp dyncast function
Definition CppUtil.cpp:918
s32_t getVCallIdx(const CallBase *cs)
Definition CppUtil.cpp:646
const Value * getVCallVtblPtr(const CallBase *cs)
Definition CppUtil.cpp:537
bool isTemplateFunc(const Function *foo)
whether foo is a cpp template function
Definition CppUtil.cpp:893
bool classTyHasVTable(const StructType *ty)
Definition CppUtil.cpp:569
bool isSameThisPtrInConstructor(const Argument *thisPtr1, const Value *thisPtr2)
Definition CppUtil.cpp:437
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:882
std::string getClassNameFromType(const StructType *ty)
Definition CppUtil.cpp:583
struct DemangledName demangle(const std::string &name)
Definition CppUtil.cpp:195
Set< std::string > getClassNameOfThisPtr(const CallBase *cs)
Definition CppUtil.cpp:601
bool isCPPThunkFunction(const Function *F)
Definition CppUtil.cpp:383
bool VCallInCtorOrDtor(const CallBase *cs)
Definition CppUtil.cpp:553
bool isClsNameSource(const Value *val)
Definition CppUtil.cpp:860
Set< std::string > extractClsNamesFromTemplate(const std::string &oname)
extract class names from template functions
Definition CppUtil.cpp:820
bool isVirtualCallSite(const CallBase *cs)
Definition CppUtil.cpp:352
const Type * cppClsNameToType(const std::string &className)
Definition CppUtil.cpp:934
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:489
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:706
bool isValVtbl(const Value *val)
Definition CppUtil.cpp:336
bool isDestructor(const Function *F)
Definition CppUtil.cpp:509
bool isDynCast(const Function *foo)
whether foo is a cpp dyncast function
Definition CppUtil.cpp:908
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::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:47
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:46
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:125