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 <algorithm> |
44 | #include <cassert> |
45 | #include <cstdint> |
46 | #include <memory> |
47 | #include <string> |
48 | #include <tuple> |
49 | #include <vector> |
50 | |
51 | using namespace llvm; |
52 | using namespace llvm::codeview; |
53 | using namespace llvm::CodeViewYAML; |
54 | using namespace llvm::CodeViewYAML::detail; |
55 | using namespace llvm::yaml; |
56 | |
57 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry) |
58 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry) |
59 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry) |
60 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock) |
61 | LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo) |
62 | LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite) |
63 | LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo) |
64 | LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport) |
65 | LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport) |
66 | LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData) |
67 | |
68 | LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, QuotingType::None) |
69 | LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind) |
70 | LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind) |
71 | LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags) |
72 | |
73 | LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport) |
74 | LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData) |
75 | LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport) |
76 | LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem) |
77 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry) |
78 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry) |
79 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry) |
80 | LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock) |
81 | LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite) |
82 | |
83 | namespace llvm { |
84 | namespace CodeViewYAML { |
85 | namespace detail { |
86 | |
87 | struct YAMLSubsectionBase { |
88 | explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {} |
89 | virtual ~YAMLSubsectionBase() = default; |
90 | |
91 | virtual void map(IO &IO) = 0; |
92 | virtual std::shared_ptr<DebugSubsection> |
93 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
94 | const codeview::StringsAndChecksums &SC) const = 0; |
95 | |
96 | DebugSubsectionKind Kind; |
97 | }; |
98 | |
99 | } // end namespace detail |
100 | } // end namespace CodeViewYAML |
101 | } // end namespace llvm |
102 | |
103 | namespace { |
104 | |
105 | struct YAMLChecksumsSubsection : public YAMLSubsectionBase { |
106 | YAMLChecksumsSubsection() |
107 | : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {} |
108 | |
109 | void map(IO &IO) override; |
110 | std::shared_ptr<DebugSubsection> |
111 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
112 | const codeview::StringsAndChecksums &SC) const override; |
113 | static Expected<std::shared_ptr<YAMLChecksumsSubsection>> |
114 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
115 | const DebugChecksumsSubsectionRef &FC); |
116 | |
117 | std::vector<SourceFileChecksumEntry> Checksums; |
118 | }; |
119 | |
120 | struct YAMLLinesSubsection : public YAMLSubsectionBase { |
121 | YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {} |
122 | |
123 | void map(IO &IO) override; |
124 | std::shared_ptr<DebugSubsection> |
125 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
126 | const codeview::StringsAndChecksums &SC) const override; |
127 | static Expected<std::shared_ptr<YAMLLinesSubsection>> |
128 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
129 | const DebugChecksumsSubsectionRef &Checksums, |
130 | const DebugLinesSubsectionRef &Lines); |
131 | |
132 | SourceLineInfo Lines; |
133 | }; |
134 | |
135 | struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { |
136 | YAMLInlineeLinesSubsection() |
137 | : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {} |
138 | |
139 | void map(IO &IO) override; |
140 | std::shared_ptr<DebugSubsection> |
141 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
142 | const codeview::StringsAndChecksums &SC) const override; |
143 | static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> |
144 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
145 | const DebugChecksumsSubsectionRef &Checksums, |
146 | const DebugInlineeLinesSubsectionRef &Lines); |
147 | |
148 | InlineeInfo InlineeLines; |
149 | }; |
150 | |
151 | struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase { |
152 | YAMLCrossModuleExportsSubsection() |
153 | : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {} |
154 | |
155 | void map(IO &IO) override; |
156 | std::shared_ptr<DebugSubsection> |
157 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
158 | const codeview::StringsAndChecksums &SC) const override; |
159 | static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> |
160 | fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports); |
161 | |
162 | std::vector<CrossModuleExport> Exports; |
163 | }; |
164 | |
165 | struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase { |
166 | YAMLCrossModuleImportsSubsection() |
167 | : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {} |
168 | |
169 | void map(IO &IO) override; |
170 | std::shared_ptr<DebugSubsection> |
171 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
172 | const codeview::StringsAndChecksums &SC) const override; |
173 | static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> |
174 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
175 | const DebugCrossModuleImportsSubsectionRef &Imports); |
176 | |
177 | std::vector<YAMLCrossModuleImport> Imports; |
178 | }; |
179 | |
180 | struct YAMLSymbolsSubsection : public YAMLSubsectionBase { |
181 | YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {} |
182 | |
183 | void map(IO &IO) override; |
184 | std::shared_ptr<DebugSubsection> |
185 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
186 | const codeview::StringsAndChecksums &SC) const override; |
187 | static Expected<std::shared_ptr<YAMLSymbolsSubsection>> |
188 | fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols); |
189 | |
190 | std::vector<CodeViewYAML::SymbolRecord> Symbols; |
191 | }; |
192 | |
193 | struct YAMLStringTableSubsection : public YAMLSubsectionBase { |
194 | YAMLStringTableSubsection() |
195 | : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {} |
196 | |
197 | void map(IO &IO) override; |
198 | std::shared_ptr<DebugSubsection> |
199 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
200 | const codeview::StringsAndChecksums &SC) const override; |
201 | static Expected<std::shared_ptr<YAMLStringTableSubsection>> |
202 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings); |
203 | |
204 | std::vector<StringRef> Strings; |
205 | }; |
206 | |
207 | struct YAMLFrameDataSubsection : public YAMLSubsectionBase { |
208 | YAMLFrameDataSubsection() |
209 | : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {} |
210 | |
211 | void map(IO &IO) override; |
212 | std::shared_ptr<DebugSubsection> |
213 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
214 | const codeview::StringsAndChecksums &SC) const override; |
215 | static Expected<std::shared_ptr<YAMLFrameDataSubsection>> |
216 | fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, |
217 | const DebugFrameDataSubsectionRef &Frames); |
218 | |
219 | std::vector<YAMLFrameData> Frames; |
220 | }; |
221 | |
222 | struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase { |
223 | YAMLCoffSymbolRVASubsection() |
224 | : YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {} |
225 | |
226 | void map(IO &IO) override; |
227 | std::shared_ptr<DebugSubsection> |
228 | toCodeViewSubsection(BumpPtrAllocator &Allocator, |
229 | const codeview::StringsAndChecksums &SC) const override; |
230 | static Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>> |
231 | fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs); |
232 | |
233 | std::vector<uint32_t> RVAs; |
234 | }; |
235 | |
236 | } // end anonymous namespace |
237 | |
238 | void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) { |
239 | io.bitSetCase(Val&: Flags, Str: "HasColumnInfo" , ConstVal: LF_HaveColumns); |
240 | io.enumFallback<Hex16>(Val&: Flags); |
241 | } |
242 | |
243 | void ScalarEnumerationTraits<FileChecksumKind>::enumeration( |
244 | IO &io, FileChecksumKind &Kind) { |
245 | io.enumCase(Val&: Kind, Str: "None" , ConstVal: FileChecksumKind::None); |
246 | io.enumCase(Val&: Kind, Str: "MD5" , ConstVal: FileChecksumKind::MD5); |
247 | io.enumCase(Val&: Kind, Str: "SHA1" , ConstVal: FileChecksumKind::SHA1); |
248 | io.enumCase(Val&: Kind, Str: "SHA256" , ConstVal: FileChecksumKind::SHA256); |
249 | } |
250 | |
251 | void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value, |
252 | void *ctx, raw_ostream &Out) { |
253 | StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()), |
254 | Value.Bytes.size()); |
255 | Out << toHex(Input: Bytes); |
256 | } |
257 | |
258 | StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt, |
259 | HexFormattedString &Value) { |
260 | std::string H = fromHex(Input: Scalar); |
261 | Value.Bytes.assign(first: H.begin(), last: H.end()); |
262 | return StringRef(); |
263 | } |
264 | |
265 | void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) { |
266 | IO.mapRequired(Key: "Offset" , Val&: Obj.Offset); |
267 | IO.mapRequired(Key: "LineStart" , Val&: Obj.LineStart); |
268 | IO.mapRequired(Key: "IsStatement" , Val&: Obj.IsStatement); |
269 | IO.mapRequired(Key: "EndDelta" , Val&: Obj.EndDelta); |
270 | } |
271 | |
272 | void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) { |
273 | IO.mapRequired(Key: "StartColumn" , Val&: Obj.StartColumn); |
274 | IO.mapRequired(Key: "EndColumn" , Val&: Obj.EndColumn); |
275 | } |
276 | |
277 | void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) { |
278 | IO.mapRequired(Key: "FileName" , Val&: Obj.FileName); |
279 | IO.mapRequired(Key: "Lines" , Val&: Obj.Lines); |
280 | IO.mapRequired(Key: "Columns" , Val&: Obj.Columns); |
281 | } |
282 | |
283 | void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) { |
284 | IO.mapRequired(Key: "LocalId" , Val&: Obj.Local); |
285 | IO.mapRequired(Key: "GlobalId" , Val&: Obj.Global); |
286 | } |
287 | |
288 | void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO, |
289 | YAMLCrossModuleImport &Obj) { |
290 | IO.mapRequired(Key: "Module" , Val&: Obj.ModuleName); |
291 | IO.mapRequired(Key: "Imports" , Val&: Obj.ImportIds); |
292 | } |
293 | |
294 | void MappingTraits<SourceFileChecksumEntry>::mapping( |
295 | IO &IO, SourceFileChecksumEntry &Obj) { |
296 | IO.mapRequired(Key: "FileName" , Val&: Obj.FileName); |
297 | IO.mapRequired(Key: "Kind" , Val&: Obj.Kind); |
298 | IO.mapRequired(Key: "Checksum" , Val&: Obj.ChecksumBytes); |
299 | } |
300 | |
301 | void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) { |
302 | IO.mapRequired(Key: "FileName" , Val&: Obj.FileName); |
303 | IO.mapRequired(Key: "LineNum" , Val&: Obj.SourceLineNum); |
304 | IO.mapRequired(Key: "Inlinee" , Val&: Obj.Inlinee); |
305 | IO.mapOptional(Key: "ExtraFiles" , Val&: Obj.ExtraFiles); |
306 | } |
307 | |
308 | void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) { |
309 | IO.mapRequired(Key: "CodeSize" , Val&: Obj.CodeSize); |
310 | IO.mapRequired(Key: "FrameFunc" , Val&: Obj.FrameFunc); |
311 | IO.mapRequired(Key: "LocalSize" , Val&: Obj.LocalSize); |
312 | IO.mapOptional(Key: "MaxStackSize" , Val&: Obj.MaxStackSize); |
313 | IO.mapOptional(Key: "ParamsSize" , Val&: Obj.ParamsSize); |
314 | IO.mapOptional(Key: "PrologSize" , Val&: Obj.PrologSize); |
315 | IO.mapOptional(Key: "RvaStart" , Val&: Obj.RvaStart); |
316 | IO.mapOptional(Key: "SavedRegsSize" , Val&: Obj.SavedRegsSize); |
317 | } |
318 | |
319 | void YAMLChecksumsSubsection::map(IO &IO) { |
320 | IO.mapTag(Tag: "!FileChecksums" , Default: true); |
321 | IO.mapRequired(Key: "Checksums" , Val&: Checksums); |
322 | } |
323 | |
324 | void YAMLLinesSubsection::map(IO &IO) { |
325 | IO.mapTag(Tag: "!Lines" , Default: true); |
326 | IO.mapRequired(Key: "CodeSize" , Val&: Lines.CodeSize); |
327 | |
328 | IO.mapRequired(Key: "Flags" , Val&: Lines.Flags); |
329 | IO.mapRequired(Key: "RelocOffset" , Val&: Lines.RelocOffset); |
330 | IO.mapRequired(Key: "RelocSegment" , Val&: Lines.RelocSegment); |
331 | IO.mapRequired(Key: "Blocks" , Val&: Lines.Blocks); |
332 | } |
333 | |
334 | void YAMLInlineeLinesSubsection::map(IO &IO) { |
335 | IO.mapTag(Tag: "!InlineeLines" , Default: true); |
336 | IO.mapRequired(Key: "HasExtraFiles" , Val&: InlineeLines.HasExtraFiles); |
337 | IO.mapRequired(Key: "Sites" , Val&: InlineeLines.Sites); |
338 | } |
339 | |
340 | void YAMLCrossModuleExportsSubsection::map(IO &IO) { |
341 | IO.mapTag(Tag: "!CrossModuleExports" , Default: true); |
342 | IO.mapOptional(Key: "Exports" , Val&: Exports); |
343 | } |
344 | |
345 | void YAMLCrossModuleImportsSubsection::map(IO &IO) { |
346 | IO.mapTag(Tag: "!CrossModuleImports" , Default: true); |
347 | IO.mapOptional(Key: "Imports" , Val&: Imports); |
348 | } |
349 | |
350 | void YAMLSymbolsSubsection::map(IO &IO) { |
351 | IO.mapTag(Tag: "!Symbols" , Default: true); |
352 | IO.mapRequired(Key: "Records" , Val&: Symbols); |
353 | } |
354 | |
355 | void YAMLStringTableSubsection::map(IO &IO) { |
356 | IO.mapTag(Tag: "!StringTable" , Default: true); |
357 | IO.mapRequired(Key: "Strings" , Val&: Strings); |
358 | } |
359 | |
360 | void YAMLFrameDataSubsection::map(IO &IO) { |
361 | IO.mapTag(Tag: "!FrameData" , Default: true); |
362 | IO.mapRequired(Key: "Frames" , Val&: Frames); |
363 | } |
364 | |
365 | void YAMLCoffSymbolRVASubsection::map(IO &IO) { |
366 | IO.mapTag(Tag: "!COFFSymbolRVAs" , Default: true); |
367 | IO.mapRequired(Key: "RVAs" , Val&: RVAs); |
368 | } |
369 | |
370 | void MappingTraits<YAMLDebugSubsection>::mapping( |
371 | IO &IO, YAMLDebugSubsection &Subsection) { |
372 | if (!IO.outputting()) { |
373 | if (IO.mapTag(Tag: "!FileChecksums" )) { |
374 | auto SS = std::make_shared<YAMLChecksumsSubsection>(); |
375 | Subsection.Subsection = SS; |
376 | } else if (IO.mapTag(Tag: "!Lines" )) { |
377 | Subsection.Subsection = std::make_shared<YAMLLinesSubsection>(); |
378 | } else if (IO.mapTag(Tag: "!InlineeLines" )) { |
379 | Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>(); |
380 | } else if (IO.mapTag(Tag: "!CrossModuleExports" )) { |
381 | Subsection.Subsection = |
382 | std::make_shared<YAMLCrossModuleExportsSubsection>(); |
383 | } else if (IO.mapTag(Tag: "!CrossModuleImports" )) { |
384 | Subsection.Subsection = |
385 | std::make_shared<YAMLCrossModuleImportsSubsection>(); |
386 | } else if (IO.mapTag(Tag: "!Symbols" )) { |
387 | Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>(); |
388 | } else if (IO.mapTag(Tag: "!StringTable" )) { |
389 | Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>(); |
390 | } else if (IO.mapTag(Tag: "!FrameData" )) { |
391 | Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>(); |
392 | } else if (IO.mapTag(Tag: "!COFFSymbolRVAs" )) { |
393 | Subsection.Subsection = std::make_shared<YAMLCoffSymbolRVASubsection>(); |
394 | } else { |
395 | llvm_unreachable("Unexpected subsection tag!" ); |
396 | } |
397 | } |
398 | Subsection.Subsection->map(IO); |
399 | } |
400 | |
401 | std::shared_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection( |
402 | BumpPtrAllocator &Allocator, |
403 | const codeview::StringsAndChecksums &SC) const { |
404 | assert(SC.hasStrings()); |
405 | auto Result = std::make_shared<DebugChecksumsSubsection>(args&: *SC.strings()); |
406 | for (const auto &CS : Checksums) { |
407 | Result->addChecksum(FileName: CS.FileName, Kind: CS.Kind, Bytes: CS.ChecksumBytes.Bytes); |
408 | } |
409 | return Result; |
410 | } |
411 | |
412 | std::shared_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection( |
413 | BumpPtrAllocator &Allocator, |
414 | const codeview::StringsAndChecksums &SC) const { |
415 | assert(SC.hasStrings() && SC.hasChecksums()); |
416 | auto Result = |
417 | std::make_shared<DebugLinesSubsection>(args&: *SC.checksums(), args&: *SC.strings()); |
418 | Result->setCodeSize(Lines.CodeSize); |
419 | Result->setRelocationAddress(Segment: Lines.RelocSegment, Offset: Lines.RelocOffset); |
420 | Result->setFlags(Lines.Flags); |
421 | for (const auto &LC : Lines.Blocks) { |
422 | Result->createBlock(FileName: LC.FileName); |
423 | if (Result->hasColumnInfo()) { |
424 | for (auto Item : zip(t: LC.Lines, u: LC.Columns)) { |
425 | auto &L = std::get<0>(t&: Item); |
426 | auto &C = std::get<1>(t&: Item); |
427 | uint32_t LE = L.LineStart + L.EndDelta; |
428 | Result->addLineAndColumnInfo(Offset: L.Offset, |
429 | Line: LineInfo(L.LineStart, LE, L.IsStatement), |
430 | ColStart: C.StartColumn, ColEnd: C.EndColumn); |
431 | } |
432 | } else { |
433 | for (const auto &L : LC.Lines) { |
434 | uint32_t LE = L.LineStart + L.EndDelta; |
435 | Result->addLineInfo(Offset: L.Offset, Line: LineInfo(L.LineStart, LE, L.IsStatement)); |
436 | } |
437 | } |
438 | } |
439 | return Result; |
440 | } |
441 | |
442 | std::shared_ptr<DebugSubsection> |
443 | YAMLInlineeLinesSubsection::toCodeViewSubsection( |
444 | BumpPtrAllocator &Allocator, |
445 | const codeview::StringsAndChecksums &SC) const { |
446 | assert(SC.hasChecksums()); |
447 | auto Result = std::make_shared<DebugInlineeLinesSubsection>( |
448 | args&: *SC.checksums(), args: InlineeLines.HasExtraFiles); |
449 | |
450 | for (const auto &Site : InlineeLines.Sites) { |
451 | Result->addInlineSite(FuncId: TypeIndex(Site.Inlinee), FileName: Site.FileName, |
452 | SourceLine: Site.SourceLineNum); |
453 | if (!InlineeLines.HasExtraFiles) |
454 | continue; |
455 | |
456 | for (auto EF : Site.ExtraFiles) { |
457 | Result->addExtraFile(FileName: EF); |
458 | } |
459 | } |
460 | return Result; |
461 | } |
462 | |
463 | std::shared_ptr<DebugSubsection> |
464 | YAMLCrossModuleExportsSubsection::toCodeViewSubsection( |
465 | BumpPtrAllocator &Allocator, |
466 | const codeview::StringsAndChecksums &SC) const { |
467 | auto Result = std::make_shared<DebugCrossModuleExportsSubsection>(); |
468 | for (const auto &M : Exports) |
469 | Result->addMapping(Local: M.Local, Global: M.Global); |
470 | return Result; |
471 | } |
472 | |
473 | std::shared_ptr<DebugSubsection> |
474 | YAMLCrossModuleImportsSubsection::toCodeViewSubsection( |
475 | BumpPtrAllocator &Allocator, |
476 | const codeview::StringsAndChecksums &SC) const { |
477 | assert(SC.hasStrings()); |
478 | |
479 | auto Result = |
480 | std::make_shared<DebugCrossModuleImportsSubsection>(args&: *SC.strings()); |
481 | for (const auto &M : Imports) { |
482 | for (const auto Id : M.ImportIds) |
483 | Result->addImport(Module: M.ModuleName, ImportId: Id); |
484 | } |
485 | return Result; |
486 | } |
487 | |
488 | std::shared_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection( |
489 | BumpPtrAllocator &Allocator, |
490 | const codeview::StringsAndChecksums &SC) const { |
491 | auto Result = std::make_shared<DebugSymbolsSubsection>(); |
492 | for (const auto &Sym : Symbols) |
493 | Result->addSymbol( |
494 | Symbol: Sym.toCodeViewSymbol(Allocator, Container: CodeViewContainer::ObjectFile)); |
495 | return Result; |
496 | } |
497 | |
498 | std::shared_ptr<DebugSubsection> |
499 | YAMLStringTableSubsection::toCodeViewSubsection( |
500 | BumpPtrAllocator &Allocator, |
501 | const codeview::StringsAndChecksums &SC) const { |
502 | auto Result = std::make_shared<DebugStringTableSubsection>(); |
503 | for (const auto &Str : this->Strings) |
504 | Result->insert(S: Str); |
505 | return Result; |
506 | } |
507 | |
508 | std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection( |
509 | BumpPtrAllocator &Allocator, |
510 | const codeview::StringsAndChecksums &SC) const { |
511 | assert(SC.hasStrings()); |
512 | |
513 | auto Result = std::make_shared<DebugFrameDataSubsection>(args: true); |
514 | for (const auto &YF : Frames) { |
515 | codeview::FrameData F; |
516 | F.CodeSize = YF.CodeSize; |
517 | F.Flags = YF.Flags; |
518 | F.LocalSize = YF.LocalSize; |
519 | F.MaxStackSize = YF.MaxStackSize; |
520 | F.ParamsSize = YF.ParamsSize; |
521 | F.PrologSize = YF.PrologSize; |
522 | F.RvaStart = YF.RvaStart; |
523 | F.SavedRegsSize = YF.SavedRegsSize; |
524 | F.FrameFunc = SC.strings()->insert(S: YF.FrameFunc); |
525 | Result->addFrameData(Frame: F); |
526 | } |
527 | return Result; |
528 | } |
529 | |
530 | std::shared_ptr<DebugSubsection> |
531 | YAMLCoffSymbolRVASubsection::toCodeViewSubsection( |
532 | BumpPtrAllocator &Allocator, |
533 | const codeview::StringsAndChecksums &SC) const { |
534 | auto Result = std::make_shared<DebugSymbolRVASubsection>(); |
535 | for (const auto &RVA : RVAs) |
536 | Result->addRVA(RVA); |
537 | return Result; |
538 | } |
539 | |
540 | static Expected<SourceFileChecksumEntry> |
541 | convertOneChecksum(const DebugStringTableSubsectionRef &Strings, |
542 | const FileChecksumEntry &CS) { |
543 | auto ExpectedString = Strings.getString(Offset: CS.FileNameOffset); |
544 | if (!ExpectedString) |
545 | return ExpectedString.takeError(); |
546 | |
547 | SourceFileChecksumEntry Result; |
548 | Result.ChecksumBytes.Bytes = CS.Checksum; |
549 | Result.Kind = CS.Kind; |
550 | Result.FileName = *ExpectedString; |
551 | return Result; |
552 | } |
553 | |
554 | static Expected<StringRef> |
555 | getFileName(const DebugStringTableSubsectionRef &Strings, |
556 | const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { |
557 | auto Iter = Checksums.getArray().at(Offset: FileID); |
558 | if (Iter == Checksums.getArray().end()) |
559 | return make_error<CodeViewError>(Args: cv_error_code::no_records); |
560 | uint32_t Offset = Iter->FileNameOffset; |
561 | return Strings.getString(Offset); |
562 | } |
563 | |
564 | Expected<std::shared_ptr<YAMLChecksumsSubsection>> |
565 | YAMLChecksumsSubsection::fromCodeViewSubsection( |
566 | const DebugStringTableSubsectionRef &Strings, |
567 | const DebugChecksumsSubsectionRef &FC) { |
568 | auto Result = std::make_shared<YAMLChecksumsSubsection>(); |
569 | |
570 | for (const auto &CS : FC) { |
571 | auto ConvertedCS = convertOneChecksum(Strings, CS); |
572 | if (!ConvertedCS) |
573 | return ConvertedCS.takeError(); |
574 | Result->Checksums.push_back(x: *ConvertedCS); |
575 | } |
576 | return Result; |
577 | } |
578 | |
579 | Expected<std::shared_ptr<YAMLLinesSubsection>> |
580 | YAMLLinesSubsection::fromCodeViewSubsection( |
581 | const DebugStringTableSubsectionRef &Strings, |
582 | const DebugChecksumsSubsectionRef &Checksums, |
583 | const DebugLinesSubsectionRef &Lines) { |
584 | auto Result = std::make_shared<YAMLLinesSubsection>(); |
585 | Result->Lines.CodeSize = Lines.header()->CodeSize; |
586 | Result->Lines.RelocOffset = Lines.header()->RelocOffset; |
587 | Result->Lines.RelocSegment = Lines.header()->RelocSegment; |
588 | Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags)); |
589 | for (const auto &L : Lines) { |
590 | SourceLineBlock Block; |
591 | auto EF = getFileName(Strings, Checksums, FileID: L.NameIndex); |
592 | if (!EF) |
593 | return EF.takeError(); |
594 | Block.FileName = *EF; |
595 | if (Lines.hasColumnInfo()) { |
596 | for (const auto &C : L.Columns) { |
597 | SourceColumnEntry SCE; |
598 | SCE.EndColumn = C.EndColumn; |
599 | SCE.StartColumn = C.StartColumn; |
600 | Block.Columns.push_back(x: SCE); |
601 | } |
602 | } |
603 | for (const auto &LN : L.LineNumbers) { |
604 | SourceLineEntry SLE; |
605 | LineInfo LI(LN.Flags); |
606 | SLE.Offset = LN.Offset; |
607 | SLE.LineStart = LI.getStartLine(); |
608 | SLE.EndDelta = LI.getLineDelta(); |
609 | SLE.IsStatement = LI.isStatement(); |
610 | Block.Lines.push_back(x: SLE); |
611 | } |
612 | Result->Lines.Blocks.push_back(x: Block); |
613 | } |
614 | return Result; |
615 | } |
616 | |
617 | Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> |
618 | YAMLInlineeLinesSubsection::fromCodeViewSubsection( |
619 | const DebugStringTableSubsectionRef &Strings, |
620 | const DebugChecksumsSubsectionRef &Checksums, |
621 | const DebugInlineeLinesSubsectionRef &Lines) { |
622 | auto Result = std::make_shared<YAMLInlineeLinesSubsection>(); |
623 | |
624 | Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles(); |
625 | for (const auto &IL : Lines) { |
626 | InlineeSite Site; |
627 | auto ExpF = getFileName(Strings, Checksums, FileID: IL.Header->FileID); |
628 | if (!ExpF) |
629 | return ExpF.takeError(); |
630 | Site.FileName = *ExpF; |
631 | Site.Inlinee = IL.Header->Inlinee.getIndex(); |
632 | Site.SourceLineNum = IL.Header->SourceLineNum; |
633 | if (Lines.hasExtraFiles()) { |
634 | for (const auto EF : IL.ExtraFiles) { |
635 | auto ExpF2 = getFileName(Strings, Checksums, FileID: EF); |
636 | if (!ExpF2) |
637 | return ExpF2.takeError(); |
638 | Site.ExtraFiles.push_back(x: *ExpF2); |
639 | } |
640 | } |
641 | Result->InlineeLines.Sites.push_back(x: Site); |
642 | } |
643 | return Result; |
644 | } |
645 | |
646 | Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> |
647 | YAMLCrossModuleExportsSubsection::fromCodeViewSubsection( |
648 | const DebugCrossModuleExportsSubsectionRef &Exports) { |
649 | auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>(); |
650 | Result->Exports.assign(first: Exports.begin(), last: Exports.end()); |
651 | return Result; |
652 | } |
653 | |
654 | Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> |
655 | YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( |
656 | const DebugStringTableSubsectionRef &Strings, |
657 | const DebugCrossModuleImportsSubsectionRef &Imports) { |
658 | auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>(); |
659 | for (const auto &CMI : Imports) { |
660 | YAMLCrossModuleImport YCMI; |
661 | auto ExpectedStr = Strings.getString(Offset: CMI.Header->ModuleNameOffset); |
662 | if (!ExpectedStr) |
663 | return ExpectedStr.takeError(); |
664 | YCMI.ModuleName = *ExpectedStr; |
665 | YCMI.ImportIds.assign(first: CMI.Imports.begin(), last: CMI.Imports.end()); |
666 | Result->Imports.push_back(x: YCMI); |
667 | } |
668 | return Result; |
669 | } |
670 | |
671 | Expected<std::shared_ptr<YAMLSymbolsSubsection>> |
672 | YAMLSymbolsSubsection::fromCodeViewSubsection( |
673 | const DebugSymbolsSubsectionRef &Symbols) { |
674 | auto Result = std::make_shared<YAMLSymbolsSubsection>(); |
675 | for (const auto &Sym : Symbols) { |
676 | auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Symbol: Sym); |
677 | if (!S) |
678 | return joinErrors(E1: make_error<CodeViewError>( |
679 | Args: cv_error_code::corrupt_record, |
680 | Args: "Invalid CodeView Symbol Record in SymbolRecord " |
681 | "subsection of .debug$S while converting to YAML!" ), |
682 | E2: S.takeError()); |
683 | |
684 | Result->Symbols.push_back(x: *S); |
685 | } |
686 | return Result; |
687 | } |
688 | |
689 | Expected<std::shared_ptr<YAMLStringTableSubsection>> |
690 | YAMLStringTableSubsection::fromCodeViewSubsection( |
691 | const DebugStringTableSubsectionRef &Strings) { |
692 | auto Result = std::make_shared<YAMLStringTableSubsection>(); |
693 | BinaryStreamReader Reader(Strings.getBuffer()); |
694 | StringRef S; |
695 | // First item is a single null string, skip it. |
696 | if (auto EC = Reader.readCString(Dest&: S)) |
697 | return std::move(EC); |
698 | assert(S.empty()); |
699 | while (Reader.bytesRemaining() > 0) { |
700 | if (auto EC = Reader.readCString(Dest&: S)) |
701 | return std::move(EC); |
702 | Result->Strings.push_back(x: S); |
703 | } |
704 | return Result; |
705 | } |
706 | |
707 | Expected<std::shared_ptr<YAMLFrameDataSubsection>> |
708 | YAMLFrameDataSubsection::fromCodeViewSubsection( |
709 | const DebugStringTableSubsectionRef &Strings, |
710 | const DebugFrameDataSubsectionRef &Frames) { |
711 | auto Result = std::make_shared<YAMLFrameDataSubsection>(); |
712 | for (const auto &F : Frames) { |
713 | YAMLFrameData YF; |
714 | YF.CodeSize = F.CodeSize; |
715 | YF.Flags = F.Flags; |
716 | YF.LocalSize = F.LocalSize; |
717 | YF.MaxStackSize = F.MaxStackSize; |
718 | YF.ParamsSize = F.ParamsSize; |
719 | YF.PrologSize = F.PrologSize; |
720 | YF.RvaStart = F.RvaStart; |
721 | YF.SavedRegsSize = F.SavedRegsSize; |
722 | |
723 | auto ES = Strings.getString(Offset: F.FrameFunc); |
724 | if (!ES) |
725 | return joinErrors( |
726 | E1: make_error<CodeViewError>( |
727 | Args: cv_error_code::no_records, |
728 | Args: "Could not find string for string id while mapping FrameData!" ), |
729 | E2: ES.takeError()); |
730 | YF.FrameFunc = *ES; |
731 | Result->Frames.push_back(x: YF); |
732 | } |
733 | return Result; |
734 | } |
735 | |
736 | Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>> |
737 | YAMLCoffSymbolRVASubsection::fromCodeViewSubsection( |
738 | const DebugSymbolRVASubsectionRef &Section) { |
739 | auto Result = std::make_shared<YAMLCoffSymbolRVASubsection>(); |
740 | for (const auto &RVA : Section) { |
741 | Result->RVAs.push_back(x: RVA); |
742 | } |
743 | return Result; |
744 | } |
745 | |
746 | Expected<std::vector<std::shared_ptr<DebugSubsection>>> |
747 | llvm::CodeViewYAML::toCodeViewSubsectionList( |
748 | BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections, |
749 | const codeview::StringsAndChecksums &SC) { |
750 | std::vector<std::shared_ptr<DebugSubsection>> Result; |
751 | if (Subsections.empty()) |
752 | return std::move(Result); |
753 | |
754 | for (const auto &SS : Subsections) { |
755 | std::shared_ptr<DebugSubsection> CVS; |
756 | CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC); |
757 | assert(CVS != nullptr); |
758 | Result.push_back(x: std::move(CVS)); |
759 | } |
760 | return std::move(Result); |
761 | } |
762 | |
763 | namespace { |
764 | |
765 | struct SubsectionConversionVisitor : public DebugSubsectionVisitor { |
766 | SubsectionConversionVisitor() = default; |
767 | |
768 | Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override; |
769 | Error visitLines(DebugLinesSubsectionRef &Lines, |
770 | const StringsAndChecksumsRef &State) override; |
771 | Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, |
772 | const StringsAndChecksumsRef &State) override; |
773 | Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, |
774 | const StringsAndChecksumsRef &State) override; |
775 | Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums, |
776 | const StringsAndChecksumsRef &State) override; |
777 | Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees, |
778 | const StringsAndChecksumsRef &State) override; |
779 | Error visitStringTable(DebugStringTableSubsectionRef &ST, |
780 | const StringsAndChecksumsRef &State) override; |
781 | Error visitSymbols(DebugSymbolsSubsectionRef &Symbols, |
782 | const StringsAndChecksumsRef &State) override; |
783 | Error visitFrameData(DebugFrameDataSubsectionRef &Symbols, |
784 | const StringsAndChecksumsRef &State) override; |
785 | Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols, |
786 | const StringsAndChecksumsRef &State) override; |
787 | |
788 | YAMLDebugSubsection Subsection; |
789 | }; |
790 | |
791 | } // end anonymous namespace |
792 | |
793 | Error SubsectionConversionVisitor::visitUnknown( |
794 | DebugUnknownSubsectionRef &Unknown) { |
795 | return make_error<CodeViewError>(Args: cv_error_code::operation_unsupported); |
796 | } |
797 | |
798 | Error SubsectionConversionVisitor::visitLines( |
799 | DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) { |
800 | auto Result = YAMLLinesSubsection::fromCodeViewSubsection( |
801 | Strings: State.strings(), Checksums: State.checksums(), Lines); |
802 | if (!Result) |
803 | return Result.takeError(); |
804 | Subsection.Subsection = *Result; |
805 | return Error::success(); |
806 | } |
807 | |
808 | Error SubsectionConversionVisitor::visitFileChecksums( |
809 | DebugChecksumsSubsectionRef &Checksums, |
810 | const StringsAndChecksumsRef &State) { |
811 | auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(Strings: State.strings(), |
812 | FC: Checksums); |
813 | if (!Result) |
814 | return Result.takeError(); |
815 | Subsection.Subsection = *Result; |
816 | return Error::success(); |
817 | } |
818 | |
819 | Error SubsectionConversionVisitor::visitInlineeLines( |
820 | DebugInlineeLinesSubsectionRef &Inlinees, |
821 | const StringsAndChecksumsRef &State) { |
822 | auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection( |
823 | Strings: State.strings(), Checksums: State.checksums(), Lines: Inlinees); |
824 | if (!Result) |
825 | return Result.takeError(); |
826 | Subsection.Subsection = *Result; |
827 | return Error::success(); |
828 | } |
829 | |
830 | Error SubsectionConversionVisitor::visitCrossModuleExports( |
831 | DebugCrossModuleExportsSubsectionRef &Exports, |
832 | const StringsAndChecksumsRef &State) { |
833 | auto Result = |
834 | YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports); |
835 | if (!Result) |
836 | return Result.takeError(); |
837 | Subsection.Subsection = *Result; |
838 | return Error::success(); |
839 | } |
840 | |
841 | Error SubsectionConversionVisitor::visitCrossModuleImports( |
842 | DebugCrossModuleImportsSubsectionRef &Imports, |
843 | const StringsAndChecksumsRef &State) { |
844 | auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( |
845 | Strings: State.strings(), Imports); |
846 | if (!Result) |
847 | return Result.takeError(); |
848 | Subsection.Subsection = *Result; |
849 | return Error::success(); |
850 | } |
851 | |
852 | Error SubsectionConversionVisitor::visitStringTable( |
853 | DebugStringTableSubsectionRef &Strings, |
854 | const StringsAndChecksumsRef &State) { |
855 | auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings); |
856 | if (!Result) |
857 | return Result.takeError(); |
858 | Subsection.Subsection = *Result; |
859 | return Error::success(); |
860 | } |
861 | |
862 | Error SubsectionConversionVisitor::visitSymbols( |
863 | DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) { |
864 | auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols); |
865 | if (!Result) |
866 | return Result.takeError(); |
867 | Subsection.Subsection = *Result; |
868 | return Error::success(); |
869 | } |
870 | |
871 | Error SubsectionConversionVisitor::visitFrameData( |
872 | DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) { |
873 | auto Result = |
874 | YAMLFrameDataSubsection::fromCodeViewSubsection(Strings: State.strings(), Frames); |
875 | if (!Result) |
876 | return Result.takeError(); |
877 | Subsection.Subsection = *Result; |
878 | return Error::success(); |
879 | } |
880 | |
881 | Error SubsectionConversionVisitor::visitCOFFSymbolRVAs( |
882 | DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) { |
883 | auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(Section: RVAs); |
884 | if (!Result) |
885 | return Result.takeError(); |
886 | Subsection.Subsection = *Result; |
887 | return Error::success(); |
888 | } |
889 | |
890 | Expected<YAMLDebugSubsection> |
891 | YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC, |
892 | const DebugSubsectionRecord &SS) { |
893 | SubsectionConversionVisitor V; |
894 | if (auto EC = visitDebugSubsection(R: SS, V, State: SC)) |
895 | return std::move(EC); |
896 | |
897 | return V.Subsection; |
898 | } |
899 | |
900 | std::vector<YAMLDebugSubsection> |
901 | llvm::CodeViewYAML::fromDebugS(ArrayRef<uint8_t> Data, |
902 | const StringsAndChecksumsRef &SC) { |
903 | BinaryStreamReader Reader(Data, llvm::endianness::little); |
904 | uint32_t Magic; |
905 | |
906 | ExitOnError Err("Invalid .debug$S section!" ); |
907 | Err(Reader.readInteger(Dest&: Magic)); |
908 | assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!" ); |
909 | |
910 | DebugSubsectionArray Subsections; |
911 | Err(Reader.readArray(Array&: Subsections, Size: Reader.bytesRemaining())); |
912 | |
913 | std::vector<YAMLDebugSubsection> Result; |
914 | |
915 | for (const auto &SS : Subsections) { |
916 | auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS)); |
917 | Result.push_back(x: YamlSS); |
918 | } |
919 | return Result; |
920 | } |
921 | |
922 | void llvm::CodeViewYAML::initializeStringsAndChecksums( |
923 | ArrayRef<YAMLDebugSubsection> Sections, codeview::StringsAndChecksums &SC) { |
924 | // String Table and Checksums subsections don't use the allocator. |
925 | BumpPtrAllocator Allocator; |
926 | |
927 | // It's possible for checksums and strings to even appear in different debug$S |
928 | // sections, so we have to make this a stateful function that can build up |
929 | // the strings and checksums field over multiple iterations. |
930 | |
931 | // File Checksums require the string table, but may become before it, so we |
932 | // have to scan for strings first, then scan for checksums again from the |
933 | // beginning. |
934 | if (!SC.hasStrings()) { |
935 | for (const auto &SS : Sections) { |
936 | if (SS.Subsection->Kind != DebugSubsectionKind::StringTable) |
937 | continue; |
938 | |
939 | auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC); |
940 | SC.setStrings( |
941 | std::static_pointer_cast<DebugStringTableSubsection>(r: Result)); |
942 | break; |
943 | } |
944 | } |
945 | |
946 | if (SC.hasStrings() && !SC.hasChecksums()) { |
947 | for (const auto &SS : Sections) { |
948 | if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums) |
949 | continue; |
950 | |
951 | auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC); |
952 | SC.setChecksums( |
953 | std::static_pointer_cast<DebugChecksumsSubsection>(r: Result)); |
954 | break; |
955 | } |
956 | } |
957 | } |
958 | |