Skip to content
This repository was archived by the owner on Sep 2, 2018. It is now read-only.

Commit bcfc7d0

Browse files
committed
[codeview] Add a type visitor to help abstract away type stream handling
Summary: Port the dumper in llvm-readobj over to it. I'm planning to use this visitor to power type stream merging. While we're at it, try to switch from StringRef to ArrayRef<uint8_t> in some places. Reviewers: zturner, amccarth Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D19899 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268535 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 5813ee1 commit bcfc7d0

File tree

7 files changed

+697
-498
lines changed

7 files changed

+697
-498
lines changed

include/llvm/DebugInfo/CodeView/CVLeafTypes.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ LEAF_TYPE(LF_UNION_16t, 0x0006)
3030
LEAF_TYPE(LF_ENUM_16t, 0x0007)
3131
LEAF_TYPE(LF_PROCEDURE_16t, 0x0008)
3232
LEAF_TYPE(LF_MFUNCTION_16t, 0x0009)
33-
LEAF_TYPE(LF_VTSHAPE, 0x000a)
33+
KNOWN_TYPE(LF_VTSHAPE, 0x000a, VTableShape)
3434
LEAF_TYPE(LF_COBOL0_16t, 0x000b)
3535
LEAF_TYPE(LF_COBOL1, 0x000c)
3636
LEAF_TYPE(LF_BARRAY_16t, 0x000d)
@@ -76,8 +76,8 @@ LEAF_TYPE(LF_VFUNCOFF_16t, 0x040d)
7676

7777
LEAF_TYPE(LF_TI16_MAX, 0x1000)
7878

