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