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 | |
14 | #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" |
15 | #include "llvm/ADT/STLExtras.h" |
16 | #include "llvm/ADT/StringExtras.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/BinaryFormat/COFF.h" |
19 | #include "llvm/DebugInfo/CodeView/CodeView.h" |
20 | #include "llvm/DebugInfo/CodeView/CodeViewError.h" |
21 | #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" |
22 | #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" |
23 | #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" |
24 | #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" |
25 | #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" |
26 | #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" |
27 | #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" |
28 | #include "llvm/DebugInfo/CodeView/DebugSubsection.h" |
29 | #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" |
30 | #include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h" |
31 | #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" |
32 | #include "llvm/DebugInfo/CodeView/Line.h" |
33 | #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" |
34 | #include "llvm/DebugInfo/CodeView/TypeIndex.h" |
35 | #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" |
36 | #include "llvm/Support/Allocator.h" |
37 | #include "llvm/Support/BinaryStreamReader.h" |
38 | #include "llvm/Support/Endian.h" |
39 | #include "llvm/Support/Error.h" |
40 | #include "llvm/Support/ErrorHandling.h" |
41 | #include "llvm/Support/YAMLTraits.h" |
42 | #include "llvm/Support/raw_ostream.h" |
43 | #include <cassert> |
44 | #include <cstdint> |
45 | #include <memory> |
46 | #include <string> |
47 | #include <vector> |
48 | |
49 | using namespace llvm; |
50 | using namespace llvm::codeview; |
51 | using namespace llvm::CodeViewYAML; |
52 | using namespace llvm::CodeViewYAML::detail; |
53 | using namespace llvm::yaml; |
54 | |
55 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry) |
56 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry) |
57 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry) |
58 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock) |
59 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo) |
60 | LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite) |
61 | LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo) |
62 | LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport) |
63 | LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport) |
64 | LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData) |
65 | |
66 | LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, QuotingType::None) |
67 | LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind) |
68 | LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind) |
69 | LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags) |
70 | |
71 | LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport) |
72 | LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData) |
73 | LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport) |
74 | LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem) |
75 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry) |
76 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry) |
77 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry) |
78 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock) |
79 | LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite) |
80 | |
81 | namespace llvm { |
82 | namespace CodeViewYAML { |
83 | namespace detail { |
84 | |
85 | struct YAMLSubsectionBase { |
86 | explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {} |
87 | virtual ~YAMLSubsectionBase() = default; |
88 | |
89 | virtual void map(IO &IO) = 0; |
90 | virtual std::shared_ptr<DebugSubsection> |
91 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
92 | const codeview::StringsAndChecksums &SC) const = 0; |
93 | |
94 | DebugSubsectionKind Kind; |
95 | }; |
96 | |
97 | } // end namespace detail |
98 | } // end namespace CodeViewYAML |
99 | } // end namespace llvm |
100 | |
101 | namespace { |
102 | |
103 | struct YAMLChecksumsSubsection : public YAMLSubsectionBase { |
104 | YAMLChecksumsSubsection() |
105 | : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {} |
106 | |
107 | void map(IO &IO) override; |
108 | std::shared_ptr<DebugSubsection> |
109 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
110 | const codeview::StringsAndChecksums &SC) const override; |
111 | static Expected<std::shared_ptr<YAMLChecksumsSubsection>> |
112 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
113 | const DebugChecksumsSubsectionRef &FC); |
114 | |
115 | std::vector<SourceFileChecksumEntry> Checksums; |
116 | }; |
117 | |
118 | struct YAMLLinesSubsection : public YAMLSubsectionBase { |
119 | YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {} |
120 | |
121 | void map(IO &IO) override; |
122 | std::shared_ptr<DebugSubsection> |
123 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
124 | const codeview::StringsAndChecksums &SC) const override; |
125 | static Expected<std::shared_ptr<YAMLLinesSubsection>> |
126 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
127 | const DebugChecksumsSubsectionRef &Checksums, |
128 | const DebugLinesSubsectionRef &Lines); |
129 | |
130 | SourceLineInfo Lines; |
131 | }; |
132 | |
133 | struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { |
134 | YAMLInlineeLinesSubsection() |
135 | : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {} |
136 | |
137 | void map(IO &IO) override; |
138 | std::shared_ptr<DebugSubsection> |
139 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
140 | const codeview::StringsAndChecksums &SC) const override; |
141 | static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> |
142 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
143 | const DebugChecksumsSubsectionRef &Checksums, |
144 | const DebugInlineeLinesSubsectionRef &Lines); |
145 | |
146 | InlineeInfo InlineeLines; |
147 | }; |
148 | |
149 | struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase { |
150 | YAMLCrossModuleExportsSubsection() |
151 | : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {} |
152 | |
153 | void map(IO &IO) override; |
154 | std::shared_ptr<DebugSubsection> |
155 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
156 | const codeview::StringsAndChecksums &SC) const override; |
157 | static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> |
158 | fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports); |
159 | |
160 | std::vector<CrossModuleExport> Exports; |
161 | }; |
162 | |
163 | struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase { |
164 | YAMLCrossModuleImportsSubsection() |
165 | : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {} |
166 | |
167 | void map(IO &IO) override; |
168 | std::shared_ptr<DebugSubsection> |
169 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
170 | const codeview::StringsAndChecksums &SC) const override; |
171 | static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> |
172 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
173 | const DebugCrossModuleImportsSubsectionRef &Imports); |
174 | |
175 | std::vector<YAMLCrossModuleImport> Imports; |
176 | }; |
177 | |
178 | struct YAMLSymbolsSubsection : public YAMLSubsectionBase { |
179 | YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {} |
180 | |
181 | void map(IO &IO) override; |
182 | std::shared_ptr<DebugSubsection> |
183 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
184 | const codeview::StringsAndChecksums &SC) const override; |
185 | static Expected<std::shared_ptr<YAMLSymbolsSubsection>> |
186 | fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols); |
187 | |
188 | std::vector<CodeViewYAML::SymbolRecord> Symbols; |
189 | }; |
190 | |
191 | struct YAMLStringTableSubsection : public YAMLSubsectionBase { |
192 | YAMLStringTableSubsection() |
193 | : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {} |
194 | |
195 | void map(IO &IO) override; |
196 | std::shared_ptr<DebugSubsection> |
197 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
198 | const codeview::StringsAndChecksums &SC) const override; |
199 | static Expected<std::shared_ptr<YAMLStringTableSubsection>> |
200 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings); |
201 | |
202 | std::vector<StringRef> Strings; |
203 | }; |
204 | |
205 | struct YAMLFrameDataSubsection : public YAMLSubsectionBase { |
206 | YAMLFrameDataSubsection() |
207 | : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {} |
208 | |
209 | void map(IO &IO) override; |
210 | std::shared_ptr<DebugSubsection> |
211 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
212 | const codeview::StringsAndChecksums &SC) const override; |
213 | static Expected<std::shared_ptr<YAMLFrameDataSubsection>> |
214 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
215 | const DebugFrameDataSubsectionRef &Frames); |
216 | |
217 | std::vector<YAMLFrameData> Frames; |
218 | }; |
219 | |
220 | struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase { |
221 | YAMLCoffSymbolRVASubsection() |
222 | : YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {} |
223 | |
224 | void map(IO &IO) override; |
225 | std::shared_ptr<DebugSubsection> |
226 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
227 | const codeview::StringsAndChecksums &SC) const override; |
228 | static Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>> |
229 | fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs); |
230 | |
231 | std::vector<uint32_t> RVAs; |
232 | }; |
233 | |
234 | } // end anonymous namespace |
235 | |
236 | void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) { |
237 | io.bitSetCase(Val&: Flags, Str: "HasColumnInfo" , ConstVal: LF_HaveColumns); |
238 | io.enumFallback<Hex16>(Val&: Flags); |
239 | } |
240 | |
241 | void ScalarEnumerationTraits<FileChecksumKind>::enumeration( |
242 | IO &io, FileChecksumKind &Kind) { |
243 | io.enumCase(Val&: Kind, Str: "None" , ConstVal: FileChecksumKind::None); |
244 | io.enumCase(Val&: Kind, Str: "MD5" , ConstVal: FileChecksumKind::MD5); |
245 | io.enumCase(Val&: Kind, Str: "SHA1" , ConstVal: FileChecksumKind::SHA1); |
246 | io.enumCase(Val&: Kind, Str: "SHA256" , ConstVal: FileChecksumKind::SHA256); |
247 | } |
248 | |
249 | void 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(Input: Bytes); |
254 | } |
255 | |
256 | StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt, |
257 | HexFormattedString &Value) { |
258 | std::string H = fromHex(Input: Scalar); |
259 | Value.Bytes.assign(first: H.begin(), last: H.end()); |
260 | return StringRef(); |
261 | } |
262 | |
263 | void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) { |
264 | IO.mapRequired(Key: "Offset" , Val&: Obj.Offset); |
265 | IO.mapRequired(Key: "LineStart" , Val&: Obj.LineStart); |
266 | IO.mapRequired(Key: "IsStatement" , Val&: Obj.IsStatement); |
267 | IO.mapRequired(Key: "EndDelta" , Val&: Obj.EndDelta); |
268 | } |
269 | |
270 | void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) { |
271 | IO.mapRequired(Key: "StartColumn" , Val&: Obj.StartColumn); |
272 | IO.mapRequired(Key: "EndColumn" , Val&: Obj.EndColumn); |
273 | } |
274 | |
275 | void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) { |
276 | IO.mapRequired(Key: "FileName" , Val&: Obj.FileName); |
277 | IO.mapRequired(Key: "Lines" , Val&: Obj.Lines); |
278 | IO.mapRequired(Key: "Columns" , Val&: Obj.Columns); |
279 | } |
280 | |
281 | void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) { |
282 | IO.mapRequired(Key: "LocalId" , Val&: Obj.Local); |
283 | IO.mapRequired(Key: "GlobalId" , Val&: Obj.Global); |
284 | } |
285 | |
286 | void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO, |
287 | YAMLCrossModuleImport &Obj) { |
288 | IO.mapRequired(Key: "Module" , Val&: Obj.ModuleName); |
289 | IO.mapRequired(Key: "Imports" , Val&: Obj.ImportIds); |
290 | } |
291 | |
292 | void MappingTraits<SourceFileChecksumEntry>::mapping( |
293 | IO &IO, SourceFileChecksumEntry &Obj) { |
294 | IO.mapRequired(Key: "FileName" , Val&: Obj.FileName); |
295 | IO.mapRequired(Key: "Kind" , Val&: Obj.Kind); |
296 | IO.mapRequired(Key: "Checksum" , Val&: Obj.ChecksumBytes); |
297 | } |
298 | |
299 | void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) { |
300 | IO.mapRequired(Key: "FileName" , Val&: Obj.FileName); |
301 | IO.mapRequired(Key: "LineNum" , Val&: Obj.SourceLineNum); |
302 | IO.mapRequired(Key: "Inlinee" , Val&: Obj.Inlinee); |
303 | IO.mapOptional(Key: "ExtraFiles" , Val&: Obj.ExtraFiles); |
304 | } |
305 | |
306 | void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) { |
307 | IO.mapRequired(Key: "CodeSize" , Val&: Obj.CodeSize); |
308 | IO.mapRequired(Key: "FrameFunc" , Val&: Obj.FrameFunc); |
309 | IO.mapRequired(Key: "LocalSize" , Val&: Obj.LocalSize); |
310 | IO.mapOptional(Key: "MaxStackSize" , Val&: Obj.MaxStackSize); |
311 | IO.mapOptional(Key: "ParamsSize" , Val&: Obj.ParamsSize); |
312 | IO.mapOptional(Key: "PrologSize" , Val&: Obj.PrologSize); |
313 | IO.mapOptional(Key: "RvaStart" , Val&: Obj.RvaStart); |
314 | IO.mapOptional(Key: "SavedRegsSize" , Val&: Obj.SavedRegsSize); |
315 | } |
316 | |
317 | void YAMLChecksumsSubsection::map(IO &IO) { |
318 | IO.mapTag(Tag: "!FileChecksums" , Default: true); |
319 | IO.mapRequired(Key: "Checksums" , Val&: Checksums); |
320 | } |
321 | |
322 | void YAMLLinesSubsection::map(IO &IO) { |
323 | IO.mapTag(Tag: "!Lines" , Default: true); |
324 | IO.mapRequired(Key: "CodeSize" , Val&: Lines.CodeSize); |
325 | |
326 | IO.mapRequired(Key: "Flags" , Val&: Lines.Flags); |
327 | IO.mapRequired(Key: "RelocOffset" , Val&: Lines.RelocOffset); |
328 | IO.mapRequired(Key: "RelocSegment" , Val&: Lines.RelocSegment); |
329 | IO.mapRequired(Key: "Blocks" , Val&: Lines.Blocks); |
330 | } |
331 | |
332 | void YAMLInlineeLinesSubsection::map(IO &IO) { |
333 | IO.mapTag(Tag: "!InlineeLines" , Default: true); |
334 | IO.mapRequired(Key: "HasExtraFiles" , Val&: InlineeLines.HasExtraFiles); |
335 | IO.mapRequired(Key: "Sites" , Val&: InlineeLines.Sites); |
336 | } |
337 | |
338 | void YAMLCrossModuleExportsSubsection::map(IO &IO) { |
339 | IO.mapTag(Tag: "!CrossModuleExports" , Default: true); |
340 | IO.mapOptional(Key: "Exports" , Val&: Exports); |
341 | } |
342 | |
343 | void YAMLCrossModuleImportsSubsection::map(IO &IO) { |
344 | IO.mapTag(Tag: "!CrossModuleImports" , Default: true); |
345 | IO.mapOptional(Key: "Imports" , Val&: Imports); |
346 | } |
347 | |
348 | void YAMLSymbolsSubsection::map(IO &IO) { |
349 | IO.mapTag(Tag: "!Symbols" , Default: true); |
350 | IO.mapRequired(Key: "Records" , Val&: Symbols); |
351 | } |
352 | |
353 | void YAMLStringTableSubsection::map(IO &IO) { |
354 | IO.mapTag(Tag: "!StringTable" , Default: true); |
355 | IO.mapRequired(Key: "Strings" , Val&: Strings); |
356 | } |
357 | |
358 | void YAMLFrameDataSubsection::map(IO &IO) { |
359 | IO.mapTag(Tag: "!FrameData" , Default: true); |
360 | IO.mapRequired(Key: "Frames" , Val&: Frames); |
361 | } |
362 | |
363 | void YAMLCoffSymbolRVASubsection::map(IO &IO) { |
364 | IO.mapTag(Tag: "!COFFSymbolRVAs" , Default: true); |
365 | IO.mapRequired(Key: "RVAs" , Val&: RVAs); |
366 | } |
367 | |
368 | void MappingTraits<YAMLDebugSubsection>::mapping( |
369 | IO &IO, YAMLDebugSubsection &Subsection) { |
370 | if (!IO.outputting()) { |
371 | if (IO.mapTag(Tag: "!FileChecksums" )) { |
372 | auto SS = std::make_shared<YAMLChecksumsSubsection>(); |
373 | Subsection.Subsection = SS; |
374 | } else if (IO.mapTag(Tag: "!Lines" )) { |
375 | Subsection.Subsection = std::make_shared<YAMLLinesSubsection>(); |
376 | } else if (IO.mapTag(Tag: "!InlineeLines" )) { |
377 | Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>(); |
378 | } else if (IO.mapTag(Tag: "!CrossModuleExports" )) { |
379 | Subsection.Subsection = |
380 | std::make_shared<YAMLCrossModuleExportsSubsection>(); |
381 | } else if (IO.mapTag(Tag: "!CrossModuleImports" )) { |
382 | Subsection.Subsection = |
383 | std::make_shared<YAMLCrossModuleImportsSubsection>(); |
384 | } else if (IO.mapTag(Tag: "!Symbols" )) { |
385 | Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>(); |
386 | } else if (IO.mapTag(Tag: "!StringTable" )) { |
387 | Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>(); |
388 | } else if (IO.mapTag(Tag: "!FrameData" )) { |
389 | Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>(); |
390 | } else if (IO.mapTag(Tag: "!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 | |
399 | std::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>(args&: *SC.strings()); |
404 | for (const auto &CS : Checksums) { |
405 | Result->addChecksum(FileName: CS.FileName, Kind: CS.Kind, Bytes: CS.ChecksumBytes.Bytes); |
406 | } |
407 | return Result; |
408 | } |
409 | |
410 | std::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>(args&: *SC.checksums(), args&: *SC.strings()); |
416 | Result->setCodeSize(Lines.CodeSize); |
417 | Result->setRelocationAddress(Segment: Lines.RelocSegment, Offset: Lines.RelocOffset); |
418 | Result->setFlags(Lines.Flags); |
419 | for (const auto &LC : Lines.Blocks) { |
420 | Result->createBlock(FileName: LC.FileName); |
421 | if (Result->hasColumnInfo()) { |
422 | for (auto Item : zip(t: LC.Lines, u: LC.Columns)) { |
423 | auto &L = std::get<0>(t&: Item); |
424 | auto &C = std::get<1>(t&: Item); |
425 | uint32_t LE = L.LineStart + L.EndDelta; |
426 | Result->addLineAndColumnInfo(Offset: L.Offset, |
427 | Line: LineInfo(L.LineStart, LE, L.IsStatement), |
428 | ColStart: C.StartColumn, ColEnd: C.EndColumn); |
429 | } |
430 | } else { |
431 | for (const auto &L : LC.Lines) { |
432 | uint32_t LE = L.LineStart + L.EndDelta; |
433 | Result->addLineInfo(Offset: L.Offset, Line: LineInfo(L.LineStart, LE, L.IsStatement)); |
434 | } |
435 | } |
436 | } |
437 | return Result; |
438 | } |
439 | |
440 | std::shared_ptr<DebugSubsection> |
441 | YAMLInlineeLinesSubsection::toCodeViewSubsection( |
442 | BumpPtrAllocator &Allocator, |
443 | const codeview::StringsAndChecksums &SC) const { |
444 | assert(SC.hasChecksums()); |
445 | auto Result = std::make_shared<DebugInlineeLinesSubsection>( |
446 | args&: *SC.checksums(), args: InlineeLines.HasExtraFiles); |
447 | |
448 | for (const auto &Site : InlineeLines.Sites) { |
449 | Result->addInlineSite(FuncId: TypeIndex(Site.Inlinee), FileName: Site.FileName, |
450 | SourceLine: Site.SourceLineNum); |
451 | if (!InlineeLines.HasExtraFiles) |
452 | continue; |
453 | |
454 | for (auto EF : Site.ExtraFiles) { |
455 | Result->addExtraFile(FileName: EF); |
456 | } |
457 | } |
458 | return Result; |
459 | } |
460 | |
461 | std::shared_ptr<DebugSubsection> |
462 | YAMLCrossModuleExportsSubsection::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(Local: M.Local, Global: M.Global); |
468 | return Result; |
469 | } |
470 | |
471 | std::shared_ptr<DebugSubsection> |
472 | YAMLCrossModuleImportsSubsection::toCodeViewSubsection( |
473 | BumpPtrAllocator &Allocator, |
474 | const codeview::StringsAndChecksums &SC) const { |
475 | assert(SC.hasStrings()); |
476 | |
477 | auto Result = |
478 | std::make_shared<DebugCrossModuleImportsSubsection>(args&: *SC.strings()); |
479 | for (const auto &M : Imports) { |
480 | for (const auto Id : M.ImportIds) |
481 | Result->addImport(Module: M.ModuleName, ImportId: Id); |
482 | } |
483 | return Result; |
484 | } |
485 | |
486 | std::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 | Symbol: Sym.toCodeViewSymbol(Allocator, Container: CodeViewContainer::ObjectFile)); |
493 | return Result; |
494 | } |
495 | |
496 | std::shared_ptr<DebugSubsection> |
497 | YAMLStringTableSubsection::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(S: Str); |
503 | return Result; |
504 | } |
505 | |
506 | std::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>(args: true); |
512 | for (const auto &YF : Frames) { |
513 | codeview::FrameData F; |
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(S: YF.FrameFunc); |
523 | Result->addFrameData(Frame: F); |
524 | } |
525 | return Result; |
526 | } |
527 | |
528 | std::shared_ptr<DebugSubsection> |
529 | YAMLCoffSymbolRVASubsection::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 | |
538 | static Expected<SourceFileChecksumEntry> |
539 | convertOneChecksum(const DebugStringTableSubsectionRef &Strings, |
540 | const FileChecksumEntry &CS) { |
541 | auto ExpectedString = Strings.getString(Offset: CS.FileNameOffset); |
542 | if (!ExpectedString) |
543 | return ExpectedString.takeError(); |
544 | |
545 | SourceFileChecksumEntry Result; |
546 | Result.ChecksumBytes.Bytes = CS.Checksum; |
547 | Result.Kind = CS.Kind; |
548 | Result.FileName = *ExpectedString; |
549 | return Result; |
550 | } |
551 | |
552 | static Expected<StringRef> |
553 | getFileName(const DebugStringTableSubsectionRef &Strings, |
554 | const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { |
555 | auto Iter = Checksums.getArray().at(Offset: FileID); |
556 | if (Iter == Checksums.getArray().end()) |
557 | return make_error<CodeViewError>(Args: cv_error_code::no_records); |
558 | uint32_t Offset = Iter->FileNameOffset; |
559 | return Strings.getString(Offset); |
560 | } |
561 | |
562 | Expected<std::shared_ptr<YAMLChecksumsSubsection>> |
563 | YAMLChecksumsSubsection::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(x: *ConvertedCS); |
573 | } |
574 | return Result; |
575 | } |
576 | |
577 | Expected<std::shared_ptr<YAMLLinesSubsection>> |
578 | YAMLLinesSubsection::fromCodeViewSubsection( |
579 | const DebugStringTableSubsectionRef &Strings, |
580 | const DebugChecksumsSubsectionRef &Checksums, |
581 | const DebugLinesSubsectionRef &Lines) { |
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) { |
588 | SourceLineBlock Block; |
589 | auto EF = getFileName(Strings, Checksums, FileID: L.NameIndex); |
590 | if (!EF) |
591 | return EF.takeError(); |
592 | Block.FileName = *EF; |
593 | if (Lines.hasColumnInfo()) { |
594 | for (const auto &C : L.Columns) { |
595 | SourceColumnEntry SCE; |
596 | SCE.EndColumn = C.EndColumn; |
597 | SCE.StartColumn = C.StartColumn; |
598 | Block.Columns.push_back(x: 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(x: SLE); |
609 | } |
610 | Result->Lines.Blocks.push_back(x: Block); |
611 | } |
612 | return Result; |
613 | } |
614 | |
615 | Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> |
616 | YAMLInlineeLinesSubsection::fromCodeViewSubsection( |
617 | const DebugStringTableSubsectionRef &Strings, |
618 | const DebugChecksumsSubsectionRef &Checksums, |
619 | const DebugInlineeLinesSubsectionRef &Lines) { |
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, FileID: 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, FileID: EF); |
634 | if (!ExpF2) |
635 | return ExpF2.takeError(); |
636 | Site.ExtraFiles.push_back(x: *ExpF2); |
637 | } |
638 | } |
639 | Result->InlineeLines.Sites.push_back(x: Site); |
640 | } |
641 | return Result; |
642 | } |
643 | |
644 | Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> |
645 | YAMLCrossModuleExportsSubsection::fromCodeViewSubsection( |
646 | const DebugCrossModuleExportsSubsectionRef &Exports) { |
647 | auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>(); |
648 | Result->Exports.assign(first: Exports.begin(), last: Exports.end()); |
649 | return Result; |
650 | } |
651 | |
652 | Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> |
653 | YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( |
654 | const DebugStringTableSubsectionRef &Strings, |
655 | const DebugCrossModuleImportsSubsectionRef &Imports) { |
656 | auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>(); |
657 | for (const auto &CMI : Imports) { |
658 | YAMLCrossModuleImport YCMI; |
659 | auto ExpectedStr = Strings.getString(Offset: CMI.Header->ModuleNameOffset); |
660 | if (!ExpectedStr) |
661 | return ExpectedStr.takeError(); |
662 | YCMI.ModuleName = *ExpectedStr; |
663 | YCMI.ImportIds.assign(first: CMI.Imports.begin(), last: CMI.Imports.end()); |
664 | Result->Imports.push_back(x: YCMI); |
665 | } |
666 | return Result; |
667 | } |
668 | |
669 | Expected<std::shared_ptr<YAMLSymbolsSubsection>> |
670 | YAMLSymbolsSubsection::fromCodeViewSubsection( |
671 | const DebugSymbolsSubsectionRef &Symbols) { |
672 | auto Result = std::make_shared<YAMLSymbolsSubsection>(); |
673 | for (const auto &Sym : Symbols) { |
674 | auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Symbol: Sym); |
675 | if (!S) |
676 | return joinErrors(E1: make_error<CodeViewError>( |
677 | Args: cv_error_code::corrupt_record, |
678 | Args: "Invalid CodeView Symbol Record in SymbolRecord " |
679 | "subsection of .debug$S while converting to YAML!" ), |
680 | E2: S.takeError()); |
681 | |
682 | Result->Symbols.push_back(x: *S); |
683 | } |
684 | return Result; |
685 | } |
686 | |
687 | Expected<std::shared_ptr<YAMLStringTableSubsection>> |
688 | YAMLStringTableSubsection::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(Dest&: S)) |
695 | return std::move(EC); |
696 | assert(S.empty()); |
697 | while (Reader.bytesRemaining() > 0) { |
698 | if (auto EC = Reader.readCString(Dest&: S)) |
699 | return std::move(EC); |
700 | Result->Strings.push_back(x: S); |
701 | } |
702 | return Result; |
703 | } |
704 | |
705 | Expected<std::shared_ptr<YAMLFrameDataSubsection>> |
706 | YAMLFrameDataSubsection::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(Offset: F.FrameFunc); |
722 | if (!ES) |
723 | return joinErrors( |
724 | E1: make_error<CodeViewError>( |
725 | Args: cv_error_code::no_records, |
726 | Args: "Could not find string for string id while mapping FrameData!" ), |
727 | E2: ES.takeError()); |
728 | YF.FrameFunc = *ES; |
729 | Result->Frames.push_back(x: YF); |
730 | } |
731 | return Result; |
732 | } |
733 | |
734 | Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>> |
735 | YAMLCoffSymbolRVASubsection::fromCodeViewSubsection( |
736 | const DebugSymbolRVASubsectionRef &Section) { |
737 | auto Result = std::make_shared<YAMLCoffSymbolRVASubsection>(); |
738 | llvm::append_range(C&: Result->RVAs, R: Section); |
739 | return Result; |
740 | } |
741 | |
742 | Expected<std::vector<std::shared_ptr<DebugSubsection>>> |
743 | llvm::CodeViewYAML::toCodeViewSubsectionList( |
744 | BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections, |
745 | const codeview::StringsAndChecksums &SC) { |
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(x: std::move(CVS)); |
755 | } |
756 | return std::move(Result); |
757 | } |
758 | |
759 | namespace { |
760 | |
761 | struct SubsectionConversionVisitor : public DebugSubsectionVisitor { |
762 | SubsectionConversionVisitor() = default; |
763 | |
764 | Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override; |
765 | Error visitLines(DebugLinesSubsectionRef &Lines, |
766 | const StringsAndChecksumsRef &State) override; |
767 | Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, |
768 | const StringsAndChecksumsRef &State) override; |
769 | Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, |
770 | const StringsAndChecksumsRef &State) override; |
771 | Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums, |
772 | const StringsAndChecksumsRef &State) override; |
773 | Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees, |
774 | const StringsAndChecksumsRef &State) override; |
775 | Error visitStringTable(DebugStringTableSubsectionRef &ST, |
776 | const StringsAndChecksumsRef &State) override; |
777 | Error visitSymbols(DebugSymbolsSubsectionRef &Symbols, |
778 | const StringsAndChecksumsRef &State) override; |
779 | Error visitFrameData(DebugFrameDataSubsectionRef &Symbols, |
780 | const StringsAndChecksumsRef &State) override; |
781 | Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols, |
782 | const StringsAndChecksumsRef &State) override; |
783 | |
784 | YAMLDebugSubsection Subsection; |
785 | }; |
786 | |
787 | } // end anonymous namespace |
788 | |
789 | Error SubsectionConversionVisitor::visitUnknown( |
790 | DebugUnknownSubsectionRef &Unknown) { |
791 | return make_error<CodeViewError>(Args: cv_error_code::operation_unsupported); |
792 | } |
793 | |
794 | Error SubsectionConversionVisitor::visitLines( |
795 | DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) { |
796 | auto Result = YAMLLinesSubsection::fromCodeViewSubsection( |
797 | Strings: State.strings(), Checksums: State.checksums(), Lines); |
798 | if (!Result) |
799 | return Result.takeError(); |
800 | Subsection.Subsection = *Result; |
801 | return Error::success(); |
802 | } |
803 | |
804 | Error SubsectionConversionVisitor::visitFileChecksums( |
805 | DebugChecksumsSubsectionRef &Checksums, |
806 | const StringsAndChecksumsRef &State) { |
807 | auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(Strings: State.strings(), |
808 | FC: Checksums); |
809 | if (!Result) |
810 | return Result.takeError(); |
811 | Subsection.Subsection = *Result; |
812 | return Error::success(); |
813 | } |
814 | |
815 | Error SubsectionConversionVisitor::visitInlineeLines( |
816 | DebugInlineeLinesSubsectionRef &Inlinees, |
817 | const StringsAndChecksumsRef &State) { |
818 | auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection( |
819 | Strings: State.strings(), Checksums: State.checksums(), Lines: Inlinees); |
820 | if (!Result) |
821 | return Result.takeError(); |
822 | Subsection.Subsection = *Result; |
823 | return Error::success(); |
824 | } |
825 | |
826 | Error SubsectionConversionVisitor::visitCrossModuleExports( |
827 | DebugCrossModuleExportsSubsectionRef &Exports, |
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 | |
837 | Error SubsectionConversionVisitor::visitCrossModuleImports( |
838 | DebugCrossModuleImportsSubsectionRef &Imports, |
839 | const StringsAndChecksumsRef &State) { |
840 | auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( |
841 | Strings: State.strings(), Imports); |
842 | if (!Result) |
843 | return Result.takeError(); |
844 | Subsection.Subsection = *Result; |
845 | return Error::success(); |
846 | } |
847 | |
848 | Error SubsectionConversionVisitor::visitStringTable( |
849 | DebugStringTableSubsectionRef &Strings, |
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 | |
858 | Error 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 | |
867 | Error SubsectionConversionVisitor::visitFrameData( |
868 | DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) { |
869 | auto Result = |
870 | YAMLFrameDataSubsection::fromCodeViewSubsection(Strings: State.strings(), Frames); |
871 | if (!Result) |
872 | return Result.takeError(); |
873 | Subsection.Subsection = *Result; |
874 | return Error::success(); |
875 | } |
876 | |
877 | Error SubsectionConversionVisitor::visitCOFFSymbolRVAs( |
878 | DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) { |
879 | auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(Section: RVAs); |
880 | if (!Result) |
881 | return Result.takeError(); |
882 | Subsection.Subsection = *Result; |
883 | return Error::success(); |
884 | } |
885 | |
886 | Expected<YAMLDebugSubsection> |
887 | YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC, |
888 | const DebugSubsectionRecord &SS) { |
889 | SubsectionConversionVisitor V; |
890 | if (auto EC = visitDebugSubsection(R: SS, V, State: SC)) |
891 | return std::move(EC); |
892 | |
893 | return V.Subsection; |
894 | } |
895 | |
896 | std::vector<YAMLDebugSubsection> |
897 | llvm::CodeViewYAML::fromDebugS(ArrayRef<uint8_t> Data, |
898 | const StringsAndChecksumsRef &SC) { |
899 | BinaryStreamReader Reader(Data, llvm::endianness::little); |
900 | uint32_t Magic; |
901 | |
902 | ExitOnError Err("Invalid .debug$S section!" ); |
903 | Err(Reader.readInteger(Dest&: Magic)); |
904 | assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!" ); |
905 | |
906 | DebugSubsectionArray Subsections; |
907 | Err(Reader.readArray(Array&: Subsections, Size: 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(x: YamlSS); |
914 | } |
915 | return Result; |
916 | } |
917 | |
918 | void llvm::CodeViewYAML::initializeStringsAndChecksums( |
919 | ArrayRef<YAMLDebugSubsection> Sections, codeview::StringsAndChecksums &SC) { |
920 | // String Table and Checksums subsections don't use the allocator. |
921 | BumpPtrAllocator 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>(r: 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>(r: Result)); |
950 | break; |
951 | } |
952 | } |
953 | } |
954 | |