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