1 //===- PDBSymbolFunc.cpp - --------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 10 11 #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" 12 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 13 #include "llvm/DebugInfo/PDB/IPDBSession.h" 14 #include "llvm/DebugInfo/PDB/PDBSymDumper.h" 15 #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 16 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 17 #include "llvm/DebugInfo/PDB/PDBTypes.h" 18 19 #include <unordered_set> 20 #include <utility> 21 #include <vector> 22 23 using namespace llvm; 24 using namespace llvm::pdb; 25 26 namespace { 27 class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> { 28 public: 29 typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType; 30 31 FunctionArgEnumerator(const IPDBSession &PDBSession, 32 const PDBSymbolFunc &PDBFunc) 33 : Session(PDBSession), Func(PDBFunc) { 34 // Arguments can appear multiple times if they have live range 35 // information, so we only take the first occurrence. 36 std::unordered_set<std::string> SeenNames; 37 auto DataChildren = Func.findAllChildren<PDBSymbolData>(); 38 while (auto Child = DataChildren->getNext()) { 39 if (Child->getDataKind() == PDB_DataKind::Param) { 40 std::string Name = Child->getName(); 41 if (SeenNames.find(Name) != SeenNames.end()) 42 continue; 43 Args.push_back(std::move(Child)); 44 SeenNames.insert(Name); 45 } 46 } 47 reset(); 48 } 49 50 uint32_t getChildCount() const override { return Args.size(); } 51 52 std::unique_ptr<PDBSymbolData> 53 getChildAtIndex(uint32_t Index) const override { 54 if (Index >= Args.size()) 55 return nullptr; 56 57 return Session.getConcreteSymbolById<PDBSymbolData>( 58 Args[Index]->getSymIndexId()); 59 } 60 61 std::unique_ptr<PDBSymbolData> getNext() override { 62 if (CurIter == Args.end()) 63 return nullptr; 64 const auto &Result = **CurIter; 65 ++CurIter; 66 return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId()); 67 } 68 69 void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); } 70 71 private: 72 typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType; 73 const IPDBSession &Session; 74 const PDBSymbolFunc &Func; 75 ArgListType Args; 76 ArgListType::const_iterator CurIter; 77 }; 78 } 79 80 std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> 81 PDBSymbolFunc::getArguments() const { 82 return llvm::make_unique<FunctionArgEnumerator>(Session, *this); 83 } 84 85 void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } 86 87 bool PDBSymbolFunc::isDestructor() const { 88 std::string Name = getName(); 89 if (Name.empty()) 90 return false; 91 if (Name[0] == '~') 92 return true; 93 if (Name == "__vecDelDtor") 94 return true; 95 return false; 96 } 97 98 std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const { 99 auto Len = RawSymbol->getLength(); 100 return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(), 101 Len ? Len : 1); 102 } 103 104 uint32_t PDBSymbolFunc::getCompilandId() const { 105 if (auto Lines = getLineNumbers()) { 106 if (auto FirstLine = Lines->getNext()) { 107 return FirstLine->getCompilandId(); 108 } 109 } 110 return 0; 111 } 112