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