llvm.org GIT mirror llvm / 2d30fac
Enable llvm-pdbutil to list enumerations using native PDB reader This extends the native reader to enable llvm-pdbutil to list the enums in a PDB and it includes a simple test. It does not yet list the values in the enumerations, which requires an actual implementation of NativeEnumSymbol::FindChildren. To exercise this code, use a command like: llvm-pdbutil pretty -native -enums foo.pdb Differential Revision: https://reviews.llvm.org/D35738 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310144 91177308-0d34-0410-b5e6-96231b3b80d8 Adrian McCarthy 2 years ago
11 changed file(s) with 354 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
0 //===- NativeEnumSymbol.h - info about enum type ----------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
10 #define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
11
12 #include "llvm/DebugInfo/CodeView/CodeView.h"
13 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
14 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
15 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
16
17 namespace llvm {
18 namespace pdb {
19
20 class NativeEnumSymbol : public NativeRawSymbol,
21 public codeview::TypeVisitorCallbacks {
22 public:
23 NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
24 const codeview::CVType &CV);
25 ~NativeEnumSymbol() override;
26
27 std::unique_ptr clone() const override;
28
29 std::unique_ptr
30 findChildren(PDB_SymType Type) const override;
31
32 Error visitKnownRecord(codeview::CVType &CVR,
33 codeview::EnumRecord &Record) override;
34 Error visitKnownMember(codeview::CVMemberRecord &CVM,
35 codeview::EnumeratorRecord &Record) override;
36
37 PDB_SymType getSymTag() const override;
38 uint32_t getClassParentId() const override;
39 uint32_t getUnmodifiedTypeId() const override;
40 bool hasConstructor() const override;
41 bool hasAssignmentOperator() const override;
42 bool hasCastOperator() const override;
43 uint64_t getLength() const override;
44 std::string getName() const override;
45 bool isNested() const override;
46 bool hasOverloadedOperator() const override;
47 bool isPacked() const override;
48 bool isScoped() const override;
49 uint32_t getTypeId() const override;
50
51 protected:
52 codeview::CVType CV;
53 codeview::EnumRecord Record;
54 };
55
56 } // namespace pdb
57 } // namespace llvm
58
59 #endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
0 //==- NativeEnumTypes.h - Native Type Enumerator impl ------------*- C++ -*-==//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H
10 #define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H
11
12 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
13 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
14 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
16
17 #include
18
19 namespace llvm {
20 namespace pdb {
21
22 class NativeSession;
23
24 class NativeEnumTypes : public IPDBEnumChildren {
25 public:
26 NativeEnumTypes(NativeSession &Session,
27 codeview::LazyRandomTypeCollection &TypeCollection,
28 codeview::TypeLeafKind Kind);
29
30 uint32_t getChildCount() const override;
31 std::unique_ptr getChildAtIndex(uint32_t Index) const override;
32 std::unique_ptr getNext() override;
33 void reset() override;
34 NativeEnumTypes *clone() const override;
35
36 private:
37 NativeEnumTypes(NativeSession &Session,
38 const std::vector &Matches,
39 codeview::TypeLeafKind Kind);
40
41 std::vector Matches;
42 uint32_t Index;
43 NativeSession &Session;
44 codeview::TypeLeafKind Kind;
45 };
46
47 } // namespace pdb
48 } // namespace llvm
49
50 #endif
3737
3838 std::unique_ptr
3939 createCompilandSymbol(DbiModuleDescriptor MI);
40
41 std::unique_ptr
42 createEnumSymbol(codeview::TypeIndex Index);
43
44 std::unique_ptr
45 createTypeEnumerator(codeview::TypeLeafKind Kind);
4046
4147 SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
4248
66 //
77 //===----------------------------------------------------------------------===//
88
9 #ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
10 #define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
9 #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOL_H
10 #define LLVM_DEBUGINFO_PDB_PDBSYMBOL_H
1111
1212 #include "ConcreteSymbolEnumerator.h"
1313 #include "IPDBRawSymbol.h"
4343 Native/NativeBuiltinSymbol.cpp
4444 Native/NativeCompilandSymbol.cpp
4545 Native/NativeEnumModules.cpp
46 Native/NativeEnumSymbol.cpp
47 Native/NativeEnumTypes.cpp
4648 Native/NativeExeSymbol.cpp
4749 Native/NativeRawSymbol.cpp
4850 Native/NamedStreamMap.cpp
0 //===- NativeEnumSymbol.cpp - info about enum type --------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
10
11 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
13 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
15
16 #include
17
18 using namespace llvm;
19 using namespace llvm::pdb;
20
21 NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
22 const codeview::CVType &CVT)
23 : NativeRawSymbol(Session, Id), CV(CVT),
24 Record(codeview::TypeRecordKind::Enum) {
25 assert(CV.kind() == codeview::TypeLeafKind::LF_ENUM);
26 cantFail(visitTypeRecord(CV, *this));
27 }
28
29 NativeEnumSymbol::~NativeEnumSymbol() {}
30
31 std::unique_ptr NativeEnumSymbol::clone() const {
32 return llvm::make_unique(Session, SymbolId, CV);
33 }
34
35 std::unique_ptr
36 NativeEnumSymbol::findChildren(PDB_SymType Type) const {
37 switch (Type) {
38 case PDB_SymType::Data: {
39 // TODO(amccarth): Provide an actual implementation.
40 return nullptr;
41 }
42 default:
43 return nullptr;
44 }
45 }
46
47 Error NativeEnumSymbol::visitKnownRecord(codeview::CVType &CVR,
48 codeview::EnumRecord &ER) {
49 Record = ER;
50 return Error::success();
51 }
52
53 Error NativeEnumSymbol::visitKnownMember(codeview::CVMemberRecord &CVM,
54 codeview::EnumeratorRecord &R) {
55 return Error::success();
56 }
57
58 PDB_SymType NativeEnumSymbol::getSymTag() const { return PDB_SymType::Enum; }
59
60 uint32_t NativeEnumSymbol::getClassParentId() const { return 0xFFFFFFFF; }
61
62 uint32_t NativeEnumSymbol::getUnmodifiedTypeId() const { return 0; }
63
64 bool NativeEnumSymbol::hasConstructor() const {
65 return bool(Record.getOptions() &
66 codeview::ClassOptions::HasConstructorOrDestructor);
67 }
68
69 bool NativeEnumSymbol::hasAssignmentOperator() const {
70 return bool(Record.getOptions() &
71 codeview::ClassOptions::HasOverloadedAssignmentOperator);
72 }
73
74 bool NativeEnumSymbol::hasCastOperator() const {
75 return bool(Record.getOptions() &
76 codeview::ClassOptions::HasConversionOperator);
77 }
78
79 uint64_t NativeEnumSymbol::getLength() const {
80 const auto Id = Session.findSymbolByTypeIndex(Record.getUnderlyingType());
81 const auto UnderlyingType =
82 Session.getConcreteSymbolById(Id);
83 return UnderlyingType ? UnderlyingType->getLength() : 0;
84 }
85
86 std::string NativeEnumSymbol::getName() const { return Record.getName(); }
87
88 bool NativeEnumSymbol::isNested() const {
89 return bool(Record.getOptions() & codeview::ClassOptions::Nested);
90 }
91
92 bool NativeEnumSymbol::hasOverloadedOperator() const {
93 return bool(Record.getOptions() &
94 codeview::ClassOptions::HasOverloadedOperator);
95 }
96
97 bool NativeEnumSymbol::isPacked() const {
98 return bool(Record.getOptions() & codeview::ClassOptions::Packed);
99 }
100
101 bool NativeEnumSymbol::isScoped() const {
102 return bool(Record.getOptions() & codeview::ClassOptions::Scoped);
103 }
104
105 uint32_t NativeEnumSymbol::getTypeId() const {
106 return Session.findSymbolByTypeIndex(Record.getUnderlyingType());
107 }
0 //==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- C++ -*-==//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
10
11 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
12 #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
13 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
16
17 namespace llvm {
18 namespace pdb {
19
20 NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
21 codeview::LazyRandomTypeCollection &Types,
22 codeview::TypeLeafKind Kind)
23 : Matches(), Index(0), Session(PDBSession), Kind(Kind) {
24 for (auto Index = Types.getFirst(); Index;
25 Index = Types.getNext(Index.getValue())) {
26 if (Types.getType(Index.getValue()).kind() == Kind)
27 Matches.push_back(Index.getValue());
28 }
29 }
30
31 NativeEnumTypes::NativeEnumTypes(
32 NativeSession &PDBSession, const std::vector &Matches,
33 codeview::TypeLeafKind Kind)
34 : Matches(Matches), Index(0), Session(PDBSession), Kind(Kind) {}
35
36 uint32_t NativeEnumTypes::getChildCount() const {
37 return static_cast(Matches.size());
38 }
39
40 std::unique_ptr
41 NativeEnumTypes::getChildAtIndex(uint32_t Index) const {
42 if (Index < Matches.size())
43 return Session.createEnumSymbol(Matches[Index]);
44 return nullptr;
45 }
46
47 std::unique_ptr NativeEnumTypes::getNext() {
48 return getChildAtIndex(Index++);
49 }
50
51 void NativeEnumTypes::reset() { Index = 0; }
52
53 NativeEnumTypes *NativeEnumTypes::clone() const {
54 return new NativeEnumTypes(Session, Matches, Kind);
55 }
56
57 } // namespace pdb
58 } // namespace llvm
1212 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
1313 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
1414 #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
15 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
1516 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
17 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
1618
1719 namespace llvm {
1820 namespace pdb {
3739 consumeError(Dbi.takeError());
3840 break;
3941 }
42 case PDB_SymType::Enum:
43 return Session.createTypeEnumerator(codeview::LF_ENUM);
4044 default:
4145 break;
4246 }
1515 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
1616 #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"
1717 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
18 #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
19 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
1820 #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
1921 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
2022 #include "llvm/DebugInfo/PDB/Native/RawError.h"
23 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
2124 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
2225 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
26 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
2327 #include "llvm/Support/Allocator.h"
2428 #include "llvm/Support/BinaryByteStream.h"
2529 #include "llvm/Support/Error.h"
2731 #include "llvm/Support/MemoryBuffer.h"
2832
2933 #include
34 #include
3035 #include
3136 #include
3237
101106 *this, std::unique_ptr(SymbolCache[Id]->clone()));
102107 }
103108
109 std::unique_ptr
110 NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
111 const auto Id = findSymbolByTypeIndex(Index);
112 return llvm::make_unique(
113 *this, std::unique_ptr(SymbolCache[Id]->clone()));
114 }
115
116 std::unique_ptr
117 NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
118 auto Tpi = Pdb->getPDBTpiStream();
119 if (!Tpi) {
120 consumeError(Tpi.takeError());
121 return nullptr;
122 }
123 auto &Types = Tpi->typeCollection();
124 return std::unique_ptr(
125 new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
126 }
127
104128 SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
105129 // First see if it's already in our cache.
106130 const auto Entry = TypeIndexToSymbolId.find(Index);
128152 return Id;
129153 }
130154
131 // TODO: Look up PDB type by type index
132
133 return 0;
155 // We need to instantiate and cache the desired type symbol.
156 auto Tpi = Pdb->getPDBTpiStream();
157 if (!Tpi) {
158 consumeError(Tpi.takeError());
159 return 0;
160 }
161 auto &Types = Tpi->typeCollection();
162 const auto &I = Types.getType(Index);
163 const auto Id = static_cast(SymbolCache.size());
164 // TODO(amccarth): Make this handle all types, not just LF_ENUMs.
165 assert(I.kind() == codeview::LF_ENUM);
166 SymbolCache.emplace_back(llvm::make_unique(*this, Id, I));
167 TypeIndexToSymbolId[Index] = Id;
168 return Id;
134169 }
135170
136171 uint64_t NativeSession::getLoadAddress() const { return 0; }
0 ; Test that the native PDB reader can enumerate the enum types.
1 ; RUN: llvm-pdbutil pretty -native -enums %p/../Inputs/every-type.pdb \
2 ; RUN: | FileCheck -check-prefix=ENUMS %s
3
4 ENUMS: enum FooClass::NestedEnum {
5 ENUMS-NEXT: }
2525 WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
2626 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
2727 if (!opts::pretty::NoEnumDefs) {
28 auto BuiltinType = Symbol.getUnderlyingType();
29 if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
30 BuiltinType->getLength() != 4) {
28 auto UnderlyingType = Symbol.getUnderlyingType();
29 if (!UnderlyingType)
30 return;
31 if (UnderlyingType->getBuiltinType() != PDB_BuiltinType::Int ||
32 UnderlyingType->getLength() != 4) {
3133 Printer << " : ";
3234 BuiltinDumper Dumper(Printer);
33 Dumper.start(*BuiltinType);
35 Dumper.start(*UnderlyingType);
3436 }
37 auto EnumValues = Symbol.findAllChildren();
3538 Printer << " {";
3639 Printer.Indent();
37 auto EnumValues = Symbol.findAllChildren();
38 while (auto EnumValue = EnumValues->getNext()) {
39 if (EnumValue->getDataKind() != PDB_DataKind::Constant)
40 continue;
41 Printer.NewLine();
42 WithColor(Printer, PDB_ColorItem::Identifier).get()
43 << EnumValue->getName();
44 Printer << " = ";
45 WithColor(Printer, PDB_ColorItem::LiteralValue).get()
46 << EnumValue->getValue();
40 if (EnumValues && EnumValues->getChildCount() > 0) {
41 while (auto EnumValue = EnumValues->getNext()) {
42 if (EnumValue->getDataKind() != PDB_DataKind::Constant)
43 continue;
44 Printer.NewLine();
45 WithColor(Printer, PDB_ColorItem::Identifier).get()
46 << EnumValue->getName();
47 Printer << " = ";
48 WithColor(Printer, PDB_ColorItem::LiteralValue).get()
49 << EnumValue->getValue();
50 }
4751 }
4852 Printer.Unindent();
4953 Printer.NewLine();