79-
LEAF_TYPE(LF_MODIFIER, 0x1001)
80-
LEAF_TYPE(LF_POINTER, 0x1002)
79+
KNOWN_TYPE(LF_MODIFIER, 0x1001, TypeModifier)
80+
KNOWN_TYPE(LF_POINTER, 0x1002, PointerType)
8181
LEAF_TYPE(LF_ARRAY_ST, 0x1003)
8282
LEAF_TYPE(LF_CLASS_ST, 0x1004)
8383
LEAF_TYPE(LF_STRUCTURE_ST, 0x1005)
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
//===- CVTypeVisitor.h ------------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
11+
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
12+
13+
#include "llvm/DebugInfo/CodeView/CodeView.h"
14+
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
15+
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
16+
#include "llvm/DebugInfo/CodeView/TypeStream.h"
17+
18+
namespace llvm {
19+
namespace codeview {
20+
21+
template <typename Derived>
22+
class CVTypeVisitor {
23+
public:
24+
CVTypeVisitor() {}
25+
26+
bool hadError() const { return HadError; }
27+
28+
template <typename T>
29+
bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
30+
if (Data.size() < sizeof(*Res)) {
31+
HadError = true;
32+
return false;
33+
}
34+
Res = reinterpret_cast<const T *>(Data.data());
35+
Data = Data.drop_front(sizeof(*Res));
36+
return true;
37+
}
38+
39+
/// Actions to take on known types. By default, they do nothing. Visit methods
40+
/// for member records take the FieldData by non-const reference and are
41+
/// expected to consume the trailing bytes used by the field.
42+
/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
43+
/// need to.
44+
#define TYPE_RECORD(ClassName, LeafEnum) \
45+
void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
46+
ArrayRef<uint8_t> LeafData) {}
47+
#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
48+
#define MEMBER_RECORD(ClassName, LeafEnum) \
49+
void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
50+
ArrayRef<uint8_t> &FieldData) {}
51+
#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
52+
#include "TypeRecords.def"
53+
54+
/// Visits the type records in Data and returns remaining data. Sets the
55+
/// error flag on parse failures.
56+
void visitTypeStream(ArrayRef<uint8_t> Data) {
57+
for (const auto &I : makeTypeRange(Data)) {
58+
ArrayRef<uint8_t> LeafData = I.LeafData;
59+
ArrayRef<uint8_t> RecordData = LeafData;
60+
auto *DerivedThis = static_cast<Derived *>(this);
61+
DerivedThis->visitTypeBegin(I.Leaf, RecordData);
62+
switch (I.Leaf) {
63+
default:
64+
DerivedThis->visitUnknownType(I.Leaf);
65+
break;
66+
case LF_FIELDLIST:
67+
DerivedThis->visitFieldList(I.Leaf, LeafData);
68+
break;
69+
case LF_METHODLIST:
70+
DerivedThis->visitMethodList(I.Leaf, LeafData);
71+
break;
72+
#define TYPE_RECORD(ClassName, LeafEnum) \
73+
case LeafEnum: { \
74+
const ClassName *Rec; \
75+
if (!CVTypeVisitor::consumeObject(LeafData, Rec)) \
76+
return; \
77+
DerivedThis->visit##ClassName(I.Leaf, Rec, LeafData); \
78+
break; \
79+
}
80+
#include "TypeRecords.def"
81+
}
82+
DerivedThis->visitTypeEnd(I.Leaf, RecordData);
83+
}
84+
}
85+
86+
/// Action to take on unknown types. By default, they are ignored.
87+
void visitUnknownType(TypeLeafKind Leaf) {}
88+
89+
/// Paired begin/end actions for all types. Receives all record data,
90+
/// including the fixed-length record prefix.
91+
void visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> RecordData) {}
92+
void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> RecordData) {}
93+
94+
static ArrayRef<uint8_t> skipPadding(ArrayRef<uint8_t> Data) {
95+
if (Data.empty())
96+
return Data;
97+
uint8_t Leaf = Data.front();
98+
if (Leaf < LF_PAD0)
99+
return Data;
100+
// Leaf is greater than 0xf0. We should advance by the number of bytes in
101+
// the low 4 bits.
102+
return Data.drop_front(Leaf & 0x0F);
103+
}
104+
105+
/// Visits individual member records of a field list record. Member records do
106+
/// not describe their own length, and need special handling.
107+
void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData) {
108+
while (!FieldData.empty()) {
109+
const ulittle16_t *LeafPtr;
110+
if (!CVTypeVisitor::consumeObject(FieldData, LeafPtr))
111+
return;
112+
TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
113+
switch (Leaf) {
114+
default:
115+
// Field list records do not describe their own length, so we cannot
116+
// continue parsing past an unknown member type.
117+
visitUnknownMember(Leaf);
118+
HadError = true;
119+
return;
120+
#define MEMBER_RECORD(ClassName, LeafEnum) \
121+
case LeafEnum: { \
122+
const ClassName *Rec; \
123+
if (!CVTypeVisitor::consumeObject(FieldData, Rec)) \
124+
return; \
125+
static_cast<Derived *>(this)->visit##ClassName(Leaf, Rec, FieldData); \
126+
break; \
127+
}
128+
#include "TypeRecords.def"
129+
}
130+
FieldData = skipPadding(FieldData);
131+
}
132+
}
133+
134+
/// Action to take on method overload lists, which do not have a common record
135+
/// prefix. The LeafData is composed of MethodListEntry objects, each of which
136+
/// may have a trailing 32-bit vftable offset.
137+
/// FIXME: Hoist this complexity into the visitor.
138+
void visitMethodList(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData) {}
139+
140+
/// Action to take on unknown members. By default, they are ignored. Member
141+
/// record parsing cannot recover from an unknown member record, so this
142+
/// method is only called at most once per field list record.
143+
void visitUnknownMember(TypeLeafKind Leaf) {}
144+
145+
private:
146+
/// Whether a type stream parsing error was encountered.
147+
bool HadError = false;
148+
};
149+
150+
} // end namespace codeview
151+
} // end namespace llvm
152+
153+
#endif // LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
3+
//
4+
// The LLVM Compiler Infrastructure
5+
//
6+
// This file is distributed under the University of Illinois Open Source
7+
// License. See LICENSE.TXT for details.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
//
11+
// See LEAF_ENUM_e in cvinfo.h. This should match the constants there.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
// If the type is known, then we have a record describing it in TypeRecord.h.
16+
#ifndef TYPE_RECORD
17+
#define TYPE_RECORD(ClassName, LeafEnum)
18+
#endif
19+
20+
#ifndef TYPE_RECORD_ALIAS
21+
#define TYPE_RECORD_ALIAS(ClassName, LeafEnum) TYPE_RECORD(ClassName, LeafEnum)
22+
#endif
23+
24+
#ifndef MEMBER_RECORD
25+
#define MEMBER_RECORD(ClassName, LeafEnum) TYPE_RECORD(ClassName, LeafEnum)
26+
#endif
27+
28+
#ifndef MEMBER_RECORD_ALIAS
29+
#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum) MEMBER_RECORD(ClassName, LeafEnum)
30+
#endif
31+
32+
33+
TYPE_RECORD(PointerType, LF_POINTER)
34+
TYPE_RECORD(TypeModifier, LF_MODIFIER)
35+
TYPE_RECORD(ProcedureType, LF_PROCEDURE)
36+
TYPE_RECORD(MemberFunctionType, LF_MFUNCTION)
37+
TYPE_RECORD(ArgList, LF_ARGLIST)
38+
39+
TYPE_RECORD(ArrayType, LF_ARRAY)
40+
TYPE_RECORD(ClassType, LF_CLASS)
41+
TYPE_RECORD_ALIAS(ClassType, LF_STRUCTURE)
42+
TYPE_RECORD_ALIAS(ClassType, LF_INTERFACE)
43+
TYPE_RECORD(UnionType, LF_UNION)
44+
TYPE_RECORD(EnumType, LF_ENUM)
45+
TYPE_RECORD(TypeServer2, LF_TYPESERVER2)
46+
TYPE_RECORD(VFTableType, LF_VFTABLE)
47+
TYPE_RECORD(VTableShape, LF_VTSHAPE)
48+
49+
// Member type records. These are generally not length prefixed, and appear
50+
// inside of a field list record.
51+
MEMBER_RECORD(BaseClass, LF_BCLASS)
52+
MEMBER_RECORD_ALIAS(BaseClass, LF_BINTERFACE)
53+
MEMBER_RECORD(VirtualBaseClass, LF_VBCLASS)
54+
MEMBER_RECORD_ALIAS(VirtualBaseClass, LF_IVBCLASS)
55+
MEMBER_RECORD(VirtualFunctionPointer, LF_VFUNCTAB)
56+
MEMBER_RECORD(StaticDataMember, LF_STMEMBER)
57+
MEMBER_RECORD(OverloadedMethod, LF_METHOD)
58+
MEMBER_RECORD(DataMember, LF_MEMBER)
59+
MEMBER_RECORD(NestedType, LF_NESTTYPE)
60+
MEMBER_RECORD(OneMethod, LF_ONEMETHOD)
61+
MEMBER_RECORD(Enumerator, LF_ENUMERATE)
62+
63+
// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
64+
65+
TYPE_RECORD(FuncId, LF_FUNC_ID)
66+
TYPE_RECORD(MemberFuncId, LF_MFUNC_ID)
67+
TYPE_RECORD(BuildInfo, LF_BUILDINFO)
68+
TYPE_RECORD_ALIAS(ArgList, LF_SUBSTR_LIST)
69+
TYPE_RECORD(StringId, LF_STRING_ID)
70+
TYPE_RECORD(UDTSrcLine, LF_UDT_SRC_LINE)
71+
72+
#undef TYPE_RECORD
73+
#undef TYPE_RECORD_ALIAS
74+
#undef MEMBER_RECORD
75+
#undef MEMBER_RECORD_ALIAS

