llvm.org GIT mirror llvm / b36db5a
[llvm-pdbdump] Dump CodeView line information. This first pass only splits apart the records and dumps the line info kinds and binary data. Subsequent patches will parse out the binary data into more useful information and dump it in detail. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271576 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 4 years ago
14 changed file(s) with 246 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
286286 CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions)
287287
288288 enum class ModuleSubstreamKind : uint32_t {
289 None = 0,
289290 Symbols = 0xf1,
290291 Lines = 0xf2,
291292 StringTable = 0xf3,
2929 ArrayRef> getCPUTypeNames();
3030 ArrayRef> getFrameProcSymFlagNames();
3131 ArrayRef> getExportSymFlagNames();
32 ArrayRef> getModuleSubstreamKindNames();
3233 ArrayRef> getThunkOrdinalNames();
3334 ArrayRef> getTrampolineNames();
3435 ArrayRef>
2222 : Stream(&Stream), ViewOffset(0), Length(Stream.getLength()) {}
2323 StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length)
2424 : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
25
26 StreamRef(const StreamRef &Stream, uint32_t Offset, uint32_t Length) = delete;
2527 StreamRef(const StreamRef &Other)
2628 : Stream(Other.Stream), ViewOffset(Other.ViewOffset),
2729 Length(Other.Length) {}
1414 #include "llvm/DebugInfo/PDB/PDBTypes.h"
1515 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
1616 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
17 #include "llvm/DebugInfo/PDB/Raw/ModuleSubstreamRecord.h"
1718 #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
1819 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
1920 #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/StreamArray.h"
1415 #include "llvm/DebugInfo/CodeView/StreamRef.h"
1516 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1617 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
18 #include "llvm/DebugInfo/PDB/Raw/ModuleSubstreamRecord.h"
1719 #include "llvm/Support/Error.h"
1820
1921 namespace llvm {
2325
2426 class ModStream {
2527 public:
28 typedef codeview::VarStreamArray LineInfoArray;
29
2630 ModStream(PDBFile &File, const ModInfo &Module);
2731 ~ModStream();
2832
3034
3135 iterator_range
3236 symbols(bool *HadError) const;
37
38 iterator_range lines(bool *HadError) const;
3339
3440 private:
3541 const ModInfo &Mod;
4046 codeview::StreamRef LinesSubstream;
4147 codeview::StreamRef C13LinesSubstream;
4248 codeview::StreamRef GlobalRefsSubstream;
49
50 LineInfoArray LineInfo;
4351 };
4452 }
4553 }
0 //===- 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
74113 } // namespace pdb
75114 } // namespace llvm
76115
230230 CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw),
231231 };
232232
233 static const EnumEntry ModuleSubstreamKindNames[] = {
234 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, None),
235 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols),
236 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines),
237 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, StringTable),
238 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, FileChecksums),
239 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, FrameData),
240 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, InlineeLines),
241 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeImports),
242 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeExports),
243 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, ILLines),
244 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, FuncMDTokenMap),
245 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, TypeMDTokenMap),
246 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, MergedAssemblyInput),
247 CV_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA),
248 };
249
233250 static const EnumEntry ExportSymFlagNames[] = {
234251 CV_ENUM_CLASS_ENT(ExportFlags, IsConstant),
235252 CV_ENUM_CLASS_ENT(ExportFlags, IsData),
330347 ArrayRef> getExportSymFlagNames() {
331348 return makeArrayRef(ExportSymFlagNames);
332349 }
350 ArrayRef> getModuleSubstreamKindNames() {
351 return makeArrayRef(ModuleSubstreamKindNames);
352 }
333353 ArrayRef> getThunkOrdinalNames() {
334354 return makeArrayRef(ThunkOrdinalNames);
335355 }
1414 using namespace llvm;
1515 using namespace llvm::codeview;
1616
17 StreamReader::StreamReader(StreamRef Stream) : Stream(Stream), Offset(0) {}
17 StreamReader::StreamReader(StreamRef S) : Stream(S), Offset(0) {}
1818
1919 Error StreamReader::readBytes(ArrayRef &Buffer, uint32_t Size) {
2020 if (auto EC = Stream.readBytes(Offset, Size, Buffer))
3232 Raw/InfoStream.cpp
3333 Raw/MappedBlockStream.cpp
3434 Raw/ModInfo.cpp
35 Raw/ModuleSubstreamRecord.cpp
3536 Raw/ModStream.cpp
3637 Raw/NameHashTable.cpp
3738 Raw/NameMap.cpp
1212 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
1313 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
1414 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
15 #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
1516
1617 using namespace llvm;
1718 using namespace llvm::pdb;
4445 return EC;
4546 if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
4647 return EC;
47 ArrayRef LineBytes;
48 codeview::StreamReader LinesReader(C13LinesSubstream);
49 if (auto EC = LinesReader.readBytes(LineBytes, C13LinesSubstream.getLength()))
48
49 codeview::StreamReader LineReader(C13LinesSubstream);
50 if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining()))
5051 return EC;
5152
5253 uint32_t GlobalRefsSize;
6667 return llvm::make_range(SymbolsSubstream.begin(HadError),
6768 SymbolsSubstream.end());
6869 }
70
71 iterator_range
72 ModStream::lines(bool *HadError) const {
73 return llvm::make_range(LineInfo.begin(HadError), LineInfo.end());
74 }
0 //===- 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; }
0 ; RUN: llvm-pdbdump -raw-headers -raw-tpi-records -raw-tpi-record-bytes -raw-module-syms \
11 ; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \
22 ; RUN: -raw-stream-summary -raw-stream-blocks -raw-ipi-records -raw-ipi-record-bytes \
3 ; RUN: -raw-section-contribs -raw-section-map -raw-section-headers %p/Inputs/empty.pdb \
4 ; RUN: | FileCheck -check-prefix=EMPTY %s
3 ; RUN: -raw-section-contribs -raw-section-map -raw-section-headers -raw-line-info \
4 ; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
55 ; RUN: llvm-pdbdump -raw-all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
66 ; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \
77 ; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
329329 ; EMPTY-NEXT: )
330330 ; EMPTY-NEXT: }
331331 ; EMPTY-NEXT: ]
332 ; EMPTY-NEXT: LineInfo [
333 ; EMPTY-NEXT: {
334 ; EMPTY-NEXT: Kind: Lines (0xF2)
335 ; EMPTY-NEXT: Data (
336 ; EMPTY-NEXT: 0000: 10000000 01000000 0A000000 00000000 |................|
337 ; EMPTY-NEXT: 0010: 03000000 24000000 00000000 05000080 |....$...........|
338 ; EMPTY-NEXT: 0020: 03000000 06000080 08000000 07000080 |................|
339 ; EMPTY-NEXT: )
340 ; EMPTY-NEXT: }
341 ; EMPTY-NEXT: {
342 ; EMPTY-NEXT: Kind: FileChecksums (0xF4)
343 ; EMPTY-NEXT: Data (
344 ; EMPTY-NEXT: 0000: 56000000 1001A0A5 BD0D3ECD 93FC29D1 |V.........>...).|
345 ; EMPTY-NEXT: 0010: 9DE826FB F4BC0000 |..&.....|
346 ; EMPTY-NEXT: )
347 ; EMPTY-NEXT: }
348 ; EMPTY-NEXT: ]
332349 ; EMPTY-NEXT: }
333350 ; EMPTY-NEXT: {
334351 ; EMPTY-NEXT: Name: * Linker *
566583 ; EMPTY-NEXT: 0010: 2E72656C 6F630000 |.reloc..|
567584 ; EMPTY-NEXT: )
568585 ; EMPTY-NEXT: }
586 ; EMPTY-NEXT: ]
587 ; EMPTY-NEXT: LineInfo [
569588 ; EMPTY-NEXT: ]
570589 ; EMPTY-NEXT: }
571590 ; EMPTY-NEXT: ]
143143 cl::opt DumpSectionContribs("raw-section-contribs",
144144 cl::desc("dump section contributions"),
145145 cl::cat(NativeOptions));
146 cl::opt DumpLineInfo("raw-line-info",
147 cl::desc("dump file and line information"),
148 cl::cat(NativeOptions));
146149 cl::opt DumpSectionMap("raw-section-map", cl::desc("dump section map"),
147150 cl::cat(NativeOptions));
148151 cl::opt
428431
429432 static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
430433 codeview::CVTypeDumper &TD) {
431 bool DumpModules =
432 opts::DumpModules || opts::DumpModuleSyms || opts::DumpModuleFiles;
434 bool DumpModules = opts::DumpModules || opts::DumpModuleSyms ||
435 opts::DumpModuleFiles || opts::DumpLineInfo;
433436 if (!opts::DumpHeaders && !DumpModules)
434437 return Error::success();
435438
486489 (Modi.Info.getModuleStreamIndex() < File.getNumStreams());
487490 bool ShouldDumpSymbols =
488491 (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
489 if (HasModuleDI && ShouldDumpSymbols) {
490 ListScope SS(P, "Symbols");
492 if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) {
491493 ModStream ModS(File, Modi.Info);
492494 if (auto EC = ModS.reload())
493495 return EC;
494496
495 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
496 bool HadError = false;
497 for (auto &S : ModS.symbols(&HadError)) {
498 DictScope DD(P, "");
499
500 if (opts::DumpModuleSyms)
501 SD.dump(S);
502 if (opts::DumpSymRecordBytes)
503 P.printBinaryBlock("Bytes", S.Data);
497 if (ShouldDumpSymbols) {
498 ListScope SS(P, "Symbols");
499 codeview::CVSymbolDumper SD(P, TD, nullptr, false);
500 bool HadError = false;
501 for (auto &S : ModS.symbols(&HadError)) {
502 DictScope DD(P, "");
503
504 if (opts::DumpModuleSyms)
505 SD.dump(S);
506 if (opts::DumpSymRecordBytes)
507 P.printBinaryBlock("Bytes", S.Data);
508 }
509 if (HadError)
510 return make_error(
511 raw_error_code::corrupt_file,
512 "DBI stream contained corrupt symbol record");
504513 }
505 if (HadError)
506 return make_error(raw_error_code::corrupt_file,
507 "DBI stream contained corrupt record");
514 if (opts::DumpLineInfo) {
515 ListScope SS(P, "LineInfo");
516 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");
527 }
528 P.printBinaryBlock("Data", Data);
529 }
530 }
508531 }
509532 }
510533 }
804827 return true;
805828 if (opts::DumpSectionMap)
806829 return true;
830 if (opts::DumpLineInfo)
831 return true;
807832 return false;
808833 }
809834
971996 opts::DumpIpiRecords = true;
972997 opts::DumpSectionMap = true;
973998 opts::DumpSectionContribs = true;
999 opts::DumpLineInfo = true;
9741000 }
9751001
9761002 // When adding filters for excluded compilands and types, we need to remember