llvm.org GIT mirror llvm / 7e17f48
[codeview] Dump line number and column information. To facilitate this, a couple of changes had to be made: 1. `ModuleSubstream` got moved from `DebugInfo/PDB` to `DebugInfo/CodeView`, and various codeview related types are defined there. It turns out `DebugInfo/CodeView/Line.h` already defines many of these structures, but this is really old code that is not endian aware, doesn't interact well with `StreamInterface` and not very helpful for getting stuff out of a PDB. Eventually we should migrate the old readobj `COFFDumper` code to these new structures, or at least merge their functionality somehow. 2. A `ModuleSubstream` visitor is introduced. Depending on where your module substream array comes from, different subsets of record types can be expected. We are already hand parsing these substream arrays in many places especially in `COFFDumper.cpp`. In the future we can migrate these paths to the visitor as well, which should reduce a lot of code in `COFFDumper.cpp`. Differential Revision: http://reviews.llvm.org/D20936 Reviewed By: ruiu, majnemer git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271621 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 4 years ago
17 changed file(s) with 485 addition(s) and 192 deletion(s). Raw diff Collapse all Expand all
0 //===- ModuleSubstream.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_MODULESUBSTREAM_H
10 #define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
11
12 #include "llvm/DebugInfo/CodeView/CodeView.h"
13 #include "llvm/DebugInfo/CodeView/StreamArray.h"
14 #include "llvm/DebugInfo/CodeView/StreamRef.h"
15 #include "llvm/Support/Endian.h"
16 #include "llvm/Support/Error.h"
17
18 namespace llvm {
19 namespace codeview {
20
21 // Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
22 struct ModuleSubsectionHeader {
23 support::ulittle32_t Kind; // codeview::ModuleSubstreamKind enum
24 support::ulittle32_t Length; // number of bytes occupied by this record.
25 };
26
27 // Corresponds to the `CV_DebugSLinesHeader_t` structure.
28 struct LineSubstreamHeader {
29 support::ulittle32_t RelocOffset; // Code offset of line contribution.
30 support::ulittle16_t RelocSegment; // Code segment of line contribution.
31 support::ulittle16_t Flags; // See LineFlags enumeration.
32 support::ulittle32_t CodeSize; // Code size of this line contribution.
33 };
34
35 // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
36 struct LineFileBlockHeader {
37 support::ulittle32_t FileOffset;
38 support::ulittle32_t NumLines; // Number of lines
39 support::ulittle32_t BlockSize; // Code size of block, in bytes.
40 // The following two variable length arrays appear immediately after the
41 // header. The structure definitions follow.
42 // LineNumberEntry Lines[NumLines];
43 // ColumnNumberEntry Columns[NumLines];
44 };
45
46 // Corresponds to `CV_Line_t` structure
47 struct LineNumberEntry {
48 support::ulittle32_t Offset; // Offset to start of code bytes for line number
49 support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1
50 };
51
52 // Corresponds to `CV_Column_t` structure
53 struct ColumnNumberEntry {
54 support::ulittle16_t StartColumn;
55 support::ulittle16_t EndColumn;
56 };
57
58 class ModuleSubstream {
59 public:
60 ModuleSubstream();
61 ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data);
62 static Error initialize(StreamRef Stream, ModuleSubstream &Info);
63 uint32_t getRecordLength() const;
64 ModuleSubstreamKind getSubstreamKind() const;
65 StreamRef getRecordData() const;
66
67 private:
68 ModuleSubstreamKind Kind;
69 StreamRef Data;
70 };
71
72 template <> struct VarStreamArrayExtractor {
73 Error operator()(StreamRef Stream, uint32_t &Length,
74 ModuleSubstream &Info) const {
75 if (auto EC = ModuleSubstream::initialize(Stream, Info))
76 return EC;
77 Length = Info.getRecordLength();
78 return Error::success();
79 }
80 };
81
82 typedef VarStreamArray ModuleSubstreamArray;
83 }
84 }
85
86 #endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
0 //===- ModuleSubstreamVisitor.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_MODULESUBSTREAMVISITOR_H
10 #define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
11
12 #include "llvm/DebugInfo/CodeView/CodeView.h"
13 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
14 #include "llvm/DebugInfo/CodeView/Line.h"
15 #include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
16 #include "llvm/DebugInfo/CodeView/StreamReader.h"
17 #include "llvm/DebugInfo/CodeView/StreamRef.h"
18
19 namespace llvm {
20 namespace codeview {
21
22 struct LineColumnEntry {
23 support::ulittle32_t Offset;
24 FixedStreamArray LineNumbers;
25 FixedStreamArray Columns;
26 };
27
28 class FileLineInfoExtractor {
29 public:
30 FileLineInfoExtractor(const LineSubstreamHeader *Header) : Header(Header) {}
31
32 Error operator()(StreamRef Stream, uint32_t &Len,
33 LineColumnEntry &Item) const {
34 const LineFileBlockHeader *BlockHeader;
35 StreamReader Reader(Stream);
36 if (auto EC = Reader.readObject(BlockHeader))
37 return EC;
38 bool HasColumn = Header->Flags & LineFlags::HaveColumns;
39 uint32_t LineInfoSize =
40 BlockHeader->NumLines *
41 (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
42 if (BlockHeader->BlockSize < sizeof(LineFileBlockHeader))
43 return make_error(cv_error_code::corrupt_record,
44 "Invalid line block record size");
45 uint32_t Size = BlockHeader->BlockSize - sizeof(LineFileBlockHeader);
46 if (LineInfoSize > Size)
47 return make_error(cv_error_code::corrupt_record,
48 "Invalid line block record size");
49 // The value recorded in BlockHeader->BlockSize includes the size of
50 // LineFileBlockHeader.
51 Len = BlockHeader->BlockSize;
52 Item.Offset = BlockHeader->FileOffset;
53 if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
54 return EC;
55 if (HasColumn) {
56 if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
57 return EC;
58 }
59 return Error::success();
60 }
61
62 private:
63 const LineSubstreamHeader *Header;
64 };
65
66 typedef VarStreamArray LineInfoArray;
67
68 class IModuleSubstreamVisitor {
69 public:
70 virtual ~IModuleSubstreamVisitor() {}
71
72 virtual Error visitUnknown(ModuleSubstreamKind Kind, StreamRef Data) = 0;
73 virtual Error visitSymbols(StreamRef Data);
74 virtual Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
75 LineInfoArray Lines);
76 virtual Error visitStringTable(StreamRef Data);
77 virtual Error visitFileChecksums(StreamRef Data);
78 virtual Error visitFrameData(StreamRef Data);
79 virtual Error visitInlineeLines(StreamRef Data);
80 virtual Error visitCrossScopeImports(StreamRef Data);
81 virtual Error visitCrossScopeExports(StreamRef Data);
82 virtual Error visitILLines(StreamRef Data);
83 virtual Error visitFuncMDTokenMap(StreamRef Data);
84 virtual Error visitTypeMDTokenMap(StreamRef Data);
85 virtual Error visitMergedAssemblyInput(StreamRef Data);
86 virtual Error visitCoffSymbolRVA(StreamRef Data);
87 };
88
89 Error visitModuleSubstream(const ModuleSubstream &R,
90 IModuleSubstreamVisitor &V);
91
92 } // namespace codeview
93 } // namespace llvm
94
95 #endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
1919 namespace codeview {
2020
2121 /// VarStreamArrayExtractor is intended to be specialized to provide customized
22 /// extraction logic. It should return the total number of bytes of the next
23 /// record (so that the array knows how much data to skip to get to the next
24 /// record, and it should initialize the second parameter with the desired
25 /// value type.
22 /// extraction logic. On input it receives a StreamRef pointing to the
23 /// beginning of the next record, but where the length of the record is not yet
24 /// known. Upon completion, it should return an appropriate Error instance if
25 /// a record could not be extracted, or if one could be extracted it should
26 /// return success and set Len to the number of bytes this record occupied in
27 /// the underlying stream, and it should fill out the fields of the value type
28 /// Item appropriately to represent the current record.
29 ///
30 /// You can specialize this template for your own custom value types to avoid
31 /// having to specify a second template argument to VarStreamArray (documented
32 /// below).
2633 template struct VarStreamArrayExtractor {
2734 // Method intentionally deleted. You must provide an explicit specialization
28 // with the following method implemented. On output return `Len` should
29 // contain the number of bytes to consume from the stream, and `Item` should
30 // be initialized with the proper value.
35 // with the following method implemented.
3136 Error operator()(StreamRef Stream, uint32_t &Len, T &Item) const = delete;
3237 };
3338
3944 /// example, could mean allocating huge amounts of memory just to allow
4045 /// re-ordering of stream data to be contiguous before iterating over it. By
4146 /// abstracting this out, we need not duplicate this memory, and we can
42 /// iterate over arrays in arbitrarily formatted streams.
47 /// iterate over arrays in arbitrarily formatted streams. Elements are parsed
48 /// lazily on iteration, so there is no upfront cost associated with building
49 /// a VarStreamArray, no matter how large it may be.
50 ///
51 /// You create a VarStreamArray by specifying a ValueType and an Extractor type.
52 /// If you do not specify an Extractor type, it expects you to specialize
53 /// VarStreamArrayExtractor for your ValueType.
54 ///
55 /// By default an Extractor is default constructed in the class, but in some
56 /// cases you might find it useful for an Extractor to maintain state across
57 /// extractions. In this case you can provide your own Extractor through a
58 /// secondary constructor. The following examples show various ways of
59 /// creating a VarStreamArray.
60 ///
61 /// // Will use VarStreamArrayExtractor as the extractor.
62 /// VarStreamArray MyTypeArray;
63 ///
64 /// // Will use a default-constructed MyExtractor as the extractor.
65 /// VarStreamArray MyTypeArray2;
66 ///
67 /// // Will use the specific instance of MyExtractor provided.
68 /// // MyExtractor need not be default-constructible in this case.
69 /// MyExtractor E(SomeContext);
70 /// VarStreamArray MyTypeArray3(E);
71 ///
4372 template class VarStreamArrayIterator;
4473
4574 template
5180 typedef VarStreamArrayIterator Iterator;
5281
5382 VarStreamArray() {}
54
55 VarStreamArray(StreamRef Stream) : Stream(Stream) {}
83 explicit VarStreamArray(const Extractor &E) : E(E) {}
84
85 explicit VarStreamArray(StreamRef Stream) : Stream(Stream) {}
86 VarStreamArray(StreamRef Stream, const Extractor &E) : Stream(Stream), E(E) {}
87
88 VarStreamArray(const VarStreamArray &Other)
89 : Stream(Other.Stream), E(Other.E) {}
5690
5791 Iterator begin(bool *HadError = nullptr) const {
58 return Iterator(*this, HadError);
59 }
60
61 Iterator end() const { return Iterator(); }
92 return Iterator(*this, E, HadError);
93 }
94
95 Iterator end() const { return Iterator(E); }
96
97 const Extractor &getExtractor() const { return E; }
6298
6399 private:
64100 StreamRef Stream;
101 Extractor E;
65102 };
66103
67104 template class VarStreamArrayIterator {
69106 typedef VarStreamArray ArrayType;
70107
71108 public:
72 VarStreamArrayIterator(const ArrayType &Array, bool *HadError = nullptr)
73 : Array(&Array), IterRef(Array.Stream), HasError(false),
74 HadError(HadError) {
109 VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
110 bool *HadError = nullptr)
111 : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) {
75112 auto EC = Extract(IterRef, ThisLen, ThisValue);
76113 if (EC) {
77114 consumeError(std::move(EC));
78115 markError();
79116 }
80117 }
81 VarStreamArrayIterator()
82 : Array(nullptr), ThisLen(0), ThisValue(), IterRef(), HasError(false),
83 HadError(nullptr) {}
118 VarStreamArrayIterator() {}
119 explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {}
84120 ~VarStreamArrayIterator() {}
85121
86122 bool operator==(const IterType &R) const {
145181 *HadError = true;
146182 }
147183
148 const ArrayType *Array;
149 uint32_t ThisLen;
150184 ValueType ThisValue;
151185 StreamRef IterRef;
152 bool HasError;
153 bool *HadError;
186 const ArrayType *Array{nullptr};
187 uint32_t ThisLen{0};
188 bool HasError{false};
189 bool *HadError{nullptr};
154190 Extractor Extract;
155191 };
156192
195231 public:
196232 FixedStreamArrayIterator(const FixedStreamArray &Array)
197233 : Array(Array), Index(uint32_t(-1)) {}
198 FixedStreamArrayIterator(const FixedStreamArray &Array, uint32_t Index)
199 : Array(Array), Index(Index) {}
234 FixedStreamArrayIterator(const FixedStreamArray &Array, uint32_t ArrayIndex)
235 : Array(Array), Index(ArrayIndex) {
236 if (Array.size() <= Index)
237 Index = uint32_t(-1);
238 }
200239
201240 bool operator==(const FixedStreamArrayIterator &R) {
202241 assert(&Array == &R.Array);
5151 return Error::success();
5252 }
5353
54 template
55 Error readArray(VarStreamArray &Array, uint32_t Size) {
54 template
55 Error readArray(VarStreamArray &Array, uint32_t Size) {
5656 StreamRef S;
5757 if (auto EC = readStreamRef(S, Size))
5858 return EC;
59 Array = VarStreamArray>(S);
59 Array = VarStreamArray, U>(S, Array.getExtractor());
6060 return Error::success();
6161 }
6262
99 #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
1010 #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
1111
12 #include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
1213 #include "llvm/DebugInfo/CodeView/StreamArray.h"
1314 #include "llvm/DebugInfo/CodeView/StreamRef.h"
1415 #include "llvm/DebugInfo/PDB/PDBTypes.h"
1516 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
1617 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
17 #include "llvm/DebugInfo/PDB/Raw/ModuleSubstreamRecord.h"
1818 #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
1919 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
2020 #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
1111
1212 #include "llvm/ADT/iterator_range.h"
1313 #include "llvm/DebugInfo/CodeView/CVRecord.h"
14 #include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
1415 #include "llvm/DebugInfo/CodeView/StreamArray.h"
1516 #include "llvm/DebugInfo/CodeView/StreamRef.h"
1617 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1718 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
18 #include "llvm/DebugInfo/PDB/Raw/ModuleSubstreamRecord.h"
1919 #include "llvm/Support/Error.h"
2020
2121 namespace llvm {
2525
2626 class ModStream {
2727 public:
28 typedef codeview::VarStreamArray LineInfoArray;
29
3028 ModStream(PDBFile &File, const ModInfo &Module);
3129 ~ModStream();
3230
3533 iterator_range
3634 symbols(bool *HadError) const;
3735
38 iterator_range<LineInfoArray::Iterator> lines(bool *HadError) const;
36 iterator_range<codeview::ModuleSubstreamArray::Iterator>
37 lines(bool *HadError) const;
3938
4039 private:
4140 const ModInfo &Mod;
4746 codeview::StreamRef C13LinesSubstream;
4847 codeview::StreamRef GlobalRefsSubstream;
4948
50 LineInfoArray LineInfo;
49 codeview::ModuleSubstreamArray LineInfo;
5150 };
5251 }
5352 }
+0
-51
include/llvm/DebugInfo/PDB/Raw/ModuleSubstreamRecord.h less more
None //===- ModuleSubstreamRecord.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_PDB_RAW_MODULESUBSTREAMRECORD_H
10 #define LLVM_DEBUGINFO_PDB_RAW_MODULESUBSTREAMRECORD_H
11
12 #include "llvm/DebugInfo/CodeView/CodeView.h"
13 #include "llvm/DebugInfo/CodeView/StreamArray.h"
14 #include "llvm/DebugInfo/CodeView/StreamRef.h"
15 #include "llvm/Support/Error.h"
16
17 namespace llvm {
18
19 namespace pdb {
20 class ModuleSubstreamRecord {
21 public:
22 ModuleSubstreamRecord();
23 ModuleSubstreamRecord(codeview::ModuleSubstreamKind Kind,
24 codeview::StreamRef Data);
25 static Error initialize(codeview::StreamRef Stream,
26 ModuleSubstreamRecord &Info);
27 uint32_t getRecordLength() const;
28 codeview::ModuleSubstreamKind getSubstreamKind() const;
29 codeview::StreamRef getRecordData() const;
30
31 private:
32 codeview::ModuleSubstreamKind Kind;
33 codeview::StreamRef Data;
34 };
35 }
36
37 namespace codeview {
38 template <> struct VarStreamArrayExtractor {
39 Error operator()(StreamRef Stream, uint32_t &Length,
40 pdb::ModuleSubstreamRecord &Info) const {
41 if (auto EC = pdb::ModuleSubstreamRecord::initialize(Stream, Info))
42 return EC;
43 Length = Info.getRecordLength();
44 return Error::success();
45 }
46 };
47 }
48 }
49
50 #endif // LLVM_DEBUGINFO_PDB_RAW_MODULESUBSTREAMRECORD_H
7171 support::ulittle32_t SecByteLength; // Byte count of the segment or group.
7272 };
7373
74 // Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
75 struct ModuleSubsectionHeader {
76 support::ulittle32_t Kind; // codeview::ModuleSubstreamKind enum
77 support::ulittle32_t Length; // number of bytes occupied by this record.
78 };
79
80 // Corresponds to the `CV_DebugSLinesHeader_t` structure.
81 struct LineTableSubsectionHeader {
82 support::ulittle32_t OffCon;
83 support::ulittle16_t SegCon;
84 support::ulittle16_t Flags;
85 support::ulittle32_t CbCon;
86 };
87
88 // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
89 struct SourceFileBlockHeader {
90 support::ulittle32_t offFile;
91 support::ulittle32_t nLines;
92 support::ulittle32_t cbBlock;
93 // LineInfo lines[nLines];
94 // ColumnInfo columns[nColumns];
95 };
96
97 // Corresponds to `CV_Line_t` structure
98 struct LineInfo {
99 unsigned long Offset; // Offset to start of code bytes for line number
100 unsigned long LinenumStart : 24; // line where statement/expression starts
101 unsigned long
102 DeltaLineEnd : 7; // delta to line where statement ends (optional)
103 unsigned long FStatement : 1; // true if a statement linenumber, else an
104 // expression line num
105 };
106
107 // Corresponds to `CV_Column_t` structure
108 struct ColumnInfo {
109 support::ulittle16_t OffColumnStart;
110 support::ulittle16_t OffColumnEnd;
111 };
112
11374 } // namespace pdb
11475 } // namespace llvm
11576
66 ListRecordBuilder.cpp
77 MemoryTypeTableBuilder.cpp
88 MethodListRecordBuilder.cpp
9 ModuleSubstream.cpp
10 ModuleSubstreamVisitor.cpp
911 RecordSerialization.cpp
1012 StreamReader.cpp
1113 SymbolDumper.cpp
0 //===- ModuleSubstream.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/ModuleSubstream.h"
10
11 #include "llvm/DebugInfo/CodeView/StreamReader.h"
12
13 using namespace llvm;
14 using namespace llvm::codeview;
15
16 ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
17
18 ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data)
19 : Kind(Kind), Data(Data) {}
20
21 Error ModuleSubstream::initialize(StreamRef Stream, ModuleSubstream &Info) {
22 const ModuleSubsectionHeader *Header;
23 StreamReader Reader(Stream);
24 if (auto EC = Reader.readObject(Header))
25 return EC;
26
27 ModuleSubstreamKind Kind =
28 static_cast(uint32_t(Header->Kind));
29 if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
30 return EC;
31 Info.Kind = Kind;
32 return Error::success();
33 }
34
35 uint32_t ModuleSubstream::getRecordLength() const {
36 return sizeof(ModuleSubsectionHeader) + Data.getLength();
37 }
38
39 ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
40
41 StreamRef ModuleSubstream::getRecordData() const { return Data; }
0 //===- ModuleSubstreamVisitor.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/ModuleSubstreamVisitor.h"
10
11 using namespace llvm;
12 using namespace llvm::codeview;
13
14 Error IModuleSubstreamVisitor::visitSymbols(StreamRef Data) {
15 return visitUnknown(ModuleSubstreamKind::Symbols, Data);
16 }
17 Error IModuleSubstreamVisitor::visitLines(StreamRef Data,
18 const LineSubstreamHeader *Header,
19 LineInfoArray Lines) {
20 return visitUnknown(ModuleSubstreamKind::Lines, Data);
21 }
22 Error IModuleSubstreamVisitor::visitStringTable(StreamRef Data) {
23 return visitUnknown(ModuleSubstreamKind::StringTable, Data);
24 }
25 Error IModuleSubstreamVisitor::visitFileChecksums(StreamRef Data) {
26 return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
27 }
28 Error IModuleSubstreamVisitor::visitFrameData(StreamRef Data) {
29 return visitUnknown(ModuleSubstreamKind::FrameData, Data);
30 }
31 Error IModuleSubstreamVisitor::visitInlineeLines(StreamRef Data) {
32 return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
33 }
34 Error IModuleSubstreamVisitor::visitCrossScopeImports(StreamRef Data) {
35 return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
36 }
37 Error IModuleSubstreamVisitor::visitCrossScopeExports(StreamRef Data) {
38 return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
39 }
40 Error IModuleSubstreamVisitor::visitILLines(StreamRef Data) {
41 return visitUnknown(ModuleSubstreamKind::ILLines, Data);
42 }
43 Error IModuleSubstreamVisitor::visitFuncMDTokenMap(StreamRef Data) {
44 return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
45 }
46 Error IModuleSubstreamVisitor::visitTypeMDTokenMap(StreamRef Data) {
47 return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
48 }
49 Error IModuleSubstreamVisitor::visitMergedAssemblyInput(StreamRef Data) {
50 return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
51 }
52 Error IModuleSubstreamVisitor::visitCoffSymbolRVA(StreamRef Data) {
53 return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
54 }
55
56 Error llvm::codeview::visitModuleSubstream(const ModuleSubstream &R,
57 IModuleSubstreamVisitor &V) {
58 switch (R.getSubstreamKind()) {
59 case ModuleSubstreamKind::Symbols:
60 return V.visitSymbols(R.getRecordData());
61 case ModuleSubstreamKind::Lines: {
62 StreamReader Reader(R.getRecordData());
63 const LineSubstreamHeader *Header;
64 if (auto EC = Reader.readObject(Header))
65 return EC;
66 FileLineInfoExtractor E(Header);
67 LineInfoArray LineInfos(E);
68 if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining()))
69 return EC;
70 return V.visitLines(R.getRecordData(), Header, LineInfos);
71 }
72 case ModuleSubstreamKind::StringTable:
73 return V.visitStringTable(R.getRecordData());
74 case ModuleSubstreamKind::FileChecksums:
75 return V.visitFileChecksums(R.getRecordData());
76 case ModuleSubstreamKind::FrameData:
77 return V.visitFrameData(R.getRecordData());
78 case ModuleSubstreamKind::InlineeLines:
79 return V.visitInlineeLines(R.getRecordData());
80 case ModuleSubstreamKind::CrossScopeImports:
81 return V.visitCrossScopeImports(R.getRecordData());
82 case ModuleSubstreamKind::CrossScopeExports:
83 return V.visitCrossScopeExports(R.getRecordData());
84 case ModuleSubstreamKind::ILLines:
85 return V.visitILLines(R.getRecordData());
86 case ModuleSubstreamKind::FuncMDTokenMap:
87 return V.visitFuncMDTokenMap(R.getRecordData());
88 case ModuleSubstreamKind::TypeMDTokenMap:
89 return V.visitTypeMDTokenMap(R.getRecordData());
90 case ModuleSubstreamKind::MergedAssemblyInput:
91 return V.visitMergedAssemblyInput(R.getRecordData());
92 case ModuleSubstreamKind::CoffSymbolRVA:
93 return V.visitCoffSymbolRVA(R.getRecordData());
94 default:
95 return V.visitUnknown(R.getSubstreamKind(), R.getRecordData());
96 }
97 }
3232 Raw/InfoStream.cpp
3333 Raw/MappedBlockStream.cpp
3434 Raw/ModInfo.cpp
35 Raw/ModuleSubstreamRecord.cpp
3635 Raw/ModStream.cpp
3736 Raw/NameHashTable.cpp
3837 Raw/NameMap.cpp
6868 SymbolsSubstream.end());
6969 }
7070
71 iterator_range<ModStream::LineInfoArray::Iterator>
71 iterator_range<codeview::ModuleSubstreamArray::Iterator>
7272 ModStream::lines(bool *HadError) const {
7373 return llvm::make_range(LineInfo.begin(HadError), LineInfo.end());
7474 }
+0
-49
lib/DebugInfo/PDB/Raw/ModuleSubstreamRecord.cpp less more
None //===- ModuleSubstreamRecord.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/PDB/Raw/ModuleSubstreamRecord.h"
10
11 #include "llvm/DebugInfo/CodeView/StreamReader.h"
12 #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
13
14 using namespace llvm;
15 using namespace llvm::codeview;
16 using namespace llvm::pdb;
17
18 ModuleSubstreamRecord::ModuleSubstreamRecord()
19 : Kind(ModuleSubstreamKind::None) {}
20
21 ModuleSubstreamRecord::ModuleSubstreamRecord(ModuleSubstreamKind Kind,
22 StreamRef Data)
23 : Kind(Kind), Data(Data) {}
24
25 Error ModuleSubstreamRecord::initialize(StreamRef Stream,
26 ModuleSubstreamRecord &Info) {
27 const ModuleSubsectionHeader *Header;
28 StreamReader Reader(Stream);
29 if (auto EC = Reader.readObject(Header))
30 return EC;
31
32 ModuleSubstreamKind Kind =
33 static_cast(uint32_t(Header->Kind));
34 if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
35 return EC;
36 Info.Kind = Kind;
37 return Error::success();
38 }
39
40 uint32_t ModuleSubstreamRecord::getRecordLength() const {
41 return sizeof(ModuleSubsectionHeader) + Data.getLength();
42 }
43
44 ModuleSubstreamKind ModuleSubstreamRecord::getSubstreamKind() const {
45 return Kind;
46 }
47
48 StreamRef ModuleSubstreamRecord::getRecordData() const { return Data; }
330330 ; EMPTY-NEXT: }
331331 ; EMPTY-NEXT: ]
332332 ; EMPTY-NEXT: LineInfo [
333 ; EMPTY-NEXT: {
334 ; EMPTY-NEXT: Kind: Lines (0xF2)
333 ; EMPTY-NEXT: Lines {
334 ; EMPTY-NEXT: FileOffset: 0
335 ; EMPTY-NEXT: Line {
336 ; EMPTY-NEXT: Offset: 0
337 ; EMPTY-NEXT: LineNumberStart: 5
338 ; EMPTY-NEXT: EndDelta: 0
339 ; EMPTY-NEXT: IsStatement: Yes
340 ; EMPTY-NEXT: }
341 ; EMPTY-NEXT: Line {
342 ; EMPTY-NEXT: Offset: 3
343 ; EMPTY-NEXT: LineNumberStart: 6
344 ; EMPTY-NEXT: EndDelta: 0
345 ; EMPTY-NEXT: IsStatement: Yes
346 ; EMPTY-NEXT: }
347 ; EMPTY-NEXT: Line {
348 ; EMPTY-NEXT: Offset: 8
349 ; EMPTY-NEXT: LineNumberStart: 7
350 ; EMPTY-NEXT: EndDelta: 0
351 ; EMPTY-NEXT: IsStatement: Yes
352 ; EMPTY-NEXT: }
335353 ; EMPTY-NEXT: Data (
336354 ; EMPTY-NEXT: 0000: 10000000 01000000 0A000000 00000000 |................|
337355 ; EMPTY-NEXT: 0010: 03000000 24000000 00000000 05000080 |....$...........|
338356 ; EMPTY-NEXT: 0020: 03000000 06000080 08000000 07000080 |................|
339357 ; EMPTY-NEXT: )
340358 ; EMPTY-NEXT: }
341 ; EMPTY-NEXT: {
342 ; EMPTY-NEXT: Kind: FileChecksums (0xF4)
359 ; EMPTY-NEXT: FileChecksums {
343360 ; EMPTY-NEXT: Data (
344361 ; EMPTY-NEXT: 0000: 56000000 1001A0A5 BD0D3ECD 93FC29D1 |V.........>...).|
345362 ; EMPTY-NEXT: 0010: 9DE826FB F4BC0000 |..&.....|
2626 #include "llvm/ADT/StringExtras.h"
2727 #include "llvm/Config/config.h"
2828 #include "llvm/DebugInfo/CodeView/EnumTables.h"
29 #include "llvm/DebugInfo/CodeView/Line.h"
30 #include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
2931 #include "llvm/DebugInfo/CodeView/StreamReader.h"
3032 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
3133 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
6769 #include "llvm/Support/raw_ostream.h"
6870
6971 using namespace llvm;
72 using namespace llvm::codeview;
7073 using namespace llvm::pdb;
7174
7275 namespace opts {
498501 ListScope SS(P, "Symbols");
499502 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
500503 bool HadError = false;
501 for (auto &S : ModS.symbols(&HadError)) {
504 for (const auto &S : ModS.symbols(&HadError)) {
502505 DictScope DD(P, "");
503506
504507 if (opts::DumpModuleSyms)
514517 if (opts::DumpLineInfo) {
515518 ListScope SS(P, "LineInfo");
516519 bool HadError = false;
517 for (auto &L : ModS.lines(&HadError)) {
518 DictScope DD(P, "");
519 P.printEnum("Kind", uint32_t(L.getSubstreamKind()),
520 codeview::getModuleSubstreamKindNames());
521 ArrayRef Data;
522 codeview::StreamReader R(L.getRecordData());
523 if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
524 return make_error(
525 raw_error_code::corrupt_file,
526 "DBI stream contained corrupt line info record");
520 // Define a locally scoped visitor to print the different
521 // substream types types.
522 class RecordVisitor : public codeview::IModuleSubstreamVisitor {
523 public:
524 RecordVisitor(ScopedPrinter &P) : P(P) {}
525 Error visitUnknown(ModuleSubstreamKind Kind,
526 StreamRef Data) override {
527 DictScope DD(P, "Unknown");
528 return printBinaryData(Data);
527529 }
528 P.printBinaryBlock("Data", Data);
530 Error visitFileChecksums(StreamRef Data) override {
531 DictScope DD(P, "FileChecksums");
532 return printBinaryData(Data);
533 }
534
535 Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
536 LineInfoArray Lines) override {
537 DictScope DD(P, "Lines");
538 for (const auto &L : Lines) {
539 P.printNumber("FileOffset", L.Offset);
540 for (const auto &N : L.LineNumbers) {
541 DictScope DDD(P, "Line");
542 LineInfo LI(N.Flags);
543 P.printNumber("Offset", N.Offset);
544 if (LI.isAlwaysStepInto())
545 P.printString("StepInto", StringRef("Always"));
546 else if (LI.isNeverStepInto())
547 P.printString("StepInto", StringRef("Never"));
548 else
549 P.printNumber("LineNumberStart", LI.getStartLine());
550 P.printNumber("EndDelta", LI.getLineDelta());
551 P.printBoolean("IsStatement", LI.isStatement());
552 }
553 for (const auto &C : L.Columns) {
554 DictScope DDD(P, "Column");
555 P.printNumber("Start", C.StartColumn);
556 P.printNumber("End", C.EndColumn);
557 }
558 }
559 return printBinaryData(Data);
560 }
561
562 private:
563 Error printBinaryData(StreamRef Stream) {
564 ArrayRef Data;
565 StreamReader R(Stream);
566 if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
567 return make_error(
568 raw_error_code::corrupt_file,
569 "DBI stream contained corrupt line info record");
570 }
571 P.printBinaryBlock("Data", Data);
572 P.flush();
573 return Error::success();
574 }
575 ScopedPrinter &P;
576 };
577 RecordVisitor V(P);
578 for (const auto &L : ModS.lines(&HadError)) {
579 if (auto EC = codeview::visitModuleSubstream(L, V))
580 return EC;
529581 }
530582 }
531583 }
773773
774774 initializeFileAndStringTables(Data);
775775
776 // TODO: Convert this over to using ModuleSubstreamVisitor.
776777 while (!Data.empty()) {
777778 // The section consists of a number of subsection in the following format:
778779 // |SubSectionType|SubSectionSize|Contents...|