diff options
13 files changed, 275 insertions, 3 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h new file mode 100644 index 00000000000..4442a1ec41f --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h @@ -0,0 +1,43 @@ +//==- NativeEnumGlobals.h - Native Global Enumerator impl --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMGLOBALS_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMGLOBALS_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +#include <vector> + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumGlobals : public IPDBEnumChildren<PDBSymbol> { +public: + NativeEnumGlobals(NativeSession &Session, + std::vector<codeview::SymbolKind> Kinds); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + +private: + std::vector<uint32_t> MatchOffsets; + uint32_t Index; + NativeSession &Session; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h new file mode 100644 index 00000000000..06eb6fcf376 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h @@ -0,0 +1,42 @@ +//===- NativeTypeTypedef.h - info about typedef ------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPETYPEDEF_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeTypedef : public NativeRawSymbol { +public: + // Create a pointer record for a non-simple type. + NativeTypeTypedef(NativeSession &Session, SymIndexId Id, + codeview::UDTSym Typedef); + + ~NativeTypeTypedef() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + SymIndexId getTypeId() const override; + +protected: + codeview::UDTSym Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h index afa1937d127..a996f34ef85 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h @@ -43,4 +43,4 @@ protected: } // namespace pdb } // namespace llvm -#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H
\ No newline at end of file diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h index 6b1c3c27973..08e1d41e6ee 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -29,12 +29,30 @@ class SymbolCache { NativeSession &Session; DbiStream *Dbi = nullptr; + /// Cache of all stable symbols, indexed by SymIndexId. Just because a + /// symbol has been parsed does not imply that it will be stable and have + /// an Id. Id allocation is an implementation, with the only guarantee + /// being that once an Id is allocated, the symbol can be assumed to be + /// cached. std::vector<std::unique_ptr<NativeRawSymbol>> Cache; + + /// For type records from the TPI stream which have been paresd and cached, + /// stores a mapping to SymIndexId of the cached symbol. DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId; + + /// For field list members which have been parsed and cached, stores a mapping + /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the + /// cached symbol. DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId> FieldListMembersToSymbolId; + + /// List of SymIndexIds for each compiland, indexed by compiland index as they + /// appear in the PDB file. std::vector<SymIndexId> Compilands; + /// Map from global symbol offset to SymIndexId. + DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId; + SymIndexId createSymbolPlaceholder() { SymIndexId Id = Cache.size(); Cache.push_back(nullptr); @@ -89,6 +107,9 @@ public: std::unique_ptr<IPDBEnumSymbols> createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds); + std::unique_ptr<IPDBEnumSymbols> + createGlobalsEnumerator(codeview::SymbolKind Kind); + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); template <typename ConcreteSymbolT, typename... Args> @@ -106,6 +127,8 @@ public: return SymId; } + SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); + std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index); uint32_t getNumCompilands() const; diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 77c09ae2184..86dcfdaa163 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -47,6 +47,7 @@ add_pdb_impl_folder(Native Native/InfoStreamBuilder.cpp Native/ModuleDebugStream.cpp Native/NativeCompilandSymbol.cpp + Native/NativeEnumGlobals.cpp Native/NativeEnumModules.cpp Native/NativeEnumTypes.cpp Native/NativeExeSymbol.cpp @@ -57,6 +58,7 @@ add_pdb_impl_folder(Native Native/NativeTypeEnum.cpp Native/NativeTypeFunctionSig.cpp Native/NativeTypePointer.cpp + Native/NativeTypeTypedef.cpp Native/NativeTypeUDT.cpp Native/NativeTypeVTShape.cpp Native/NamedStreamMap.cpp diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp new file mode 100644 index 00000000000..6eece3df2db --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp @@ -0,0 +1,55 @@ +//==- NativeEnumGlobals.cpp - Native Global Enumerator impl ------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" + +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeEnumGlobals::NativeEnumGlobals(NativeSession &PDBSession, + std::vector<codeview::SymbolKind> Kinds) + : Index(0), Session(PDBSession) { + GlobalsStream &GS = cantFail(Session.getPDBFile().getPDBGlobalsStream()); + SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream()); + for (uint32_t Off : GS.getGlobalsTable()) { + CVSymbol S = SS.readRecord(Off); + if (!llvm::is_contained(Kinds, S.kind())) + continue; + MatchOffsets.push_back(Off); + } +} + +uint32_t NativeEnumGlobals::getChildCount() const { + return static_cast<uint32_t>(MatchOffsets.size()); +} + +std::unique_ptr<PDBSymbol> +NativeEnumGlobals::getChildAtIndex(uint32_t N) const { + if (N >= MatchOffsets.size()) + return nullptr; + + SymIndexId Id = + Session.getSymbolCache().getOrCreateGlobalSymbolByOffset(MatchOffsets[N]); + return Session.getSymbolCache().getSymbolById(Id); +} + +std::unique_ptr<PDBSymbol> NativeEnumGlobals::getNext() { + return getChildAtIndex(Index++); +} + +void NativeEnumGlobals::reset() { Index = 0; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index e86f836ee14..6dde5d08a50 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -56,6 +56,8 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const { case PDB_SymType::FunctionSig: return Session.getSymbolCache().createTypeEnumerator( {codeview::LF_PROCEDURE, codeview::LF_MFUNCTION}); + case PDB_SymType::Typedef: + return Session.getSymbolCache().createGlobalsEnumerator(codeview::S_UDT); default: break; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp new file mode 100644 index 00000000000..60b37328226 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp @@ -0,0 +1,27 @@ +#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeTypedef::NativeTypeTypedef(NativeSession &Session, SymIndexId Id, + codeview::UDTSym Typedef) + : NativeRawSymbol(Session, PDB_SymType::Typedef, Id), + Record(std::move(Typedef)) {} + +NativeTypeTypedef::~NativeTypeTypedef() {} + +void NativeTypeTypedef::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); +} + +std::string NativeTypeTypedef::getName() const { return Record.Name; } + +SymIndexId NativeTypeTypedef::getTypeId() const { + return Session.getSymbolCache().findSymbolByTypeIndex(Record.Type); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index eb254493131..7485341a206 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -1,9 +1,12 @@ #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" @@ -12,9 +15,11 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" @@ -85,6 +90,12 @@ SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { new NativeEnumTypes(Session, Types, std::move(Kinds))); } +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) { + return std::unique_ptr<IPDBEnumSymbols>( + new NativeEnumGlobals(Session, {Kind})); +} + SymIndexId SymbolCache::createSimpleType(TypeIndex Index, ModifierOptions Mods) { if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) @@ -247,6 +258,32 @@ uint32_t SymbolCache::getNumCompilands() const { return Dbi->modules().getModuleCount(); } +SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) { + auto Iter = GlobalOffsetToSymbolId.find(Offset); + if (Iter != GlobalOffsetToSymbolId.end()) + return Iter->second; + + SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream()); + CVSymbol CVS = SS.readRecord(Offset); + SymIndexId Id = 0; + switch (CVS.kind()) { + case SymbolKind::S_UDT: { + UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS)); + Id = createSymbol<NativeTypeTypedef>(std::move(US)); + break; + } + default: + Id = createSymbolPlaceholder(); + break; + } + if (Id != 0) { + assert(GlobalOffsetToSymbolId.count(Offset) == 0); + GlobalOffsetToSymbolId[Offset] = Id; + } + + return Id; +} + std::unique_ptr<PDBSymbolCompiland> SymbolCache::getOrCreateCompiland(uint32_t Index) { if (!Dbi) diff --git a/llvm/test/DebugInfo/PDB/Native/pdb-native-typedefs.test b/llvm/test/DebugInfo/PDB/Native/pdb-native-typedefs.test new file mode 100644 index 00000000000..5784fcc37f0 --- /dev/null +++ b/llvm/test/DebugInfo/PDB/Native/pdb-native-typedefs.test @@ -0,0 +1,33 @@ +; Test that the native PDB reader can enumerate typedefs. The output being +; checked against is golden output generated by llvm-pdbutil without the +; -native flag. Then we check that we generate the same output. + +; RUN: llvm-pdbutil pretty -native -typedefs %p/../Inputs/symbolformat.pdb \ +; RUN: | FileCheck -check-prefix=PRETTY %s + +; RUN: llvm-pdbutil diadump -native -typedefs %p/../Inputs/symbolformat.pdb \ +; RUN: | FileCheck -check-prefix=DUMP %s + +PRETTY: Typedefs: (3 items) +PRETTY-NEXT: typedef int IntType +PRETTY-NEXT: typedef class A ClassAType +PRETTY-NEXT: typedef int[3] int_array + +DUMP: { +DUMP-NEXT: symIndexId: 2 +DUMP-NEXT: symTag: Typedef +DUMP-NEXT: name: IntType +DUMP-NEXT: typeId: 3 +DUMP-NEXT: } +DUMP-NEXT: { +DUMP-NEXT: symIndexId: 4 +DUMP-NEXT: symTag: Typedef +DUMP-NEXT: name: ClassAType +DUMP-NEXT: typeId: 5 +DUMP-NEXT: } +DUMP-NEXT: { +DUMP-NEXT: symIndexId: 6 +DUMP-NEXT: symTag: Typedef +DUMP-NEXT: name: int_array +DUMP-NEXT: typeId: 7 +DUMP-NEXT: } diff --git a/llvm/test/tools/llvm-pdbdump/type-qualifiers.test b/llvm/test/tools/llvm-pdbdump/type-qualifiers.test index ff68e2ff95c..0969c15873c 100644 --- a/llvm/test/tools/llvm-pdbdump/type-qualifiers.test +++ b/llvm/test/tools/llvm-pdbdump/type-qualifiers.test @@ -16,7 +16,7 @@ ; GLOBALS_DATA-DAG: static volatile int* __restrict NS::p_data_member ; QUALS: ---TYPES--- -; QUALS-DAG: typedef RankNArray +; QUALS-DAG: typedef volatile int*[100][10] RankNArray ; QUALS-DAG: typedef long* __restrict RestrictTypedef ; QUALS: union Union ; QUALS-DAG: int* __restrict x_member diff --git a/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp index 65443d6bca9..2b3f3691ed9 100644 --- a/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp @@ -12,6 +12,7 @@ #include "LinePrinter.h" #include "PrettyBuiltinDumper.h" #include "PrettyFunctionDumper.h" +#include "PrettyTypeDumper.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" @@ -35,7 +36,10 @@ void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) { << Symbol.getName(); } -void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {} +void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) { + TypeDumper Dumper(Printer); + Dumper.dump(Symbol); +} void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { BuiltinDumper Dumper(Printer); diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index 49bcc55f279..da9a64487ed 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -197,6 +197,8 @@ static cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"), cl::sub(DiaDumpSubcommand)); static cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"), cl::sub(DiaDumpSubcommand)); +static cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"), + cl::sub(DiaDumpSubcommand)); } // namespace diadump namespace pretty { @@ -1027,6 +1029,8 @@ static void dumpDia(StringRef Path) { SymTypes.push_back(PDB_SymType::ArrayType); if (opts::diadump::VTShapes) SymTypes.push_back(PDB_SymType::VTableShape); + if (opts::diadump::Typedefs) + SymTypes.push_back(PDB_SymType::Typedef); PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None : PdbSymbolIdField::All; |