Static Value-Flow Analysis
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 
40 using namespace SVF;
41 
42 // label for global vtbl value before demangle
43 const std::string vtblLabelAfterDemangle = "vtable for ";
44 
45 // label for multi inheritance virtual function
46 const std::string NVThunkFunLabel = "non-virtual thunk to ";
47 const std::string VThunkFuncLabel = "virtual thunk to ";
48 
49 // label for global vtbl value before demangle
51 
52 // label for virtual functions
54 
55 const std::string clsName = "class.";
56 const std::string structName = "struct.";
57 const std::string vtableType = "(...)**";
58 
59 const std::string znwm = "_Znwm";
60 const std::string zn1Label = "_ZN1"; // c++ constructor
61 const std::string znstLabel = "_ZNSt";
62 const std::string znst5Label = "_ZNSt5"; // _ZNSt5dequeIPK1ASaIS2_EE5frontEv -> std::deque<A const*, std::allocator<A const*> >::front()
63 const std::string znst12Label = "_ZNSt12"; // _ZNSt12forward_listIPK1ASaIS2_EEC2Ev -> std::forward_list<A const*, std::allocator<A const*> >::forward_list()
64 const std::string znst6Label = "_ZNSt6"; // _ZNSt6vectorIP1ASaIS1_EEC2Ev -> std::vector<A*, std::allocator<A*> >::vector()
65 const std::string znst7Label = "_ZNSt7"; // _ZNSt7__cxx114listIPK1ASaIS3_EEC2Ev -> std::__cxx11::list<A const*, std::allocator<A const*> >::list()
66 const std::string znst14Label = "_ZNSt14"; // _ZNSt14_Fwd_list_baseI1ASaIS0_EEC2Ev -> std::_Fwd_list_base<A, std::allocator<A> >::_Fwd_list_base()
67 
68 
69 const std::string znkstLabel = "_ZNKSt";
70 const std::string znkst5Label = "_ZNKSt15_"; // _ZNKSt15_Deque_iteratorIPK1ARS2_PS2_EdeEv -> std::_Deque_iterator<A const*, A const*&, A const**>::operator*() const
71 const std::string znkst20Label = "_ZNKSt20_"; // _ZNKSt20_List_const_iteratorIPK1AEdeEv -> std::_List_const_iterator<A const*>::operator*() const
72 
73 const std::string znkst23Label = "_ZNKSt23_"; // _ZNKSt23_Rb_tree_const_iteratorISt4pairIKi1AEEptEv -> std::_List_const_iterator<A const*>::operator*() const
74 
75 
76 const std::string znkLabel = "_ZNK";
77 const 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 
79 const std::string ztilabel = "_ZTI";
80 const std::string ztiprefix = "typeinfo for ";
81 const std::string dyncast = "__dynamic_cast";
82 
83 
84 static 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 
108 {
109  size_t lastRightParen = name.rfind(')');
110  assert(lastRightParen > 0);
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 
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 
195 struct cppUtil::DemangledName cppUtil::demangle(const std::string& name)
196 {
197  struct cppUtil::DemangledName dname;
198  dname.isThunkFunc = false;
199 
200  s32_t status;
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);
210  std::string beforeParenthesis = getBeforeParenthesis(realnameStr);
211  if (beforeParenthesis.find("::") == std::string::npos ||
212  isOperOverload(beforeParenthesis))
213  {
214  dname.className = "";
215  dname.funcName = "";
216  }
217  else
218  {
219  std::string beforeBracket = getBeforeBrackets(beforeParenthesis);
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 
235  handleThunkFunction(dname);
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 {
244  Set<std::string> res;
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 
269  s32_t status;
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);
296  removePointerAndReference(param);
297  res.insert(param);
298  }
299  std::free(realname);
300  }
301  return res;
302 }
303 
305 {
306  std::string className = "";
307 
308  s32_t status;
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  {
316  className = realnameStr.substr(vtblLabelAfterDemangle.size());
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 
336 bool cppUtil::isValVtbl(const Value* val)
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();
368  if (const GetElementPtrInst* vfuncptrgepinst =
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 
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 {
476  size_t colon = dname.className.rfind("::");
477  if (colon == std::string::npos)
478  {
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  }
498  struct cppUtil::DemangledName dname = cppUtil::demangle(funcName.c_str());
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  }
518  struct cppUtil::DemangledName dname = cppUtil::demangle(funcName.c_str());
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();
543  const GetElementPtrInst* gepInst =
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 {
555  Set<std::string> classNameOfThisPtrs = cppUtil::getClassNameOfThisPtr(cs);
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 {
603  Set<std::string> thisPtrNames;
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 
617  Set<std::string> ans;
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();
652  const GetElementPtrInst* vfuncptrgepinst =
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());
656  s32_t idx_value;
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  {
676  if (cppUtil::isValVtbl(v))
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  }
697  return LLVMUtil::isConstDataOrAggData(val);
698 }
699 
707 {
708  assert(foo->hasName() && "foo does not have a name? possible indirect call");
709  const std::string &name = foo->getName().str();
710  if (isConstructor(foo) || isDestructor(foo))
711  {
712  // c++ constructor or destructor
713  DemangledName demangledName = cppUtil::demangle(name);
714  Set<std::string> clsNameInBrackets =
716  clsNameInBrackets.insert(demangledName.className);
717  return clsNameInBrackets;
718  }
719  else if (isTemplateFunc(foo))
720  {
721  // array index
723  assert(!classNames.empty() && "empty class names?");
724  return classNames;
725  }
726  return {};
727 }
728 
735 std::vector<std::string> findInnermostBrackets(const std::string &input)
736 {
737  typedef std::pair<u32_t, u32_t> StEdIdxPair;
738  std::stack<int> stack;
739  std::vector<StEdIdxPair> innerMostPairs;
740  std::vector<bool> used(input.length(), false);
741 
742  for (u32_t i = 0; i < input.length(); ++i)
743  {
744  if (input[i] == '<')
745  {
746  stack.push(i);
747  }
748  else if (input[i] == '>' && i > 0 && input[i - 1] != '-')
749  {
750  if (!stack.empty())
751  {
752  int openIndex = stack.top();
753  stack.pop();
754 
755  // Check if this pair is innermost
756  bool isInnermost = true;
757  for (u32_t j = openIndex + 1; j < i && isInnermost; ++j)
758  {
759  if (used[j])
760  {
761  isInnermost = false;
762  }
763  }
764 
765  if (isInnermost)
766  {
767  innerMostPairs.emplace_back(openIndex, i);
768  used[openIndex] = used[i] = true; // Mark these indices as used
769  }
770  }
771  }
772  }
773  std::vector<std::string> ans(innerMostPairs.size());
774  std::transform(innerMostPairs.begin(), innerMostPairs.end(), ans.begin(), [&input](StEdIdxPair &p) -> std::string
775  {
776  return input.substr(p.first + 1, p.second - p.first - 1);
777  });
778  return ans;
779 }
780 
787 {
788  auto start = std::find_if(str.begin(), str.end(), [](unsigned char ch)
789  {
790  return !std::isspace(ch);
791  });
792  auto end = std::find_if(str.rbegin(), str.rend(), [](unsigned char ch)
793  {
794  return !std::isspace(ch);
795  }).base();
796 
797  return (start < end) ? std::string(start, end) : std::string();
798 }
799 
800 std::vector<std::string> splitAndStrip(const std::string &input, char delimiter)
801 {
802  std::vector<std::string> tokens;
803  size_t start = 0, end = 0;
804 
805  while ((end = input.find(delimiter, start)) != std::string::npos)
806  {
807  tokens.push_back(stripWhitespaces(input.substr(start, end - start)));
808  start = end + 1;
809  }
810 
811  tokens.push_back(stripWhitespaces(input.substr(start)));
812 
813  return tokens;
814 }
815 
822 {
823  // "std::array<A const*, 2ul>" -> A
824  // "std::queue<A*, std::deque<A*, std::allocator<A*> > >" -> A
825  // __gnu_cxx::__aligned_membuf<std::pair<int const, A> >::_M_ptr() const -> A
826  Set<std::string> ans;
827  std::string demangleName = llvm::demangle(oname);
828  std::vector<std::string> innermosts = findInnermostBrackets(demangleName);
829  for (const auto &innermost: innermosts)
830  {
831  const std::vector<std::string> &allstrs = splitAndStrip(innermost, ',');
832  for (const auto &str: allstrs)
833  {
834  size_t spacePos = str.find(' ');
835  if (spacePos != std::string::npos)
836  {
837  // A const* -> A
838  ans.insert(str.substr(0, spacePos));
839  }
840  else
841  {
842  size_t starPos = str.find('*');
843  if (starPos != std::string::npos)
844  // A* -> A
845  ans.insert(str.substr(0, starPos));
846  else
847  ans.insert(str);
848  }
849  }
850  }
851  return ans;
852 }
853 
854 
862 {
863  if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(val))
864  {
865  const Function *foo = callBase->getCalledFunction();
866  // indirect call
867  if(!foo) return false;
868  return isConstructor(foo) || isDestructor(foo) || isTemplateFunc(foo) || isDynCast(foo);
869  }
870  else if (const auto *func = SVFUtil::dyn_cast<Function>(val))
871  {
872  return isConstructor(func) || isDestructor(func) || isTemplateFunc(func);
873  }
874  return false;
875 }
876 
883 bool cppUtil::matchesLabel(const std::string &foo, const std::string &label)
884 {
885  return foo.compare(0, label.size(), label) == 0;
886 }
887 
895 {
896  assert(foo->hasName() && "foo does not have a name? possible indirect call");
897  const std::string &name = foo->getName().str();
898  bool matchedLabel = matchesLabel(name, znstLabel) || matchesLabel(name, znkstLabel) ||
900  // we exclude "_ZNK6cArray3dupEv" -> cArray::dup() const
901  const std::string &demangledName = llvm::demangle(name);
902  return matchedLabel && demangledName.find('<') != std::string::npos && demangledName.find('>') != std::string::npos;
903 }
904 
910 bool cppUtil::isDynCast(const Function *foo)
911 {
912  assert(foo->hasName() && "foo does not have a name? possible indirect call");
913  return foo->getName().str() == dyncast;
914 }
915 
922 {
923  Value *tgtCast = callBase->getArgOperand(2);
924  const std::string &valueStr = LLVMUtil::dumpValue(tgtCast);
925  u32_t leftPos = valueStr.find(ztilabel);
926  assert(leftPos != (u32_t) std::string::npos && "does not find ZTI for dyncast?");
927  u32_t rightPos = leftPos;
928  while (rightPos < valueStr.size() && valueStr[rightPos] != ' ') rightPos++;
929  const std::string &substr = valueStr.substr(leftPos, rightPos - leftPos);
930  std::string demangleName = llvm::demangle(substr);
931  const std::string &realName = demangleName.substr(ztiprefix.size(),
932  demangleName.size() - ztiprefix.size());
933  assert(realName != "" && "real name for dyncast empty?");
934  return realName;
935 }
936 
938 {
939  StructType *classTy = StructType::getTypeByName(LLVMModuleSet::getLLVMModuleSet()->getContext(),
940  clsName + className);
941  return classTy ? classTy : LLVMModuleSet::getLLVMModuleSet()->getTypeInference()->ptrType();
942 }
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
std::vector< std::string > splitAndStrip(const std::string &input, char delimiter)
Definition: CppUtil.cpp:800
const std::string znstLabel
Definition: CppUtil.cpp:61
std::string stripWhitespaces(const std::string &str)
Definition: CppUtil.cpp:786
const std::string zn1Label
Definition: CppUtil.cpp:60
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
std::vector< std::string > findInnermostBrackets(const std::string &input)
Definition: CppUtil.cpp:735
const std::string vtableType
Definition: CppUtil.cpp:57
const std::string ztilabel
Definition: CppUtil.cpp:79
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
const char *const string
Definition: cJSON.h:172
static LLVMModuleSet * getLLVMModuleSet()
Definition: LLVMModule.h:118
ObjTypeInference * getTypeInference()
Definition: LLVMModule.cpp:97
Set< std::string > & inferThisPtrClsName(const Value *thisPtr)
get or infer the class names of thisptr
std::vector< const SVFType * > & getFlattenFieldTypes()
Definition: SVFType.h:106
std::string dumpType(const Type *type)
Definition: LLVMUtil.cpp:596
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:579
std::string dumpValue(const Value *val)
Definition: LLVMUtil.cpp:585
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:921
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:894
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:883
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:861
Set< std::string > extractClsNamesFromTemplate(const std::string &oname)
extract class names from template functions
Definition: CppUtil.cpp:821
bool isVirtualCallSite(const CallBase *cs)
Definition: CppUtil.cpp:352
const Type * cppClsNameToType(const std::string &className)
Definition: CppUtil.cpp:937
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:910
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
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
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96