llvm.org GIT mirror llvm / 63d2fab
Resubmit "[codeview] Make obj2yaml/yaml2obj support .debug$S..." This was originally reverted because of some non-deterministic failures on certain buildbots. Luckily ASAN eventually caught this as a stack-use-after-scope, so the fix is included in this patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305393 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
28 changed file(s) with 590 addition(s) and 339 deletion(s). Raw diff Collapse all Expand all
4848 Error commit(BinaryStreamWriter &Writer) const override;
4949
5050 void addFrameData(const FrameData &Frame);
51 void setFrames(ArrayRef Frames);
5152
5253 private:
5354 std::vector Frames;
4848
4949 class DebugSubsectionRecordBuilder {
5050 public:
51 DebugSubsectionRecordBuilder(std::unique_ptr Subsection,
51 DebugSubsectionRecordBuilder(std::shared_ptr Subsection,
5252 CodeViewContainer Container);
5353 uint32_t calculateSerializedLength();
5454 Error commit(BinaryStreamWriter &Writer) const;
5555
5656 private:
57 std::unique_ptr Subsection;
57 std::shared_ptr Subsection;
5858 CodeViewContainer Container;
5959 };
6060
6363 template <> struct VarStreamArrayExtractor {
6464 Error operator()(BinaryStreamRef Stream, uint32_t &Length,
6565 codeview::DebugSubsectionRecord &Info) {
66 // FIXME: We need to pass the container type through to this function. In
67 // practice this isn't super important since the subsection header describes
68 // its length and we can just skip it. It's more important when writing.
6669 if (auto EC = codeview::DebugSubsectionRecord::initialize(
6770 Stream, Info, codeview::CodeViewContainer::Pdb))
6871 return EC;
1111
1212 #include "llvm/DebugInfo/CodeView/CodeView.h"
1313 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
14 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
1415 #include "llvm/Support/Error.h"
1516 #include
1617
2930 class DebugSymbolRVASubsectionRef;
3031 class DebugSymbolsSubsectionRef;
3132 class DebugUnknownSubsectionRef;
32
33 struct DebugSubsectionState {
34 public:
35 // If no subsections are known about initially, we find as much as we can.
36 DebugSubsectionState();
37
38 // If only a string table subsection is given, we find a checksums subsection.
39 explicit DebugSubsectionState(const DebugStringTableSubsectionRef &Strings);
40
41 // If both subsections are given, we don't need to find anything.
42 DebugSubsectionState(const DebugStringTableSubsectionRef &Strings,
43 const DebugChecksumsSubsectionRef &Checksums);
44
45 template void initialize(T &&FragmentRange) {
46 for (const DebugSubsectionRecord &R : FragmentRange) {
47 if (Strings && Checksums)
48 return;
49 if (R.kind() == DebugSubsectionKind::FileChecksums) {
50 initializeChecksums(R);
51 continue;
52 }
53 if (R.kind() == DebugSubsectionKind::StringTable && !Strings) {
54 // While in practice we should never encounter a string table even
55 // though the string table is already initialized, in theory it's
56 // possible. PDBs are supposed to have one global string table and
57 // then this subsection should not appear. Whereas object files are
58 // supposed to have this subsection appear exactly once. However,
59 // for testing purposes it's nice to be able to test this subsection
60 // independently of one format or the other, so for some tests we
61 // manually construct a PDB that contains this subsection in addition
62 // to a global string table.
63 initializeStrings(R);
64 continue;
65 }
66 }
67 }
68
69 const DebugStringTableSubsectionRef &strings() const { return *Strings; }
70 const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; }
71
72 private:
73 void initializeStrings(const DebugSubsectionRecord &SR);
74 void initializeChecksums(const DebugSubsectionRecord &FCR);
75
76 std::unique_ptr OwnedStrings;
77 std::unique_ptr OwnedChecksums;
78
79 const DebugStringTableSubsectionRef *Strings = nullptr;
80 const DebugChecksumsSubsectionRef *Checksums = nullptr;
81 };
33 class StringsAndChecksumsRef;
8234
8335 class DebugSubsectionVisitor {
8436 public:
8840 return Error::success();
8941 }
9042 virtual Error visitLines(DebugLinesSubsectionRef &Lines,
91 const DebugSubsectionState &State) = 0;
43 const StringsAndChecksumsRef &State) = 0;
9244 virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
93 const DebugSubsectionState &State) = 0;
45 const StringsAndChecksumsRef &State) = 0;
9446 virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
95 const DebugSubsectionState &State) = 0;
47 const StringsAndChecksumsRef &State) = 0;
9648 virtual Error
9749 visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
98 const DebugSubsectionState &State) = 0;
50 const StringsAndChecksumsRef &State) = 0;
9951 virtual Error
10052 visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE,
101 const DebugSubsectionState &State) = 0;
53 const StringsAndChecksumsRef &State) = 0;
10254
10355 virtual Error visitStringTable(DebugStringTableSubsectionRef &ST,
104 const DebugSubsectionState &State) = 0;
56 const StringsAndChecksumsRef &State) = 0;
10557
10658 virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE,
107 const DebugSubsectionState &State) = 0;
59 const StringsAndChecksumsRef &State) = 0;
10860
10961 virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD,
110 const DebugSubsectionState &State) = 0;
62 const StringsAndChecksumsRef &State) = 0;
11163 virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs,
112 const DebugSubsectionState &State) = 0;
64 const StringsAndChecksumsRef &State) = 0;
11365 };
11466
11567 Error visitDebugSubsection(const DebugSubsectionRecord &R,
11668 DebugSubsectionVisitor &V,
117 const DebugSubsectionState &State);
69 const StringsAndChecksumsRef &State);
11870
11971 namespace detail {
12072 template
12173 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
122 DebugSubsectionState &State) {
74 StringsAndChecksumsRef &State) {
12375 State.initialize(std::forward(FragmentRange));
12476
12577 for (const DebugSubsectionRecord &L : FragmentRange) {
13284
13385 template
13486 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
135 DebugSubsectionState State;
87 StringsAndChecksumsRef State;
13688 return detail::visitDebugSubsections(std::forward(FragmentRange), V,
13789 State);
13890 }
14092 template
14193 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
14294 const DebugStringTableSubsectionRef &Strings) {
143 DebugSubsectionState State(Strings);
95 StringsAndChecksumsRef State(Strings);
14496 return detail::visitDebugSubsections(std::forward(FragmentRange), V,
14597 State);
14698 }
149101 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
150102 const DebugStringTableSubsectionRef &Strings,
151103 const DebugChecksumsSubsectionRef &Checksums) {
152 DebugSubsectionState State(Strings, Checksums);
104 StringsAndChecksumsRef State(Strings, Checksums);
153105 return detail::visitDebugSubsections(std::forward(FragmentRange), V,
154106 State);
155107 }
0 //===- StringsAndChecksums.h ------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGS_AND_CHECKSUMS_H
10 #define LLVM_DEBUGINFO_CODEVIEW_STRINGS_AND_CHECKSUMS_H
11
12 #include "llvm/DebugInfo/CodeView/CodeView.h"
13 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
14
15 #include
16
17 namespace llvm {
18 namespace codeview {
19
20 class DebugSubsectionRecord;
21 class DebugChecksumsSubsectionRef;
22 class DebugStringTableSubsectionRef;
23 class DebugChecksumsSubsection;
24 class DebugStringTableSubsection;
25
26 class StringsAndChecksumsRef {
27 public:
28 // If no subsections are known about initially, we find as much as we can.
29 StringsAndChecksumsRef();
30
31 // If only a string table subsection is given, we find a checksums subsection.
32 explicit StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings);
33
34 // If both subsections are given, we don't need to find anything.
35 StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings,
36 const DebugChecksumsSubsectionRef &Checksums);
37
38 template void initialize(T &&FragmentRange) {
39 for (const DebugSubsectionRecord &R : FragmentRange) {
40 if (Strings && Checksums)
41 return;
42 if (R.kind() == DebugSubsectionKind::FileChecksums) {
43 initializeChecksums(R);
44 continue;
45 }
46 if (R.kind() == DebugSubsectionKind::StringTable && !Strings) {
47 // While in practice we should never encounter a string table even
48 // though the string table is already initialized, in theory it's
49 // possible. PDBs are supposed to have one global string table and
50 // then this subsection should not appear. Whereas object files are
51 // supposed to have this subsection appear exactly once. However,
52 // for testing purposes it's nice to be able to test this subsection
53 // independently of one format or the other, so for some tests we
54 // manually construct a PDB that contains this subsection in addition
55 // to a global string table.
56 initializeStrings(R);
57 continue;
58 }
59 }
60 }
61
62 const DebugStringTableSubsectionRef &strings() const { return *Strings; }
63 const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; }
64
65 bool hasStrings() const { return Strings != nullptr; }
66 bool hasChecksums() const { return Checksums != nullptr; }
67
68 private:
69 void initializeStrings(const DebugSubsectionRecord &SR);
70 void initializeChecksums(const DebugSubsectionRecord &FCR);
71
72 std::unique_ptr OwnedStrings;
73 std::unique_ptr OwnedChecksums;
74
75 const DebugStringTableSubsectionRef *Strings = nullptr;
76 const DebugChecksumsSubsectionRef *Checksums = nullptr;
77 };
78
79 class StringsAndChecksums {
80 public:
81 using StringsPtr = std::shared_ptr;
82 using ChecksumsPtr = std::shared_ptr;
83 // If no subsections are known about initially, we find as much as we can.
84 StringsAndChecksums() {}
85
86 void setStrings(const StringsPtr &SP) { Strings = SP; }
87 void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; }
88
89 const StringsPtr &strings() const { return Strings; }
90 const ChecksumsPtr &checksums() const { return Checksums; }
91
92 bool hasStrings() const { return Strings != nullptr; }
93 bool hasChecksums() const { return Checksums != nullptr; }
94
95 private:
96 StringsPtr Strings;
97 ChecksumsPtr Checksums;
98 };
99
100 } // namespace codeview
101 } // namespace llvm
102
103 #endif
4949 void addSymbol(codeview::CVSymbol Symbol);
5050
5151 void
52 addDebugSubsection(std::unique_ptr Subsection);
52 addDebugSubsection(std::shared_ptr Subsection);
5353
5454 uint16_t getStreamIndex() const;
5555 StringRef getModuleName() const { return ModuleName; }
4444
4545 FixedStreamArray name_ids() const;
4646
47 codeview::DebugStringTableSubsectionRef getStringTable() const;
47 const codeview::DebugStringTableSubsectionRef &getStringTable() const;
4848
4949 private:
5050 Error readHeader(BinaryStreamReader &Reader);
4040 uint32_t calculateSerializedSize() const;
4141 Error commit(BinaryStreamWriter &Writer) const;
4242
43 codeview::DebugStringTableSubsection &getStrings() { return Strings; }
44 const codeview::DebugStringTableSubsection &getStrings() const {
45 return Strings;
46 }
43 void setStrings(const codeview::DebugStringTableSubsection &Strings);
4744
4845 private:
4946 uint32_t calculateHashTableSize() const;
1515
1616 #include "llvm/ADT/Optional.h"
1717 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
19 #include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
1820 #include "llvm/ObjectYAML/YAML.h"
1921
2022 namespace llvm {
5557 COFF::section Header;
5658 unsigned Alignment = 0;
5759 yaml::BinaryRef SectionData;
60 std::vector DebugS;
61 std::vector DebugT;
5862 std::vector Relocations;
5963 StringRef Name;
6064 Section();
2727 class DebugChecksumsSubsectionRef;
2828 class DebugStringTableSubsection;
2929 class DebugChecksumsSubsection;
30 class StringsAndChecksums;
31 class StringsAndChecksumsRef;
3032 }
3133 namespace CodeViewYAML {
3234
102104
103105 struct YAMLDebugSubsection {
104106 static Expected
105 fromCodeViewSubection(const codeview::DebugStringTableSubsectionRef &Strings,
106 const codeview::DebugChecksumsSubsectionRef &Checksums,
107 fromCodeViewSubection(const codeview::StringsAndChecksumsRef &SC,
107108 const codeview::DebugSubsectionRecord &SS);
108109
109110 std::shared_ptr Subsection;
110111 };
111112
112 Expected>>
113 struct DebugSubsectionState {};
114
115 Expected>>
113116 toCodeViewSubsectionList(BumpPtrAllocator &Allocator,
114117 ArrayRef Subsections,
115 codeview::DebugStringTableSubsection &Strings);
116 Expected>>
117 toCodeViewSubsectionList(
118 BumpPtrAllocator &Allocator, ArrayRef Subsections,
119 std::unique_ptr &TakeStrings,
120 codeview::DebugStringTableSubsection *StringsRef);
118 const codeview::StringsAndChecksums &SC);
121119
122 std::unique_ptr
123 findStringTable(ArrayRef Sections);
120 std::vector
121 fromDebugS(ArrayRef Data, const codeview::StringsAndChecksumsRef &SC);
122
123 void initializeStringsAndChecksums(ArrayRef Sections,
124 codeview::StringsAndChecksums &SC);
124125
125126 } // namespace CodeViewYAML
126127 } // namespace llvm
4040 codeview::CVType toCodeViewRecord(codeview::TypeTableBuilder &TS) const;
4141 static Expected fromCodeViewRecord(codeview::CVType Type);
4242 };
43
44 std::vector fromDebugT(ArrayRef DebugT);
45 ArrayRef toDebugT(ArrayRef, BumpPtrAllocator &Alloc);
4346 } // namespace CodeViewYAML
4447 } // namespace llvm
4548
1919 LazyRandomTypeCollection.cpp
2020 Line.cpp
2121 RecordSerialization.cpp
22 StringsAndChecksums.cpp
2223 SymbolRecordMapping.cpp
2324 SymbolDumper.cpp
2425 SymbolSerializer.cpp
3132 TypeSerializer.cpp
3233 TypeStreamMerger.cpp
3334 TypeTableCollection.cpp
34
35
3536 ADDITIONAL_HEADER_DIRS
3637 ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
3738 )
5757 uint32_t Begin = Writer.getOffset();
5858 uint32_t End = Begin + StringSize;
5959
60 // Write a null string at the beginning.
61 if (auto EC = Writer.writeCString(StringRef()))
62 return EC;
63
6064 for (auto &Pair : Strings) {
6165 StringRef S = Pair.getKey();
6266 uint32_t Offset = Begin + Pair.getValue();
6771 }
6872
6973 Writer.setOffset(End);
74 assert((End - Begin) == StringSize);
7075 return Error::success();
7176 }
7277
4949 BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
5050
5151 DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
52 std::unique_ptr Subsection, CodeViewContainer Container)
52 std::shared_ptr Subsection, CodeViewContainer Container)
5353 : Subsection(std::move(Subsection)), Container(Container) {}
5454
5555 uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
2525 using namespace llvm;
2626 using namespace llvm::codeview;
2727
28 DebugSubsectionState::DebugSubsectionState() {}
29
30 DebugSubsectionState::DebugSubsectionState(
31 const DebugStringTableSubsectionRef &Strings)
32 : Strings(&Strings) {}
33
34 DebugSubsectionState::DebugSubsectionState(
35 const DebugStringTableSubsectionRef &Strings,
36 const DebugChecksumsSubsectionRef &Checksums)
37 : Strings(&Strings), Checksums(&Checksums) {}
38
39 void DebugSubsectionState::initializeStrings(const DebugSubsectionRecord &SR) {
40 assert(SR.kind() == DebugSubsectionKind::StringTable);
41 assert(!Strings && "Found a string table even though we already have one!");
42
43 OwnedStrings = llvm::make_unique();
44 consumeError(OwnedStrings->initialize(SR.getRecordData()));
45 Strings = OwnedStrings.get();
46 }
47
48 void DebugSubsectionState::initializeChecksums(
49 const DebugSubsectionRecord &FCR) {
50 assert(FCR.kind() == DebugSubsectionKind::FileChecksums);
51 if (Checksums)
52 return;
53
54 OwnedChecksums = llvm::make_unique();
55 consumeError(OwnedChecksums->initialize(FCR.getRecordData()));
56 Checksums = OwnedChecksums.get();
57 }
58
59 Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R,
60 DebugSubsectionVisitor &V,
61 const DebugSubsectionState &State) {
28 Error llvm::codeview::visitDebugSubsection(
29 const DebugSubsectionRecord &R, DebugSubsectionVisitor &V,
30 const StringsAndChecksumsRef &State) {
6231 BinaryStreamReader Reader(R.getRecordData());
6332 switch (R.kind()) {
6433 case DebugSubsectionKind::Lines: {
0 //===- StringsAndChecksums.cpp ----------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
10 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
11 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
12 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
13
14 using namespace llvm;
15 using namespace llvm::codeview;
16
17 StringsAndChecksumsRef::StringsAndChecksumsRef() {}
18
19 StringsAndChecksumsRef::StringsAndChecksumsRef(
20 const DebugStringTableSubsectionRef &Strings)
21 : Strings(&Strings) {}
22
23 StringsAndChecksumsRef::StringsAndChecksumsRef(
24 const DebugStringTableSubsectionRef &Strings,
25 const DebugChecksumsSubsectionRef &Checksums)
26 : Strings(&Strings), Checksums(&Checksums) {}
27
28 void StringsAndChecksumsRef::initializeStrings(
29 const DebugSubsectionRecord &SR) {
30 assert(SR.kind() == DebugSubsectionKind::StringTable);
31 assert(!Strings && "Found a string table even though we already have one!");
32
33 OwnedStrings = llvm::make_unique();
34 consumeError(OwnedStrings->initialize(SR.getRecordData()));
35 Strings = OwnedStrings.get();
36 }
37
38 void StringsAndChecksumsRef::initializeChecksums(
39 const DebugSubsectionRecord &FCR) {
40 assert(FCR.kind() == DebugSubsectionKind::FileChecksums);
41 if (Checksums)
42 return;
43
44 OwnedChecksums = llvm::make_unique();
45 consumeError(OwnedChecksums->initialize(FCR.getRecordData()));
46 Checksums = OwnedChecksums.get();
47 }
176176 }
177177
178178 void DbiModuleDescriptorBuilder::addDebugSubsection(
179 std::unique_ptr Subsection) {
179 std::shared_ptr Subsection) {
180180 assert(Subsection);
181181 C13Builders.push_back(llvm::make_unique(
182182 std::move(Subsection), CodeViewContainer::Pdb));
5555 return Error::success();
5656 }
5757
58 codeview::DebugStringTableSubsectionRef PDBStringTable::getStringTable() const {
58 const codeview::DebugStringTableSubsectionRef &
59 PDBStringTable::getStringTable() const {
5960 return Strings;
6061 }
6162
4949 Size += calculateHashTableSize();
5050 Size += sizeof(uint32_t); // The /names stream ends with the string count.
5151 return Size;
52 }
53
54 void PDBStringTableBuilder::setStrings(
55 const codeview::DebugStringTableSubsection &Strings) {
56 this->Strings = Strings;
5257 }
5358
5459 Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
487487 IO.mapOptional("VirtualAddress", Sec.Header.VirtualAddress, 0U);
488488 IO.mapOptional("VirtualSize", Sec.Header.VirtualSize, 0U);
489489 IO.mapOptional("Alignment", Sec.Alignment, 0U);
490 IO.mapRequired("SectionData", Sec.SectionData);
490
491 // If this is a .debug$S or .debug$T section parse the semantic representation
492 // of the symbols/types. If it is any other kind of section, just deal in raw
493 // bytes.
494 IO.mapOptional("SectionData", Sec.SectionData);
495 if (Sec.Name == ".debug$S")
496 IO.mapOptional("Subsections", Sec.DebugS);
497 else if (Sec.Name == ".debug$T")
498 IO.mapOptional("Types", Sec.DebugT);
499
491500 IO.mapOptional("Relocations", Sec.Relocations);
492501 }
493502
2727 #include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
2828 #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
2929 #include "llvm/DebugInfo/CodeView/EnumTables.h"
30 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
3031 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
3132 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
3233 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
7475 virtual ~YAMLSubsectionBase() {}
7576
7677 virtual void map(IO &IO) = 0;
77 virtual std::unique_ptr
78 virtual std::shared_ptr
7879 toCodeViewSubsection(BumpPtrAllocator &Allocator,
79 DebugStringTableSubsection *UseStrings,
80 DebugChecksumsSubsection *UseChecksums) const = 0;
80 const codeview::StringsAndChecksums &SC) const = 0;
8181 };
8282 }
8383 }
8989 : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
9090
9191 void map(IO &IO) override;
92 std::unique_ptr
92 std::shared_ptr
9393 toCodeViewSubsection(BumpPtrAllocator &Allocator,
94 DebugStringTableSubsection *Strings,
95 DebugChecksumsSubsection *Checksums) const override;
94 const codeview::StringsAndChecksums &SC) const override;
9695 static Expected>
9796 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
9897 const DebugChecksumsSubsectionRef &FC);
104103 YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
105104
106105 void map(IO &IO) override;
107 std::unique_ptr
106 std::shared_ptr
108107 toCodeViewSubsection(BumpPtrAllocator &Allocator,
109 DebugStringTableSubsection *Strings,
110 DebugChecksumsSubsection *Checksums) const override;
108 const codeview::StringsAndChecksums &SC) const override;
111109 static Expected>
112110 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
113111 const DebugChecksumsSubsectionRef &Checksums,
121119 : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
122120
123121 void map(IO &IO) override;
124 std::unique_ptr
122 std::shared_ptr
125123 toCodeViewSubsection(BumpPtrAllocator &Allocator,
126 DebugStringTableSubsection *Strings,
127 DebugChecksumsSubsection *Checksums) const override;
124 const codeview::StringsAndChecksums &SC) const override;
128125 static Expected>
129126 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
130127 const DebugChecksumsSubsectionRef &Checksums,
138135 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
139136
140137 void map(IO &IO) override;
141 std::unique_ptr
138 std::shared_ptr
142139 toCodeViewSubsection(BumpPtrAllocator &Allocator,
143 DebugStringTableSubsection *Strings,
144 DebugChecksumsSubsection *Checksums) const override;
140 const codeview::StringsAndChecksums &SC) const override;
145141 static Expected>
146142 fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
147143
153149 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
154150
155151 void map(IO &IO) override;
156 std::unique_ptr
152 std::shared_ptr
157153 toCodeViewSubsection(BumpPtrAllocator &Allocator,
158 DebugStringTableSubsection *Strings,
159 DebugChecksumsSubsection *Checksums) const override;
154 const codeview::StringsAndChecksums &SC) const override;
160155 static Expected>
161156 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
162157 const DebugCrossModuleImportsSubsectionRef &Imports);
168163 YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
169164
170165 void map(IO &IO) override;
171 std::unique_ptr
166 std::shared_ptr
172167 toCodeViewSubsection(BumpPtrAllocator &Allocator,
173 DebugStringTableSubsection *Strings,
174 DebugChecksumsSubsection *Checksums) const override;
168 const codeview::StringsAndChecksums &SC) const override;
175169 static Expected>
176170 fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
177171
183177 : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
184178
185179 void map(IO &IO) override;
186 std::unique_ptr
180 std::shared_ptr
187181 toCodeViewSubsection(BumpPtrAllocator &Allocator,
188 DebugStringTableSubsection *Strings,
189 DebugChecksumsSubsection *Checksums) const override;
182 const codeview::StringsAndChecksums &SC) const override;
190183 static Expected>
191184 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
192185
198191 : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
199192
200193 void map(IO &IO) override;
201 std::unique_ptr
194 std::shared_ptr
202195 toCodeViewSubsection(BumpPtrAllocator &Allocator,
203 DebugStringTableSubsection *Strings,
204 DebugChecksumsSubsection *Checksums) const override;
196 const codeview::StringsAndChecksums &SC) const override;
205197 static Expected>
206198 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
207199 const DebugFrameDataSubsectionRef &Frames);
214206 : YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {}
215207
216208 void map(IO &IO) override;
217 std::unique_ptr
209 std::shared_ptr
218210 toCodeViewSubsection(BumpPtrAllocator &Allocator,
219 DebugStringTableSubsection *Strings,
220 DebugChecksumsSubsection *Checksums) const override;
211 const codeview::StringsAndChecksums &SC) const override;
221212 static Expected>
222213 fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs);
223214
388379 Subsection.Subsection->map(IO);
389380 }
390381
391 static std::shared_ptr
392 findChecksums(ArrayRef Subsections) {
393 for (const auto &SS : Subsections) {
394 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
395 return std::static_pointer_cast(SS.Subsection);
396 }
397 }
398
399 return nullptr;
400 }
401
402 std::unique_ptr YAMLChecksumsSubsection::toCodeViewSubsection(
403 BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
404 DebugChecksumsSubsection *UseChecksums) const {
405 assert(UseStrings && !UseChecksums);
406 auto Result = llvm::make_unique(*UseStrings);
382 std::shared_ptr YAMLChecksumsSubsection::toCodeViewSubsection(
383 BumpPtrAllocator &Allocator,
384 const codeview::StringsAndChecksums &SC) const {
385 assert(SC.hasStrings());
386 auto Result = std::make_shared(*SC.strings());
407387 for (const auto &CS : Checksums) {
408388 Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
409389 }
410 return std::move(Result);
411 }
412
413 std::unique_ptr YAMLLinesSubsection::toCodeViewSubsection(
414 BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
415 DebugChecksumsSubsection *UseChecksums) const {
416 assert(UseStrings && UseChecksums);
390 return Result;
391 }
392
393 std::shared_ptr YAMLLinesSubsection::toCodeViewSubsection(
394 BumpPtrAllocator &Allocator,
395 const codeview::StringsAndChecksums &SC) const {
396 assert(SC.hasStrings() && SC.hasChecksums());
417397 auto Result =
418 llvm::make_unique(*UseChecksums, *UseStrings);
398 std::make_shared(*SC.checksums(), *SC.strings());
419399 Result->setCodeSize(Lines.CodeSize);
420400 Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
421401 Result->setFlags(Lines.Flags);
437417 }
438418 }
439419 }
440 return llvm::cast(std::move(Result));
441 }
442
443 std::unique_ptr
420 return Result;
421 }
422
423 std::shared_ptr
444424 YAMLInlineeLinesSubsection::toCodeViewSubsection(
445 BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
446 DebugChecksumsSubsection *UseChecksums) const {
447 assert(UseChecksums);
448 auto Result = llvm::make_unique(
449 *UseChecksums, InlineeLines.HasExtraFiles);
425 BumpPtrAllocator &Allocator,
426 const codeview::StringsAndChecksums &SC) const {
427 assert(SC.hasChecksums());
428 auto Result = std::make_shared(
429 *SC.checksums(), InlineeLines.HasExtraFiles);
450430
451431 for (const auto &Site : InlineeLines.Sites) {
452432 Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
458438 Result->addExtraFile(EF);
459439 }
460440 }
461 return llvm::cast(std::move(Result));
462 }
463
464 std::unique_ptr
441 return Result;
442 }
443
444 std::shared_ptr
465445 YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
466 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
467 DebugChecksumsSubsection *Checksums) const {
468 auto Result = llvm::make_unique();
446 BumpPtrAllocator &Allocator,
447 const codeview::StringsAndChecksums &SC) const {
448 auto Result = std::make_shared();
469449 for (const auto &M : Exports)
470450 Result->addMapping(M.Local, M.Global);
471 return llvm::cast(std::move(Result));
472 }
473
474 std::unique_ptr
451 return Result;
452 }
453
454 std::shared_ptr
475455 YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
476 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
477 DebugChecksumsSubsection *Checksums) const {
478 auto Result = llvm::make_unique(*Strings);
456 BumpPtrAllocator &Allocator,
457 const codeview::StringsAndChecksums &SC) const {
458 assert(SC.hasStrings());
459
460 auto Result =
461 std::make_shared(*SC.strings());
479462 for (const auto &M : Imports) {
480463 for (const auto Id : M.ImportIds)
481464 Result->addImport(M.ModuleName, Id);
482465 }
483 return llvm::cast(std::move(Result));
484 }
485
486 std::unique_ptr YAMLSymbolsSubsection::toCodeViewSubsection(
487 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
488 DebugChecksumsSubsection *Checksums) const {
489 auto Result = llvm::make_unique();
466 return Result;
467 }
468
469 std::shared_ptr YAMLSymbolsSubsection::toCodeViewSubsection(
470 BumpPtrAllocator &Allocator,
471 const codeview::StringsAndChecksums &SC) const {
472 auto Result = std::make_shared();
490473 for (const auto &Sym : Symbols)
491474 Result->addSymbol(
492475 Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
493 return std::move(Result);
494 }
495
496 std::unique_ptr
476 return Result;
477 }
478
479 std::shared_ptr
497480 YAMLStringTableSubsection::toCodeViewSubsection(
498 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
499 DebugChecksumsSubsection *Checksums) const {
500 auto Result = llvm::make_unique();
481 BumpPtrAllocator &Allocator,
482 const codeview::StringsAndChecksums &SC) const {
483 auto Result = std::make_shared();
501484 for (const auto &Str : this->Strings)
502485 Result->insert(Str);
503 return std::move(Result);
504 }
505
506 std::unique_ptr YAMLFrameDataSubsection::toCodeViewSubsection(
507 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
508 DebugChecksumsSubsection *Checksums) const {
509 assert(Strings);
510 auto Result = llvm::make_unique();
486 return Result;
487 }
488
489 std::shared_ptr YAMLFrameDataSubsection::toCodeViewSubsection(
490 BumpPtrAllocator &Allocator,
491 const codeview::StringsAndChecksums &SC) const {
492 assert(SC.hasStrings());
493
494 auto Result = std::make_shared();
511495 for (const auto &YF : Frames) {
512496 codeview::FrameData F;
513497 F.CodeSize = YF.CodeSize;
518502 F.PrologSize = YF.PrologSize;
519503 F.RvaStart = YF.RvaStart;
520504 F.SavedRegsSize = YF.SavedRegsSize;
521 F.FrameFunc = Strings->insert(YF.FrameFunc);
505 F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
522506 Result->addFrameData(F);
523507 }
524 return std::move(Result);
525 }
526
527 std::unique_ptr
508 return Result;
509 }
510
511 std::shared_ptr
528512 YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
529 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
530 DebugChecksumsSubsection *Checksums) const {
531 auto Result = llvm::make_unique();
513 BumpPtrAllocator &Allocator,
514 const codeview::StringsAndChecksums &SC) const {
515 auto Result = std::make_shared();
532516 for (const auto &RVA : RVAs)
533517 Result->addRVA(RVA);
534 return std::move(Result);
518 return Result;
535519 }
536520
537521 static Expected
740724 return Result;
741725 }
742726
743 Expectedunique_ptr>>
727 Expectedshared_ptr>>
744728 llvm::CodeViewYAML::toCodeViewSubsectionList(
745729 BumpPtrAllocator &Allocator, ArrayRef Subsections,
746 DebugStringTableSubsection &Strings) {
747 std::vector> Result;
730 const codeview::StringsAndChecksums &SC) {
731 std::vector> Result;
748732 if (Subsections.empty())
749733 return std::move(Result);
750734
751 auto Checksums = findChecksums(Subsections);
752 std::unique_ptr ChecksumsBase;
753 if (Checksums)
754 ChecksumsBase =
755 Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr);
756 DebugChecksumsSubsection *CS =
757 static_cast(ChecksumsBase.get());
758735 for (const auto &SS : Subsections) {
759 // We've already converted the checksums subsection, don't do it
760 // twice.
761 std::unique_ptr CVS;
762 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
763 CVS = std::move(ChecksumsBase);
764 else
765 CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS);
766 assert(CVS != nullptr);
767 Result.push_back(std::move(CVS));
768 }
769 return std::move(Result);
770 }
771
772 Expected>>
773 llvm::CodeViewYAML::toCodeViewSubsectionList(
774 BumpPtrAllocator &Allocator, ArrayRef Subsections,
775 std::unique_ptr &TakeStrings,
776 DebugStringTableSubsection *StringsRef) {
777 std::vector> Result;
778 if (Subsections.empty())
779 return std::move(Result);
780
781 auto Checksums = findChecksums(Subsections);
782
783 std::unique_ptr ChecksumsBase;
784 if (Checksums)
785 ChecksumsBase =
786 Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr);
787 DebugChecksumsSubsection *CS =
788 static_cast(ChecksumsBase.get());
789 for (const auto &SS : Subsections) {
790 // We've already converted the checksums and string table subsection, don't
791 // do it twice.
792 std::unique_ptr CVS;
793 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
794 CVS = std::move(ChecksumsBase);
795 else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) {
796 assert(TakeStrings && "No string table!");
797 CVS = std::move(TakeStrings);
798 } else
799 CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS);
736 std::shared_ptr CVS;
737 CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
800738 assert(CVS != nullptr);
801739 Result.push_back(std::move(CVS));
802740 }
809747
810748 Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
811749 Error visitLines(DebugLinesSubsectionRef &Lines,
812 const DebugSubsectionState &State) override;
750 const StringsAndChecksumsRef &State) override;
813751 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
814 const DebugSubsectionState &State) override;
752 const StringsAndChecksumsRef &State) override;
815753 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
816 const DebugSubsectionState &State) override;
754 const StringsAndChecksumsRef &State) override;
817755 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
818 const DebugSubsectionState &State) override;
756 const StringsAndChecksumsRef &State) override;
819757 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
820 const DebugSubsectionState &State) override;
758 const StringsAndChecksumsRef &State) override;
821759 Error visitStringTable(DebugStringTableSubsectionRef &ST,
822 const DebugSubsectionState &State) override;
760 const StringsAndChecksumsRef &State) override;
823761 Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
824 const DebugSubsectionState &State) override;
762 const StringsAndChecksumsRef &State) override;
825763 Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
826 const DebugSubsectionState &State) override;
764 const StringsAndChecksumsRef &State) override;
827765 Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols,
828 const DebugSubsectionState &State) override;
766 const StringsAndChecksumsRef &State) override;
829767
830768 YAMLDebugSubsection Subsection;
831769 };
836774 }
837775
838776 Error SubsectionConversionVisitor::visitLines(
839 DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) {
777 DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) {
840778 auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
841779 State.strings(), State.checksums(), Lines);
842780 if (!Result)
846784 }
847785
848786 Error SubsectionConversionVisitor::visitFileChecksums(
849 DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) {
787 DebugChecksumsSubsectionRef &Checksums,
788 const StringsAndChecksumsRef &State) {
850789 auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
851790 Checksums);
852791 if (!Result)
857796
858797 Error SubsectionConversionVisitor::visitInlineeLines(
859798 DebugInlineeLinesSubsectionRef &Inlinees,
860 const DebugSubsectionState &State) {
799 const StringsAndChecksumsRef &State) {
861800 auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
862801 State.strings(), State.checksums(), Inlinees);
863802 if (!Result)
868807
869808 Error SubsectionConversionVisitor::visitCrossModuleExports(
870809 DebugCrossModuleExportsSubsectionRef &Exports,
871 const DebugSubsectionState &State) {
810 const StringsAndChecksumsRef &State) {
872811 auto Result =
873812 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
874813 if (!Result)
879818
880819 Error SubsectionConversionVisitor::visitCrossModuleImports(
881820 DebugCrossModuleImportsSubsectionRef &Imports,
882 const DebugSubsectionState &State) {
821 const StringsAndChecksumsRef &State) {
883822 auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
884823 State.strings(), Imports);
885824 if (!Result)
889828 }
890829
891830 Error SubsectionConversionVisitor::visitStringTable(
892 DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) {
831 DebugStringTableSubsectionRef &Strings,
832 const StringsAndChecksumsRef &State) {
893833 auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
894834 if (!Result)
895835 return Result.takeError();
898838 }
899839
900840 Error SubsectionConversionVisitor::visitSymbols(
901 DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) {
841 DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
902842 auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
903843 if (!Result)
904844 return Result.takeError();
907847 }
908848
909849 Error SubsectionConversionVisitor::visitFrameData(
910 DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) {
850 DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) {
911851 auto Result =
912852 YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
913853 if (!Result)
917857 }
918858
919859 Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
920 DebugSymbolRVASubsectionRef &RVAs, const DebugSubsectionState &State) {
860 DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) {
921861 auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs);
922862 if (!Result)
923863 return Result.takeError();
926866 }
927867 }
928868
929 Expected YAMLDebugSubsection::fromCodeViewSubection(
930 const DebugStringTableSubsectionRef &Strings,
931 const DebugChecksumsSubsectionRef &Checksums,
932 const DebugSubsectionRecord &SS) {
933 DebugSubsectionState State(Strings, Checksums);
869 Expected
870 YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC,
871 const DebugSubsectionRecord &SS) {
934872 SubsectionConversionVisitor V;
935 if (auto EC = visitDebugSubsection(SS, V, State))
873 if (auto EC = visitDebugSubsection(SS, V, SC))
936874 return std::move(EC);
937875
938876 return V.Subsection;
939877 }
940878
941 std::unique_ptr
942 llvm::CodeViewYAML::findStringTable(ArrayRef Sections) {
943 for (const auto &SS : Sections) {
944 if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
945 continue;
946
947 // String Table doesn't use the allocator.
948 BumpPtrAllocator Allocator;
949 auto Result =
950 SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr);
951 return llvm::cast(std::move(Result));
952 }
953 return nullptr;
954 }
879 std::vector
880 llvm::CodeViewYAML::fromDebugS(ArrayRef Data,
881 const StringsAndChecksumsRef &SC) {
882 BinaryStreamReader Reader(Data, support::little);
883 uint32_t Magic;
884
885 ExitOnError Err("Invalid .debug$S section!");
886 Err(Reader.readInteger(Magic));
887 assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
888
889 DebugSubsectionArray Subsections;
890 Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
891
892 std::vector Result;
893
894 for (const auto &SS : Subsections) {
895 auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
896 Result.push_back(YamlSS);
897 }
898 return Result;
899 }
900
901 void llvm::CodeViewYAML::initializeStringsAndChecksums(
902 ArrayRef Sections, codeview::StringsAndChecksums &SC) {
903 // String Table and Checksums subsections don't use the allocator.
904 BumpPtrAllocator Allocator;
905
906 // It's possible for checksums and strings to even appear in different debug$S
907 // sections, so we have to make this a stateful function that can build up
908 // the strings and checksums field over multiple iterations.
909
910 // File Checksums require the string table, but may become before it, so we
911 // have to scan for strings first, then scan for checksums again from the
912 // beginning.
913 if (!SC.hasStrings()) {
914 for (const auto &SS : Sections) {
915 if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
916 continue;
917
918 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
919 SC.setStrings(
920 std::static_pointer_cast(Result));
921 break;
922 }
923 }
924
925 if (SC.hasStrings() && !SC.hasChecksums()) {
926 for (const auto &SS : Sections) {
927 if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
928 continue;
929
930 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
931 SC.setChecksums(
932 std::static_pointer_cast(Result));
933 break;
934 }
935 }
936 }
713713 default: { llvm_unreachable("Unknown member kind!"); }
714714 }
715715 }
716
717 std::vector
718 llvm::CodeViewYAML::fromDebugT(ArrayRef DebugT) {
719 ExitOnError Err("Invalid .debug$T section!");
720 BinaryStreamReader Reader(DebugT, support::little);
721 CVTypeArray Types;
722 uint32_t Magic;
723
724 Err(Reader.readInteger(Magic));
725 assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$T section!");
726
727 std::vector Result;
728 Err(Reader.readArray(Types, Reader.bytesRemaining()));
729 for (const auto &T : Types) {
730 auto CVT = Err(LeafRecord::fromCodeViewRecord(T));
731 Result.push_back(CVT);
732 }
733 return Result;
734 }
735
736 ArrayRef llvm::CodeViewYAML::toDebugT(ArrayRef Leafs,
737 BumpPtrAllocator &Alloc) {
738 TypeTableBuilder TTB(Alloc, false);
739 uint32_t Size = sizeof(uint32_t);
740 for (const auto &Leaf : Leafs) {
741 CVType T = Leaf.toCodeViewRecord(TTB);
742 Size += T.length();
743 assert(T.length() % 4 == 0 && "Improper type record alignment!");
744 }
745 uint8_t *ResultBuffer = Alloc.Allocate(Size);
746 MutableArrayRef Output(ResultBuffer, Size);
747 BinaryStreamWriter Writer(Output, support::little);
748 ExitOnError Err("Error writing type record to .debug$T section");
749 Err(Writer.writeInteger(COFF::DEBUG_SECTION_MAGIC));
750 for (const auto &R : TTB.records()) {
751 Err(Writer.writeBytes(R));
752 }
753 assert(Writer.bytesRemaining() == 0 && "Didn't write all type record bytes!");
754 return Output;
755 }
2727 #include "llvm/DebugInfo/CodeView/EnumTables.h"
2828 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
2929 #include "llvm/DebugInfo/CodeView/Line.h"
30 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
3031 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
3132 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
3233 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
104105 }
105106
106107 Error visitLines(DebugLinesSubsectionRef &Lines,
107 const DebugSubsectionState &State) override {
108 const StringsAndChecksumsRef &State) override {
108109 if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines))
109110 return Error::success();
110111
145146 }
146147
147148 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
148 const DebugSubsectionState &State) override {
149 const StringsAndChecksumsRef &State) override {
149150 if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums))
150151 return Error::success();
151152
163164 }
164165
165166 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
166 const DebugSubsectionState &State) override {
167 const StringsAndChecksumsRef &State) override {
167168 if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines))
168169 return Error::success();
169170
190191 }
191192
192193 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
193 const DebugSubsectionState &State) override {
194 const StringsAndChecksumsRef &State) override {
194195 if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports))
195196 return Error::success();
196197
204205 }
205206
206207 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI,
207 const DebugSubsectionState &State) override {
208 const StringsAndChecksumsRef &State) override {
208209 if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports))
209210 return Error::success();
210211
221222 }
222223
223224 Error visitFrameData(DebugFrameDataSubsectionRef &FD,
224 const DebugSubsectionState &State) override {
225 const StringsAndChecksumsRef &State) override {
225226 if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData))
226227 return Error::success();
227228
247248 }
248249
249250 Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
250 const DebugSubsectionState &State) override {
251 const StringsAndChecksumsRef &State) override {
251252 if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols))
252253 return Error::success();
253254 ListScope L(P, "Symbols");
269270 }
270271
271272 Error visitStringTable(DebugStringTableSubsectionRef &Strings,
272 const DebugSubsectionState &State) override {
273 const StringsAndChecksumsRef &State) override {
273274 if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable))
274275 return Error::success();
275276
287288 }
288289
289290 Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs,
290 const DebugSubsectionState &State) override {
291 const StringsAndChecksumsRef &State) override {
291292 if (!opts::checkModuleSubsection(opts::ModuleSubsection::CoffSymbolRVAs))
292293 return Error::success();
293294
308309 return EC;
309310 }
310311 }
311
312
312313 if (!Success) {
313314 P.printString(
314315 llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
317318 return Error::success();
318319 }
319320 Error printFileName(StringRef Label, uint32_t Offset,
320 const DebugSubsectionState &State) {
321 const StringsAndChecksumsRef &State) {
321322 if (auto Result = getNameFromChecksumsBuffer(Offset, State)) {
322323 P.printString(Label, *Result);
323324 return Error::success();
326327 }
327328
328329 Expected
329 getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) {
330 getNameFromStringTable(uint32_t Offset, const StringsAndChecksumsRef &State) {
330331 return State.strings().getString(Offset);
331332 }
332333
333334 Expected
334335 getNameFromChecksumsBuffer(uint32_t Offset,
335 const DebugSubsectionState &State) {
336 const StringsAndChecksumsRef &State) {
336337 auto Array = State.checksums().getArray();
337338 auto ChecksumIter = Array.at(Offset);
338339 if (ChecksumIter == Array.end())
1717 #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
1818 #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
1919 #include "llvm/DebugInfo/CodeView/Line.h"
20 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
2021 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
2122 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
2223 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
235236 if (!ExpectedChecksums)
236237 return ExpectedChecksums.takeError();
237238
239 StringsAndChecksumsRef SC(ExpectedST->getStringTable(),
240 *ExpectedChecksums);
241
238242 for (const auto &SS : ModS.subsections()) {
239243 opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind());
240244 if (!opts::checkModuleSubsection(OptionKind))
241245 continue;
242246
243247 auto Converted =
244 CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(
245 ExpectedST->getStringTable(), *ExpectedChecksums, SS);
248 CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(SC, SS);
246249 if (!Converted)
247250 return Converted.takeError();
248251 DMI.Subsections.push_back(*Converted);
3434 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
3535 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
3636 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
37 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
3738 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
3839 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
3940 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
510511 for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
511512 ExitOnErr(Builder.getMsfBuilder().addStream(0));
512513
514 StringsAndChecksums Strings;
515 Strings.setStrings(std::make_shared());
516
513517 if (YamlObj.StringTable.hasValue()) {
514 auto &Strings = Builder.getStringTableBuilder();
515518 for (auto S : *YamlObj.StringTable)
516 Strings.insert(S);
519 Strings.strings()->insert(S);
517520 }
518521
519522 pdb::yaml::PdbInfoStream DefaultInfoStream;
530533 InfoBuilder.setVersion(Info.Version);
531534 for (auto F : Info.Features)
532535 InfoBuilder.addFeature(F);
533
534 auto &Strings = Builder.getStringTableBuilder().getStrings();
535536
536537 const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
537538 auto &DbiBuilder = Builder.getDbiBuilder();
556557 }
557558 }
558559
560 // Each module has its own checksum subsection, so scan for it every time.
561 Strings.setChecksums(nullptr);
562 CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
563
559564 auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
560565 Allocator, MI.Subsections, Strings));
561566 for (auto &SS : CodeViewSubsections) {
562 ModiBuilder.addDebugSubsection(std::move(SS));
567 ModiBuilder.addDebugSubsection(SS);
563568 }
564569 }
565570
578583 CVType Type = R.toCodeViewRecord(Allocator);
579584 IpiBuilder.addTypeRecord(Type.RecordData, None);
580585 }
586
587 Builder.getStringTableBuilder().setStrings(*Strings.strings());
581588
582589 ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
583590 }
0 set(LLVM_LINK_COMPONENTS
1 DebugInfoCodeView
12 DebugInfoDWARF
23 Object
34 ObjectYAML
77 //===----------------------------------------------------------------------===//
88
99 #include "obj2yaml.h"
10 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
11 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
12 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
1013 #include "llvm/Object/COFF.h"
1114 #include "llvm/ObjectYAML/COFFYAML.h"
15 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
16 #include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
1217 #include "llvm/Support/ErrorHandling.h"
1318 #include "llvm/Support/YAMLTraits.h"
1419
98103 YAMLObj.Header.Characteristics = Obj.getCharacteristics();
99104 }
100105
106 static void
107 initializeFileAndStringTable(const llvm::object::COFFObjectFile &Obj,
108 codeview::StringsAndChecksumsRef &SC) {
109
110 ExitOnError Err("Invalid .debug$S section!");
111 // Iterate all .debug$S sections looking for the checksums and string table.
112 // Exit as soon as both sections are found.
113 for (const auto &S : Obj.sections()) {
114 if (SC.hasStrings() && SC.hasChecksums())
115 break;
116
117 StringRef SectionName;
118 S.getName(SectionName);
119 ArrayRef sectionData;
120 if (SectionName != ".debug$S")
121 continue;
122
123 const object::coff_section *COFFSection = Obj.getCOFFSection(S);
124
125 Obj.getSectionContents(COFFSection, sectionData);
126
127 BinaryStreamReader Reader(sectionData, support::little);
128 uint32_t Magic;
129
130 Err(Reader.readInteger(Magic));
131 assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
132
133 codeview::DebugSubsectionArray Subsections;
134 Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
135
136 SC.initialize(Subsections);
137 }
138 }
139
101140 void COFFDumper::dumpSections(unsigned NumSections) {
102141 std::vector &YAMLSections = YAMLObj.Sections;
142 codeview::StringsAndChecksumsRef SC;
143 initializeFileAndStringTable(Obj, SC);
144
103145 for (const auto &ObjSection : Obj.sections()) {
104146 const object::coff_section *COFFSection = Obj.getCOFFSection(ObjSection);
105147 COFFYAML::Section NewYAMLSection;
107149 NewYAMLSection.Header.Characteristics = COFFSection->Characteristics;
108150 NewYAMLSection.Header.VirtualAddress = ObjSection.getAddress();
109151 NewYAMLSection.Header.VirtualSize = COFFSection->VirtualSize;
152 NewYAMLSection.Header.NumberOfLineNumbers =
153 COFFSection->NumberOfLinenumbers;
154 NewYAMLSection.Header.NumberOfRelocations =
155 COFFSection->NumberOfRelocations;
156 NewYAMLSection.Header.PointerToLineNumbers =
157 COFFSection->PointerToLinenumbers;
158 NewYAMLSection.Header.PointerToRawData = COFFSection->PointerToRawData;
159 NewYAMLSection.Header.PointerToRelocations =
160 COFFSection->PointerToRelocations;
161 NewYAMLSection.Header.SizeOfRawData = COFFSection->SizeOfRawData;
110162 NewYAMLSection.Alignment = ObjSection.getAlignment();
111163 assert(NewYAMLSection.Alignment <= 8192);
112164
114166 if (!ObjSection.isBSS())
115167 Obj.getSectionContents(COFFSection, sectionData);
116168 NewYAMLSection.SectionData = yaml::BinaryRef(sectionData);
169
170 if (NewYAMLSection.Name == ".debug$S")
171 NewYAMLSection.DebugS = CodeViewYAML::fromDebugS(sectionData, SC);
172 else if (NewYAMLSection.Name == ".debug$T")
173 NewYAMLSection.DebugT = CodeViewYAML::fromDebugT(sectionData);
117174
118175 std::vector Relocations;
119176 for (const auto &Reloc : ObjSection.relocations()) {
0 set(LLVM_LINK_COMPONENTS
1 DebugInfoCodeView
12 MC
23 Object
34 ObjectYAML
1616 #include "llvm/ADT/StringExtras.h"
1717 #include "llvm/ADT/StringMap.h"
1818 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
20 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
1921 #include "llvm/Object/COFF.h"
2022 #include "llvm/ObjectYAML/ObjectYAML.h"
2123 #include "llvm/Support/Endian.h"
141143
142144 COFFYAML::Object &Obj;
143145
146 codeview::StringsAndChecksums StringsAndChecksums;
147 BumpPtrAllocator Allocator;
144148 StringMap StringTableMap;
145149 std::string StringTable;
146150 uint32_t SectionTableStart;
164168 enum { DOSStubSize = 128 };
165169 }
166170
171 static yaml::BinaryRef
172 toDebugS(ArrayRef Subsections,
173 const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator) {
174 using namespace codeview;
175 ExitOnError Err("Error occurred writing .debug$S section");
176 auto CVSS =
177 Err(CodeViewYAML::toCodeViewSubsectionList(Allocator, Subsections, SC));
178
179 std::vector Builders;
180 uint32_t Size = sizeof(uint32_t);
181 for (auto &SS : CVSS) {
182 DebugSubsectionRecordBuilder B(SS, CodeViewContainer::ObjectFile);
183 Size += B.calculateSerializedLength();
184 Builders.push_back(std::move(B));
185 }
186 uint8_t *Buffer = Allocator.Allocate(Size);
187 MutableArrayRef Output(Buffer, Size);
188 BinaryStreamWriter Writer(Output, support::little);
189
190 Err(Writer.writeInteger(COFF::DEBUG_SECTION_MAGIC));
191 for (const auto &B : Builders) {
192 Err(B.commit(Writer));
193 }
194 return {Output};
195 }
196
167197 // Take a CP and assign addresses and sizes to everything. Returns false if the
168198 // layout is not valid to do.
169199 static bool layoutCOFF(COFFParser &CP) {
178208 uint32_t CurrentSectionDataOffset =
179209 CP.SectionTableStart + CP.SectionTableSize;
180210
211 for (COFFYAML::Section &S : CP.Obj.Sections) {
212 // We support specifying exactly one of SectionData or Subsections. So if
213 // there is already some SectionData, then we don't need to do any of this.
214 if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) {
215 CodeViewYAML::initializeStringsAndChecksums(S.DebugS,
216 CP.StringsAndChecksums);
217 if (CP.StringsAndChecksums.hasChecksums() &&
218 CP.StringsAndChecksums.hasStrings())
219 break;
220 }
221 }
222
181223 // Assign each section data address consecutively.
182224 for (COFFYAML::Section &S : CP.Obj.Sections) {
225 if (S.Name == ".debug$S") {
226 if (S.SectionData.binary_size() == 0) {
227 assert(CP.StringsAndChecksums.hasStrings() &&
228 "Object file does not have debug string table!");
229
230 S.SectionData =
231 toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator);
232 }
233 } else if (S.Name == ".debug$T") {
234 if (S.SectionData.binary_size() == 0)
235 S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator);
236 }
237
183238 if (S.SectionData.binary_size() > 0) {
184239 CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset,
185240 CP.isPE() ? CP.getFileAlignment() : 4);
542597 errs() << "yaml2obj: Failed to layout optional header for COFF file!\n";
543598 return 1;
544599 }
600
545601 if (!layoutCOFF(CP)) {
546602 errs() << "yaml2obj: Failed to layout COFF file!\n";
547603 return 1;