llvm.org GIT mirror llvm / 27f68cf
Revert "[CodeView] Provide a common interface for type collections." This is a squash of ~5 reverts of, well, pretty much everything I did today. Something is seriously broken with lit on Windows right now, and as a result assertions that fire in tests are triggering failures. I've been breaking non-Windows bots all day which has seriously confused me because all my tests have been passing, and after running lit with -a to view the output even on successful runs, I find out that the tool is crashing and yet lit is still reporting it as a success! At this point I don't even know where to start, so rather than leave the tree broken for who knows how long, I will get this back to green, and then once lit is fixed on Windows, hopefully hopefully fix the remaining set of problems for real. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303409 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
39 changed file(s) with 720 addition(s) and 995 deletion(s). Raw diff Collapse all Expand all
3131 uint32_t length() const { return RecordData.size(); }
3232 Kind kind() const { return Type; }
3333 ArrayRef data() const { return RecordData; }
34 StringRef str_data() const {
35 return StringRef(reinterpret_cast(RecordData.data()),
36 RecordData.size());
37 }
3834
3935 ArrayRef content() const {
4036 return RecordData.drop_front(sizeof(RecordPrefix));
0 //===-- CVTypeDumper.h - CodeView type info dumper --------------*- 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_CODEVIEW_CVTYPEDUMPER_H
10 #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H
11
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/StringSet.h"
14 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
15 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
18 #include "llvm/Support/ScopedPrinter.h"
19
20 namespace llvm {
21
22 namespace codeview {
23
24 class TypeServerHandler;
25
26 /// Dumper for CodeView type streams found in COFF object files and PDB files.
27 class CVTypeDumper {
28 public:
29 explicit CVTypeDumper(TypeDatabase &TypeDB,
30 TypeServerHandler *Handler = nullptr)
31 : TypeDB(TypeDB), Handler(Handler) {}
32
33 /// Dumps one type record. Returns false if there was a type parsing error,
34 /// and true otherwise. This should be called in order, since the dumper
35 /// maintains state about previous records which are necessary for cross
36 /// type references.
37 Error dump(const CVType &Record, TypeVisitorCallbacks &Dumper);
38
39 /// Dumps the type records in Types. Returns false if there was a type stream
40 /// parse error, and true otherwise.
41 Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper);
42
43 /// Dumps the type records in Data. Returns false if there was a type stream
44 /// parse error, and true otherwise. Use this method instead of the
45 /// CVTypeArray overload when type records are laid out contiguously in
46 /// memory.
47 Error dump(ArrayRef Data, TypeVisitorCallbacks &Dumper);
48
49 static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
50 TypeIndex TI, TypeDatabase &DB);
51
52 private:
53 TypeDatabase &TypeDB;
54 TypeServerHandler *Handler;
55 };
56
57 } // end namespace codeview
58 } // end namespace llvm
59
60 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
99 #ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
1010 #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
1111
12 #include "llvm/ADT/TinyPtrVector.h"
1213 #include "llvm/DebugInfo/CodeView/CVRecord.h"
1314 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
15 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
16 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
1417 #include "llvm/Support/Error.h"
1518
1619 namespace llvm {
1720 namespace codeview {
18 class TypeCollection;
19 class TypeServerHandler;
20 class TypeVisitorCallbacks;
21
22 class CVTypeVisitor {
23 public:
24 explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
25
26 void addTypeServerHandler(TypeServerHandler &Handler);
27
28 Error visitTypeRecord(CVType &Record, TypeIndex Index);
29 Error visitTypeRecord(CVType &Record);
30 Error visitMemberRecord(CVMemberRecord Record);
31
32 /// Visits the type records in Data. Sets the error flag on parse failures.
33 Error visitTypeStream(const CVTypeArray &Types);
34 Error visitTypeStream(CVTypeRange Types);
35
36 Error visitFieldListMemberStream(ArrayRef FieldList);
37 Error visitFieldListMemberStream(BinaryStreamReader Reader);
38
39 private:
40 Expected handleTypeServer(CVType &Record);
41 Error finishVisitation(CVType &Record);
42
43 /// The interface to the class that gets notified of each visitation.
44 TypeVisitorCallbacks &Callbacks;
45
46 TinyPtrVector Handlers;
47 };
2148
2249 enum VisitorDataSource {
2350 VDS_BytesPresent, // The record bytes are passed into the the visitation
4875 TypeServerHandler *TS = nullptr);
4976 Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks,
5077 TypeServerHandler *TS = nullptr);
51 Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks,
52 TypeServerHandler *TS = nullptr);
5378
5479 } // end namespace codeview
5580 } // end namespace llvm
+0
-103
include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h less more
None //===- LazyRandomTypeCollection.h ---------------------------- *- 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_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
10 #define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
11
12 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
13 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
14 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
15 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/Support/Error.h"
18
19 namespace llvm {
20 namespace codeview {
21
22 class TypeDatabase;
23 class TypeVisitorCallbacks;
24
25 /// \brief Provides amortized O(1) random access to a CodeView type stream.
26 /// Normally to access a type from a type stream, you must know its byte
27 /// offset into the type stream, because type records are variable-lengthed.
28 /// However, this is not the way we prefer to access them. For example, given
29 /// a symbol record one of the fields may be the TypeIndex of the symbol's
30 /// type record. Or given a type record such as an array type, there might
31 /// be a TypeIndex for the element type. Sequential access is perfect when
32 /// we're just dumping every entry, but it's very poor for real world usage.
33 ///
34 /// Type streams in PDBs contain an additional field which is a list of pairs
35 /// containing indices and their corresponding offsets, roughly every ~8KB of
36 /// record data. This general idea need not be confined to PDBs though. By
37 /// supplying such an array, the producer of a type stream can allow the
38 /// consumer much better access time, because the consumer can find the nearest
39 /// index in this array, and do a linear scan forward only from there.
40 ///
41 /// LazyRandomTypeCollection implements this algorithm, but additionally goes
42 /// one step further by caching offsets of every record that has been visited at
43 /// least once. This way, even repeated visits of the same record will never
44 /// require more than one linear scan. For a type stream of N elements divided
45 /// into M chunks of roughly equal size, this yields a worst case lookup time
46 /// of O(N/M) and an amortized time of O(1).
47 class LazyRandomTypeCollection : public TypeCollection {
48 typedef FixedStreamArray PartialOffsetArray;
49
50 public:
51 explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
52 LazyRandomTypeCollection(StringRef Data, uint32_t RecordCountHint);
53 LazyRandomTypeCollection(ArrayRef Data, uint32_t RecordCountHint);
54 LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint,
55 PartialOffsetArray PartialOffsets);
56 LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
57
58 void reset(ArrayRef Data);
59 void reset(StringRef Data);
60
61 CVType getType(TypeIndex Index) override;
62 StringRef getTypeName(TypeIndex Index) override;
63 bool contains(TypeIndex Index) override;
64 uint32_t size() override;
65 uint32_t capacity() override;
66 TypeIndex getFirst() override;
67 Optional getNext(TypeIndex Prev) override;
68
69 private:
70 const TypeDatabase &database() const { return Database; }
71 Error ensureTypeExists(TypeIndex Index);
72
73 Error visitRangeForType(TypeIndex TI);
74 Error fullScanForType(TypeIndex TI);
75 Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
76 Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);
77
78 /// Visited records get automatically added to the type database.
79 TypeDatabase Database;
80
81 /// The type array to allow random access visitation of.
82 CVTypeArray Types;
83
84 /// The database visitor which adds new records to the database.
85 TypeDatabaseVisitor DatabaseVisitor;
86
87 /// A vector mapping type indices to type offset. For every record that has
88 /// been visited, contains the absolute offset of that record in the record
89 /// array.
90 std::vector KnownOffsets;
91
92 /// An array of index offsets for the given type stream, allowing log(N)
93 /// lookups of a type record by index. Similar to KnownOffsets but only
94 /// contains offsets for some type indices, some of which may not have
95 /// ever been visited.
96 PartialOffsetArray PartialOffsets;
97 };
98
99 } // end namespace codeview
100 } // end namespace llvm
101
102 #endif // LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
0 //===- RandomAccessTypeVisitor.h ------------------------------ *- 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_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
10 #define LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
11
12 #include "llvm/ADT/TinyPtrVector.h"
13 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
14 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
15 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/Support/Error.h"
18
19 namespace llvm {
20 namespace codeview {
21
22 class TypeDatabase;
23 class TypeServerHandler;
24 class TypeVisitorCallbacks;
25
26 /// \brief Provides amortized O(1) random access to a CodeView type stream.
27 /// Normally to access a type from a type stream, you must know its byte
28 /// offset into the type stream, because type records are variable-lengthed.
29 /// However, this is not the way we prefer to access them. For example, given
30 /// a symbol record one of the fields may be the TypeIndex of the symbol's
31 /// type record. Or given a type record such as an array type, there might
32 /// be a TypeIndex for the element type. Sequential access is perfect when
33 /// we're just dumping every entry, but it's very poor for real world usage.
34 ///
35 /// Type streams in PDBs contain an additional field which is a list of pairs
36 /// containing indices and their corresponding offsets, roughly every ~8KB of
37 /// record data. This general idea need not be confined to PDBs though. By
38 /// supplying such an array, the producer of a type stream can allow the
39 /// consumer much better access time, because the consumer can find the nearest
40 /// index in this array, and do a linear scan forward only from there.
41 ///
42 /// RandomAccessTypeVisitor implements this algorithm, but additionally goes one
43 /// step further by caching offsets of every record that has been visited at
44 /// least once. This way, even repeated visits of the same record will never
45 /// require more than one linear scan. For a type stream of N elements divided
46 /// into M chunks of roughly equal size, this yields a worst case lookup time
47 /// of O(N/M) and an amortized time of O(1).
48 class RandomAccessTypeVisitor {
49 typedef FixedStreamArray PartialOffsetArray;
50
51 public:
52 RandomAccessTypeVisitor(const CVTypeArray &Types, uint32_t NumRecords,
53 PartialOffsetArray PartialOffsets);
54
55 Error visitTypeIndex(TypeIndex Index, TypeVisitorCallbacks &Callbacks);
56
57 const TypeDatabase &database() const { return Database; }
58
59 private:
60 Error visitRangeForType(TypeIndex TI);
61 Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
62
63 /// Visited records get automatically added to the type database.
64 TypeDatabase Database;
65
66 /// The type array to allow random access visitation of.
67 const CVTypeArray &Types;
68
69 /// The database visitor which adds new records to the database.
70 TypeDatabaseVisitor DatabaseVisitor;
71
72 /// A vector mapping type indices to type offset. For every record that has
73 /// been visited, contains the absolute offset of that record in the record
74 /// array.
75 std::vector KnownOffsets;
76
77 /// An array of index offsets for the given type stream, allowing log(N)
78 /// lookups of a type record by index. Similar to KnownOffsets but only
79 /// contains offsets for some type indices, some of which may not have
80 /// ever been visited.
81 PartialOffsetArray PartialOffsets;
82 };
83
84 } // end namespace codeview
85 } // end namespace llvm
86
87 #endif // LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
1919 class ScopedPrinter;
2020
2121 namespace codeview {
22 class TypeCollection;
22 class TypeDatabase;
2323
2424 /// Dumper for CodeView symbol streams found in COFF object files and PDB files.
2525 class CVSymbolDumper {
2626 public:
27 CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types,
27 CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB,
2828 std::unique_ptr ObjDelegate,
2929 bool PrintRecordBytes)
30 : W(W), Types(Types), ObjDelegate(std::move(ObjDelegate)),
30 : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)),
3131 PrintRecordBytes(PrintRecordBytes) {}
3232
3333 /// Dumps one type record. Returns false if there was a type parsing error,
4242
4343 private:
4444 ScopedPrinter &W;
45 TypeCollection &Types;
45 TypeDatabase &TypeDB;
4646 std::unique_ptr ObjDelegate;
4747
4848 bool PrintRecordBytes;
+0
-38
include/llvm/DebugInfo/CodeView/TypeCollection.h less more
None //===- TypeCollection.h - A collection of CodeView type records -*- 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_CODEVIEW_TYPECOLLECTION_H
10 #define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H
11
12 #include "llvm/ADT/StringRef.h"
13
14 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
15 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
16
17 namespace llvm {
18 namespace codeview {
19 class TypeCollection {
20 public:
21 virtual ~TypeCollection() = default;
22
23 bool empty() { return size() == 0; }
24
25 virtual TypeIndex getFirst() = 0;
26 virtual Optional getNext(TypeIndex Prev) = 0;
27
28 virtual CVType getType(TypeIndex Index) = 0;
29 virtual StringRef getTypeName(TypeIndex Index) = 0;
30 virtual bool contains(TypeIndex Index) = 0;
31 virtual uint32_t size() = 0;
32 virtual uint32_t capacity() = 0;
33 };
34 }
35 }
36
37 #endif
1212 #include "llvm/ADT/BitVector.h"
1313 #include "llvm/ADT/SmallVector.h"
1414 #include "llvm/ADT/StringRef.h"
15 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
1615 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
1716 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1817 #include "llvm/Support/Allocator.h"
2019
2120 namespace llvm {
2221 namespace codeview {
23 class TypeDatabase : public TypeCollection {
22 class TypeDatabase {
2423 friend class RandomAccessTypeVisitor;
2524
2625 public:
4140 CVType &getTypeRecord(TypeIndex Index);
4241
4342 bool contains(TypeIndex Index) const;
43
4444 uint32_t size() const;
4545 uint32_t capacity() const;
4646 bool empty() const;
4747
48 CVType getType(TypeIndex Index) override;
49 StringRef getTypeName(TypeIndex Index) override;
50 bool contains(TypeIndex Index) override;
51 uint32_t size() override;
52 uint32_t capacity() override;
53
54 TypeIndex getFirst() override;
55 Optional getNext(TypeIndex Prev) override;
56
57 Optional largestTypeIndexLessThan(TypeIndex TI) const;
48 TypeIndex getAppendIndex() const;
5849
5950 private:
60 TypeIndex getAppendIndex() const;
61
6251 void grow();
63 void grow(TypeIndex Index);
6452
6553 BumpPtrAllocator Allocator;
6654
6755 uint32_t Count = 0;
68 TypeIndex LargestTypeIndex;
6956
7057 /// All user defined type records in .debug$T live in here. Type indices
7158 /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
1111
1212 #include "llvm/ADT/ArrayRef.h"
1313 #include "llvm/ADT/StringSet.h"
14 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1415 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
1516 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1617 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2021
2122 namespace codeview {
2223
23 class TypeCollection;
24
2524 /// Dumper for CodeView type streams found in COFF object files and PDB files.
2625 class TypeDumpVisitor : public TypeVisitorCallbacks {
2726 public:
28 TypeDumpVisitor(TypeCollection &TpiTypes, ScopedPrinter *W,
29 bool PrintRecordBytes)
30 : W(W), PrintRecordBytes(PrintRecordBytes), TpiTypes(TpiTypes) {}
27 TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes)
28 : W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {}
3129
3230 /// When dumping types from an IPI stream in a PDB, a type index may refer to
3331 /// a type or an item ID. The dumper will lookup the "name" of the index in
3432 /// the item database if appropriate. If ItemDB is null, it will use TypeDB,
3533 /// which is correct when dumping types from an object file (/Z7).
36 void setIpiTypes(TypeCollection &Types) { IpiTypes = &Types; }
34 void setItemDB(TypeDatabase &DB) { ItemDB = &DB; }
3735
3836 void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
3937
6765 /// Get the database of indices for the stream that we are dumping. If ItemDB
6866 /// is set, then we must be dumping an item (IPI) stream. This will also
6967 /// always get the appropriate DB for printing item names.
70 TypeCollection &getSourceTypes() const {
71 return IpiTypes ? *IpiTypes : TpiTypes;
72 }
68 TypeDatabase &getSourceDB() const { return ItemDB ? *ItemDB : TypeDB; }
7369
7470 ScopedPrinter *W;
7571
7672 bool PrintRecordBytes = false;
7773
78 TypeCollection &TpiTypes;
79 TypeCollection *IpiTypes = nullptr;
74 TypeDatabase &TypeDB;
75 TypeDatabase *ItemDB = nullptr;
8076 };
8177
8278 } // end namespace codeview
1414 #include
1515
1616 namespace llvm {
17
18 class ScopedPrinter;
19
2017 namespace codeview {
21
22 class TypeCollection;
2318
2419 enum class SimpleTypeKind : uint32_t {
2520 None = 0x0000, // uncharacterized type (no type)
242237 return Result;
243238 }
244239
245 friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
246 assert(A >= B);
247 return A.toArrayIndex() - B.toArrayIndex();
248 }
249
250240 private:
251241 support::ulittle32_t Index;
252242 };
258248 TypeIndex Type;
259249 support::ulittle32_t Offset;
260250 };
261
262 void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
263 TypeCollection &Types);
264251 }
265252 }
266253
+0
-42
include/llvm/DebugInfo/CodeView/TypeTableCollection.h less more
None //===- TypeTableCollection.h ---------------------------------- *- 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_CODEVIEW_TYPETABLECOLLECTION_H
10 #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
11
12 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
13 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
14
15 namespace llvm {
16 namespace codeview {
17
18 class TypeTableCollection : public TypeCollection {
19 public:
20 explicit TypeTableCollection(ArrayRef> Records);
21
22 TypeIndex getFirst() override;
23 Optional getNext(TypeIndex Prev) override;
24
25 CVType getType(TypeIndex Index) override;
26 StringRef getTypeName(TypeIndex Index) override;
27 bool contains(TypeIndex Index) override;
28 uint32_t size() override;
29 uint32_t capacity() override;
30
31 private:
32 bool hasCapacityFor(TypeIndex Index) const;
33 void ensureTypeExists(TypeIndex Index);
34
35 ArrayRef> Records;
36 TypeDatabase Database;
37 };
38 }
39 }
40
41 #endif
1616 namespace codeview {
1717
1818 class TypeVisitorCallbacks {
19 friend class CVTypeVisitor;
20
1921 public:
2022 virtual ~TypeVisitorCallbacks() = default;
2123
1212 #include "llvm/ADT/SmallString.h"
1313 #include "llvm/ADT/SmallVector.h"
1414 #include "llvm/ADT/StringMap.h"
15 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1516 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1617 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
1718 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
1212
1313 #include "CodeViewDebug.h"
1414 #include "llvm/ADT/TinyPtrVector.h"
15 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
1516 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1617 #include "llvm/DebugInfo/CodeView/CodeView.h"
1718 #include "llvm/DebugInfo/CodeView/Line.h"
2122 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
2223 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
2324 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
24 #include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
2525 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2626 #include "llvm/IR/Constants.h"
2727 #include "llvm/MC/MCAsmInfo.h"
468468 CommentPrefix += ' ';
469469 }
470470
471 TypeTableCollection Table(TypeTable.records());
472 Optional B = Table.getFirst();
473 do {
474 // This will fail if the record data is invalid.
475 CVType Record = Table.getType(*B);
476
471 TypeDatabase TypeDB(TypeTable.records().size());
472 CVTypeDumper CVTD(TypeDB);
473 TypeTable.ForEachRecord([&](TypeIndex Index, ArrayRef Record) {
477474 if (OS.isVerboseAsm()) {
478475 // Emit a block comment describing the type record for readability.
479476 SmallString<512> CommentBlock;
480477 raw_svector_ostream CommentOS(CommentBlock);
481478 ScopedPrinter SP(CommentOS);
482479 SP.setPrefix(CommentPrefix);
483 TypeDumpVisitor TDV(Table, &SP, false);
484
485 Error E = codeview::visitTypeRecord(Record, *B, TDV);
480 TypeDumpVisitor TDV(TypeDB, &SP, false);
481 Error E = CVTD.dump(Record, TDV);
486482 if (E) {
487483 logAllUnhandledErrors(std::move(E), errs(), "error: ");
488484 llvm_unreachable("produced malformed type record");
492488 // newline.
493489 OS.emitRawComment(
494490 CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
495 }
496 OS.EmitBinaryData(Record.str_data());
497 } while ((B = Table.getNext(*B)));
491 } else {
492 #ifndef NDEBUG
493 // Assert that the type data is valid even if we aren't dumping
494 // comments. The MSVC linker doesn't do much type record validation,
495 // so the first link of an invalid type record can succeed while
496 // subsequent links will fail with LNK1285.
497 BinaryByteStream Stream(Record, llvm::support::little);
498 CVTypeArray Types;
499 BinaryStreamReader Reader(Stream);
500 Error E = Reader.readArray(Types, Reader.getLength());
501 if (!E) {
502 TypeVisitorCallbacks C;
503 E = codeview::visitTypeStream(Types, C);
504 }
505 if (E) {
506 logAllUnhandledErrors(std::move(E), errs(), "error: ");
507 llvm_unreachable("produced malformed type record");
508 }
509 #endif
510 }
511 StringRef S(reinterpret_cast(Record.data()), Record.size());
512 OS.EmitBinaryData(S);
513 });
498514 }
499515
500516 namespace {
11 CodeViewError.cpp
22 CodeViewRecordIO.cpp
33 CVSymbolVisitor.cpp
4 CVTypeDumper.cpp
45 CVTypeVisitor.cpp
56 EnumTables.cpp
67 Formatters.cpp
7 LazyRandomTypeCollection.cpp
88 Line.cpp
99 ModuleDebugFileChecksumFragment.cpp
1010 ModuleDebugFragment.cpp
1212 ModuleDebugFragmentVisitor.cpp
1313 ModuleDebugInlineeLinesFragment.cpp
1414 ModuleDebugLineFragment.cpp
15 RandomAccessTypeVisitor.cpp
1516 RecordSerialization.cpp
1617 StringTable.cpp
1718 SymbolRecordMapping.cpp
2021 TypeDatabase.cpp
2122 TypeDatabaseVisitor.cpp
2223 TypeDumpVisitor.cpp
23 TypeIndex.cpp
2424 TypeRecordMapping.cpp
2525 TypeSerializer.cpp
2626 TypeStreamMerger.cpp
27 TypeTableCollection.cpp
28
27
2928 ADDITIONAL_HEADER_DIRS
3029 ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
3130 )
0 //===-- CVTypeDumper.cpp - CodeView type info dumper ------------*- 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/CodeView/CVTypeDumper.h"
10 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
11 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
12 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
13 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
14 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
15 #include "llvm/Support/BinaryByteStream.h"
16
17 using namespace llvm;
18 using namespace llvm::codeview;
19
20 Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
21 TypeDatabaseVisitor DBV(TypeDB);
22 TypeVisitorCallbackPipeline Pipeline;
23 Pipeline.addCallbackToPipeline(DBV);
24 Pipeline.addCallbackToPipeline(Dumper);
25
26 CVType RecordCopy = Record;
27 return codeview::visitTypeRecord(RecordCopy, Pipeline, VDS_BytesPresent,
28 Handler);
29 }
30
31 Error CVTypeDumper::dump(const CVTypeArray &Types,
32 TypeVisitorCallbacks &Dumper) {
33 TypeDatabaseVisitor DBV(TypeDB);
34 TypeVisitorCallbackPipeline Pipeline;
35 Pipeline.addCallbackToPipeline(DBV);
36 Pipeline.addCallbackToPipeline(Dumper);
37
38 return codeview::visitTypeStream(Types, Pipeline, Handler);
39 }
40
41 Error CVTypeDumper::dump(ArrayRef Data, TypeVisitorCallbacks &Dumper) {
42 BinaryByteStream Stream(Data, llvm::support::little);
43 CVTypeArray Types;
44 BinaryStreamReader Reader(Stream);
45 if (auto EC = Reader.readArray(Types, Reader.getLength()))
46 return EC;
47
48 return dump(Types, Dumper);
49 }
50
51 void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
52 TypeIndex TI, TypeDatabase &DB) {
53 StringRef TypeName;
54 if (!TI.isNoneType())
55 TypeName = DB.getTypeName(TI);
56 if (!TypeName.empty())
57 Printer.printHex(FieldName, TypeName, TI.getIndex());
58 else
59 Printer.printHex(FieldName, TI.getIndex());
60 }
88
99 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1010
11 #include "llvm/ADT/TinyPtrVector.h"
1211 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
1412 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1513 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
1614 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
2321 using namespace llvm;
2422 using namespace llvm::codeview;
2523
24 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
25 : Callbacks(Callbacks) {}
2626
2727 template
2828 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
6565 return R;
6666 }
6767
68 void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
69 Handlers.push_back(&Handler);
70 }
71
72 Expected CVTypeVisitor::handleTypeServer(CVType &Record) {
73 if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
74 auto TS = deserializeTypeServerRecord(Record);
75 if (!TS)
76 return TS.takeError();
77
78 for (auto Handler : Handlers) {
79 auto ExpectedResult = Handler->handle(*TS, Callbacks);
80 // If there was an error, return the error.
81 if (!ExpectedResult)
82 return ExpectedResult.takeError();
83
84 // If the handler processed the record, return success.
85 if (*ExpectedResult)
86 return true;
87
88 // Otherwise keep searching for a handler, eventually falling out and
89 // using the default record handler.
90 }
91 }
92 return false;
93 }
94
95 Error CVTypeVisitor::finishVisitation(CVType &Record) {
96 switch (Record.Type) {
97 default:
98 if (auto EC = Callbacks.visitUnknownType(Record))
99 return EC;
100 break;
101 #define TYPE_RECORD(EnumName, EnumVal, Name) \
102 case EnumName: { \
103 if (auto EC = visitKnownRecord(Record, Callbacks)) \
104 return EC; \
105 break; \
106 }
107 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
108 TYPE_RECORD(EnumVal, EnumVal, AliasName)
109 #define MEMBER_RECORD(EnumName, EnumVal, Name)
110 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
111 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
112 }
113
114 if (auto EC = Callbacks.visitTypeEnd(Record))
115 return EC;
116
117 return Error::success();
118 }
119
120 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
121 auto ExpectedResult = handleTypeServer(Record);
122 if (!ExpectedResult)
123 return ExpectedResult.takeError();
124 if (*ExpectedResult)
125 return Error::success();
126
127 if (auto EC = Callbacks.visitTypeBegin(Record, Index))
128 return EC;
129
130 return finishVisitation(Record);
131 }
132
133 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
134 auto ExpectedResult = handleTypeServer(Record);
135 if (!ExpectedResult)
136 return ExpectedResult.takeError();
137 if (*ExpectedResult)
138 return Error::success();
139
140 if (auto EC = Callbacks.visitTypeBegin(Record))
141 return EC;
142
143 return finishVisitation(Record);
144 }
145
68146 static Error visitMemberRecord(CVMemberRecord &Record,
69147 TypeVisitorCallbacks &Callbacks) {
70148 if (auto EC = Callbacks.visitMemberBegin(Record))
94172 return Error::success();
95173 }
96174
97 namespace {
98
99 class CVTypeVisitor {
100 public:
101 explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
102
103 void addTypeServerHandler(TypeServerHandler &Handler);
104
105 Error visitTypeRecord(CVType &Record, TypeIndex Index);
106 Error visitTypeRecord(CVType &Record);
107
108 /// Visits the type records in Data. Sets the error flag on parse failures.
109 Error visitTypeStream(const CVTypeArray &Types);
110 Error visitTypeStream(CVTypeRange Types);
111 Error visitTypeStream(TypeCollection &Types);
112
113 Error visitMemberRecord(CVMemberRecord Record);
114 Error visitFieldListMemberStream(BinaryStreamReader &Stream);
115
116 private:
117 Expected handleTypeServer(CVType &Record);
118 Error finishVisitation(CVType &Record);
119
120 /// The interface to the class that gets notified of each visitation.
121 TypeVisitorCallbacks &Callbacks;
122
123 TinyPtrVector Handlers;
124 };
125
126 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
127 : Callbacks(Callbacks) {}
128
129 void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
130 Handlers.push_back(&Handler);
131 }
132
133 Expected CVTypeVisitor::handleTypeServer(CVType &Record) {
134 if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
135 auto TS = deserializeTypeServerRecord(Record);
136 if (!TS)
137 return TS.takeError();
138
139 for (auto Handler : Handlers) {
140 auto ExpectedResult = Handler->handle(*TS, Callbacks);
141 // If there was an error, return the error.
142 if (!ExpectedResult)
143 return ExpectedResult.takeError();
144
145 // If the handler processed the record, return success.
146 if (*ExpectedResult)
147 return true;
148
149 // Otherwise keep searching for a handler, eventually falling out and
150 // using the default record handler.
151 }
152 }
153 return false;
154 }
155
156 Error CVTypeVisitor::finishVisitation(CVType &Record) {
157 switch (Record.Type) {
158 default:
159 if (auto EC = Callbacks.visitUnknownType(Record))
160 return EC;
161 break;
162 #define TYPE_RECORD(EnumName, EnumVal, Name) \
163 case EnumName: { \
164 if (auto EC = visitKnownRecord(Record, Callbacks)) \
165 return EC; \
166 break; \
167 }
168 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
169 TYPE_RECORD(EnumVal, EnumVal, AliasName)
170 #define MEMBER_RECORD(EnumName, EnumVal, Name)
171 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
172 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
173 }
174
175 if (auto EC = Callbacks.visitTypeEnd(Record))
176 return EC;
177
178 return Error::success();
179 }
180
181 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
182 auto ExpectedResult = handleTypeServer(Record);
183 if (!ExpectedResult)
184 return ExpectedResult.takeError();
185 if (*ExpectedResult)
186 return Error::success();
187
188 if (auto EC = Callbacks.visitTypeBegin(Record, Index))
189 return EC;
190
191 return finishVisitation(Record);
192 }
193
194 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
195 auto ExpectedResult = handleTypeServer(Record);
196 if (!ExpectedResult)
197 return ExpectedResult.takeError();
198 if (*ExpectedResult)
199 return Error::success();
200
201 if (auto EC = Callbacks.visitTypeBegin(Record))
202 return EC;
203
204 return finishVisitation(Record);
205 }
206
207175 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
208176 return ::visitMemberRecord(Record, Callbacks);
209177 }
225193 return Error::success();
226194 }
227195
228 Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
229 if (Types.empty())
230 return Error::success();
231
232 Optional I = Types.getFirst();
233 do {
234 CVType Type = Types.getType(*I);
235 if (auto EC = visitTypeRecord(Type, *I))
236 return EC;
237 } while ((I = Types.getNext(*I)));
238 return Error::success();
239 }
240
241 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
196 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
197 FieldListDeserializer Deserializer(Reader);
198 TypeVisitorCallbackPipeline Pipeline;
199 Pipeline.addCallbackToPipeline(Deserializer);
200 Pipeline.addCallbackToPipeline(Callbacks);
201
242202 TypeLeafKind Leaf;
243203 while (!Reader.empty()) {
244204 if (auto EC = Reader.readEnum(Leaf))
246206
247207 CVMemberRecord Record;
248208 Record.Kind = Leaf;
249 if (auto EC = ::visitMemberRecord(Record, Callbacks))
250 return EC;
251 }
252
253 return Error::success();
254 }
255
209 if (auto EC = ::visitMemberRecord(Record, Pipeline))
210 return EC;
211 }
212
213 return Error::success();
214 }
215
216 Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef Data) {
217 BinaryByteStream S(Data, llvm::support::little);
218 BinaryStreamReader SR(S);
219 return visitFieldListMemberStream(SR);
220 }
221
222 namespace {
256223 struct FieldListVisitHelper {
257224 FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef Data,
258225 VisitorDataSource Source)
273240 };
274241
275242 struct VisitHelper {
276 VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
243 VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source,
244 TypeServerHandler *TS)
277245 : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
246 if (TS)
247 Visitor.addTypeServerHandler(*TS);
278248 if (Source == VDS_BytesPresent) {
279249 Pipeline.addCallbackToPipeline(Deserializer);
280250 Pipeline.addCallbackToPipeline(Callbacks);
291261 TypeVisitorCallbacks &Callbacks,
292262 VisitorDataSource Source,
293263 TypeServerHandler *TS) {
294 VisitHelper V(Callbacks, Source);
295 if (TS)
296 V.Visitor.addTypeServerHandler(*TS);
297 return V.Visitor.visitTypeRecord(Record, Index);
264 VisitHelper Helper(Callbacks, Source, TS);
265 return Helper.Visitor.visitTypeRecord(Record, Index);
298266 }
299267
300268 Error llvm::codeview::visitTypeRecord(CVType &Record,
301269 TypeVisitorCallbacks &Callbacks,
302270 VisitorDataSource Source,
303271 TypeServerHandler *TS) {
304 VisitHelper V(Callbacks, Source);
305 if (TS)
306 V.Visitor.addTypeServerHandler(*TS);
307 return V.Visitor.visitTypeRecord(Record);
308 }
309
310 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
311 TypeVisitorCallbacks &Callbacks,
312 TypeServerHandler *TS) {
313 VisitHelper V(Callbacks, VDS_BytesPresent);
314 if (TS)
315 V.Visitor.addTypeServerHandler(*TS);
316 return V.Visitor.visitTypeStream(Types);
317 }
318
319 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
320 TypeVisitorCallbacks &Callbacks,
321 TypeServerHandler *TS) {
322 VisitHelper V(Callbacks, VDS_BytesPresent);
323 if (TS)
324 V.Visitor.addTypeServerHandler(*TS);
325 return V.Visitor.visitTypeStream(Types);
326 }
327
328 Error llvm::codeview::visitTypeStream(TypeCollection &Types,
329 TypeVisitorCallbacks &Callbacks,
330 TypeServerHandler *TS) {
331 // When the internal visitor calls Types.getType(Index) the interface is
332 // required to return a CVType with the bytes filled out. So we can assume
333 // that the bytes will be present when individual records are visited.
334 VisitHelper V(Callbacks, VDS_BytesPresent);
335 if (TS)
336 V.Visitor.addTypeServerHandler(*TS);
337 return V.Visitor.visitTypeStream(Types);
272 VisitHelper Helper(Callbacks, Source, TS);
273 return Helper.Visitor.visitTypeRecord(Record);
274 }
275
276 Error llvm::codeview::visitMemberRecordStream(ArrayRef FieldList,
277 TypeVisitorCallbacks &Callbacks) {
278 CVTypeVisitor Visitor(Callbacks);
279 return Visitor.visitFieldListMemberStream(FieldList);
338280 }
339281
340282 Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
341283 TypeVisitorCallbacks &Callbacks,
342284 VisitorDataSource Source) {
343 FieldListVisitHelper V(Callbacks, Record.Data, Source);
344 return V.Visitor.visitMemberRecord(Record);
285 FieldListVisitHelper Helper(Callbacks, Record.Data, Source);
286 return Helper.Visitor.visitMemberRecord(Record);
345287 }
346288
347289 Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
353295 return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
354296 }
355297
356 Error llvm::codeview::visitMemberRecordStream(ArrayRef FieldList,
357 TypeVisitorCallbacks &Callbacks) {
358 FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
359 return V.Visitor.visitFieldListMemberStream(V.Reader);
360 }
298 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
299 TypeVisitorCallbacks &Callbacks,
300 TypeServerHandler *TS) {
301 VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
302 return Helper.Visitor.visitTypeStream(Types);
303 }
304
305 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
306 TypeVisitorCallbacks &Callbacks,
307 TypeServerHandler *TS) {
308 VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
309 return Helper.Visitor.visitTypeStream(Types);
310 }
+0
-226
lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp less more
None //===- LazyRandomTypeCollection.cpp ---------------------------- *- 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/CodeView/LazyRandomTypeCollection.h"
10
11 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
14 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
15 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
16
17 using namespace llvm;
18 using namespace llvm::codeview;
19
20 static void error(Error &&EC) {
21 assert(!static_cast(EC));
22 if (EC)
23 consumeError(std::move(EC));
24 }
25
26 LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)
27 : LazyRandomTypeCollection(CVTypeArray(), RecordCountHint,
28 PartialOffsetArray()) {}
29
30 LazyRandomTypeCollection::LazyRandomTypeCollection(
31 const CVTypeArray &Types, uint32_t RecordCountHint,
32 PartialOffsetArray PartialOffsets)
33 : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database),
34 PartialOffsets(PartialOffsets) {
35 KnownOffsets.resize(Database.capacity());
36 }
37
38 LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef Data,
39 uint32_t RecordCountHint)
40 : LazyRandomTypeCollection(RecordCountHint) {
41 reset(Data);
42 }
43
44 LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
45 uint32_t RecordCountHint)
46 : LazyRandomTypeCollection(
47 makeArrayRef(Data.bytes_begin(), Data.bytes_end()), RecordCountHint) {
48 }
49
50 LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,
51 uint32_t NumRecords)
52 : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
53
54 void LazyRandomTypeCollection::reset(StringRef Data) {
55 reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end()));
56 }
57
58 void LazyRandomTypeCollection::reset(ArrayRef Data) {
59 PartialOffsets = PartialOffsetArray();
60
61 BinaryStreamReader Reader(Data, support::little);
62 error(Reader.readArray(Types, Reader.getLength()));
63
64 KnownOffsets.resize(Database.capacity());
65 }
66
67 CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
68 error(ensureTypeExists(Index));
69 return Database.getTypeRecord(Index);
70 }
71
72 StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
73 if (!Index.isSimple()) {
74 // Try to make sure the type exists. Even if it doesn't though, it may be
75 // because we're dumping a symbol stream with no corresponding type stream
76 // present, in which case we still want to be able to print
77 // for the type names.
78 consumeError(ensureTypeExists(Index));
79 }
80
81 return Database.getTypeName(Index);
82 }
83
84 bool LazyRandomTypeCollection::contains(TypeIndex Index) {
85 return Database.contains(Index);
86 }
87
88 uint32_t LazyRandomTypeCollection::size() { return Database.size(); }
89
90 uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); }
91
92 Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
93 if (!Database.contains(TI)) {
94 if (auto EC = visitRangeForType(TI))
95 return EC;
96 }
97 return Error::success();
98 }
99
100 Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
101 if (PartialOffsets.empty())
102 return fullScanForType(TI);
103
104 auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
105 [](TypeIndex Value, const TypeIndexOffset &IO) {
106 return Value < IO.Type;
107 });
108
109 assert(Next != PartialOffsets.begin());
110 auto Prev = std::prev(Next);
111
112 TypeIndex TIB = Prev->Type;
113 if (Database.contains(TIB)) {
114 // They've asked us to fetch a type index, but the entry we found in the
115 // partial offsets array has already been visited. Since we visit an entire
116 // block every time, that means this record should have been previously
117 // discovered. Ultimately, this means this is a request for a non-existant
118 // type index.
119 return make_error("Invalid type index");
120 }
121
122 TypeIndex TIE;
123 if (Next == PartialOffsets.end()) {
124 TIE = TypeIndex::fromArrayIndex(Database.capacity());
125 } else {
126 TIE = Next->Type;
127 }
128
129 if (auto EC = visitRange(TIB, Prev->Offset, TIE))
130 return EC;
131 return Error::success();
132 }
133
134 TypeIndex LazyRandomTypeCollection::getFirst() {
135 TypeIndex TI = TypeIndex::fromArrayIndex(0);
136 error(ensureTypeExists(TI));
137 return TI;
138 }
139
140 Optional LazyRandomTypeCollection::getNext(TypeIndex Prev) {
141 // We can't be sure how long this type stream is, given that the initial count
142 // given to the constructor is just a hint. So just try to make sure the next
143 // record exists, and if anything goes wrong, we must be at the end.
144 if (auto EC = ensureTypeExists(Prev + 1)) {
145 consumeError(std::move(EC));
146 return None;
147 }
148
149 return Prev + 1;
150 }
151
152 Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {
153 assert(PartialOffsets.empty());
154
155 TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
156 uint32_t Offset = 0;
157 auto Begin = Types.begin();
158
159 if (!Database.empty()) {
160 // In the case of type streams which we don't know the number of records of,
161 // it's possible to search for a type index triggering a full scan, but then
162 // later additional records are added since we didn't know how many there
163 // would be until we did a full visitation, then you try to access the new
164 // type triggering another full scan. To avoid this, we assume that if the
165 // database has some records, this must be what's going on. So we ask the
166 // database for the largest type index less than the one we're searching for
167 // and only do the forward scan from there.
168 auto Prev = Database.largestTypeIndexLessThan(TI);
169 assert(Prev.hasValue() && "Empty database with valid types?");
170 Offset = KnownOffsets[Prev->toArrayIndex()];
171 CurrentTI = *Prev;
172 ++CurrentTI;
173 Begin = Types.at(Offset);
174 ++Begin;
175 Offset = Begin.offset();
176 }
177
178 auto End = Types.end();
179 while (Begin != End) {
180 if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin))
181 return EC;
182
183 Offset += Begin.getRecordLength();
184 ++Begin;
185 ++CurrentTI;
186 }
187 if (CurrentTI <= TI) {
188 return make_error("Type Index does not exist!");
189 }
190 return Error::success();
191 }
192
193 Error LazyRandomTypeCollection::visitRange(TypeIndex Begin,
194 uint32_t BeginOffset,
195 TypeIndex End) {
196
197 auto RI = Types.at(BeginOffset);
198 assert(RI != Types.end());
199
200 while (Begin != End) {
201 if (auto EC = visitOneRecord(Begin, BeginOffset, *RI))
202 return EC;
203
204 BeginOffset += RI.getRecordLength();
205 ++Begin;
206 ++RI;
207 }
208
209 return Error::success();
210 }
211
212 Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset,
213 CVType &Record) {
214 assert(!Database.contains(TI));
215 if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor))
216 return EC;
217 // Keep the KnownOffsets array the same size as the Database's capacity. Since
218 // we don't always know how many records are in the type stream, we need to be
219 // prepared for the database growing and receicing a type index that can't fit
220 // in our current buffer.
221 if (KnownOffsets.size() < Database.capacity())
222 KnownOffsets.resize(Database.capacity());
223 KnownOffsets[TI.toArrayIndex()] = Offset;
224 return Error::success();
225 }
0 //===- RandomAccessTypeVisitor.cpp ---------------------------- *- 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/CodeView/RandomAccessTypeVisitor.h"
10
11 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
13 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
14 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
15
16 using namespace llvm;
17 using namespace llvm::codeview;
18
19 RandomAccessTypeVisitor::RandomAccessTypeVisitor(
20 const CVTypeArray &Types, uint32_t NumRecords,
21 PartialOffsetArray PartialOffsets)
22 : Database(NumRecords), Types(Types), DatabaseVisitor(Database),
23 PartialOffsets(PartialOffsets) {
24
25 KnownOffsets.resize(Database.capacity());
26 }
27
28 Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI,
29 TypeVisitorCallbacks &Callbacks) {
30 assert(TI.toArrayIndex() < Database.capacity());
31
32 if (!Database.contains(TI)) {
33 if (auto EC = visitRangeForType(TI))
34 return EC;
35 }
36
37 assert(Database.contains(TI));
38 auto &Record = Database.getTypeRecord(TI);
39 return codeview::visitTypeRecord(Record, TI, Callbacks);
40 }
41
42 Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) {
43 if (PartialOffsets.empty()) {
44 TypeIndex TIB(TypeIndex::FirstNonSimpleIndex);
45 TypeIndex TIE = TIB + Database.capacity();
46 return visitRange(TIB, 0, TIE);
47 }
48
49 auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
50 [](TypeIndex Value, const TypeIndexOffset &IO) {
51 return Value < IO.Type;
52 });
53
54 assert(Next != PartialOffsets.begin());
55 auto Prev = std::prev(Next);
56
57 TypeIndex TIB = Prev->Type;
58 TypeIndex TIE;
59 if (Next == PartialOffsets.end()) {
60 TIE = TypeIndex::fromArrayIndex(Database.capacity());
61 } else {
62 TIE = Next->Type;
63 }
64
65 if (auto EC = visitRange(TIB, Prev->Offset, TIE))
66 return EC;
67 return Error::success();
68 }
69
70 Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset,
71 TypeIndex End) {
72
73 auto RI = Types.at(BeginOffset);
74 assert(RI != Types.end());
75
76 while (Begin != End) {
77 assert(!Database.contains(Begin));
78 if (auto EC = codeview::visitTypeRecord(*RI, Begin, DatabaseVisitor))
79 return EC;
80 KnownOffsets[Begin.toArrayIndex()] = BeginOffset;
81
82 BeginOffset += RI.getRecordLength();
83 ++Begin;
84 ++RI;
85 }
86
87 return Error::success();
88 }
1010 #include "llvm/ADT/DenseMap.h"
1111 #include "llvm/ADT/SmallString.h"
1212 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
13 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
1314 #include "llvm/DebugInfo/CodeView/EnumTables.h"
1415 #include "llvm/DebugInfo/CodeView/StringTable.h"
1516 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
3132 /// the visitor out of SymbolDumper.h.
3233 class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
3334 public:
34 CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
35 CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate,
3536 ScopedPrinter &W, bool PrintRecordBytes)
36 : Types(Types), ObjDelegate(ObjDelegate), W(W),
37 : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
3738 PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
3839
3940 /// CVSymbolVisitor overrides.
5253 void printLocalVariableAddrGap(ArrayRef Gaps);
5354 void printTypeIndex(StringRef FieldName, TypeIndex TI);
5455
55 TypeCollection &Types;
56 TypeDatabase &TypeDB;
5657 SymbolDumpDelegate *ObjDelegate;
5758 ScopedPrinter &W;
5859
8182 }
8283
8384 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
84 codeview::printTypeIndex(W, FieldName, TI, Types);
85 CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB);
8586 }
8687
8788 Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
668669 Error CVSymbolDumper::dump(CVRecord &Record) {
669670 SymbolVisitorCallbackPipeline Pipeline;
670671 SymbolDeserializer Deserializer(ObjDelegate.get());
671 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
672 CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
672673
673674 Pipeline.addCallbackToPipeline(Deserializer);
674675 Pipeline.addCallbackToPipeline(Dumper);
679680 Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
680681 SymbolVisitorCallbackPipeline Pipeline;
681682 SymbolDeserializer Deserializer(ObjDelegate.get());
682 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
683 CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
683684
684685 Pipeline.addCallbackToPipeline(Deserializer);
685686 Pipeline.addCallbackToPipeline(Dumper);
7171 }
7272
7373 TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) {
74 LargestTypeIndex = getAppendIndex();
75 if (LargestTypeIndex.toArrayIndex() >= capacity())
74 TypeIndex TI;
75 TI = getAppendIndex();
76 if (TI.toArrayIndex() >= capacity())
7677 grow();
77 recordType(Name, LargestTypeIndex, Data);
78 return LargestTypeIndex;
78 recordType(Name, TI, Data);
79 return TI;
7980 }
8081
8182 void TypeDatabase::recordType(StringRef Name, TypeIndex Index,
8283 const CVType &Data) {
83 LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex);
84
85 if (LargestTypeIndex.toArrayIndex() >= capacity())
86 grow(Index);
87
8884 uint32_t AI = Index.toArrayIndex();
8985
9086 assert(!contains(Index));
147143
148144 uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); }
149145
150 CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); }
151
152 StringRef TypeDatabase::getTypeName(TypeIndex Index) {
153 return static_cast(this)->getTypeName(Index);
154 }
155
156 bool TypeDatabase::contains(TypeIndex Index) {
157 return static_cast(this)->contains(Index);
158 }
159
160 uint32_t TypeDatabase::size() {
161 return static_cast(this)->size();
162 }
163
164 uint32_t TypeDatabase::capacity() {
165 return static_cast(this)->capacity();
166 }
167
168 void TypeDatabase::grow() { grow(LargestTypeIndex + 1); }
169
170 void TypeDatabase::grow(TypeIndex NewIndex) {
171 uint32_t NewSize = NewIndex.toArrayIndex() + 1;
172
173 if (NewSize <= capacity())
174 return;
175
176 uint32_t NewCapacity = NewSize * 3 / 2;
177
178 TypeRecords.resize(NewCapacity);
179 CVUDTNames.resize(NewCapacity);
180 ValidRecords.resize(NewCapacity);
146 void TypeDatabase::grow() {
147 TypeRecords.emplace_back();
148 CVUDTNames.emplace_back();
149 ValidRecords.resize(ValidRecords.size() + 1);
181150 }
182151
183152 bool TypeDatabase::empty() const { return size() == 0; }
184
185 Optional TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const {
186 uint32_t AI = TI.toArrayIndex();
187 int N = ValidRecords.find_prev(AI);
188 if (N == -1)
189 return None;
190 return TypeIndex::fromArrayIndex(N);
191 }
192153
193154 TypeIndex TypeDatabase::getAppendIndex() const {
194155 if (empty())
195156 return TypeIndex::fromArrayIndex(0);
196157
197 return LargestTypeIndex + 1;
158 int Index = ValidRecords.find_last();
159 assert(Index != -1);
160 return TypeIndex::fromArrayIndex(Index) + 1;
198161 }
199
200 TypeIndex TypeDatabase::getFirst() {
201 int N = ValidRecords.find_first();
202 assert(N != -1);
203 return TypeIndex::fromArrayIndex(N);
204 }
205
206 Optional TypeDatabase::getNext(TypeIndex Prev) {
207 int N = ValidRecords.find_next(Prev.toArrayIndex());
208 if (N == -1)
209 return None;
210 return TypeIndex::fromArrayIndex(N);
211 }
99 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
1010
1111 #include "llvm/ADT/SmallString.h"
12 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
1213 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1314 #include "llvm/DebugInfo/CodeView/Formatters.h"
14 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
1515 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1616 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1718 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
1819 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
20 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
1921 #include "llvm/Support/BinaryByteStream.h"
2022 #include "llvm/Support/FormatVariadic.h"
2123 #include "llvm/Support/ScopedPrinter.h"
162164 }
163165
164166 void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
165 codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
167 CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB);
166168 }
167169
168170 void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
169 codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
171 CVTypeDumper::printTypeIndex(*W, FieldName, TI, getSourceDB());
170172 }
171173
172174 Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
173 return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
175 TypeIndex TI = getSourceDB().getAppendIndex();
176 return visitTypeBegin(Record, TI);
174177 }
175178
176179 Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
241244 W->printNumber("NumStrings", Size);
242245 ListScope Arguments(*W, "Strings");
243246 for (uint32_t I = 0; I < Size; ++I) {
244 printItemIndex("String", Indices[I]);
247 printTypeIndex("String", Indices[I]);
245248 }
246249 return Error::success();
247250 }
+0
-27
lib/DebugInfo/CodeView/TypeIndex.cpp less more
None //===-- TypeIndex.cpp - CodeView type index ---------------------*- 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/CodeView/TypeIndex.h"
10
11 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
12 #include "llvm/Support/ScopedPrinter.h"
13
14 using namespace llvm;
15 using namespace llvm::codeview;
16
17 void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
18 TypeIndex TI, TypeCollection &Types) {
19 StringRef TypeName;
20 if (!TI.isNoneType())
21 TypeName = Types.getTypeName(TI);
22 if (!TypeName.empty())
23 Printer.printHex(FieldName, TypeName, TI.getIndex());
24 else
25 Printer.printHex(FieldName, TI.getIndex());
26 }
1010 #include "llvm/ADT/SmallString.h"
1111 #include "llvm/ADT/StringExtras.h"
1212 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
13 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1314 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
1415 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1516 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
17 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
1618 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
1719 #include "llvm/Support/Error.h"
1820 #include "llvm/Support/ScopedPrinter.h"
+0
-82
lib/DebugInfo/CodeView/TypeTableCollection.cpp less more
None //===- TypeTableCollection.cpp -------------------------------- *- 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/CodeView/TypeTableCollection.h"
10
11 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
13 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
14 #include "llvm/Support/BinaryByteStream.h"
15 #include "llvm/Support/BinaryStreamReader.h"
16
17 using namespace llvm;
18 using namespace llvm::codeview;
19
20 static void error(Error &&EC) {
21 assert(!static_cast(EC));
22 if (EC)
23 consumeError(std::move(EC));
24 }
25
26 TypeTableCollection::TypeTableCollection(
27 ArrayRef> Records)
28 : Records(Records), Database(Records.size()) {}
29
30 TypeIndex TypeTableCollection::getFirst() {
31 assert(!empty());
32 return TypeIndex::fromArrayIndex(0);
33 }
34
35 Optional TypeTableCollection::getNext(TypeIndex Prev) {
36 ++Prev;
37 assert(Prev.toArrayIndex() <= size());
38 if (Prev.toArrayIndex() == size())
39 return None;
40 return Prev;
41 }
42
43 void TypeTableCollection::ensureTypeExists(TypeIndex Index) {
44 assert(hasCapacityFor(Index));
45
46 if (Database.contains(Index))
47 return;
48
49 BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little);
50
51 CVType Type;
52 uint32_t Len;
53 error(VarStreamArrayExtractor::extract(Bytes, Len, Type));
54
55 TypeDatabaseVisitor DBV(Database);
56 error(codeview::visitTypeRecord(Type, Index, DBV));
57 assert(Database.contains(Index));
58 }
59
60 CVType TypeTableCollection::getType(TypeIndex Index) {
61 ensureTypeExists(Index);
62 return Database.getTypeRecord(Index);
63 }
64
65 StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
66 if (!Index.isSimple())
67 ensureTypeExists(Index);
68 return Database.getTypeName(Index);
69 }
70
71 bool TypeTableCollection::contains(TypeIndex Index) {
72 return Database.contains(Index);
73 }
74
75 uint32_t TypeTableCollection::size() { return Records.size(); }
76
77 uint32_t TypeTableCollection::capacity() { return Records.size(); }
78
79 bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const {
80 return Index.toArrayIndex() < Records.size();
81 }
2020
2121 #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
2222
23 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
2423 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
2524 #include "llvm/DebugInfo/PDB/GenericError.h"
2625 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
88
99 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
1010 #include "llvm/ADT/iterator_range.h"
11 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1113 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
14 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
1215 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1316 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
1417 #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
325325 ; EMPTY-NEXT: TypeLeafKind: LF_SUBSTR_LIST (0x1604)
326326 ; EMPTY-NEXT: NumStrings: 1
327327 ; EMPTY-NEXT: Strings [
328 ; EMPTY-NEXT: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows
328 ; EMPTY-NEXT: String: __vc_attributes::threadingAttribute (0x100B)
329329 ; EMPTY-NEXT: ]
330330 ; EMPTY-NEXT: }
331331 ; EMPTY-NEXT: Bytes (
12521252 ; ALL: TypeLeafKind: LF_SUBSTR_LIST (0x1604)
12531253 ; ALL: NumStrings: 1
12541254 ; ALL: Strings [
1255 ; ALL: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows (0x100B)
1255 ; ALL: String: __vc_attributes::threadingAttribute (0x100B)
12561256 ; ALL: ]
12571257 ; ALL: }
12581258 ; ALL: }
1313 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1414 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1515 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
16 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1617 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1718 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
1819 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2828 return StringRef();
2929 }
3030
31 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
31 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
3232 ScopedPrinter *W)
33 : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex),
33 : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex),
3434 W) {}
3535
36 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
36 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
3737 TypeIndex FirstTI,
3838 ScopedPrinter *W)
39 : W(W), TI(FirstTI), Offset(0), Types(Types) {}
39 : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {}
4040
4141 Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
4242 return Error::success();
4545 Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
4646 uint32_t I = TI.getIndex();
4747 StringRef Leaf = getLeafName(Record.Type);
48 StringRef Name = Types.getTypeName(TI);
48 StringRef Name = TypeDB.getTypeName(TI);
4949 W->printString(
5050 llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I,
5151 Record.length(), Offset, Leaf, Name)
1616 namespace llvm {
1717 class ScopedPrinter;
1818 namespace codeview {
19 class TypeCollection;
19 class TypeDatabase;
2020 }
2121
2222 namespace pdb {
2525 /// Dumps records on a single line, and ignores member records.
2626 class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
2727 public:
28 CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W);
29 CompactTypeDumpVisitor(codeview::TypeCollection &Types,
28 CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
29 CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB,
3030 codeview::TypeIndex FirstTI, ScopedPrinter *W);
3131
3232 /// Paired begin/end actions for all types. Receives all record data,
3939
4040 codeview::TypeIndex TI;
4141 uint32_t Offset;
42 codeview::TypeCollection &Types;
42 codeview::TypeDatabase &TypeDB;
4343 };
4444
4545 } // end namespace pdb
1313 #include "StreamUtil.h"
1414 #include "llvm-pdbdump.h"
1515
16 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
1617 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1718 #include "llvm/DebugInfo/CodeView/EnumTables.h"
18 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
1919 #include "llvm/DebugInfo/CodeView/Line.h"
2020 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
2121 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
2424 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
2525 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
2626 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
27 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
2728 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
2829 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
2930 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
8283
8384 class C13RawVisitor : public C13DebugFragmentVisitor {
8485 public:
85 C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI)
86 C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI)
8687 : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
8788
8889 Error handleLines() override {
158159 if (auto EC = printFileName("FileName", L.Header->FileID))
159160 return EC;
160161
161 if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
162 if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee))
162163 return EC;
163164 P.printNumber("SourceLine", L.Header->SourceLineNum);
164165 if (IL.hasExtraFiles()) {
174175 }
175176
176177 private:
177 Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
178 CompactTypeDumpVisitor CTDV(IPI, Index, &P);
178 Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) {
179 CompactTypeDumpVisitor CTDV(DB, Index, &P);
179180 DictScope D(P, Label);
180 if (IPI.contains(Index)) {
181 CVType Type = IPI.getType(Index);
181 if (DB.contains(Index)) {
182 CVType &Type = DB.getTypeRecord(Index);
182183 if (auto EC = codeview::visitTypeRecord(Type, CTDV))
183184 return EC;
184185 } else {
197198 }
198199
199200 ScopedPrinter &P;
200 LazyRandomTypeCollection &IPI;
201 TypeDatabase &IPI;
201202 };
202203 }
203204
607608 VerLabel = "IPI Version";
608609 }
609610
611 if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
612 return Error::success();
613
610614 auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
611615 : File.getPDBIpiStream();
612616 if (!Tpi)
613617 return Tpi.takeError();
614618
615 auto ExpectedTypes = initializeTypeDatabase(StreamIdx);
616 if (!ExpectedTypes)
617 return ExpectedTypes.takeError();
618 auto &Types = *ExpectedTypes;
619
620 if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
621 return Error::success();
622
623619 std::unique_ptr StreamScope;
624620 std::unique_ptr RecordScope;
625621
627623 P.printNumber(VerLabel, Tpi->getTpiVersion());
628624 P.printNumber("Record count", Tpi->getNumTypeRecords());
629625
626 Optional &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB;
627
630628 std::vector> Visitors;
631629
630 if (!StreamDB.hasValue()) {
631 StreamDB.emplace(Tpi->getNumTypeRecords());
632 Visitors.push_back(make_unique(*StreamDB));
633 }
632634 // If we're in dump mode, add a dumper with the appropriate detail level.
633635 if (DumpRecords) {
634636 std::unique_ptr Dumper;
635637 if (opts::raw::CompactRecords)
636 Dumper = make_unique(Types, &P);
638 Dumper = make_unique(*StreamDB, &P);
637639 else {
638 assert(TpiTypes);
639
640 auto X = make_unique(*TpiTypes, &P, false);
640 assert(TypeDB.hasValue());
641
642 auto X = make_unique(*TypeDB, &P, false);
641643 if (StreamIdx == StreamIPI)
642 X->setIpiTypes(*IpiTypes);
644 X->setItemDB(*ItemDB);
643645 Dumper = std::move(X);
644646 }
645647 Visitors.push_back(std::move(Dumper));
657659 if (DumpRecords || DumpRecordBytes)
658660 RecordScope = llvm::make_unique(P, "Records");
659661
660 Optional I = Types.getFirst();
661 do {
662 bool HadError = false;
663
664 TypeIndex T(TypeIndex::FirstNonSimpleIndex);
665 for (auto Type : Tpi->types(&HadError)) {
662666 std::unique_ptr OneRecordScope;
663667
664668 if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
665669 OneRecordScope = llvm::make_unique(P, "");
666670
667 auto T = Types.getType(*I);
668 if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline))
671 if (auto EC = codeview::visitTypeRecord(Type, Pipeline))
669672 return EC;
670 } while ((I = Types.getNext(*I)));
673
674 ++T;
675 }
676 if (HadError)
677 return make_error(raw_error_code::corrupt_file,
678 "TPI stream contained corrupt record");
671679
672680 if (DumpTpiHash) {
673681 DictScope DD(P, "Hash");
702710 return Error::success();
703711 }
704712
705 Expected
706 LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) {
707 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
713 Error LLVMOutputStyle::buildTypeDatabase(uint32_t SN) {
714 assert(SN == StreamIPI || SN == StreamTPI);
715
716 auto &DB = (SN == StreamIPI) ? ItemDB : TypeDB;
717
718 if (DB.hasValue())
719 return Error::success();
720
708721 auto Tpi =
709722 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
723
710724 if (!Tpi)
711725 return Tpi.takeError();
712726
713 if (!TypeCollection) {
714 // Initialize the type collection, even if we're not going to dump it. This
715 // way if some other part of the dumper decides it wants to use some or all
716 // of the records for whatever purposes, it can still access them lazily.
717 auto &Types = Tpi->typeArray();
718 uint32_t Count = Tpi->getNumTypeRecords();
719 auto Offsets = Tpi->getTypeIndexOffsets();
720 TypeCollection =
721 llvm::make_unique(Types, Count, Offsets);
722 }
723
724 return *TypeCollection;
727 DB.emplace(Tpi->getNumTypeRecords());
728
729 TypeDatabaseVisitor DBV(*DB);
730
731 auto HashValues = Tpi->getHashValues();
732 if (HashValues.empty())
733 return codeview::visitTypeStream(Tpi->typeArray(), DBV);
734
735 TypeVisitorCallbackPipeline Pipeline;
736 Pipeline.addCallbackToPipeline(DBV);
737
738 TpiHashVerifier HashVerifier(HashValues, Tpi->getNumHashBuckets());
739 Pipeline.addCallbackToPipeline(HashVerifier);
740
741 return codeview::visitTypeStream(Tpi->typeArray(), Pipeline);
725742 }
726743
727744 Error LLVMOutputStyle::dumpDbiStream() {
796813 return EC;
797814
798815 if (ShouldDumpSymbols) {
799 auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
800 if (!ExpectedTypes)
801 return ExpectedTypes.takeError();
802 auto &Types = *ExpectedTypes;
816 if (auto EC = buildTypeDatabase(StreamTPI))
817 return EC;
803818
804819 ListScope SS(P, "Symbols");
805 codeview::CVSymbolDumper SD(P, Types, nullptr, false);
820 codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
806821 bool HadError = false;
807822 for (auto S : ModS.symbols(&HadError)) {
808823 DictScope LL(P, "");
823838 }
824839 if (opts::raw::DumpLineInfo) {
825840 ListScope SS(P, "LineInfo");
826 auto ExpectedTypes = initializeTypeDatabase(StreamIPI);
827 if (!ExpectedTypes)
828 return ExpectedTypes.takeError();
829 auto &IpiItems = *ExpectedTypes;
830 C13RawVisitor V(P, File, IpiItems);
841 if (auto EC = buildTypeDatabase(StreamIPI))
842 return EC;
843
844 C13RawVisitor V(P, File, *ItemDB);
831845 if (auto EC = codeview::visitModuleDebugFragments(
832846 ModS.linesAndChecksums(), V))
833847 return EC;
945959 P.printList("Section Offsets", Publics->getSectionOffsets(),
946960 printSectionOffset);
947961 ListScope L(P, "Symbols");
948 auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
949 if (!ExpectedTypes)
950 return ExpectedTypes.takeError();
951 auto &Tpi = *ExpectedTypes;
952
953 codeview::CVSymbolDumper SD(P, Tpi, nullptr, false);
962 if (auto EC = buildTypeDatabase(StreamTPI))
963 return EC;
964
965 codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
954966 bool HadError = false;
955967 for (auto S : Publics->getSymbols(&HadError)) {
956968 DictScope DD(P, "");
2020
2121 namespace llvm {
2222 class BitVector;
23
24 namespace codeview {
25 class LazyRandomTypeCollection;
26 }
27
2823 namespace pdb {
2924 class LLVMOutputStyle : public OutputStyle {
3025 public:
3328 Error dump() override;
3429
3530 private:
36 Expected
37 initializeTypeDatabase(uint32_t SN);
31 Error buildTypeDatabase(uint32_t SN);
3832
3933 Error dumpFileHeaders();
4034 Error dumpStreamSummary();
5953
6054 PDBFile &File;
6155 ScopedPrinter P;
62 std::unique_ptr TpiTypes;
63 std::unique_ptr IpiTypes;
56 Optional TypeDB;
57 Optional ItemDB;
6458 SmallVector StreamPurposes;
6559 };
6660 }
1818 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
1919 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
2020 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
21 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
2122 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
2223 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
2324 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
369370 void MappingContextTraits::
370371 mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
371372 pdb::yaml::SerializationContext &Context) {
373
372374 if (IO.outputting()) {
373375 // For PDB to Yaml, deserialize into a high level record type, then dump it.
374376 consumeError(codeview::visitTypeRecord(Obj.Record, Context.Dumper));
1212 #include "OutputStyle.h"
1313 #include "PdbYaml.h"
1414
15 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
1516 #include "llvm/Support/ScopedPrinter.h"
1617 #include "llvm/Support/YAMLTraits.h"
1718
1212
1313 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1414 #include "llvm/DebugInfo/CodeView/EnumTables.h"
15 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1516 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1617 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
1718 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
3030 #include "llvm/ADT/STLExtras.h"
3131 #include "llvm/ADT/StringExtras.h"
3232 #include "llvm/Config/config.h"
33 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
3433 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
3534 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
3635 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
885884 DestIpi.addTypeRecord(Data, None);
886885 });
887886
888 SmallString<64> OutFile(opts::merge::PdbOutputFile);
887 SmallString<64> OutFile = opts::merge::PdbOutputFile;
889888 if (OutFile.empty()) {
890889 OutFile = opts::merge::InputFilenames[0];
891890 llvm::sys::path::replace_extension(OutFile, "merged.pdb");
2121 #include "llvm/ADT/DenseMap.h"
2222 #include "llvm/ADT/SmallString.h"
2323 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
24 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
2525 #include "llvm/DebugInfo/CodeView/CodeView.h"
26 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
2726 #include "llvm/DebugInfo/CodeView/Line.h"
2827 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
2928 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
3433 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
3534 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
3635 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
37 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
3836 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
3937 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
4038 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
4139 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
4240 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
43 #include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
4441 #include "llvm/Object/COFF.h"
4542 #include "llvm/Object/ObjectFile.h"
4643 #include "llvm/Support/BinaryStreamReader.h"
7269 public:
7370 friend class COFFObjectDumpDelegate;
7471 COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
75 : ObjDumper(Writer), Obj(Obj), Writer(Writer), Types(100) {}
72 : ObjDumper(Writer), Obj(Obj), Writer(Writer), TypeDB(100) {}
7673
7774 void printFileHeaders() override;
7875 void printSections() override;
108105 void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
109106 void printTypeIndex(StringRef FieldName, TypeIndex TI) {
110107 // Forward to CVTypeDumper for simplicity.
111 codeview::printTypeIndex(Writer, FieldName, TI, Types);
108 CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB);
112109 }
113110
114111 void printCodeViewSymbolsSubsection(StringRef Subsection,
161158 StringTableRef CVStringTable;
162159
163160 ScopedPrinter &Writer;
164 BinaryByteStream TypeContents;
165 LazyRandomTypeCollection Types;
161 TypeDatabase TypeDB;
166162 };
167163
168164 class COFFObjectDumpDelegate : public SymbolDumpDelegate {
978974 Subsection.bytes_end());
979975 auto CODD = llvm::make_unique(*this, Section, Obj,
980976 SectionContents);
981 CVSymbolDumper CVSD(W, Types, std::move(CODD), opts::CodeViewSubsectionBytes);
977
978 CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
979 opts::CodeViewSubsectionBytes);
982980 CVSymbolArray Symbols;
983981 BinaryStreamReader Reader(BinaryData, llvm::support::little);
984982 if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
10951093 if (Magic != COFF::DEBUG_SECTION_MAGIC)
10961094 return error(object_error::parse_failed);
10971095
1098 Types.reset(Data);
1099
1100 TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
1101 error(codeview::visitTypeStream(Types, TDV));
1102 W.flush();
1096 CVTypeDumper CVTD(TypeDB);
1097 TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes);
1098 if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) {
1099 W.flush();
1100 error(llvm::errorToErrorCode(std::move(EC)));
1101 }
11031102 }
11041103
11051104 void COFFDumper::printSections() {
16391638 TypeBuf.append(Record.begin(), Record.end());
16401639 });
16411640
1642 TypeTableCollection TpiTypes(CVTypes.records());
1641 TypeDatabase TypeDB(CVTypes.records().size());
16431642 {
16441643 ListScope S(Writer, "MergedTypeStream");
1645 TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
1646 error(codeview::visitTypeStream(TpiTypes, TDV));
1647 Writer.flush();
1644 CVTypeDumper CVTD(TypeDB);
1645 TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
1646 if (auto EC = CVTD.dump(
1647 {TypeBuf.str().bytes_begin(), TypeBuf.str().bytes_end()}, TDV)) {
1648 Writer.flush();
1649 error(std::move(EC));
1650 }
16481651 }
16491652
16501653 // Flatten the id stream and print it next. The ID stream refers to names from
16511654 // the type stream.
1652 TypeTableCollection IpiTypes(IDTable.records());
1655 SmallString<0> IDBuf;
1656 IDTable.ForEachRecord([&](TypeIndex TI, ArrayRef Record) {
1657 IDBuf.append(Record.begin(), Record.end());
1658 });
1659
16531660 {
16541661 ListScope S(Writer, "MergedIDStream");
1655 TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
1656 TDV.setIpiTypes(IpiTypes);
1657 error(codeview::visitTypeStream(IpiTypes, TDV));
1658 Writer.flush();
1659 }
1660 }
1662 TypeDatabase IDDB(IDTable.records().size());
1663 CVTypeDumper CVTD(IDDB);
1664 TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
1665 TDV.setItemDB(IDDB);
1666 if (auto EC = CVTD.dump(
1667 {IDBuf.str().bytes_begin(), IDBuf.str().bytes_end()}, TDV)) {
1668 Writer.flush();
1669 error(std::move(EC));
1670 }
1671 }
1672 }
1010
1111 #include "llvm/ADT/SmallBitVector.h"
1212 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
13 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
13 #include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1415 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1516 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
1617 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
1718 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
1819 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
20 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
1921 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
2022 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
2123 #include "llvm/Support/Allocator.h"
127129
128130 void SetUp() override {
129131 TestState = llvm::make_unique();
132
133 TestState->Pipeline.addCallbackToPipeline(TestState->Deserializer);
134 TestState->Pipeline.addCallbackToPipeline(TestState->Callbacks);
130135 }
131136
132137 void TearDown() override { TestState.reset(); }
133138
134139 protected:
135 bool ValidateDatabaseRecord(LazyRandomTypeCollection &Types, uint32_t Index) {
140 bool ValidateDatabaseRecord(const RandomAccessTypeVisitor &Visitor,
141 uint32_t Index) {
136142 TypeIndex TI = TypeIndex::fromArrayIndex(Index);
137 if (!Types.contains(TI))
138 return false;
139 if (GlobalState->TypeVector[Index] != Types.getType(TI))
143 if (!Visitor.database().contains(TI))
144 return false;
145 if (GlobalState->TypeVector[Index] != Visitor.database().getTypeRecord(TI))
140146 return false;
141147 return true;
142148 }
177183 struct PerTestState {
178184 FixedStreamArray Offsets;
179185
186 TypeVisitorCallbackPipeline Pipeline;
187 TypeDeserializer Deserializer;
180188 MockCallbacks Callbacks;
181189 };
182190
209217
210218 TEST_F(RandomAccessVisitorTest, MultipleVisits) {
211219 TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8});
212 LazyRandomTypeCollection Types(GlobalState->TypeArray,
213 GlobalState->TypeVector.size(),
214 TestState->Offsets);
220 RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
221 GlobalState->TypeVector.size(),
222 TestState->Offsets);
215223
216224 std::vector IndicesToVisit = {5, 5, 5};
217225
218226 for (uint32_t I : IndicesToVisit) {
219227 TypeIndex TI = TypeIndex::fromArrayIndex(I);
220 CVType T = Types.getType(TI);
221 EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
228 EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
222229 }
223230
224231 // [0,8) should be present
225 EXPECT_EQ(8u, Types.size());
232 EXPECT_EQ(8u, Visitor.database().size());
226233 for (uint32_t I = 0; I < 8; ++I)
227 EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
234 EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
228235
229236 // 5, 5, 5
230237 EXPECT_EQ(3u, TestState->Callbacks.count());
240247
241248 std::vector IndicesToVisit = {7, 4, 2};
242249
243 LazyRandomTypeCollection Types(GlobalState->TypeArray,
244 GlobalState->TypeVector.size(),
245 TestState->Offsets);
246 for (uint32_t I : IndicesToVisit) {
247 TypeIndex TI = TypeIndex::fromArrayIndex(I);
248 CVType T = Types.getType(TI);
249 EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
250 RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
251 GlobalState->TypeVector.size(),
252 TestState->Offsets);
253
254 for (uint32_t I : IndicesToVisit) {
255 TypeIndex TI = TypeIndex::fromArrayIndex(I);
256 EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
250257 }
251258
252259 // [0, 7]
253 EXPECT_EQ(8u, Types.size());
260 EXPECT_EQ(8u, Visitor.database().size());
254261 for (uint32_t I = 0; I < 8; ++I)
255 EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
262 EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
256263
257264 // 2, 4, 7
258265 EXPECT_EQ(3u, TestState->Callbacks.count());
268275
269276 std::vector IndicesToVisit = {2, 4, 7};
270277
271 LazyRandomTypeCollection Types(GlobalState->TypeArray,
272 GlobalState->TypeVector.size(),
273 TestState->Offsets);
274 for (uint32_t I : IndicesToVisit) {
275 TypeIndex TI = TypeIndex::fromArrayIndex(I);
276 CVType T = Types.getType(TI);
277 EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
278 RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
279 GlobalState->TypeVector.size(),
280 TestState->Offsets);
281
282 for (uint32_t I : IndicesToVisit) {
283 TypeIndex TI = TypeIndex::fromArrayIndex(I);
284 EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
278285 }
279286
280287 // [0, 7]
281 EXPECT_EQ(8u, Types.size());
288 EXPECT_EQ(8u, Visitor.database().size());
282289 for (uint32_t I = 0; I < 8; ++I)
283 EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
290 EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
284291
285292 // 2, 4, 7
286293 EXPECT_EQ(3u, TestState->Callbacks.count());
297304
298305 std::vector IndicesToVisit = {0, 1, 2};
299306
300 LazyRandomTypeCollection Types(GlobalState->TypeArray,
301 GlobalState->TypeVector.size(),
302 TestState->Offsets);
303
304 for (uint32_t I : IndicesToVisit) {
305 TypeIndex TI = TypeIndex::fromArrayIndex(I);
306 CVType T = Types.getType(TI);
307 EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
307 RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
308 GlobalState->TypeVector.size(),
309 TestState->Offsets);
310
311 for (uint32_t I : IndicesToVisit) {
312 TypeIndex TI = TypeIndex::fromArrayIndex(I);
313 EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
308314 }
309315
310316 // [0, 8) should be visited.
311 EXPECT_EQ(8u, Types.size());
317 EXPECT_EQ(8u, Visitor.database().size());
312318 for (uint32_t I = 0; I < 8; ++I)
313 EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
319 EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
314320
315321 // [0, 2]
316322 EXPECT_EQ(3u, TestState->Callbacks.count());
326332
327333 std::vector IndicesToVisit = {5, 7};
328334
329 LazyRandomTypeCollection Types(GlobalState->TypeArray,
330 GlobalState->TypeVector.size(),
331 TestState->Offsets);
332
333 for (uint32_t I : IndicesToVisit) {
334 TypeIndex TI = TypeIndex::fromArrayIndex(I);
335 CVType T = Types.getType(TI);
336 EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
335 RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
336 GlobalState->TypeVector.size(),
337 TestState->Offsets);
338
339 for (uint32_t I : IndicesToVisit) {
340 TypeIndex TI = TypeIndex::fromArrayIndex(I);
341 EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
337342 }
338343
339344 // [4, 9)
340 EXPECT_EQ(5u, Types.size());
345 EXPECT_EQ(5u, Visitor.database().size());
341346 for (uint32_t I = 4; I < 9; ++I)
342 EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
347 EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
343348
344349 // 5, 7
345350 EXPECT_EQ(2u, TestState->Callbacks.count());