10b57cec5SDimitry Andric //===- PDBSymbolFunc.cpp - --------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" 120b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 13*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h" 15*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" 160b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymDumper.h" 170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #include <unordered_set> 220b57cec5SDimitry Andric #include <utility> 230b57cec5SDimitry Andric #include <vector> 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric using namespace llvm::pdb; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace { 290b57cec5SDimitry Andric class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> { 300b57cec5SDimitry Andric public: 310b57cec5SDimitry Andric typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType; 320b57cec5SDimitry Andric FunctionArgEnumerator(const IPDBSession & PDBSession,const PDBSymbolFunc & PDBFunc)330b57cec5SDimitry Andric FunctionArgEnumerator(const IPDBSession &PDBSession, 340b57cec5SDimitry Andric const PDBSymbolFunc &PDBFunc) 350b57cec5SDimitry Andric : Session(PDBSession), Func(PDBFunc) { 360b57cec5SDimitry Andric // Arguments can appear multiple times if they have live range 370b57cec5SDimitry Andric // information, so we only take the first occurrence. 380b57cec5SDimitry Andric std::unordered_set<std::string> SeenNames; 390b57cec5SDimitry Andric auto DataChildren = Func.findAllChildren<PDBSymbolData>(); 400b57cec5SDimitry Andric while (auto Child = DataChildren->getNext()) { 410b57cec5SDimitry Andric if (Child->getDataKind() == PDB_DataKind::Param) { 420b57cec5SDimitry Andric std::string Name = Child->getName(); 430b57cec5SDimitry Andric if (SeenNames.find(Name) != SeenNames.end()) 440b57cec5SDimitry Andric continue; 450b57cec5SDimitry Andric Args.push_back(std::move(Child)); 460b57cec5SDimitry Andric SeenNames.insert(Name); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric reset(); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric getChildCount() const520b57cec5SDimitry Andric uint32_t getChildCount() const override { return Args.size(); } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric std::unique_ptr<PDBSymbolData> getChildAtIndex(uint32_t Index) const550b57cec5SDimitry Andric getChildAtIndex(uint32_t Index) const override { 560b57cec5SDimitry Andric if (Index >= Args.size()) 570b57cec5SDimitry Andric return nullptr; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric return Session.getConcreteSymbolById<PDBSymbolData>( 600b57cec5SDimitry Andric Args[Index]->getSymIndexId()); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric getNext()630b57cec5SDimitry Andric std::unique_ptr<PDBSymbolData> getNext() override { 640b57cec5SDimitry Andric if (CurIter == Args.end()) 650b57cec5SDimitry Andric return nullptr; 660b57cec5SDimitry Andric const auto &Result = **CurIter; 670b57cec5SDimitry Andric ++CurIter; 680b57cec5SDimitry Andric return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId()); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric reset()710b57cec5SDimitry Andric void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric private: 740b57cec5SDimitry Andric typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType; 750b57cec5SDimitry Andric const IPDBSession &Session; 760b57cec5SDimitry Andric const PDBSymbolFunc &Func; 770b57cec5SDimitry Andric ArgListType Args; 780b57cec5SDimitry Andric ArgListType::const_iterator CurIter; 790b57cec5SDimitry Andric }; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const830b57cec5SDimitry AndricPDBSymbolFunc::getArguments() const { 848bcb0991SDimitry Andric return std::make_unique<FunctionArgEnumerator>(Session, *this); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric dump(PDBSymDumper & Dumper) const870b57cec5SDimitry Andricvoid PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } 880b57cec5SDimitry Andric isDestructor() const890b57cec5SDimitry Andricbool PDBSymbolFunc::isDestructor() const { 900b57cec5SDimitry Andric std::string Name = getName(); 910b57cec5SDimitry Andric if (Name.empty()) 920b57cec5SDimitry Andric return false; 930b57cec5SDimitry Andric if (Name[0] == '~') 940b57cec5SDimitry Andric return true; 950b57cec5SDimitry Andric if (Name == "__vecDelDtor") 960b57cec5SDimitry Andric return true; 970b57cec5SDimitry Andric return false; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric getLineNumbers() const1000b57cec5SDimitry Andricstd::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const { 1010b57cec5SDimitry Andric auto Len = RawSymbol->getLength(); 1020b57cec5SDimitry Andric return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(), 1030b57cec5SDimitry Andric Len ? Len : 1); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric getCompilandId() const1060b57cec5SDimitry Andricuint32_t PDBSymbolFunc::getCompilandId() const { 1070b57cec5SDimitry Andric if (auto Lines = getLineNumbers()) { 1080b57cec5SDimitry Andric if (auto FirstLine = Lines->getNext()) { 1090b57cec5SDimitry Andric return FirstLine->getCompilandId(); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric return 0; 1130b57cec5SDimitry Andric } 114