llvm.org GIT mirror llvm / 21ff13f
[llvm-pdbutil] Dig deeper into the PDB and DBI streams when explaining. This will show more detail when using `llvm-pdbutil explain` on an offset in the DBI or PDB streams. Specifically, it will dig into individual header fields and substreams to give a more precise description of what the byte represents. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328878 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 5 months ago
11 changed file(s) with 539 addition(s) and 74 deletion(s). Raw diff Collapse all Expand all
6262
6363 PDB_Machine getMachineType() const;
6464
65 const DbiStreamHeader *getHeader() const { return Header; }
66
6567 BinarySubstreamRef getSectionContributionData() const;
6668 BinarySubstreamRef getSecMapSubstreamData() const;
6769 BinarySubstreamRef getModiSubstreamData() const;
3535
3636 uint32_t getStreamSize() const;
3737
38 const InfoStreamHeader *getHeader() const { return Header; }
39
3840 bool containsIdStream() const;
3941 PdbRaw_ImplVer getVersion() const;
4042 uint32_t getSignature() const;
5557 private:
5658 std::unique_ptr Stream;
5759
58 // PDB file format version. We only support VC70. See the enumeration
59 // `PdbRaw_ImplVer` for the other possible values.
60 uint32_t Version;
61
62 // A 32-bit signature unique across all PDBs. This is generated with
63 // a call to time() when the PDB is written, but obviously this is not
64 // universally unique.
65 uint32_t Signature;
66
67 // The number of times the PDB has been written. Might also be used to
68 // ensure that the PDB matches the executable.
69 uint32_t Age;
70
71 // Due to the aforementioned limitations with `Signature`, this is a new
72 // signature present on VC70 and higher PDBs which is guaranteed to be
73 // universally unique.
74 codeview::GUID Guid;
60 const InfoStreamHeader *Header;
7561
7662 BinarySubstreamRef SubNamedStreams;
7763
2020 using namespace llvm::pdb;
2121
2222 InfoStream::InfoStream(std::unique_ptr Stream)
23 : Stream(std::move(Stream)) {}
23 : Stream(std::move(Stream)), Header(nullptr) {}
2424
2525 Error InfoStream::reload() {
2626 BinaryStreamReader Reader(*Stream);
2727
28 const InfoStreamHeader *H;
29 if (auto EC = Reader.readObject(H))
28 if (auto EC = Reader.readObject(Header))
3029 return joinErrors(
3130 std::move(EC),
3231 make_error(raw_error_code::corrupt_file,
3332 "PDB Stream does not contain a header."));
3433
35 switch (H->Version) {
34 switch (Header->Version) {
3635 case PdbImplVC70:
3736 case PdbImplVC80:
3837 case PdbImplVC110:
4241 return make_error(raw_error_code::corrupt_file,
4342 "Unsupported PDB stream version.");
4443 }
45
46 Version = H->Version;
47 Signature = H->Signature;
48 Age = H->Age;
49 Guid = H->Guid;
5044
5145 uint32_t Offset = Reader.getOffset();
5246 if (auto EC = NamedStreams.load(Reader))
107101 }
108102
109103 PdbRaw_ImplVer InfoStream::getVersion() const {
110 return static_cast(Version);
104 return static_cast(uint32_t(Header->Version));
111105 }
112106
113 uint32_t InfoStream::getSignature() const { return Signature; }
107 uint32_t InfoStream::getSignature() const {
108 return uint32_t(Header->Signature);
109 }
114110
115 uint32_t InfoStream::getAge() const { return Age; }
111 uint32_t InfoStream::getAge() const { return uint32_t(Header->Age); }
116112
117 GUID InfoStream::getGuid() const { return Guid; }
113 GUID InfoStream::getGuid() const { return Header->Guid; }
118114
119115 uint32_t InfoStream::getNamedStreamMapByteSize() const {
120116 return NamedStreamMapByteSize;
0 ; RUN: llvm-pdbutil explain \
1 ; RUN: -offset=0xF000 \
2 ; RUN: -offset=0xF004 \
3 ; RUN: -offset=0xF008 \
4 ; RUN: -offset=0xF00C \
5 ; RUN: -offset=0xF00E \
6 ; RUN: -offset=0xF010 \
7 ; RUN: -offset=0xF012 \
8 ; RUN: -offset=0xF014 \
9 ; RUN: -offset=0xF016 \
10 ; RUN: -offset=0xF018 \
11 ; RUN: -offset=0xF01C \
12 ; RUN: -offset=0xF020 \
13 ; RUN: -offset=0xF024 \
14 ; RUN: -offset=0xF028 \
15 ; RUN: -offset=0xF02C \
16 ; RUN: -offset=0xF030 \
17 ; RUN: -offset=0xF034 \
18 ; RUN: -offset=0xF038 \
19 ; RUN: -offset=0xF03A \
20 ; RUN: -offset=0xF03C \
21 ; RUN: -offset=0xF03E \
22 ; RUN: -offset=0xF040 \
23 ; RUN: -offset=0xF0DC \
24 ; RUN: %p/Inputs/InjectedSource.pdb | FileCheck %s
25
26 CHECK: Block:Offset = F:0000.
27 CHECK-NEXT: Address is in block 15 (allocated).
28 CHECK-NEXT: Address is at offset 0/781 of Stream 3 (DBI Stream).
29 CHECK-NEXT: Within the DBI stream:
30 CHECK-NEXT: address is at offset 0/64 of the DBI Stream Header.
31 CHECK-NEXT: which contains the DBI Stream Version Signature.
32 CHECK-NEXT: The current value is -1.
33
34 CHECK: Block:Offset = F:0004.
35 CHECK-NEXT: Address is in block 15 (allocated).
36 CHECK-NEXT: Address is at offset 4/781 of Stream 3 (DBI Stream).
37 CHECK-NEXT: Within the DBI stream:
38 CHECK-NEXT: address is at offset 4/64 of the DBI Stream Header.
39 CHECK-NEXT: which contains the DBI Stream Version Header.
40 CHECK-NEXT: The current value is 19990903.
41
42 CHECK: Block:Offset = F:0008.
43 CHECK-NEXT: Address is in block 15 (allocated).
44 CHECK-NEXT: Address is at offset 8/781 of Stream 3 (DBI Stream).
45 CHECK-NEXT: Within the DBI stream:
46 CHECK-NEXT: address is at offset 8/64 of the DBI Stream Header.
47 CHECK-NEXT: which contains the age of the DBI Stream.
48 CHECK-NEXT: The current value is 1.
49
50 CHECK: Block:Offset = F:000C.
51 CHECK-NEXT: Address is in block 15 (allocated).
52 CHECK-NEXT: Address is at offset 12/781 of Stream 3 (DBI Stream).
53 CHECK-NEXT: Within the DBI stream:
54 CHECK-NEXT: address is at offset 12/64 of the DBI Stream Header.
55 CHECK-NEXT: which contains the index of the Global Symbol Stream.
56 CHECK-NEXT: The current value is 7.
57
58 CHECK: Block:Offset = F:000E.
59 CHECK-NEXT: Address is in block 15 (allocated).
60 CHECK-NEXT: Address is at offset 14/781 of Stream 3 (DBI Stream).
61 CHECK-NEXT: Within the DBI stream:
62 CHECK-NEXT: address is at offset 14/64 of the DBI Stream Header.
63 CHECK-NEXT: which contains the build number.
64 CHECK-NEXT: The current value is 36363.
65
66 CHECK: Block:Offset = F:0010.
67 CHECK-NEXT: Address is in block 15 (allocated).
68 CHECK-NEXT: Address is at offset 16/781 of Stream 3 (DBI Stream).
69 CHECK-NEXT: Within the DBI stream:
70 CHECK-NEXT: address is at offset 16/64 of the DBI Stream Header.
71 CHECK-NEXT: which contains the index of the Public Symbol Stream.
72 CHECK-NEXT: The current value is 8.
73
74 CHECK: Block:Offset = F:0012.
75 CHECK-NEXT: Address is in block 15 (allocated).
76 CHECK-NEXT: Address is at offset 18/781 of Stream 3 (DBI Stream).
77 CHECK-NEXT: Within the DBI stream:
78 CHECK-NEXT: address is at offset 18/64 of the DBI Stream Header.
79 CHECK-NEXT: which contains the version of mspdb.dll.
80 CHECK-NEXT: The current value is 25547.
81
82 CHECK: Block:Offset = F:0014.
83 CHECK-NEXT: Address is in block 15 (allocated).
84 CHECK-NEXT: Address is at offset 20/781 of Stream 3 (DBI Stream).
85 CHECK-NEXT: Within the DBI stream:
86 CHECK-NEXT: address is at offset 20/64 of the DBI Stream Header.
87 CHECK-NEXT: which contains the index of the Symbol Record Stream.
88 CHECK-NEXT: The current value is 9.
89
90 CHECK: Block:Offset = F:0016.
91 CHECK-NEXT: Address is in block 15 (allocated).
92 CHECK-NEXT: Address is at offset 22/781 of Stream 3 (DBI Stream).
93 CHECK-NEXT: Within the DBI stream:
94 CHECK-NEXT: address is at offset 22/64 of the DBI Stream Header.
95 CHECK-NEXT: which contains the rbld of mspdb.dll.
96 CHECK-NEXT: The current value is 0.
97
98 CHECK: Block:Offset = F:0018.
99 CHECK-NEXT: Address is in block 15 (allocated).
100 CHECK-NEXT: Address is at offset 24/781 of Stream 3 (DBI Stream).
101 CHECK-NEXT: Within the DBI stream:
102 CHECK-NEXT: address is at offset 24/64 of the DBI Stream Header.
103 CHECK-NEXT: which contains the size of the Module Info Substream.
104 CHECK-NEXT: The current value is 232.
105
106 CHECK: Block:Offset = F:001C.
107 CHECK-NEXT: Address is in block 15 (allocated).
108 CHECK-NEXT: Address is at offset 28/781 of Stream 3 (DBI Stream).
109 CHECK-NEXT: Within the DBI stream:
110 CHECK-NEXT: address is at offset 28/64 of the DBI Stream Header.
111 CHECK-NEXT: which contains the size of the Section Contribution Substream.
112 CHECK-NEXT: The current value is 172.
113
114 CHECK: Block:Offset = F:0020.
115 CHECK-NEXT: Address is in block 15 (allocated).
116 CHECK-NEXT: Address is at offset 32/781 of Stream 3 (DBI Stream).
117 CHECK-NEXT: Within the DBI stream:
118 CHECK-NEXT: address is at offset 32/64 of the DBI Stream Header.
119 CHECK-NEXT: which contains the size of the Section Map Substream.
120 CHECK-NEXT: The current value is 84.
121
122 CHECK: Block:Offset = F:0024.
123 CHECK-NEXT: Address is in block 15 (allocated).
124 CHECK-NEXT: Address is at offset 36/781 of Stream 3 (DBI Stream).
125 CHECK-NEXT: Within the DBI stream:
126 CHECK-NEXT: address is at offset 36/64 of the DBI Stream Header.
127 CHECK-NEXT: which contains the size of the File Info Substream.
128 CHECK-NEXT: The current value is 132.
129
130 CHECK: Block:Offset = F:0028.
131 CHECK-NEXT: Address is in block 15 (allocated).
132 CHECK-NEXT: Address is at offset 40/781 of Stream 3 (DBI Stream).
133 CHECK-NEXT: Within the DBI stream:
134 CHECK-NEXT: address is at offset 40/64 of the DBI Stream Header.
135 CHECK-NEXT: which contains the size of the Type Server Map.
136 CHECK-NEXT: The current value is 0.
137
138 CHECK: Block:Offset = F:002C.
139 CHECK-NEXT: Address is in block 15 (allocated).
140 CHECK-NEXT: Address is at offset 44/781 of Stream 3 (DBI Stream).
141 CHECK-NEXT: Within the DBI stream:
142 CHECK-NEXT: address is at offset 44/64 of the DBI Stream Header.
143 CHECK-NEXT: which contains the index of the MFC Type Server stream.
144 CHECK-NEXT: The current value is 0.
145
146 CHECK: Block:Offset = F:0030.
147 CHECK-NEXT: Address is in block 15 (allocated).
148 CHECK-NEXT: Address is at offset 48/781 of Stream 3 (DBI Stream).
149 CHECK-NEXT: Within the DBI stream:
150 CHECK-NEXT: address is at offset 48/64 of the DBI Stream Header.
151 CHECK-NEXT: which contains the size of the Optional Debug Stream array.
152 CHECK-NEXT: The current value is 22.
153
154 CHECK: Block:Offset = F:0034.
155 CHECK-NEXT: Address is in block 15 (allocated).
156 CHECK-NEXT: Address is at offset 52/781 of Stream 3 (DBI Stream).
157 CHECK-NEXT: Within the DBI stream:
158 CHECK-NEXT: address is at offset 52/64 of the DBI Stream Header.
159 CHECK-NEXT: which contains the size of the Edit & Continue Substream.
160 CHECK-NEXT: The current value is 75.
161
162 CHECK: Block:Offset = F:0038.
163 CHECK-NEXT: Address is in block 15 (allocated).
164 CHECK-NEXT: Address is at offset 56/781 of Stream 3 (DBI Stream).
165 CHECK-NEXT: Within the DBI stream:
166 CHECK-NEXT: address is at offset 56/64 of the DBI Stream Header.
167 CHECK-NEXT: which contains the DBI Stream flags.
168 CHECK-NEXT: The current value is 0.
169
170 CHECK: Block:Offset = F:003A.
171 CHECK-NEXT: Address is in block 15 (allocated).
172 CHECK-NEXT: Address is at offset 58/781 of Stream 3 (DBI Stream).
173 CHECK-NEXT: Within the DBI stream:
174 CHECK-NEXT: address is at offset 58/64 of the DBI Stream Header.
175 CHECK-NEXT: which contains the machine type.
176 CHECK-NEXT: The current value is 34404.
177
178 CHECK: Block:Offset = F:003C.
179 CHECK-NEXT: Address is in block 15 (allocated).
180 CHECK-NEXT: Address is at offset 60/781 of Stream 3 (DBI Stream).
181 CHECK-NEXT: Within the DBI stream:
182 CHECK-NEXT: address is at offset 60/64 of the DBI Stream Header.
183 CHECK-NEXT: which contains reserved data.
184 CHECK-NEXT: The current value is 0.
185
186 CHECK: Block:Offset = F:003E.
187 CHECK-NEXT: Address is in block 15 (allocated).
188 CHECK-NEXT: Address is at offset 62/781 of Stream 3 (DBI Stream).
189 CHECK-NEXT: Within the DBI stream:
190 CHECK-NEXT: address is at offset 62/64 of the DBI Stream Header.
191 CHECK-NEXT: which contains reserved data.
192 CHECK-NEXT: The current value is 0.
193
194 CHECK: Block:Offset = F:0040.
195 CHECK-NEXT: Address is in block 15 (allocated).
196 CHECK-NEXT: Address is at offset 64/781 of Stream 3 (DBI Stream).
197 CHECK-NEXT: Within the DBI stream:
198 CHECK-NEXT: address is at offset 0/232 of the Module Info Substream.
199 CHECK-NEXT: which contains the descriptor for module 0 (D:\sandbox\nvtest\nvtest\x64\Debug\nvtest.obj).
200
201 CHECK: Block:Offset = F:00DC.
202 CHECK-NEXT: Address is in block 15 (allocated).
203 CHECK-NEXT: Address is at offset 220/781 of Stream 3 (DBI Stream).
204 CHECK-NEXT: Within the DBI stream:
205 CHECK-NEXT: address is at offset 156/232 of the Module Info Substream.
206 CHECK-NEXT: which contains the descriptor for module 1 (* Linker *).
0 ; RUN: llvm-pdbutil explain \
1 ; RUN: -offset=0x11000 \
2 ; RUN: -offset=0x11004 \
3 ; RUN: -offset=0x11008 \
4 ; RUN: -offset=0x1100C \
5 ; RUN: -offset=0x1101C \
6 ; RUN: %p/Inputs/InjectedSource.pdb | FileCheck %s
7
8
9 CHECK: Block:Offset = 11:0000.
10 CHECK-NEXT: Address is in block 17 (allocated).
11 CHECK-NEXT: Address is at offset 0/202 of Stream 1 (PDB Stream).
12 CHECK-NEXT: Within the PDB stream:
13 CHECK-NEXT: address is at offset 0/28 of the PDB Stream Header.
14 CHECK-NEXT: which contains the PDB Stream Version Signature.
15 CHECK-NEXT: The current value is 20000404.
16
17 CHECK: Block:Offset = 11:0004.
18 CHECK-NEXT: Address is in block 17 (allocated).
19 CHECK-NEXT: Address is at offset 4/202 of Stream 1 (PDB Stream).
20 CHECK-NEXT: Within the PDB stream:
21 CHECK-NEXT: address is at offset 4/28 of the PDB Stream Header.
22 CHECK-NEXT: which contains the signature of the PDB Stream.
23 CHECK-NEXT: The current value is 1521153653.
24
25 CHECK: Block:Offset = 11:0008.
26 CHECK-NEXT: Address is in block 17 (allocated).
27 CHECK-NEXT: Address is at offset 8/202 of Stream 1 (PDB Stream).
28 CHECK-NEXT: Within the PDB stream:
29 CHECK-NEXT: address is at offset 8/28 of the PDB Stream Header.
30 CHECK-NEXT: which contains the age of the PDB.
31 CHECK-NEXT: The current value is 1.
32
33 CHECK: Block:Offset = 11:000C.
34 CHECK-NEXT: Address is in block 17 (allocated).
35 CHECK-NEXT: Address is at offset 12/202 of Stream 1 (PDB Stream).
36 CHECK-NEXT: Within the PDB stream:
37 CHECK-NEXT: address is at offset 12/28 of the PDB Stream Header.
38 CHECK-NEXT: which contains the guid of the PDB.
39 CHECK-NEXT: The current value is {826BE46E-02ED-7043-9C27-20CCC07E92A7}.
40
41 CHECK: Block:Offset = 11:001C.
42 CHECK-NEXT: Address is in block 17 (allocated).
43 CHECK-NEXT: Address is at offset 28/202 of Stream 1 (PDB Stream).
44 CHECK-NEXT: Within the PDB stream:
45 CHECK-NEXT: address is at offset 0/166 of the Named Stream Map.
1212 #include "StreamUtil.h"
1313 #include "llvm-pdbutil.h"
1414
15 #include "llvm/DebugInfo/CodeView/Formatters.h"
1516 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
17 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
18 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
1619 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
20 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
21 #include "llvm/Support/BinaryStreamArray.h"
22 #include "llvm/Support/Error.h"
1723
1824 using namespace llvm;
1925 using namespace llvm::codeview;
200206 P.formatLine("Address is at offset {0}/{1} of Stream {2} ({3}){4}.",
201207 StreamOff, Layout.Length, Stream, S.getLongName(),
202208 (StreamOff > Layout.Length) ? " in unused space" : "");
209 switch (S.getPurpose()) {
210 case StreamPurpose::DBI:
211 explainDbiStream(Stream, StreamOff);
212 break;
213 case StreamPurpose::PDB:
214 explainPdbStream(Stream, StreamOff);
215 break;
216 case StreamPurpose::IPI:
217 case StreamPurpose::TPI:
218 case StreamPurpose::ModuleStream:
219 case StreamPurpose::NamedStream:
220 default:
221 break;
222 }
203223 }
204224
205225 void ExplainOutputStyle::explainStreamDirectoryOffset() {
217237 void ExplainOutputStyle::explainUnknownBlock() {
218238 P.formatLine("Address has unknown purpose.");
219239 }
240
241 template
242 static void printStructField(LinePrinter &P, StringRef Label, T Value) {
243 P.formatLine("which contains {0}.", Label);
244 P.formatLine("The current value is {0}.", Value);
245 }
246
247 static void explainDbiHeaderOffset(LinePrinter &P, DbiStream &Dbi,
248 uint32_t Offset) {
249 const DbiStreamHeader *Header = Dbi.getHeader();
250 assert(Header != nullptr);
251
252 if (Offset < endof(DbiStreamHeader, VersionSignature))
253 printStructField(P, "the DBI Stream Version Signature",
254 int32_t(Header->VersionSignature));
255 else if (Offset < endof(DbiStreamHeader, VersionHeader))
256 printStructField(P, "the DBI Stream Version Header",
257 uint32_t(Header->VersionHeader));
258 else if (Offset < endof(DbiStreamHeader, Age))
259 printStructField(P, "the age of the DBI Stream", uint32_t(Header->Age));
260 else if (Offset < endof(DbiStreamHeader, GlobalSymbolStreamIndex))
261 printStructField(P, "the index of the Global Symbol Stream",
262 uint16_t(Header->GlobalSymbolStreamIndex));
263 else if (Offset < endof(DbiStreamHeader, BuildNumber))
264 printStructField(P, "the build number", uint16_t(Header->BuildNumber));
265 else if (Offset < endof(DbiStreamHeader, PublicSymbolStreamIndex))
266 printStructField(P, "the index of the Public Symbol Stream",
267 uint16_t(Header->PublicSymbolStreamIndex));
268 else if (Offset < endof(DbiStreamHeader, PdbDllVersion))
269 printStructField(P, "the version of mspdb.dll",
270 uint16_t(Header->PdbDllVersion));
271 else if (Offset < endof(DbiStreamHeader, SymRecordStreamIndex))
272 printStructField(P, "the index of the Symbol Record Stream",
273 uint16_t(Header->SymRecordStreamIndex));
274 else if (Offset < endof(DbiStreamHeader, PdbDllRbld))
275 printStructField(P, "the rbld of mspdb.dll", uint16_t(Header->PdbDllRbld));
276 else if (Offset < endof(DbiStreamHeader, ModiSubstreamSize))
277 printStructField(P, "the size of the Module Info Substream",
278 int32_t(Header->ModiSubstreamSize));
279 else if (Offset < endof(DbiStreamHeader, SecContrSubstreamSize))
280 printStructField(P, "the size of the Section Contribution Substream",
281 int32_t(Header->SecContrSubstreamSize));
282 else if (Offset < endof(DbiStreamHeader, SectionMapSize))
283 printStructField(P, "the size of the Section Map Substream",
284 int32_t(Header->SectionMapSize));
285 else if (Offset < endof(DbiStreamHeader, FileInfoSize))
286 printStructField(P, "the size of the File Info Substream",
287 int32_t(Header->FileInfoSize));
288 else if (Offset < endof(DbiStreamHeader, TypeServerSize))
289 printStructField(P, "the size of the Type Server Map",
290 int32_t(Header->TypeServerSize));
291 else if (Offset < endof(DbiStreamHeader, MFCTypeServerIndex))
292 printStructField(P, "the index of the MFC Type Server stream",
293 uint32_t(Header->MFCTypeServerIndex));
294 else if (Offset < endof(DbiStreamHeader, OptionalDbgHdrSize))
295 printStructField(P, "the size of the Optional Debug Stream array",
296 int32_t(Header->OptionalDbgHdrSize));
297 else if (Offset < endof(DbiStreamHeader, ECSubstreamSize))
298 printStructField(P, "the size of the Edit & Continue Substream",
299 int32_t(Header->ECSubstreamSize));
300 else if (Offset < endof(DbiStreamHeader, Flags))
301 printStructField(P, "the DBI Stream flags", uint16_t(Header->Flags));
302 else if (Offset < endof(DbiStreamHeader, MachineType))
303 printStructField(P, "the machine type", uint16_t(Header->MachineType));
304 else if (Offset < endof(DbiStreamHeader, Reserved))
305 printStructField(P, "reserved data", uint32_t(Header->Reserved));
306 }
307
308 static void explainDbiModiSubstreamOffset(LinePrinter &P, DbiStream &Dbi,
309 uint32_t Offset) {
310 VarStreamArray ModuleDescriptors;
311 BinaryStreamRef ModiSubstreamData = Dbi.getModiSubstreamData().StreamData;
312 BinaryStreamReader Reader(ModiSubstreamData);
313
314 cantFail(Reader.readArray(ModuleDescriptors, ModiSubstreamData.getLength()));
315 auto Prev = ModuleDescriptors.begin();
316 assert(Prev.offset() == 0);
317 auto Current = Prev;
318 uint32_t Index = 0;
319 while (true) {
320 Prev = Current;
321 ++Current;
322 if (Current == ModuleDescriptors.end() || Offset < Current.offset())
323 break;
324 ++Index;
325 }
326
327 DbiModuleDescriptor &Descriptor = *Prev;
328 P.formatLine("which contains the descriptor for module {0} ({1}).", Index,
329 Descriptor.getModuleName());
330 }
331
332 template
333 static void dontExplain(LinePrinter &Printer, T &Stream, uint32_t Offset) {}
334
335 template
336 static void explainSubstreamOffset(LinePrinter &P, uint32_t OffsetInStream,
337 T &Stream,
338 const SubstreamRangeT &Substreams) {
339 uint32_t SubOffset = OffsetInStream;
340 for (const auto &Entry : Substreams) {
341 if (Entry.Size == 0)
342 continue;
343 if (SubOffset < Entry.Size) {
344 P.formatLine("address is at offset {0}/{1} of the {2}.", SubOffset,
345 Entry.Size, Entry.Label);
346 Entry.Explain(P, Stream, SubOffset);
347 return;
348 }
349 SubOffset -= Entry.Size;
350 }
351 }
352
353 void ExplainOutputStyle::explainDbiStream(uint32_t StreamIdx,
354 uint32_t OffsetInStream) {
355 P.printLine("Within the DBI stream:");
356 DbiStream &Dbi = cantFail(File.getPDBDbiStream());
357 AutoIndent Indent(P);
358 const DbiStreamHeader *Header = Dbi.getHeader();
359 assert(Header != nullptr);
360
361 struct SubstreamInfo {
362 uint32_t Size;
363 StringRef Label;
364 void (*Explain)(LinePrinter &, DbiStream &, uint32_t);
365 } Substreams[] = {
366 {sizeof(DbiStreamHeader), "DBI Stream Header", explainDbiHeaderOffset},
367 {Header->ModiSubstreamSize, "Module Info Substream",
368 explainDbiModiSubstreamOffset},
369 {Header->SecContrSubstreamSize, "Section Contribution Substream",
370 dontExplain},
371 {Header->SectionMapSize, "Section Map", dontExplain},
372 {Header->FileInfoSize, "File Info Substream", dontExplain},
373 {Header->TypeServerSize, "Type Server Map Substream",
374 dontExplain},
375 {Header->ECSubstreamSize, "Edit & Continue Substream",
376 dontExplain},
377 {Header->OptionalDbgHdrSize, "Optional Debug Stream Array",
378 dontExplain},
379 };
380
381 explainSubstreamOffset(P, OffsetInStream, Dbi, Substreams);
382 }
383
384 static void explainPdbStreamHeaderOffset(LinePrinter &P, InfoStream &Info,
385 uint32_t Offset) {
386 const InfoStreamHeader *Header = Info.getHeader();
387 assert(Header != nullptr);
388
389 if (Offset < endof(InfoStreamHeader, Version))
390 printStructField(P, "the PDB Stream Version Signature",
391 uint32_t(Header->Version));
392 else if (Offset < endof(InfoStreamHeader, Signature))
393 printStructField(P, "the signature of the PDB Stream",
394 uint32_t(Header->Signature));
395 else if (Offset < endof(InfoStreamHeader, Age))
396 printStructField(P, "the age of the PDB", uint32_t(Header->Age));
397 else if (Offset < endof(InfoStreamHeader, Guid))
398 printStructField(P, "the guid of the PDB", fmt_guid(Header->Guid.Guid));
399 }
400
401 void ExplainOutputStyle::explainPdbStream(uint32_t StreamIdx,
402 uint32_t OffsetInStream) {
403 P.printLine("Within the PDB stream:");
404 InfoStream &Info = cantFail(File.getPDBInfoStream());
405 AutoIndent Indent(P);
406
407 struct SubstreamInfo {
408 uint32_t Size;
409 StringRef Label;
410 void (*Explain)(LinePrinter &, InfoStream &, uint32_t);
411 } Substreams[] = {{sizeof(InfoStreamHeader), "PDB Stream Header",
412 explainPdbStreamHeaderOffset},
413 {Info.getNamedStreamMapByteSize(), "Named Stream Map",
414 dontExplain},
415 {Info.getStreamSize(), "PDB Feature Signatures",
416 dontExplain}};
417
418 explainSubstreamOffset(P, OffsetInStream, Info, Substreams);
419 }
1818
1919 namespace pdb {
2020
21 class DbiStream;
2122 class PDBFile;
2223
2324 class ExplainOutputStyle : public OutputStyle {
4647 void explainStreamOffset(uint32_t Stream);
4748 void explainUnknownBlock();
4849
50 void explainDbiStream(uint32_t StreamIdx, uint32_t OffsetInStream);
51 void explainPdbStream(uint32_t StreamIdx, uint32_t OffsetInStream);
52
4953 PDBFile &File;
5054 const uint64_t FileOffset;
5155 const uint64_t BlockIndex;
4848 return Result;
4949 }
5050
51 static inline StreamInfo otherStream(StringRef Label, uint32_t Idx) {
52 return StreamInfo::createStream(StreamPurpose::Other, Label, Idx);
53 }
54
55 static inline StreamInfo namedStream(StringRef Label, uint32_t Idx) {
56 return StreamInfo::createStream(StreamPurpose::NamedStream, Label, Idx);
57 }
58
59 static inline StreamInfo symbolStream(StringRef Label, uint32_t Idx) {
60 return StreamInfo::createStream(StreamPurpose::Symbols, Label, Idx);
51 static inline StreamInfo stream(StreamPurpose Purpose, StringRef Label,
52 uint32_t Idx) {
53 return StreamInfo::createStream(Purpose, Label, Idx);
6154 }
6255
6356 static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,
10497 Streams.resize(StreamCount);
10598 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
10699 if (StreamIdx == OldMSFDirectory)
107 Streams[StreamIdx] = otherStream("Old MSF Directory", StreamIdx);
100 Streams[StreamIdx] =
101 stream(StreamPurpose::Other, "Old MSF Directory", StreamIdx);
108102 else if (StreamIdx == StreamPDB)
109 Streams[StreamIdx] = otherStream("PDB Stream", StreamIdx);
103 Streams[StreamIdx] = stream(StreamPurpose::PDB, "PDB Stream", StreamIdx);
110104 else if (StreamIdx == StreamDBI)
111 Streams[StreamIdx] = otherStream("DBI Stream", StreamIdx);
105 Streams[StreamIdx] = stream(StreamPurpose::DBI, "DBI Stream", StreamIdx);
112106 else if (StreamIdx == StreamTPI)
113 Streams[StreamIdx] = otherStream("TPI Stream", StreamIdx);
107 Streams[StreamIdx] = stream(StreamPurpose::TPI, "TPI Stream", StreamIdx);
114108 else if (StreamIdx == StreamIPI)
115 Streams[StreamIdx] = otherStream("IPI Stream", StreamIdx);
109 Streams[StreamIdx] = stream(StreamPurpose::IPI, "IPI Stream", StreamIdx);
116110 else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
117 Streams[StreamIdx] = otherStream("Global Symbol Hash", StreamIdx);
111 Streams[StreamIdx] =
112 stream(StreamPurpose::GlobalHash, "Global Symbol Hash", StreamIdx);
118113 else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
119 Streams[StreamIdx] = otherStream("Public Symbol Hash", StreamIdx);
114 Streams[StreamIdx] =
115 stream(StreamPurpose::PublicHash, "Public Symbol Hash", StreamIdx);
120116 else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
121 Streams[StreamIdx] = symbolStream("Symbol Records", StreamIdx);
117 Streams[StreamIdx] =
118 stream(StreamPurpose::Symbols, "Symbol Records", StreamIdx);
122119 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
123 Streams[StreamIdx] = otherStream("TPI Hash", StreamIdx);
120 Streams[StreamIdx] =
121 stream(StreamPurpose::TpiHash, "TPI Hash", StreamIdx);
124122 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
125 Streams[StreamIdx] = otherStream("TPI Aux Hash", StreamIdx);
123 Streams[StreamIdx] =
124 stream(StreamPurpose::Other, "TPI Aux Hash", StreamIdx);
126125 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
127 Streams[StreamIdx] = otherStream("IPI Hash", StreamIdx);
126 Streams[StreamIdx] =
127 stream(StreamPurpose::IpiHash, "IPI Hash", StreamIdx);
128128 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
129 Streams[StreamIdx] = otherStream("IPI Aux Hash", StreamIdx);
129 Streams[StreamIdx] =
130 stream(StreamPurpose::Other, "IPI Aux Hash", StreamIdx);
130131 else if (Dbi &&
131132 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
132 Streams[StreamIdx] = otherStream("Exception Data", StreamIdx);
133 Streams[StreamIdx] =
134 stream(StreamPurpose::Other, "Exception Data", StreamIdx);
133135 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
134 Streams[StreamIdx] = otherStream("Fixup Data", StreamIdx);
136 Streams[StreamIdx] =
137 stream(StreamPurpose::Other, "Fixup Data", StreamIdx);
135138 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
136 Streams[StreamIdx] = otherStream("FPO Data", StreamIdx);
139 Streams[StreamIdx] = stream(StreamPurpose::Other, "FPO Data", StreamIdx);
137140 else if (Dbi &&
138141 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
139 Streams[StreamIdx] = otherStream("New FPO Data", StreamIdx);
142 Streams[StreamIdx] =
143 stream(StreamPurpose::Other, "New FPO Data", StreamIdx);
140144 else if (Dbi &&
141145 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
142 Streams[StreamIdx] = otherStream("Omap From Source Data", StreamIdx);
146 Streams[StreamIdx] =
147 stream(StreamPurpose::Other, "Omap From Source Data", StreamIdx);
143148 else if (Dbi &&
144149 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
145 Streams[StreamIdx] = otherStream("Omap To Source Data", StreamIdx);
150 Streams[StreamIdx] =
151 stream(StreamPurpose::Other, "Omap To Source Data", StreamIdx);
146152 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
147 Streams[StreamIdx] = otherStream("Pdata", StreamIdx);
153 Streams[StreamIdx] = stream(StreamPurpose::Other, "Pdata", StreamIdx);
148154 else if (Dbi &&
149155 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
150 Streams[StreamIdx] = otherStream("Section Header Data", StreamIdx);
156 Streams[StreamIdx] =
157 stream(StreamPurpose::Other, "Section Header Data", StreamIdx);
151158 else if (Dbi &&
152159 StreamIdx ==
153160 Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
154 Streams[StreamIdx] =
155 otherStream("Section Header Original Data", StreamIdx);
161 Streams[StreamIdx] = stream(StreamPurpose::Other,
162 "Section Header Original Data", StreamIdx);
156163 else if (Dbi &&
157164 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
158 Streams[StreamIdx] = otherStream("Token Rid Data", StreamIdx);
165 Streams[StreamIdx] =
166 stream(StreamPurpose::Other, "Token Rid Data", StreamIdx);
159167 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
160 Streams[StreamIdx] = otherStream("Xdata", StreamIdx);
168 Streams[StreamIdx] = stream(StreamPurpose::Other, "Xdata", StreamIdx);
161169 else {
162170 auto ModIter = ModStreams.find(StreamIdx);
163171 auto NSIter = NamedStreams.find(StreamIdx);
166174 moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx,
167175 ModIter->second.Modi);
168176 } else if (NSIter != NamedStreams.end()) {
169 Streams[StreamIdx] = namedStream(NSIter->second, StreamIdx);
177 Streams[StreamIdx] =
178 stream(StreamPurpose::NamedStream, NSIter->second, StreamIdx);
170179 } else {
171 Streams[StreamIdx] = otherStream("???", StreamIdx);
180 Streams[StreamIdx] = stream(StreamPurpose::Other, "???", StreamIdx);
172181 }
173182 }
174183 }
1818 namespace llvm {
1919 namespace pdb {
2020 class PDBFile;
21 enum class StreamPurpose { NamedStream, ModuleStream, Symbols, Other };
21 enum class StreamPurpose {
22 NamedStream,
23 ModuleStream,
24 Symbols,
25 PDB,
26 DBI,
27 TPI,
28 IPI,
29 GlobalHash,
30 PublicHash,
31 TpiHash,
32 IpiHash,
33 Other
34 };
2235
2336 struct StreamInfo {
2437 public:
614614 cl::desc(""), cl::Required,
615615 cl::sub(ExplainSubcommand));
616616
617 cl::opt Offset("offset", cl::desc("The file offset to explain"),
618 cl::sub(ExplainSubcommand), cl::Required,
619 cl::OneOrMore);
617 cl::list Offsets("offset", cl::desc("The file offset to explain"),
618 cl::sub(ExplainSubcommand), cl::OneOrMore);
620619 } // namespace explain
621620 }
622621
10901089 static void explain() {
10911090 std::unique_ptr Session;
10921091 PDBFile &File = loadPDB(opts::explain::InputFilename.front(), Session);
1093 auto O = llvm::make_unique(File, opts::explain::Offset);
1094
1095 ExitOnErr(O->dump());
1092
1093 for (uint64_t Off : opts::explain::Offsets) {
1094 auto O = llvm::make_unique(File, Off);
1095
1096 ExitOnErr(O->dump());
1097 }
10961098 }
10971099
10981100 static bool parseRange(StringRef Str,
190190
191191 namespace explain {
192192 extern llvm::cl::list InputFilename;
193 extern llvm::cl::opt Offset;
193 extern llvm::cl::list Offsets;
194194 } // namespace explain
195195 }
196196