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 if (SeenNames.insert(Child->getName()).second) 42 Args.push_back(std::move(Child)); 43 } 44 } 45 reset(); 46 } 47 48 uint32_t getChildCount() const override { return Args.size(); } 49 50 std::unique_ptr<PDBSymbolData> 51 getChildAtIndex(uint32_t Index) const override { 52 if (Index >= Args.size()) 53 return nullptr; 54 55 return Session.getConcreteSymbolById<PDBSymbolData>( 56 Args[Index]->getSymIndexId()); 57 } 58 59 std::unique_ptr<PDBSymbolData> getNext() override { 60 if (CurIter == Args.end()) 61 return nullptr; 62 const auto &Result = **CurIter; 63 ++CurIter; 64 return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId()); 65 } 66 67 void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); } 68 69 private: 70 typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType; 71 const IPDBSession &Session; 72 const PDBSymbolFunc &Func; 73 ArgListType Args; 74 ArgListType::const_iterator CurIter; 75 }; 76 } 77 78 std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> 79 PDBSymbolFunc::getArguments() const { 80 return std::make_unique<FunctionArgEnumerator>(Session, *this); 81 } 82 83 void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } 84 85 bool PDBSymbolFunc::isDestructor() const { 86 std::string Name = getName(); 87 if (Name.empty()) 88 return false; 89 if (Name[0] == '~') 90 return true; 91 if (Name == "__vecDelDtor") 92 return true; 93 return false; 94 } 95 96 std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const { 97 auto Len = RawSymbol->getLength(); 98 return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(), 99 Len ? Len : 1); 100 } 101 102 uint32_t PDBSymbolFunc::getCompilandId() const { 103 if (auto Lines = getLineNumbers()) { 104 if (auto FirstLine = Lines->getNext()) { 105 return FirstLine->getCompilandId(); 106 } 107 } 108 return 0; 109 } 110