blob: baf98d1b0831895c1c0fd39e1f278a409774a1bc [file] [log] [blame]
Zachary Turner1b88f4f2017-05-31 04:17:13 +00001//===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines classes for handling the YAML representation of CodeView
11// Debug Info.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
16
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/DebugInfo/CodeView/CodeViewError.h"
Zachary Turner92dcdda2017-06-02 19:49:14 +000020#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
Zachary Turner349c18f2017-06-05 21:40:33 +000021#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
22#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
Zachary Turner92dcdda2017-06-02 19:49:14 +000023#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
24#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
25#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
26#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
Zachary Turner1b88f4f2017-05-31 04:17:13 +000027#include "llvm/DebugInfo/CodeView/EnumTables.h"
28#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
29
30using namespace llvm;
31using namespace llvm::codeview;
32using namespace llvm::CodeViewYAML;
33using namespace llvm::CodeViewYAML::detail;
34using namespace llvm::yaml;
35
36LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry)
37LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry)
38LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry)
39LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock)
40LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)
41LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)
42LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
Zachary Turner349c18f2017-06-05 21:40:33 +000043LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
44LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
Zachary Turner1b88f4f2017-05-31 04:17:13 +000045LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
Zachary Turner349c18f2017-06-05 21:40:33 +000046LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
Zachary Turner1b88f4f2017-05-31 04:17:13 +000047
48LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
Zachary Turner92dcdda2017-06-02 19:49:14 +000049LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)
Zachary Turner1b88f4f2017-05-31 04:17:13 +000050LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
51LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
52
Zachary Turner349c18f2017-06-05 21:40:33 +000053LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport)
54LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)
55LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)
Zachary Turner92dcdda2017-06-02 19:49:14 +000056LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
57LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)
58LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)
59LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock)
60LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite)
61
62namespace llvm {
63namespace CodeViewYAML {
64namespace detail {
65struct YAMLSubsectionBase {
66 explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
67 DebugSubsectionKind Kind;
68 virtual ~YAMLSubsectionBase() {}
69
70 virtual void map(IO &IO) = 0;
71 virtual std::unique_ptr<DebugSubsection>
72 toCodeViewSubsection(DebugStringTableSubsection *UseStrings,
73 DebugChecksumsSubsection *UseChecksums) const = 0;
74};
75}
76}
77}
78
79namespace {
80struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
81 YAMLChecksumsSubsection()
82 : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
83
84 void map(IO &IO) override;
85 std::unique_ptr<DebugSubsection>
86 toCodeViewSubsection(DebugStringTableSubsection *Strings,
87 DebugChecksumsSubsection *Checksums) const override;
88 static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
89 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
90 const DebugChecksumsSubsectionRef &FC);
91
92 std::vector<SourceFileChecksumEntry> Checksums;
93};
94
95struct YAMLLinesSubsection : public YAMLSubsectionBase {
96 YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
97
98 void map(IO &IO) override;
99 std::unique_ptr<DebugSubsection>
100 toCodeViewSubsection(DebugStringTableSubsection *Strings,
101 DebugChecksumsSubsection *Checksums) const override;
102 static Expected<std::shared_ptr<YAMLLinesSubsection>>
103 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
104 const DebugChecksumsSubsectionRef &Checksums,
105 const DebugLinesSubsectionRef &Lines);
106
107 SourceLineInfo Lines;
108};
109
110struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
111 YAMLInlineeLinesSubsection()
112 : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
113
114 void map(IO &IO) override;
115 std::unique_ptr<DebugSubsection>
116 toCodeViewSubsection(DebugStringTableSubsection *Strings,
117 DebugChecksumsSubsection *Checksums) const override;
118 static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
119 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
120 const DebugChecksumsSubsectionRef &Checksums,
121 const DebugInlineeLinesSubsectionRef &Lines);
122
123 InlineeInfo InlineeLines;
124};
Zachary Turner349c18f2017-06-05 21:40:33 +0000125
126struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
127 YAMLCrossModuleExportsSubsection()
128 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
129
130 void map(IO &IO) override;
131 std::unique_ptr<DebugSubsection>
132 toCodeViewSubsection(DebugStringTableSubsection *Strings,
133 DebugChecksumsSubsection *Checksums) const override;
134 static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
135 fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
136
137 std::vector<CrossModuleExport> Exports;
138};
139
140struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
141 YAMLCrossModuleImportsSubsection()
142 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
143
144 void map(IO &IO) override;
145 std::unique_ptr<DebugSubsection>
146 toCodeViewSubsection(DebugStringTableSubsection *Strings,
147 DebugChecksumsSubsection *Checksums) const override;
148 static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
149 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
150 const DebugCrossModuleImportsSubsectionRef &Imports);
151
152 std::vector<YAMLCrossModuleImport> Imports;
153};
Zachary Turner92dcdda2017-06-02 19:49:14 +0000154}
Zachary Turner1b88f4f2017-05-31 04:17:13 +0000155
156void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
157 io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
158 io.enumFallback<Hex16>(Flags);
159}
160
161void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
162 IO &io, FileChecksumKind &Kind) {
163 io.enumCase(Kind, "None", FileChecksumKind::None);
164 io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
165 io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
166 io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
167}
168
169void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
170 void *ctx, raw_ostream &Out) {
171 StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
172 Value.Bytes.size());
173 Out << toHex(Bytes);
174}
175
176StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
177 HexFormattedString &Value) {
178 std::string H = fromHex(Scalar);
179 Value.Bytes.assign(H.begin(), H.end());
180 return StringRef();
181}
182
183void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
184 IO.mapRequired("Offset", Obj.Offset);
185 IO.mapRequired("LineStart", Obj.LineStart);
186 IO.mapRequired("IsStatement", Obj.IsStatement);
187 IO.mapRequired("EndDelta", Obj.EndDelta);
188}
189
190void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
191 IO.mapRequired("StartColumn", Obj.StartColumn);
192 IO.mapRequired("EndColumn", Obj.EndColumn);
193}
194
195void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
196 IO.mapRequired("FileName", Obj.FileName);
197 IO.mapRequired("Lines", Obj.Lines);
198 IO.mapRequired("Columns", Obj.Columns);
199}
200
Zachary Turner349c18f2017-06-05 21:40:33 +0000201void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) {
202 IO.mapRequired("LocalId", Obj.Local);
203 IO.mapRequired("GlobalId", Obj.Global);
204}
205
206void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO,
207 YAMLCrossModuleImport &Obj) {
208 IO.mapRequired("Module", Obj.ModuleName);
209 IO.mapRequired("Imports", Obj.ImportIds);
210}
211
Zachary Turner1b88f4f2017-05-31 04:17:13 +0000212void MappingTraits<SourceFileChecksumEntry>::mapping(
213 IO &IO, SourceFileChecksumEntry &Obj) {
214 IO.mapRequired("FileName", Obj.FileName);
215 IO.mapRequired("Kind", Obj.Kind);
216 IO.mapRequired("Checksum", Obj.ChecksumBytes);
217}
218
Zachary Turner1b88f4f2017-05-31 04:17:13 +0000219void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
220 IO.mapRequired("FileName", Obj.FileName);
221 IO.mapRequired("LineNum", Obj.SourceLineNum);
222 IO.mapRequired("Inlinee", Obj.Inlinee);
223 IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
224}
225
Zachary Turner92dcdda2017-06-02 19:49:14 +0000226void YAMLChecksumsSubsection::map(IO &IO) {
227 IO.mapTag("!FileChecksums", true);
228 IO.mapRequired("Checksums", Checksums);
229}
230
231void YAMLLinesSubsection::map(IO &IO) {
232 IO.mapTag("!Lines", true);
233 IO.mapRequired("CodeSize", Lines.CodeSize);
234
235 IO.mapRequired("Flags", Lines.Flags);
236 IO.mapRequired("RelocOffset", Lines.RelocOffset);
237 IO.mapRequired("RelocSegment", Lines.RelocSegment);
238 IO.mapRequired("Blocks", Lines.Blocks);
239}
240
241void YAMLInlineeLinesSubsection::map(IO &IO) {
242 IO.mapTag("!InlineeLines", true);
243 IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
244 IO.mapRequired("Sites", InlineeLines.Sites);
245}
246
Zachary Turner349c18f2017-06-05 21:40:33 +0000247void YAMLCrossModuleExportsSubsection::map(IO &IO) {
248 IO.mapTag("!CrossModuleExports", true);
249 IO.mapOptional("Exports", Exports);
250}
251
252void YAMLCrossModuleImportsSubsection::map(IO &IO) {
253 IO.mapTag("!CrossModuleImports", true);
254 IO.mapOptional("Imports", Imports);
255}
256
Zachary Turner92dcdda2017-06-02 19:49:14 +0000257void MappingTraits<YAMLDebugSubsection>::mapping(
258 IO &IO, YAMLDebugSubsection &Subsection) {
259 if (!IO.outputting()) {
260 if (IO.mapTag("!FileChecksums")) {
261 auto SS = std::make_shared<YAMLChecksumsSubsection>();
262 Subsection.Subsection = SS;
263 } else if (IO.mapTag("!Lines")) {
264 Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
265 } else if (IO.mapTag("!InlineeLines")) {
266 Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
Zachary Turner349c18f2017-06-05 21:40:33 +0000267 } else if (IO.mapTag("!CrossModuleExports")) {
268 Subsection.Subsection =
269 std::make_shared<YAMLCrossModuleExportsSubsection>();
270 } else if (IO.mapTag("!CrossModuleImports")) {
271 Subsection.Subsection =
272 std::make_shared<YAMLCrossModuleImportsSubsection>();
Zachary Turner92dcdda2017-06-02 19:49:14 +0000273 } else {
274 llvm_unreachable("Unexpected subsection tag!");
275 }
276 }
277 Subsection.Subsection->map(IO);
278}
279
Zachary Turner349c18f2017-06-05 21:40:33 +0000280static std::shared_ptr<YAMLChecksumsSubsection>
Zachary Turner92dcdda2017-06-02 19:49:14 +0000281findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) {
282 for (const auto &SS : Subsections) {
283 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
Zachary Turner349c18f2017-06-05 21:40:33 +0000284 return std::static_pointer_cast<YAMLChecksumsSubsection>(SS.Subsection);
Zachary Turner92dcdda2017-06-02 19:49:14 +0000285 }
286 }
Zachary Turner349c18f2017-06-05 21:40:33 +0000287
288 return nullptr;
Zachary Turner92dcdda2017-06-02 19:49:14 +0000289}
290
291std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
292 DebugStringTableSubsection *UseStrings,
293 DebugChecksumsSubsection *UseChecksums) const {
294 assert(UseStrings && !UseChecksums);
295 auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
296 for (const auto &CS : Checksums) {
297 Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
298 }
299 return std::move(Result);
300}
301
302std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
303 DebugStringTableSubsection *UseStrings,
304 DebugChecksumsSubsection *UseChecksums) const {
305 assert(UseStrings && UseChecksums);
306 auto Result =
307 llvm::make_unique<DebugLinesSubsection>(*UseChecksums, *UseStrings);
308 Result->setCodeSize(Lines.CodeSize);
309 Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
310 Result->setFlags(Lines.Flags);
311 for (const auto &LC : Lines.Blocks) {
312 Result->createBlock(LC.FileName);
313 if (Result->hasColumnInfo()) {
314 for (const auto &Item : zip(LC.Lines, LC.Columns)) {
315 auto &L = std::get<0>(Item);
316 auto &C = std::get<1>(Item);
317 uint32_t LE = L.LineStart + L.EndDelta;
318 Result->addLineAndColumnInfo(L.Offset,
319 LineInfo(L.LineStart, LE, L.IsStatement),
320 C.StartColumn, C.EndColumn);
321 }
322 } else {
323 for (const auto &L : LC.Lines) {
324 uint32_t LE = L.LineStart + L.EndDelta;
325 Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
326 }
327 }
328 }
Zachary Turner4bedb5f2017-06-02 20:00:10 +0000329 return llvm::cast<DebugSubsection>(std::move(Result));
Zachary Turner92dcdda2017-06-02 19:49:14 +0000330}
331
332std::unique_ptr<DebugSubsection>
333YAMLInlineeLinesSubsection::toCodeViewSubsection(
334 DebugStringTableSubsection *UseStrings,
335 DebugChecksumsSubsection *UseChecksums) const {
336 assert(UseChecksums);
337 auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
338 *UseChecksums, InlineeLines.HasExtraFiles);
339
340 for (const auto &Site : InlineeLines.Sites) {
341 Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
342 Site.SourceLineNum);
343 if (!InlineeLines.HasExtraFiles)
344 continue;
345
346 for (auto EF : Site.ExtraFiles) {
347 Result->addExtraFile(EF);
348 }
349 }
Zachary Turner4bedb5f2017-06-02 20:00:10 +0000350 return llvm::cast<DebugSubsection>(std::move(Result));
Zachary Turner92dcdda2017-06-02 19:49:14 +0000351}
352
Zachary Turner349c18f2017-06-05 21:40:33 +0000353std::unique_ptr<DebugSubsection>
354YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
355 DebugStringTableSubsection *Strings,
356 DebugChecksumsSubsection *Checksums) const {
357 auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>();
358 for (const auto &M : Exports)
359 Result->addMapping(M.Local, M.Global);
360 return llvm::cast<DebugSubsection>(std::move(Result));
361}
362
363std::unique_ptr<DebugSubsection>
364YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
365 DebugStringTableSubsection *Strings,
366 DebugChecksumsSubsection *Checksums) const {
367 auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings);
368 for (const auto &M : Imports) {
369 for (const auto Id : M.ImportIds)
370 Result->addImport(M.ModuleName, Id);
371 }
372 return llvm::cast<DebugSubsection>(std::move(Result));
373}
374
Zachary Turner92dcdda2017-06-02 19:49:14 +0000375static Expected<SourceFileChecksumEntry>
376convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
377 const FileChecksumEntry &CS) {
378 auto ExpectedString = Strings.getString(CS.FileNameOffset);
379 if (!ExpectedString)
380 return ExpectedString.takeError();
381
382 SourceFileChecksumEntry Result;
383 Result.ChecksumBytes.Bytes = CS.Checksum;
384 Result.Kind = CS.Kind;
385 Result.FileName = *ExpectedString;
386 return Result;
387}
388
389static Expected<StringRef>
390getFileName(const DebugStringTableSubsectionRef &Strings,
391 const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
392 auto Iter = Checksums.getArray().at(FileID);
393 if (Iter == Checksums.getArray().end())
394 return make_error<CodeViewError>(cv_error_code::no_records);
395 uint32_t Offset = Iter->FileNameOffset;
396 return Strings.getString(Offset);
397}
398
399Expected<std::shared_ptr<YAMLChecksumsSubsection>>
400YAMLChecksumsSubsection::fromCodeViewSubsection(
401 const DebugStringTableSubsectionRef &Strings,
402 const DebugChecksumsSubsectionRef &FC) {
403 auto Result = std::make_shared<YAMLChecksumsSubsection>();
404
405 for (const auto &CS : FC) {
406 auto ConvertedCS = convertOneChecksum(Strings, CS);
407 if (!ConvertedCS)
408 return ConvertedCS.takeError();
409 Result->Checksums.push_back(*ConvertedCS);
410 }
411 return Result;
412}
413
414Expected<std::shared_ptr<YAMLLinesSubsection>>
415YAMLLinesSubsection::fromCodeViewSubsection(
416 const DebugStringTableSubsectionRef &Strings,
417 const DebugChecksumsSubsectionRef &Checksums,
418 const DebugLinesSubsectionRef &Lines) {
419 auto Result = std::make_shared<YAMLLinesSubsection>();
420 Result->Lines.CodeSize = Lines.header()->CodeSize;
421 Result->Lines.RelocOffset = Lines.header()->RelocOffset;
422 Result->Lines.RelocSegment = Lines.header()->RelocSegment;
423 Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
424 for (const auto &L : Lines) {
425 SourceLineBlock Block;
426 auto EF = getFileName(Strings, Checksums, L.NameIndex);
427 if (!EF)
428 return EF.takeError();
429 Block.FileName = *EF;
430 if (Lines.hasColumnInfo()) {
431 for (const auto &C : L.Columns) {
432 SourceColumnEntry SCE;
433 SCE.EndColumn = C.EndColumn;
434 SCE.StartColumn = C.StartColumn;
435 Block.Columns.push_back(SCE);
436 }
437 }
438 for (const auto &LN : L.LineNumbers) {
439 SourceLineEntry SLE;
440 LineInfo LI(LN.Flags);
441 SLE.Offset = LN.Offset;
442 SLE.LineStart = LI.getStartLine();
443 SLE.EndDelta = LI.getLineDelta();
444 SLE.IsStatement = LI.isStatement();
445 Block.Lines.push_back(SLE);
446 }
447 Result->Lines.Blocks.push_back(Block);
448 }
449 return Result;
450}
451
452Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
453YAMLInlineeLinesSubsection::fromCodeViewSubsection(
454 const DebugStringTableSubsectionRef &Strings,
455 const DebugChecksumsSubsectionRef &Checksums,
456 const DebugInlineeLinesSubsectionRef &Lines) {
457 auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
458
459 Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
460 for (const auto &IL : Lines) {
461 InlineeSite Site;
462 auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
463 if (!ExpF)
464 return ExpF.takeError();
465 Site.FileName = *ExpF;
466 Site.Inlinee = IL.Header->Inlinee.getIndex();
467 Site.SourceLineNum = IL.Header->SourceLineNum;
468 if (Lines.hasExtraFiles()) {
469 for (const auto EF : IL.ExtraFiles) {
470 auto ExpF2 = getFileName(Strings, Checksums, EF);
471 if (!ExpF2)
472 return ExpF2.takeError();
473 Site.ExtraFiles.push_back(*ExpF2);
474 }
475 }
476 Result->InlineeLines.Sites.push_back(Site);
477 }
478 return Result;
479}
480
Zachary Turner349c18f2017-06-05 21:40:33 +0000481Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
482YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
483 const DebugCrossModuleExportsSubsectionRef &Exports) {
484 auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
485 Result->Exports.assign(Exports.begin(), Exports.end());
486 return Result;
487}
488
489Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
490YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
491 const DebugStringTableSubsectionRef &Strings,
492 const DebugCrossModuleImportsSubsectionRef &Imports) {
493 auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
494 for (const auto &CMI : Imports) {
495 YAMLCrossModuleImport YCMI;
496 auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
497 if (!ExpectedStr)
498 return ExpectedStr.takeError();
499 YCMI.ModuleName = *ExpectedStr;
500 YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
501 Result->Imports.push_back(YCMI);
502 }
503 return Result;
504}
505
Zachary Turner92dcdda2017-06-02 19:49:14 +0000506Expected<std::vector<std::unique_ptr<DebugSubsection>>>
507llvm::CodeViewYAML::convertSubsectionList(
508 ArrayRef<YAMLDebugSubsection> Subsections,
509 DebugStringTableSubsection &Strings) {
510 std::vector<std::unique_ptr<DebugSubsection>> Result;
511 if (Subsections.empty())
Zachary Turner64726f22017-06-02 21:00:22 +0000512 return std::move(Result);
Zachary Turner92dcdda2017-06-02 19:49:14 +0000513
514 auto Checksums = findChecksums(Subsections);
Zachary Turner349c18f2017-06-05 21:40:33 +0000515 std::unique_ptr<DebugSubsection> ChecksumsBase;
516 if (Checksums)
517 ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
518 DebugChecksumsSubsection *CS =
519 static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
Zachary Turner92dcdda2017-06-02 19:49:14 +0000520 for (const auto &SS : Subsections) {
521 // We've already converted the checksums subsection, don't do it
522 // twice.
523 std::unique_ptr<DebugSubsection> CVS;
524 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
525 CVS = std::move(ChecksumsBase);
526 else
Zachary Turner349c18f2017-06-05 21:40:33 +0000527 CVS = SS.Subsection->toCodeViewSubsection(&Strings, CS);
528 assert(CVS != nullptr);
Zachary Turner92dcdda2017-06-02 19:49:14 +0000529 Result.push_back(std::move(CVS));
530 }
531 return std::move(Result);
532}
533
534namespace {
535struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
Zachary Turner1bf77622017-06-08 23:49:01 +0000536 SubsectionConversionVisitor() {}
Zachary Turner92dcdda2017-06-02 19:49:14 +0000537
538 Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
Zachary Turner1bf77622017-06-08 23:49:01 +0000539 Error visitLines(DebugLinesSubsectionRef &Lines,
540 const DebugSubsectionState &State) override;
541 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
542 const DebugSubsectionState &State) override;
543 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
544 const DebugSubsectionState &State) override;
545 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
546 const DebugSubsectionState &State) override;
547 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
548 const DebugSubsectionState &State) override;
Zachary Turner92dcdda2017-06-02 19:49:14 +0000549
550 YAMLDebugSubsection Subsection;
Zachary Turner92dcdda2017-06-02 19:49:14 +0000551};
552
553Error SubsectionConversionVisitor::visitUnknown(
554 DebugUnknownSubsectionRef &Unknown) {
555 return make_error<CodeViewError>(cv_error_code::operation_unsupported);
556}
557
Zachary Turner1bf77622017-06-08 23:49:01 +0000558Error SubsectionConversionVisitor::visitLines(
559 DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) {
560 auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
561 State.strings(), State.checksums(), Lines);
Zachary Turner92dcdda2017-06-02 19:49:14 +0000562 if (!Result)
563 return Result.takeError();
564 Subsection.Subsection = *Result;
565 return Error::success();
566}
567
568Error SubsectionConversionVisitor::visitFileChecksums(
Zachary Turner1bf77622017-06-08 23:49:01 +0000569 DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) {
570 auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
571 Checksums);
Zachary Turner92dcdda2017-06-02 19:49:14 +0000572 if (!Result)
573 return Result.takeError();
574 Subsection.Subsection = *Result;
575 return Error::success();
576}
577
578Error SubsectionConversionVisitor::visitInlineeLines(
Zachary Turner1bf77622017-06-08 23:49:01 +0000579 DebugInlineeLinesSubsectionRef &Inlinees,
580 const DebugSubsectionState &State) {
Zachary Turner92dcdda2017-06-02 19:49:14 +0000581 auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
Zachary Turner1bf77622017-06-08 23:49:01 +0000582 State.strings(), State.checksums(), Inlinees);
Zachary Turner92dcdda2017-06-02 19:49:14 +0000583 if (!Result)
584 return Result.takeError();
585 Subsection.Subsection = *Result;
586 return Error::success();
587}
Zachary Turner349c18f2017-06-05 21:40:33 +0000588
589Error SubsectionConversionVisitor::visitCrossModuleExports(
Zachary Turner1bf77622017-06-08 23:49:01 +0000590 DebugCrossModuleExportsSubsectionRef &Exports,
591 const DebugSubsectionState &State) {
Zachary Turner349c18f2017-06-05 21:40:33 +0000592 auto Result =
593 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
594 if (!Result)
595 return Result.takeError();
596 Subsection.Subsection = *Result;
597 return Error::success();
598}
599
600Error SubsectionConversionVisitor::visitCrossModuleImports(
Zachary Turner1bf77622017-06-08 23:49:01 +0000601 DebugCrossModuleImportsSubsectionRef &Imports,
602 const DebugSubsectionState &State) {
Zachary Turner349c18f2017-06-05 21:40:33 +0000603 auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
Zachary Turner1bf77622017-06-08 23:49:01 +0000604 State.strings(), Imports);
Zachary Turner349c18f2017-06-05 21:40:33 +0000605 if (!Result)
606 return Result.takeError();
607 Subsection.Subsection = *Result;
608 return Error::success();
609}
Zachary Turner92dcdda2017-06-02 19:49:14 +0000610}
611
612Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
613 const DebugStringTableSubsectionRef &Strings,
614 const DebugChecksumsSubsectionRef &Checksums,
615 const DebugSubsectionRecord &SS) {
Zachary Turner1bf77622017-06-08 23:49:01 +0000616 DebugSubsectionState State(Strings, Checksums);
617 SubsectionConversionVisitor V;
618 if (auto EC = visitDebugSubsection(SS, V, State))
Zachary Turner92dcdda2017-06-02 19:49:14 +0000619 return std::move(EC);
620
621 return V.Subsection;
Zachary Turner1b88f4f2017-05-31 04:17:13 +0000622}