llvm.org GIT mirror llvm / e551b3a
[PDB/CodeView] Read/write codeview inlinee line information. Previously we wrote line information and file checksum information, but we did not write information about inlinee lines and functions. This patch adds support for that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301936 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
24 changed file(s) with 508 addition(s) and 68 deletion(s). Raw diff Collapse all Expand all
126126 bool isNeverStepInto() const { return LineInf.isNeverStepInto(); }
127127 };
128128
129 enum class InlineeLinesSignature : uint32_t {
130 Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE
131 ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
132 };
133
134 struct InlineeSourceLine {
135 TypeIndex Inlinee; // ID of the function that was inlined.
136 ulittle32_t FileID; // Offset into FileChecksums subsection.
137 ulittle32_t SourceLineNum; // First line of inlined code.
138 // If extra files present:
139 // ulittle32_t ExtraFileCount;
140 // ulittle32_t Files[];
141 };
142
143129 } // namespace codeview
144130 } // namespace llvm
145131
3838 return Error::success();
3939 }
4040
41 virtual Error visitInlineeLines(ModuleDebugInlineeLineFragmentRef &Inlinees) {
42 return Error::success();
43 }
44
4145 virtual Error finished() { return Error::success(); }
4246 };
4347
0 //===- ModuleDebugInlineeLinesFragment.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_MODULEDEBUGINLINEELINESFRAGMENT_H
10 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H
11
12 #include "llvm/DebugInfo/CodeView/Line.h"
13 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
14 #include "llvm/Support/BinaryStreamArray.h"
15 #include "llvm/Support/BinaryStreamReader.h"
16 #include "llvm/Support/Error.h"
17
18 namespace llvm {
19 namespace codeview {
20
21 class ModuleDebugInlineeLineFragmentRef;
22
23 enum class InlineeLinesSignature : uint32_t {
24 Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE
25 ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
26 };
27
28 struct InlineeSourceLineHeader {
29 TypeIndex Inlinee; // ID of the function that was inlined.
30 support::ulittle32_t FileID; // Offset into FileChecksums subsection.
31 support::ulittle32_t SourceLineNum; // First line of inlined code.
32 // If extra files present:
33 // ulittle32_t ExtraFileCount;
34 // ulittle32_t Files[];
35 };
36
37 struct InlineeSourceLine {
38 const InlineeSourceLineHeader *Header;
39 FixedStreamArray ExtraFiles;
40 };
41 }
42
43 template <> struct VarStreamArrayExtractor {
44 typedef codeview::ModuleDebugInlineeLineFragmentRef ContextType;
45
46 static Error extract(BinaryStreamRef Stream, uint32_t &Len,
47 codeview::InlineeSourceLine &Item,
48 ContextType *Fragment);
49 };
50
51 namespace codeview {
52 class ModuleDebugInlineeLineFragmentRef final : public ModuleDebugFragmentRef {
53 typedef VarStreamArray LinesArray;
54 typedef LinesArray::Iterator Iterator;
55
56 public:
57 ModuleDebugInlineeLineFragmentRef();
58
59 static bool classof(const ModuleDebugFragmentRef *S) {
60 return S->kind() == ModuleDebugFragmentKind::InlineeLines;
61 }
62
63 Error initialize(BinaryStreamReader Reader);
64 bool hasExtraFiles() const;
65
66 Iterator begin() const { return Lines.begin(); }
67 Iterator end() const { return Lines.end(); }
68
69 private:
70 InlineeLinesSignature Signature;
71 VarStreamArray Lines;
72 };
73
74 class ModuleDebugInlineeLineFragment final : public ModuleDebugFragment {
75 public:
76 explicit ModuleDebugInlineeLineFragment(bool HasExtraFiles);
77
78 static bool classof(const ModuleDebugFragment *S) {
79 return S->kind() == ModuleDebugFragmentKind::InlineeLines;
80 }
81
82 Error commit(BinaryStreamWriter &Writer) override;
83 uint32_t calculateSerializedLength() override;
84
85 void addInlineSite(TypeIndex FuncId, uint32_t FileOffset,
86 uint32_t SourceLine);
87 void addExtraFile(uint32_t FileOffset);
88
89 private:
90 bool HasExtraFiles = false;
91 uint32_t ExtraFileCount = 0;
92
93 struct Entry {
94 std::vector ExtraFiles;
95 InlineeSourceLineHeader Header;
96 };
97 std::vector Entries;
98 };
99 }
100 }
101
102 #endif
1111
1212 #include "llvm/ADT/StringRef.h"
1313 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
14 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
1415 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
1516 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1617 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
4748 void setObjFileName(StringRef Name);
4849 void addSymbol(codeview::CVSymbol Symbol);
4950
50 void
51 addC13LineFragment(std::unique_ptr Lines);
51 void addC13Fragment(std::unique_ptr Lines);
52 void addC13Fragment(
53 std::unique_ptr Inlinees);
5254 void setC13FileChecksums(
5355 std::unique_ptr Checksums);
5456
7981 std::string ObjFileName;
8082 std::vector SourceFiles;
8183 std::vector Symbols;
84
85 std::unique_ptr ChecksumInfo;
8286 std::vector> LineInfo;
83 std::unique_ptr ChecksumInfo;
87 std::vector>
88 Inlinees;
8489
8590 std::vector>
8691 C13Builders;
2929 /// although no methods are overridable.
3030 class BinaryStreamWriter {
3131 public:
32 // FIXME: We should be able to slice and drop_front etc on Writers / Readers.
33
3234 BinaryStreamWriter() = default;
3335 explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
3436 virtual ~BinaryStreamWriter() {}
1616 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1717 #include "llvm/DebugInfo/CodeView/CodeView.h"
1818 #include "llvm/DebugInfo/CodeView/Line.h"
19 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
1920 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
2021 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
2122 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
1010 ModuleDebugFragment.cpp
1111 ModuleDebugFragmentRecord.cpp
1212 ModuleDebugFragmentVisitor.cpp
13 ModuleDebugInlineeLinesFragment.cpp
1314 ModuleDebugLineFragment.cpp
1415 ModuleDebugUnknownFragment.cpp
1516 RecordSerialization.cpp
6767 // This maps the offset of this string in the string table to the offset
6868 // of this checksum entry in the checksum buffer.
6969 OffsetMap[StringTableOffset] = SerializedSize;
70 SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size();
70 assert(SerializedSize % 4 == 0);
71
72 uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
73 SerializedSize += Len;
7174 }
7275
7376 uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
8487 return EC;
8588 if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
8689 return EC;
90 if (auto EC = Writer.padToAlignment(4))
91 return EC;
8792 }
8893 return Error::success();
8994 }
3333 switch (Kind) {
3434 case ModuleDebugFragmentKind::FileChecksums:
3535 case ModuleDebugFragmentKind::Lines:
36 case ModuleDebugFragmentKind::InlineeLines:
3637 break;
3738 default:
3839 llvm_unreachable("Unexpected debug fragment kind!");
1010
1111 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
1212 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
13 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
1314 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
1415 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
1516 #include "llvm/Support/BinaryStreamReader.h"
3637
3738 return V.visitFileChecksums(Fragment);
3839 }
40 case ModuleDebugFragmentKind::InlineeLines: {
41 ModuleDebugInlineeLineFragmentRef Fragment;
42 if (auto EC = Fragment.initialize(Reader))
43 return EC;
44 return V.visitInlineeLines(Fragment);
45 }
3946 default: {
4047 ModuleDebugUnknownFragmentRef Fragment(R.kind(), R.getRecordData());
4148 return V.visitUnknown(Fragment);
0 //===- ModuleDebugInlineeLineFragment.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/ModuleDebugInlineeLinesFragment.h"
10
11 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
12 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
13
14 using namespace llvm;
15 using namespace llvm::codeview;
16
17 Error VarStreamArrayExtractor::extract(
18 BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item,
19 ContextType *Fragment) {
20 BinaryStreamReader Reader(Stream);
21
22 if (auto EC = Reader.readObject(Item.Header))
23 return EC;
24
25 if (Fragment->hasExtraFiles()) {
26 uint32_t ExtraFileCount;
27 if (auto EC = Reader.readInteger(ExtraFileCount))
28 return EC;
29 if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
30 return EC;
31 }
32
33 Len = Reader.getOffset();
34 return Error::success();
35 }
36
37 ModuleDebugInlineeLineFragmentRef::ModuleDebugInlineeLineFragmentRef()
38 : ModuleDebugFragmentRef(ModuleDebugFragmentKind::InlineeLines) {}
39
40 Error ModuleDebugInlineeLineFragmentRef::initialize(BinaryStreamReader Reader) {
41 if (auto EC = Reader.readEnum(Signature))
42 return EC;
43
44 if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining(), this))
45 return EC;
46
47 assert(Reader.bytesRemaining() == 0);
48 return Error::success();
49 }
50
51 bool ModuleDebugInlineeLineFragmentRef::hasExtraFiles() const {
52 return Signature == InlineeLinesSignature::ExtraFiles;
53 }
54
55 ModuleDebugInlineeLineFragment::ModuleDebugInlineeLineFragment(
56 bool HasExtraFiles)
57 : ModuleDebugFragment(ModuleDebugFragmentKind::InlineeLines),
58 HasExtraFiles(HasExtraFiles) {}
59
60 uint32_t ModuleDebugInlineeLineFragment::calculateSerializedLength() {
61 // 4 bytes for the signature
62 uint32_t Size = sizeof(InlineeLinesSignature);
63
64 // one header for each entry.
65 Size += Entries.size() * sizeof(InlineeSourceLineHeader);
66 if (HasExtraFiles) {
67 // If extra files are enabled, one count for each entry.
68 Size += Entries.size() * sizeof(uint32_t);
69
70 // And one file id for each file.
71 Size += ExtraFileCount * sizeof(uint32_t);
72 }
73 assert(Size % 4 == 0);
74 return Size;
75 }
76
77 Error ModuleDebugInlineeLineFragment::commit(BinaryStreamWriter &Writer) {
78 InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
79 if (HasExtraFiles)
80 Sig = InlineeLinesSignature::ExtraFiles;
81
82 if (auto EC = Writer.writeEnum(Sig))
83 return EC;
84
85 for (const auto &E : Entries) {
86 if (auto EC = Writer.writeObject(E.Header))
87 return EC;
88
89 if (!HasExtraFiles)
90 continue;
91
92 if (auto EC = Writer.writeInteger(E.ExtraFiles.size()))
93 return EC;
94 if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
95 return EC;
96 }
97
98 return Error::success();
99 }
100
101 void ModuleDebugInlineeLineFragment::addExtraFile(uint32_t FileOffset) {
102 auto &Entry = Entries.back();
103 Entry.ExtraFiles.push_back(ulittle32_t(FileOffset));
104 ++ExtraFileCount;
105 }
106
107 void ModuleDebugInlineeLineFragment::addInlineSite(TypeIndex FuncId,
108 uint32_t FileOffset,
109 uint32_t SourceLine) {
110 Entries.emplace_back();
111 auto &Entry = Entries.back();
112 Entry.Header.FileID = FileOffset;
113 Entry.Header.SourceLineNum = SourceLine;
114 Entry.Header.Inlinee = FuncId;
115 }
160160 return Error::success();
161161 }
162162
163 void DbiModuleDescriptorBuilder::addC13LineFragment(
163 void DbiModuleDescriptorBuilder::addC13Fragment(
164164 std::unique_ptr Lines) {
165165 ModuleDebugLineFragment &Frag = *Lines;
166166
174174 llvm::make_unique(Frag.kind(), Frag));
175175 }
176176
177 void DbiModuleDescriptorBuilder::addC13Fragment(
178 std::unique_ptr Inlinees) {
179 ModuleDebugInlineeLineFragment &Frag = *Inlinees;
180
181 // File Checksums have to come first, so push an empty entry on if this
182 // is the first.
183 if (C13Builders.empty())
184 C13Builders.push_back(nullptr);
185
186 this->Inlinees.push_back(std::move(Inlinees));
187 C13Builders.push_back(
188 llvm::make_unique(Frag.kind(), Frag));
189 }
190
177191 void DbiModuleDescriptorBuilder::setC13FileChecksums(
178192 std::unique_ptr Checksums) {
179193 assert(!ChecksumInfo && "Can't have more than one checksum info!");
0 ---
1 StringTable:
2 - 'junk_a'
3 - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
4 - 'junk_b'
51 DbiStream:
62 Modules:
73 - Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
139 - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
1410 Kind: MD5
1511 Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC
12 - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
13 Kind: MD5
14 Checksum: 1154D69F5B2650196E1FC34F4134E56B
1615 Lines:
1716 - CodeSize: 10
1817 Flags: [ ]
3433 IsStatement: true
3534 EndDelta: 0
3635 Columns:
36 InlineeLines:
37 - HasExtraFiles: false
38 Sites:
39 - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
40 LineNum: 26950
41 Inlinee: 22767
3742 ...
1515 LINES-NEXT: Kind: MD5 (0x1)
1616 LINES-NEXT: Checksum (
1717 LINES-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
18 LINES-NEXT: )
19 LINES-NEXT: }
20 LINES-NEXT: Checksum {
21 LINES-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
22 LINES-NEXT: Kind: MD5 (0x1)
23 LINES-NEXT: Checksum (
24 LINES-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k|
1825 LINES-NEXT: )
1926 LINES-NEXT: }
2027 LINES-NEXT: }
4754 LINES-NEXT: }
4855 LINES-NEXT: }
4956 LINES-NEXT: }
57 LINES-NEXT: InlineeLines {
58 LINES-NEXT: HasExtraFiles: No
59 LINES-NEXT: Lines [
60 LINES-NEXT: Inlinee {
61 LINES-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
62 LINES-NEXT: Function {
63 LINES-NEXT: Index: 0x58ef (unknown function)
64 LINES-NEXT: }
65 LINES-NEXT: SourceLine: 26950
66 LINES-NEXT: }
67 LINES-NEXT: ]
68 LINES-NEXT: }
5069 LINES-NEXT: ]
5170 LINES-NEXT: }
99 #include "C13DebugFragmentVisitor.h"
1010
1111 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
12 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
1213 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
1314 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
1415 #include "llvm/DebugInfo/PDB/Native/RawError.h"
4041 return Error::success();
4142 }
4243
44 Error C13DebugFragmentVisitor::visitInlineeLines(
45 codeview::ModuleDebugInlineeLineFragmentRef &Lines) {
46 this->InlineeLines.push_back(Lines);
47 return Error::success();
48 }
49
4350 Error C13DebugFragmentVisitor::finished() {
4451 if (!Checksums.hasValue()) {
4552 assert(Lines.empty());
4956 return EC;
5057
5158 if (auto EC = handleLines())
59 return EC;
60
61 if (auto EC = handleInlineeLines())
5262 return EC;
5363
5464 return Error::success();
3434
3535 Error visitLines(codeview::ModuleDebugLineFragmentRef &Lines) final;
3636
37 Error
38 visitInlineeLines(codeview::ModuleDebugInlineeLineFragmentRef &Lines) final;
39
3740 Error finished() final;
3841
3942 protected:
4043 virtual Error handleFileChecksums() { return Error::success(); }
4144 virtual Error handleLines() { return Error::success(); }
45 virtual Error handleInlineeLines() { return Error::success(); }
4246
4347 Expected getNameFromStringTable(uint32_t Offset);
4448 Expected getNameFromChecksumsBuffer(uint32_t Offset);
4549
4650 Optional Checksums;
51 std::vector InlineeLines;
4752 std::vector Lines;
4853
4954 PDBFile &F;
3030
3131 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
3232 ScopedPrinter *W)
33 : W(W), TI(TypeIndex::None()), Offset(0), TypeDB(TypeDB) {}
33 : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex),
34 W) {}
35
36 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
37 TypeIndex FirstTI,
38 ScopedPrinter *W)
39 : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {}
3440
3541 Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
36 if (TI == TypeIndex::None())
37 TI.setIndex(TypeIndex::FirstNonSimpleIndex);
38 else
39 TI.setIndex(TI.getIndex() + 1);
40
4142 return Error::success();
4243 }
4344
5152 .str());
5253
5354 Offset += Record.length();
55 TI.setIndex(TI.getIndex() + 1);
5456
5557 return Error::success();
5658 }
2626 class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
2727 public:
2828 CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
29 CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB,
30 codeview::TypeIndex FirstTI, ScopedPrinter *W);
2931
3032 /// Paired begin/end actions for all types. Receives all record data,
3133 /// including the fixed-length record prefix.
1919 #include "llvm/DebugInfo/CodeView/Line.h"
2020 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
2121 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
22 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
2223 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
2324 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
2425 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
8182
8283 class C13RawVisitor : public C13DebugFragmentVisitor {
8384 public:
84 C13RawVisitor(ScopedPrinter &P, PDBFile &F)
85 : C13DebugFragmentVisitor(F), P(P) {}
85 C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI)
86 : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
8687
8788 Error handleLines() override {
89 if (Lines.empty())
90 return Error::success();
91
8892 DictScope DD(P, "Lines");
8993
9094 for (const auto &Fragment : Lines) {
125129 }
126130
127131 Error handleFileChecksums() override {
132 if (!Checksums.hasValue())
133 return Error::success();
134
128135 DictScope DD(P, "FileChecksums");
129136 for (const auto &CS : *Checksums) {
130137 DictScope DDD(P, "Checksum");
138145 return Error::success();
139146 }
140147
148 Error handleInlineeLines() override {
149 if (InlineeLines.empty())
150 return Error::success();
151
152 DictScope D(P, "InlineeLines");
153 for (const auto &IL : InlineeLines) {
154 P.printBoolean("HasExtraFiles", IL.hasExtraFiles());
155 ListScope LS(P, "Lines");
156 for (const auto &L : IL) {
157 DictScope DDD(P, "Inlinee");
158 if (auto EC = printFileName("FileName", L.Header->FileID))
159 return EC;
160
161 if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee))
162 return EC;
163 P.printNumber("SourceLine", L.Header->SourceLineNum);
164 if (IL.hasExtraFiles()) {
165 ListScope DDDD(P, "ExtraFiles");
166 for (const auto &EF : L.ExtraFiles) {
167 if (auto EC = printFileName("File", EF))
168 return EC;
169 }
170 }
171 }
172 }
173 return Error::success();
174 }
175
141176 private:
177 Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) {
178 CompactTypeDumpVisitor CTDV(DB, Index, &P);
179 CVTypeVisitor Visitor(CTDV);
180 DictScope D(P, Label);
181 if (DB.containsTypeIndex(Index)) {
182 CVType &Type = DB.getTypeRecord(Index);
183 if (auto EC = Visitor.visitTypeRecord(Type))
184 return EC;
185 } else {
186 P.printString(
187 llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
188 .str());
189 }
190 return Error::success();
191 }
142192 Error printFileName(StringRef Label, uint32_t Offset) {
143193 if (auto Result = getNameFromChecksumsBuffer(Offset)) {
144194 P.printString(Label, *Result);
148198 }
149199
150200 ScopedPrinter &P;
201 TypeDatabase &IPI;
151202 };
152203 }
153204
617668
618669 if (auto EC = Visitor.visitTypeRecord(Type))
619670 return EC;
671 T.setIndex(T.getIndex() + 1);
620672 }
621673 if (HadError)
622674 return make_error(raw_error_code::corrupt_file,
749801 if (opts::raw::DumpLineInfo) {
750802 ListScope SS(P, "LineInfo");
751803
752 C13RawVisitor V(P, File);
804 C13RawVisitor V(P, File, ItemDB);
753805 if (auto EC = codeview::visitModuleDebugFragments(
754806 ModS.linesAndChecksums(), V))
755807 return EC;
4040 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceColumnEntry)
4141 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineBlock)
4242 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineInfo)
43 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeSite)
44 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeInfo)
4345 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSymbolRecord)
4446 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord)
4547 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
335337 mapping(IO &IO, PdbSourceLineInfo &Obj,
336338 pdb::yaml::SerializationContext &Context) {
337339 IO.mapRequired("CodeSize", Obj.CodeSize);
340
338341 IO.mapRequired("Flags", Obj.Flags);
339342 IO.mapRequired("RelocOffset", Obj.RelocOffset);
340343 IO.mapRequired("RelocSegment", Obj.RelocSegment);
347350 pdb::yaml::SerializationContext &Context) {
348351 IO.mapOptionalWithContext("Checksums", Obj.FileChecksums, Context);
349352 IO.mapOptionalWithContext("Lines", Obj.LineFragments, Context);
353 IO.mapOptionalWithContext("InlineeLines", Obj.Inlinees, Context);
354 }
355
356 void MappingContextTraits::mapping(
357 IO &IO, PdbInlineeSite &Obj, SerializationContext &Context) {
358 IO.mapRequired("FileName", Obj.FileName);
359 IO.mapRequired("LineNum", Obj.SourceLineNum);
360 IO.mapRequired("Inlinee", Obj.Inlinee);
361 IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
362 }
363
364 void MappingContextTraits::mapping(
365 IO &IO, PdbInlineeInfo &Obj, SerializationContext &Context) {
366 IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles);
367 IO.mapRequired("Sites", Obj.Sites, Context);
350368 }
351369
352370 void MappingContextTraits::
101101 std::vector Blocks;
102102 };
103103
104 struct PdbInlineeSite {
105 codeview::TypeIndex Inlinee;
106 StringRef FileName;
107 uint32_t SourceLineNum;
108 std::vector ExtraFiles;
109 };
110
111 struct PdbInlineeInfo {
112 bool HasExtraFiles;
113 std::vector Sites;
114 };
115
104116 struct PdbSourceFileInfo {
105117 std::vector FileChecksums;
106118 std::vector LineFragments;
119 std::vector Inlinees;
107120 };
108121
109122 struct PdbDbiModuleInfo {
258271 };
259272
260273 template <>
274 struct MappingContextTraits
275 pdb::yaml::SerializationContext> {
276 static void mapping(IO &IO, pdb::yaml::PdbInlineeInfo &Obj,
277 pdb::yaml::SerializationContext &Context);
278 };
279
280 template <>
281 struct MappingContextTraits
282 pdb::yaml::SerializationContext> {
283 static void mapping(IO &IO, pdb::yaml::PdbInlineeSite &Obj,
284 pdb::yaml::SerializationContext &Context);
285 };
286
287 template <>
261288 struct MappingContextTraits
262289 pdb::yaml::SerializationContext> {
263290 static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
1616 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
1717 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
1818 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
19 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
1920 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
2021 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
2122 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
142143 Column.StartColumn = C.StartColumn;
143144 Column.EndColumn = C.EndColumn;
144145 Block.Columns.push_back(Column);
146 }
147 }
148 }
149 }
150 return Error::success();
151 }
152
153 Error handleInlineeLines() override {
154 for (const auto &ILF : InlineeLines) {
155 Info.Inlinees.emplace_back();
156 auto &Inlinee = Info.Inlinees.back();
157
158 Inlinee.HasExtraFiles = ILF.hasExtraFiles();
159 for (const auto &IL : ILF) {
160 Inlinee.Sites.emplace_back();
161 auto &Site = Inlinee.Sites.back();
162 if (auto Result = getNameFromChecksumsBuffer(IL.Header->FileID))
163 Site.FileName = *Result;
164 else
165 return Result.takeError();
166
167 Site.Inlinee = IL.Header->Inlinee;
168 Site.SourceLineNum = IL.Header->SourceLineNum;
169 if (ILF.hasExtraFiles()) {
170 for (const auto &EF : IL.ExtraFiles) {
171 if (auto Result = getNameFromChecksumsBuffer(EF))
172 Site.ExtraFiles.push_back(*Result);
173 else
174 return Result.takeError();
145175 }
146176 }
147177 }
3030 #include "llvm/ADT/STLExtras.h"
3131 #include "llvm/ADT/StringExtras.h"
3232 #include "llvm/Config/config.h"
33 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
34 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
35 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
3336 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
3437 #include "llvm/DebugInfo/PDB/GenericError.h"
3538 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
420423
421424 static ExitOnError ExitOnErr;
422425
426 static uint32_t
427 getFileChecksumOffset(StringRef FileName,
428 ModuleDebugFileChecksumFragment &Checksums,
429 StringTableBuilder &Strings) {
430 // The offset in the line info record is the offset of the checksum
431 // entry for the corresponding file. That entry then contains an
432 // offset into the global string table of the file name. So to
433 // compute the proper offset to write into the line info record, we
434 // must first get its offset in the global string table, then ask the
435 // checksum builder to find the offset in its serialized buffer that
436 // it mapped that filename string table offset to.
437 uint32_t StringOffset = Strings.insert(FileName);
438 return Checksums.mapChecksumOffset(StringOffset);
439 }
440
423441 static void yamlToPdb(StringRef Path) {
424442 BumpPtrAllocator Allocator;
425443 ErrorOr> ErrorOrBuffer =
502520 if (!FLI.FileChecksums.empty()) {
503521 auto &Strings = Builder.getStringTableBuilder();
504522 for (auto &FC : FLI.FileChecksums) {
505 uint32_t STOffset = Strings.getStringIndex(FC.FileName);
523 uint32_t STOffset = Strings.insert(FC.FileName);
506524 Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes);
507525 }
508526 }
509527 ModiBuilder.setC13FileChecksums(std::move(Checksums));
528
529 // FIXME: StringTable / StringTableBuilder should really be in
530 // DebugInfoCodeView. This would allow us to construct the
531 // ModuleDebugLineFragment with a reference to the string table,
532 // and we could just pass strings around rather than having to
533 // remember how to calculate the right offset.
534 auto &Strings = Builder.getStringTableBuilder();
510535
511536 for (const auto &Fragment : FLI.LineFragments) {
512537 auto Lines = llvm::make_unique();
515540 Fragment.RelocOffset);
516541 Lines->setFlags(Fragment.Flags);
517542 for (const auto &LC : Fragment.Blocks) {
518 // FIXME: StringTable / StringTableBuilder should really be in
519 // DebugInfoCodeView. This would allow us to construct the
520 // ModuleDebugLineFragment with a reference to the string table,
521 // and we could just pass strings around rather than having to
522 // remember how to calculate the right offset.
523 auto &Strings = Builder.getStringTableBuilder();
524 // The offset in the line info record is the offset of the checksum
525 // entry for the corresponding file. That entry then contains an
526 // offset into the global string table of the file name. So to
527 // compute the proper offset to write into the line info record, we
528 // must first get its offset in the global string table, then ask the
529 // checksum builder to find the offset in its serialized buffer that
530 // it mapped that filename string table offset to.
531 uint32_t StringOffset = Strings.getStringIndex(LC.FileName);
532 uint32_t ChecksumOffset = ChecksumRef.mapChecksumOffset(StringOffset);
543 uint32_t ChecksumOffset =
544 getFileChecksumOffset(LC.FileName, ChecksumRef, Strings);
533545
534546 Lines->createBlock(ChecksumOffset);
535547 if (Lines->hasColumnInfo()) {
549561 }
550562 }
551563 }
552 ModiBuilder.addC13LineFragment(std::move(Lines));
564 ModiBuilder.addC13Fragment(std::move(Lines));
565 }
566
567 for (const auto &Inlinee : FLI.Inlinees) {
568 auto Inlinees = llvm::make_unique(
569 Inlinee.HasExtraFiles);
570 for (const auto &Site : Inlinee.Sites) {
571 uint32_t FileOff =
572 getFileChecksumOffset(Site.FileName, ChecksumRef, Strings);
573
574 Inlinees->addInlineSite(Site.Inlinee, FileOff, Site.SourceLineNum);
575 if (!Inlinee.HasExtraFiles)
576 continue;
577
578 for (auto EF : Site.ExtraFiles) {
579 FileOff = getFileChecksumOffset(EF, ChecksumRef, Strings);
580 Inlinees->addExtraFile(FileOff);
581 }
582 }
583 ModiBuilder.addC13Fragment(std::move(Inlinees));
553584 }
554585 }
555586 }
2525 #include "llvm/DebugInfo/CodeView/CodeView.h"
2626 #include "llvm/DebugInfo/CodeView/Line.h"
2727 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
28 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
2829 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
2930 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
3031 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
985986 void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
986987 BinaryByteStream S(Subsection, llvm::support::little);
987988 BinaryStreamReader SR(S);
988 uint32_t Signature;
989 error(SR.readInteger(Signature));
990 bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
991
992 while (!SR.empty()) {
993 const InlineeSourceLine *ISL;
994 error(SR.readObject(ISL));
989 ModuleDebugInlineeLineFragmentRef Lines;
990 error(Lines.initialize(SR));
991
992 for (auto &Line : Lines) {
995993 DictScope S(W, "InlineeSourceLine");
996 printTypeIndex("Inlinee", ISL->Inlinee);
997 printFileNameForOffset("FileID", ISL->FileID);
998 W.printNumber("SourceLineNum", ISL->SourceLineNum);
999
1000 if (HasExtraFiles) {
1001 uint32_t ExtraFileCount;
1002 error(SR.readInteger(ExtraFileCount));
1003 W.printNumber("ExtraFileCount", ExtraFileCount);
994 printTypeIndex("Inlinee", Line.Header->Inlinee);
995 printFileNameForOffset("FileID", Line.Header->FileID);
996 W.printNumber("SourceLineNum", Line.Header->SourceLineNum);
997
998 if (Lines.hasExtraFiles()) {
999 W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
10041000 ListScope ExtraFiles(W, "ExtraFiles");
1005 for (unsigned I = 0; I < ExtraFileCount; ++I) {
1006 uint32_t FileID;
1007 error(SR.readInteger(FileID));
1008 printFileNameForOffset("FileID", FileID);
1001 for (const auto &FID : Line.ExtraFiles) {
1002 printFileNameForOffset("FileID", FID);
10091003 }
10101004 }
10111005 }