include/llvm/DebugInfo/CodeView/TypeStream.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ class TypeIterator {
4949
struct TypeRecord {
5050
std::size_t Length;
5151
TypeLeafKind Leaf;
52-
StringRef LeafData;
52+
ArrayRef<uint8_t> LeafData;
5353
};
5454

55-
explicit TypeIterator(const StringRef &SectionData)
55+
explicit TypeIterator(const ArrayRef<uint8_t> &SectionData)
5656
: Data(SectionData), AtEnd(false) {
5757
next(); // Prime the pump
5858
}
@@ -99,12 +99,15 @@ class TypeIterator {
9999
return;
100100
}
101101

102-
const TypeRecordPrefix *Rec;
103-
if (consumeObject(Data, Rec))
102+
// FIXME: Use consumeObject when it deals in ArrayRef<uint8_t>.
103+
if (Data.size() < sizeof(TypeRecordPrefix))
104104
return;
105+
const auto *Rec = reinterpret_cast<const TypeRecordPrefix *>(Data.data());
106+
Data = Data.drop_front(sizeof(TypeRecordPrefix));
107+
105108
Current.Length = Rec->Len;
106109
Current.Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));
107-
Current.LeafData = Data.substr(0, Current.Length - 2);
110+
Current.LeafData = Data.slice(0, Current.Length - 2);
108111

109112
// The next record starts immediately after this one.
110113
Data = Data.drop_front(Current.LeafData.size());
@@ -116,15 +119,16 @@ class TypeIterator {
116119
return;
117120
}
118121

119-
StringRef Data;
122+
ArrayRef<uint8_t> Data;
120123
TypeRecord Current;
121124
bool AtEnd;
122125
};
123126

124-
inline iterator_range<TypeIterator> makeTypeRange(StringRef Data) {
127+
inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data) {
125128
return make_range(TypeIterator(Data), TypeIterator());
126129
}
127-
}
128-
}
130+
131+
} // end namespace codeview
132+
} // end namespace llvm
129133

130134
#endif

include/llvm/Support/ScopedPrinter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ class ScopedPrinter {
277277
printBinaryImpl(Label, StringRef(), V, false);
278278
}
279279

280+
void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
281+
printBinaryImpl(Label, StringRef(), Value, true);
282+
}
283+
280284
void printBinaryBlock(StringRef Label, StringRef Value) {
281285
auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
282286
Value.size());

lib/DebugInfo/PDB/Raw/TpiStream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,5 @@ uint32_t TpiStream::NumTypeRecords() const {
116116
}
117117

118118
iterator_range<codeview::TypeIterator> TpiStream::types() const {
119-
return codeview::makeTypeRange(RecordsBuffer.str());
119+
return codeview::makeTypeRange(RecordsBuffer.data());
120120
}

0 commit comments

Comments
 (0)