LLVM 22.0.0git
CodeViewYAMLDebugSections.cpp
Go to the documentation of this file.
1//===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines classes for handling the YAML representation of CodeView
10// Debug Info.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/StringRef.h"
38#include "llvm/Support/Endian.h"
39#include "llvm/Support/Error.h"
43#include <cassert>
44#include <cstdint>
45#include <memory>
46#include <string>
47#include <vector>
48
49using namespace llvm;
50using namespace llvm::codeview;
51using namespace llvm::CodeViewYAML;
52using namespace llvm::CodeViewYAML::detail;
53using namespace llvm::yaml;
54
65
70
80
81namespace llvm {
82namespace CodeViewYAML {
83namespace detail {
84
87 virtual ~YAMLSubsectionBase() = default;
88
89 virtual void map(IO &IO) = 0;
90 virtual std::shared_ptr<DebugSubsection>
92 const codeview::StringsAndChecksums &SC) const = 0;
93
95};
96
97} // end namespace detail
98} // end namespace CodeViewYAML
99} // end namespace llvm
100
101namespace {
102
103struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
104 YAMLChecksumsSubsection()
105 : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
106
107 void map(IO &IO) override;
108 std::shared_ptr<DebugSubsection>
110 const codeview::StringsAndChecksums &SC) const override;
112 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
114
115 std::vector<SourceFileChecksumEntry> Checksums;
116};
117
118struct YAMLLinesSubsection : public YAMLSubsectionBase {
119 YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
120
121 void map(IO &IO) override;
122 std::shared_ptr<DebugSubsection>
124 const codeview::StringsAndChecksums &SC) const override;
126 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
127 const DebugChecksumsSubsectionRef &Checksums,
128 const DebugLinesSubsectionRef &Lines);
129
131};
132
133struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
134 YAMLInlineeLinesSubsection()
136
137 void map(IO &IO) override;
138 std::shared_ptr<DebugSubsection>
140 const codeview::StringsAndChecksums &SC) const override;
142 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
143 const DebugChecksumsSubsectionRef &Checksums,
145
147};
148
149struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
150 YAMLCrossModuleExportsSubsection()
152
153 void map(IO &IO) override;
154 std::shared_ptr<DebugSubsection>
156 const codeview::StringsAndChecksums &SC) const override;
158 fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
159
160 std::vector<CrossModuleExport> Exports;
161};
162
163struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
164 YAMLCrossModuleImportsSubsection()
166
167 void map(IO &IO) override;
168 std::shared_ptr<DebugSubsection>
170 const codeview::StringsAndChecksums &SC) const override;
172 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
174
175 std::vector<YAMLCrossModuleImport> Imports;
176};
177
178struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
179 YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
180
181 void map(IO &IO) override;
182 std::shared_ptr<DebugSubsection>
184 const codeview::StringsAndChecksums &SC) const override;
186 fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
187
188 std::vector<CodeViewYAML::SymbolRecord> Symbols;
189};
190
191struct YAMLStringTableSubsection : public YAMLSubsectionBase {
192 YAMLStringTableSubsection()
194
195 void map(IO &IO) override;
196 std::shared_ptr<DebugSubsection>
198 const codeview::StringsAndChecksums &SC) const override;
200 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
201
202 std::vector<StringRef> Strings;
203};
204
205struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
206 YAMLFrameDataSubsection()
208
209 void map(IO &IO) override;
210 std::shared_ptr<DebugSubsection>
212 const codeview::StringsAndChecksums &SC) const override;
214 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
215 const DebugFrameDataSubsectionRef &Frames);
216
217 std::vector<YAMLFrameData> Frames;
218};
219
220struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase {
221 YAMLCoffSymbolRVASubsection()
223
224 void map(IO &IO) override;
225 std::shared_ptr<DebugSubsection>
227 const codeview::StringsAndChecksums &SC) const override;
229 fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs);
230
231 std::vector<uint32_t> RVAs;
232};
233
234} // end anonymous namespace
235
236void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
237 io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
238 io.enumFallback<Hex16>(Flags);
239}
240
241void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
242 IO &io, FileChecksumKind &Kind) {
243 io.enumCase(Kind, "None", FileChecksumKind::None);
244 io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
245 io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
246 io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
247}
248
249void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
250 void *ctx, raw_ostream &Out) {
251 StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
252 Value.Bytes.size());
253 Out << toHex(Bytes);
254}
255
256StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
258 std::string H = fromHex(Scalar);
259 Value.Bytes.assign(H.begin(), H.end());
260 return StringRef();
261}
262
264 IO.mapRequired("Offset", Obj.Offset);
265 IO.mapRequired("LineStart", Obj.LineStart);
266 IO.mapRequired("IsStatement", Obj.IsStatement);
267 IO.mapRequired("EndDelta", Obj.EndDelta);
268}
269
271 IO.mapRequired("StartColumn", Obj.StartColumn);
272 IO.mapRequired("EndColumn", Obj.EndColumn);
273}
274
276 IO.mapRequired("FileName", Obj.FileName);
277 IO.mapRequired("Lines", Obj.Lines);
278 IO.mapRequired("Columns", Obj.Columns);
279}
280
282 IO.mapRequired("LocalId", Obj.Local);
283 IO.mapRequired("GlobalId", Obj.Global);
284}
285
288 IO.mapRequired("Module", Obj.ModuleName);
289 IO.mapRequired("Imports", Obj.ImportIds);
290}
291
293 IO &IO, SourceFileChecksumEntry &Obj) {
294 IO.mapRequired("FileName", Obj.FileName);
295 IO.mapRequired("Kind", Obj.Kind);
296 IO.mapRequired("Checksum", Obj.ChecksumBytes);
297}
298
300 IO.mapRequired("FileName", Obj.FileName);
301 IO.mapRequired("LineNum", Obj.SourceLineNum);
302 IO.mapRequired("Inlinee", Obj.Inlinee);
303 IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
304}
305
307 IO.mapRequired("CodeSize", Obj.CodeSize);
308 IO.mapRequired("FrameFunc", Obj.FrameFunc);
309 IO.mapRequired("LocalSize", Obj.LocalSize);
310 IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
311 IO.mapOptional("ParamsSize", Obj.ParamsSize);
312 IO.mapOptional("PrologSize", Obj.PrologSize);
313 IO.mapOptional("RvaStart", Obj.RvaStart);
314 IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
315}
316
317void YAMLChecksumsSubsection::map(IO &IO) {
318 IO.mapTag("!FileChecksums", true);
319 IO.mapRequired("Checksums", Checksums);
320}
321
322void YAMLLinesSubsection::map(IO &IO) {
323 IO.mapTag("!Lines", true);
324 IO.mapRequired("CodeSize", Lines.CodeSize);
325
326 IO.mapRequired("Flags", Lines.Flags);
327 IO.mapRequired("RelocOffset", Lines.RelocOffset);
328 IO.mapRequired("RelocSegment", Lines.RelocSegment);
329 IO.mapRequired("Blocks", Lines.Blocks);
330}
331
332void YAMLInlineeLinesSubsection::map(IO &IO) {
333 IO.mapTag("!InlineeLines", true);
334 IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
335 IO.mapRequired("Sites", InlineeLines.Sites);
336}
337
338void YAMLCrossModuleExportsSubsection::map(IO &IO) {
339 IO.mapTag("!CrossModuleExports", true);
340 IO.mapOptional("Exports", Exports);
341}
342
343void YAMLCrossModuleImportsSubsection::map(IO &IO) {
344 IO.mapTag("!CrossModuleImports", true);
345 IO.mapOptional("Imports", Imports);
346}
347
348void YAMLSymbolsSubsection::map(IO &IO) {
349 IO.mapTag("!Symbols", true);
350 IO.mapRequired("Records", Symbols);
351}
352
353void YAMLStringTableSubsection::map(IO &IO) {
354 IO.mapTag("!StringTable", true);
355 IO.mapRequired("Strings", Strings);
356}
357
358void YAMLFrameDataSubsection::map(IO &IO) {
359 IO.mapTag("!FrameData", true);
360 IO.mapRequired("Frames", Frames);
361}
362
363void YAMLCoffSymbolRVASubsection::map(IO &IO) {
364 IO.mapTag("!COFFSymbolRVAs", true);
365 IO.mapRequired("RVAs", RVAs);
366}
367
369 IO &IO, YAMLDebugSubsection &Subsection) {
370 if (!IO.outputting()) {
371 if (IO.mapTag("!FileChecksums")) {
372 auto SS = std::make_shared<YAMLChecksumsSubsection>();
373 Subsection.Subsection = SS;
374 } else if (IO.mapTag("!Lines")) {
375 Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
376 } else if (IO.mapTag("!InlineeLines")) {
377 Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
378 } else if (IO.mapTag("!CrossModuleExports")) {
379 Subsection.Subsection =
380 std::make_shared<YAMLCrossModuleExportsSubsection>();
381 } else if (IO.mapTag("!CrossModuleImports")) {
382 Subsection.Subsection =
383 std::make_shared<YAMLCrossModuleImportsSubsection>();
384 } else if (IO.mapTag("!Symbols")) {
385 Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
386 } else if (IO.mapTag("!StringTable")) {
387 Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
388 } else if (IO.mapTag("!FrameData")) {
389 Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>();
390 } else if (IO.mapTag("!COFFSymbolRVAs")) {
391 Subsection.Subsection = std::make_shared<YAMLCoffSymbolRVASubsection>();
392 } else {
393 llvm_unreachable("Unexpected subsection tag!");
394 }
395 }
396 Subsection.Subsection->map(IO);
397}
398
399std::shared_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
400 BumpPtrAllocator &Allocator,
401 const codeview::StringsAndChecksums &SC) const {
402 assert(SC.hasStrings());
403 auto Result = std::make_shared<DebugChecksumsSubsection>(*SC.strings());
404 for (const auto &CS : Checksums) {
405 Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
406 }
407 return Result;
408}
409
410std::shared_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
411 BumpPtrAllocator &Allocator,
412 const codeview::StringsAndChecksums &SC) const {
413 assert(SC.hasStrings() && SC.hasChecksums());
414 auto Result =
415 std::make_shared<DebugLinesSubsection>(*SC.checksums(), *SC.strings());
416 Result->setCodeSize(Lines.CodeSize);
417 Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
418 Result->setFlags(Lines.Flags);
419 for (const auto &LC : Lines.Blocks) {
420 Result->createBlock(LC.FileName);
421 if (Result->hasColumnInfo()) {
422 for (auto Item : zip(LC.Lines, LC.Columns)) {
423 auto &L = std::get<0>(Item);
424 auto &C = std::get<1>(Item);
425 uint32_t LE = L.LineStart + L.EndDelta;
426 Result->addLineAndColumnInfo(L.Offset,
427 LineInfo(L.LineStart, LE, L.IsStatement),
428 C.StartColumn, C.EndColumn);
429 }
430 } else {
431 for (const auto &L : LC.Lines) {
432 uint32_t LE = L.LineStart + L.EndDelta;
433 Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
434 }
435 }
436 }
437 return Result;
438}
439
440std::shared_ptr<DebugSubsection>
441YAMLInlineeLinesSubsection::toCodeViewSubsection(
442 BumpPtrAllocator &Allocator,
443 const codeview::StringsAndChecksums &SC) const {
444 assert(SC.hasChecksums());
445 auto Result = std::make_shared<DebugInlineeLinesSubsection>(
446 *SC.checksums(), InlineeLines.HasExtraFiles);
447
448 for (const auto &Site : InlineeLines.Sites) {
449 Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
450 Site.SourceLineNum);
451 if (!InlineeLines.HasExtraFiles)
452 continue;
453
454 for (auto EF : Site.ExtraFiles) {
455 Result->addExtraFile(EF);
456 }
457 }
458 return Result;
459}
460
461std::shared_ptr<DebugSubsection>
462YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
463 BumpPtrAllocator &Allocator,
464 const codeview::StringsAndChecksums &SC) const {
465 auto Result = std::make_shared<DebugCrossModuleExportsSubsection>();
466 for (const auto &M : Exports)
467 Result->addMapping(M.Local, M.Global);
468 return Result;
469}
470
471std::shared_ptr<DebugSubsection>
472YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
473 BumpPtrAllocator &Allocator,
474 const codeview::StringsAndChecksums &SC) const {
475 assert(SC.hasStrings());
476
477 auto Result =
478 std::make_shared<DebugCrossModuleImportsSubsection>(*SC.strings());
479 for (const auto &M : Imports) {
480 for (const auto Id : M.ImportIds)
481 Result->addImport(M.ModuleName, Id);
482 }
483 return Result;
484}
485
486std::shared_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
487 BumpPtrAllocator &Allocator,
488 const codeview::StringsAndChecksums &SC) const {
489 auto Result = std::make_shared<DebugSymbolsSubsection>();
490 for (const auto &Sym : Symbols)
491 Result->addSymbol(
492 Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
493 return Result;
494}
495
496std::shared_ptr<DebugSubsection>
497YAMLStringTableSubsection::toCodeViewSubsection(
498 BumpPtrAllocator &Allocator,
499 const codeview::StringsAndChecksums &SC) const {
500 auto Result = std::make_shared<DebugStringTableSubsection>();
501 for (const auto &Str : this->Strings)
502 Result->insert(Str);
503 return Result;
504}
505
506std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
507 BumpPtrAllocator &Allocator,
508 const codeview::StringsAndChecksums &SC) const {
509 assert(SC.hasStrings());
510
511 auto Result = std::make_shared<DebugFrameDataSubsection>(true);
512 for (const auto &YF : Frames) {
514 F.CodeSize = YF.CodeSize;
515 F.Flags = YF.Flags;
516 F.LocalSize = YF.LocalSize;
517 F.MaxStackSize = YF.MaxStackSize;
518 F.ParamsSize = YF.ParamsSize;
519 F.PrologSize = YF.PrologSize;
520 F.RvaStart = YF.RvaStart;
521 F.SavedRegsSize = YF.SavedRegsSize;
522 F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
523 Result->addFrameData(F);
524 }
525 return Result;
526}
527
528std::shared_ptr<DebugSubsection>
529YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
530 BumpPtrAllocator &Allocator,
531 const codeview::StringsAndChecksums &SC) const {
532 auto Result = std::make_shared<DebugSymbolRVASubsection>();
533 for (const auto &RVA : RVAs)
534 Result->addRVA(RVA);
535 return Result;
536}
537
540 const FileChecksumEntry &CS) {
541 auto ExpectedString = Strings.getString(CS.FileNameOffset);
542 if (!ExpectedString)
543 return ExpectedString.takeError();
544
546 Result.ChecksumBytes.Bytes = CS.Checksum;
547 Result.Kind = CS.Kind;
548 Result.FileName = *ExpectedString;
549 return Result;
550}
551
554 const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
555 auto Iter = Checksums.getArray().at(FileID);
556 if (Iter == Checksums.getArray().end())
557 return make_error<CodeViewError>(cv_error_code::no_records);
558 uint32_t Offset = Iter->FileNameOffset;
559 return Strings.getString(Offset);
560}
561
563YAMLChecksumsSubsection::fromCodeViewSubsection(
564 const DebugStringTableSubsectionRef &Strings,
565 const DebugChecksumsSubsectionRef &FC) {
566 auto Result = std::make_shared<YAMLChecksumsSubsection>();
567
568 for (const auto &CS : FC) {
569 auto ConvertedCS = convertOneChecksum(Strings, CS);
570 if (!ConvertedCS)
571 return ConvertedCS.takeError();
572 Result->Checksums.push_back(*ConvertedCS);
573 }
574 return Result;
575}
576
578YAMLLinesSubsection::fromCodeViewSubsection(
579 const DebugStringTableSubsectionRef &Strings,
580 const DebugChecksumsSubsectionRef &Checksums,
582 auto Result = std::make_shared<YAMLLinesSubsection>();
583 Result->Lines.CodeSize = Lines.header()->CodeSize;
584 Result->Lines.RelocOffset = Lines.header()->RelocOffset;
585 Result->Lines.RelocSegment = Lines.header()->RelocSegment;
586 Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
587 for (const auto &L : Lines) {
589 auto EF = getFileName(Strings, Checksums, L.NameIndex);
590 if (!EF)
591 return EF.takeError();
592 Block.FileName = *EF;
593 if (Lines.hasColumnInfo()) {
594 for (const auto &C : L.Columns) {
596 SCE.EndColumn = C.EndColumn;
597 SCE.StartColumn = C.StartColumn;
598 Block.Columns.push_back(SCE);
599 }
600 }
601 for (const auto &LN : L.LineNumbers) {
602 SourceLineEntry SLE;
603 LineInfo LI(LN.Flags);
604 SLE.Offset = LN.Offset;
605 SLE.LineStart = LI.getStartLine();
606 SLE.EndDelta = LI.getLineDelta();
607 SLE.IsStatement = LI.isStatement();
608 Block.Lines.push_back(SLE);
609 }
610 Result->Lines.Blocks.push_back(Block);
611 }
612 return Result;
613}
614
616YAMLInlineeLinesSubsection::fromCodeViewSubsection(
617 const DebugStringTableSubsectionRef &Strings,
618 const DebugChecksumsSubsectionRef &Checksums,
620 auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
621
622 Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
623 for (const auto &IL : Lines) {
624 InlineeSite Site;
625 auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
626 if (!ExpF)
627 return ExpF.takeError();
628 Site.FileName = *ExpF;
629 Site.Inlinee = IL.Header->Inlinee.getIndex();
630 Site.SourceLineNum = IL.Header->SourceLineNum;
631 if (Lines.hasExtraFiles()) {
632 for (const auto EF : IL.ExtraFiles) {
633 auto ExpF2 = getFileName(Strings, Checksums, EF);
634 if (!ExpF2)
635 return ExpF2.takeError();
636 Site.ExtraFiles.push_back(*ExpF2);
637 }
638 }
639 Result->InlineeLines.Sites.push_back(Site);
640 }
641 return Result;
642}
643
645YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
647 auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
648 Result->Exports.assign(Exports.begin(), Exports.end());
649 return Result;
650}
651
653YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
654 const DebugStringTableSubsectionRef &Strings,
656 auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
657 for (const auto &CMI : Imports) {
659 auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
660 if (!ExpectedStr)
661 return ExpectedStr.takeError();
662 YCMI.ModuleName = *ExpectedStr;
663 YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
664 Result->Imports.push_back(YCMI);
665 }
666 return Result;
667}
668
670YAMLSymbolsSubsection::fromCodeViewSubsection(
671 const DebugSymbolsSubsectionRef &Symbols) {
672 auto Result = std::make_shared<YAMLSymbolsSubsection>();
673 for (const auto &Sym : Symbols) {
675 if (!S)
676 return joinErrors(make_error<CodeViewError>(
677 cv_error_code::corrupt_record,
678 "Invalid CodeView Symbol Record in SymbolRecord "
679 "subsection of .debug$S while converting to YAML!"),
680 S.takeError());
681
682 Result->Symbols.push_back(*S);
683 }
684 return Result;
685}
686
688YAMLStringTableSubsection::fromCodeViewSubsection(
689 const DebugStringTableSubsectionRef &Strings) {
690 auto Result = std::make_shared<YAMLStringTableSubsection>();
691 BinaryStreamReader Reader(Strings.getBuffer());
692 StringRef S;
693 // First item is a single null string, skip it.
694 if (auto EC = Reader.readCString(S))
695 return std::move(EC);
696 assert(S.empty());
697 while (Reader.bytesRemaining() > 0) {
698 if (auto EC = Reader.readCString(S))
699 return std::move(EC);
700 Result->Strings.push_back(S);
701 }
702 return Result;
703}
704
706YAMLFrameDataSubsection::fromCodeViewSubsection(
707 const DebugStringTableSubsectionRef &Strings,
708 const DebugFrameDataSubsectionRef &Frames) {
709 auto Result = std::make_shared<YAMLFrameDataSubsection>();
710 for (const auto &F : Frames) {
711 YAMLFrameData YF;
712 YF.CodeSize = F.CodeSize;
713 YF.Flags = F.Flags;
714 YF.LocalSize = F.LocalSize;
715 YF.MaxStackSize = F.MaxStackSize;
716 YF.ParamsSize = F.ParamsSize;
717 YF.PrologSize = F.PrologSize;
718 YF.RvaStart = F.RvaStart;
719 YF.SavedRegsSize = F.SavedRegsSize;
720
721 auto ES = Strings.getString(F.FrameFunc);
722 if (!ES)
723 return joinErrors(
724 make_error<CodeViewError>(
725 cv_error_code::no_records,
726 "Could not find string for string id while mapping FrameData!"),
727 ES.takeError());
728 YF.FrameFunc = *ES;
729 Result->Frames.push_back(YF);
730 }
731 return Result;
732}
733
735YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(
736 const DebugSymbolRVASubsectionRef &Section) {
737 auto Result = std::make_shared<YAMLCoffSymbolRVASubsection>();
738 llvm::append_range(Result->RVAs, Section);
739 return Result;
740}
741
744 BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
746 std::vector<std::shared_ptr<DebugSubsection>> Result;
747 if (Subsections.empty())
748 return std::move(Result);
749
750 for (const auto &SS : Subsections) {
751 std::shared_ptr<DebugSubsection> CVS;
752 CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
753 assert(CVS != nullptr);
754 Result.push_back(std::move(CVS));
755 }
756 return std::move(Result);
757}
758
759namespace {
760
761struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
762 SubsectionConversionVisitor() = default;
763
766 const StringsAndChecksumsRef &State) override;
768 const StringsAndChecksumsRef &State) override;
770 const StringsAndChecksumsRef &State) override;
772 const StringsAndChecksumsRef &State) override;
774 const StringsAndChecksumsRef &State) override;
776 const StringsAndChecksumsRef &State) override;
778 const StringsAndChecksumsRef &State) override;
780 const StringsAndChecksumsRef &State) override;
782 const StringsAndChecksumsRef &State) override;
783
784 YAMLDebugSubsection Subsection;
785};
786
787} // end anonymous namespace
788
789Error SubsectionConversionVisitor::visitUnknown(
791 return make_error<CodeViewError>(cv_error_code::operation_unsupported);
792}
793
794Error SubsectionConversionVisitor::visitLines(
796 auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
797 State.strings(), State.checksums(), Lines);
798 if (!Result)
799 return Result.takeError();
800 Subsection.Subsection = *Result;
801 return Error::success();
802}
803
804Error SubsectionConversionVisitor::visitFileChecksums(
806 const StringsAndChecksumsRef &State) {
807 auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
808 Checksums);
809 if (!Result)
810 return Result.takeError();
811 Subsection.Subsection = *Result;
812 return Error::success();
813}
814
815Error SubsectionConversionVisitor::visitInlineeLines(
817 const StringsAndChecksumsRef &State) {
818 auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
819 State.strings(), State.checksums(), Inlinees);
820 if (!Result)
821 return Result.takeError();
822 Subsection.Subsection = *Result;
823 return Error::success();
824}
825
826Error SubsectionConversionVisitor::visitCrossModuleExports(
828 const StringsAndChecksumsRef &State) {
829 auto Result =
830 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
831 if (!Result)
832 return Result.takeError();
833 Subsection.Subsection = *Result;
834 return Error::success();
835}
836
837Error SubsectionConversionVisitor::visitCrossModuleImports(
839 const StringsAndChecksumsRef &State) {
840 auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
841 State.strings(), Imports);
842 if (!Result)
843 return Result.takeError();
844 Subsection.Subsection = *Result;
845 return Error::success();
846}
847
848Error SubsectionConversionVisitor::visitStringTable(
850 const StringsAndChecksumsRef &State) {
851 auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
852 if (!Result)
853 return Result.takeError();
854 Subsection.Subsection = *Result;
855 return Error::success();
856}
857
858Error SubsectionConversionVisitor::visitSymbols(
859 DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
860 auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
861 if (!Result)
862 return Result.takeError();
863 Subsection.Subsection = *Result;
864 return Error::success();
865}
866
867Error SubsectionConversionVisitor::visitFrameData(
869 auto Result =
870 YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
871 if (!Result)
872 return Result.takeError();
873 Subsection.Subsection = *Result;
874 return Error::success();
875}
876
877Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
879 auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs);
880 if (!Result)
881 return Result.takeError();
882 Subsection.Subsection = *Result;
883 return Error::success();
884}
885
888 const DebugSubsectionRecord &SS) {
889 SubsectionConversionVisitor V;
890 if (auto EC = visitDebugSubsection(SS, V, SC))
891 return std::move(EC);
892
893 return V.Subsection;
894}
895
896std::vector<YAMLDebugSubsection>
898 const StringsAndChecksumsRef &SC) {
900 uint32_t Magic;
901
902 ExitOnError Err("Invalid .debug$S section!");
903 Err(Reader.readInteger(Magic));
904 assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
905
906 DebugSubsectionArray Subsections;
907 Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
908
909 std::vector<YAMLDebugSubsection> Result;
910
911 for (const auto &SS : Subsections) {
912 auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
913 Result.push_back(YamlSS);
914 }
915 return Result;
916}
917
920 // String Table and Checksums subsections don't use the allocator.
922
923 // It's possible for checksums and strings to even appear in different debug$S
924 // sections, so we have to make this a stateful function that can build up
925 // the strings and checksums field over multiple iterations.
926
927 // File Checksums require the string table, but may become before it, so we
928 // have to scan for strings first, then scan for checksums again from the
929 // beginning.
930 if (!SC.hasStrings()) {
931 for (const auto &SS : Sections) {
932 if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
933 continue;
934
935 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
936 SC.setStrings(
937 std::static_pointer_cast<DebugStringTableSubsection>(Result));
938 break;
939 }
940 }
941
942 if (SC.hasStrings() && !SC.hasChecksums()) {
943 for (const auto &SS : Sections) {
944 if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
945 continue;
946
947 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
948 SC.setChecksums(
949 std::static_pointer_cast<DebugChecksumsSubsection>(Result));
950 break;
951 }
952 }
953}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)
static Expected< SourceFileChecksumEntry > convertOneChecksum(const DebugStringTableSubsectionRef &Strings, const FileChecksumEntry &CS)
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define F(x, y, z)
Definition: MD5.cpp:55
#define H(x, y, z)
Definition: MD5.cpp:57
Basic Register Allocator
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
#define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)
#define LLVM_YAML_IS_SEQUENCE_VECTOR(type)
#define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)
#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)
#define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:142
Provides read only access to a subclass of BinaryStream.
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
uint64_t bytesRemaining() const
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:67
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
static ErrorSuccess success()
Create a success value.
Definition: Error.h:336
Helper for check-and-exit error handling.
Definition: Error.h:1444
Tagged union holding either a T or a Error.
Definition: Error.h:485
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:151
A table of densely packed, null-terminated strings indexed by offset.
Definition: StringTable.h:33
LLVM Value Representation.
Definition: Value.h:75
Iterator at(uint32_t Offset) const
given an offset into the array's underlying stream, return an iterator to the record at that offset.
Iterator end() const
Represents a read-only view of a CodeView string table.
virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State)=0
virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE, const StringsAndChecksumsRef &State)=0
virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD, const StringsAndChecksumsRef &State)=0
virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, const StringsAndChecksumsRef &State)=0
virtual Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, const StringsAndChecksumsRef &State)=0
virtual Error visitUnknown(DebugUnknownSubsectionRef &Unknown)
virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, const StringsAndChecksumsRef &State)=0
virtual Error visitStringTable(DebugStringTableSubsectionRef &ST, const StringsAndChecksumsRef &State)=0
virtual Error visitLines(DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State)=0
virtual Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE, const StringsAndChecksumsRef &State)=0
const DebugStringTableSubsectionRef & strings() const
const DebugChecksumsSubsectionRef & checksums() const
void setStrings(const StringsPtr &SP)
const StringsPtr & strings() const
void setChecksums(const ChecksumsPtr &CP)
const ChecksumsPtr & checksums() const
A 32-bit type reference.
Definition: TypeIndex.h:97
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ DEBUG_SECTION_MAGIC
Definition: COFF.h:839
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
LLVM_ABI void initializeStringsAndChecksums(ArrayRef< YAMLDebugSubsection > Sections, codeview::StringsAndChecksums &SC)
LLVM_ABI Expected< std::vector< std::shared_ptr< codeview::DebugSubsection > > > toCodeViewSubsectionList(BumpPtrAllocator &Allocator, ArrayRef< YAMLDebugSubsection > Subsections, const codeview::StringsAndChecksums &SC)
LLVM_ABI std::vector< YAMLDebugSubsection > fromDebugS(ArrayRef< uint8_t > Data, const codeview::StringsAndChecksumsRef &SC)
@ SS
Definition: X86.h:215
Error visitDebugSubsection(const DebugSubsectionRecord &R, DebugSubsectionVisitor &V, const StringsAndChecksumsRef &State)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition: STLExtras.h:860
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2155
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:442
@ SCE
Tune debug info for SCE targets (e.g. PS4).
std::vector< SourceLineEntry > Lines
std::vector< SourceColumnEntry > Columns
static LLVM_ABI Expected< SymbolRecord > fromCodeViewSymbol(codeview::CVSymbol Symbol)
std::shared_ptr< detail::YAMLSubsectionBase > Subsection
static LLVM_ABI Expected< YAMLDebugSubsection > fromCodeViewSubection(const codeview::StringsAndChecksumsRef &SC, const codeview::DebugSubsectionRecord &SS)
virtual std::shared_ptr< DebugSubsection > toCodeViewSubsection(BumpPtrAllocator &Allocator, const codeview::StringsAndChecksums &SC) const =0
support::ulittle32_t Local
Definition: CodeView.h:583
support::ulittle32_t Global
Definition: CodeView.h:584
Data in the SUBSEC_FRAMEDATA subection.
Definition: CodeView.h:558