llvm.org GIT mirror llvm / 16e473d
[codeview] Make obj2yaml/yaml2obj support .debug$S/T sections. This allows us to use yaml2obj and obj2yaml to round-trip CodeView symbol and type information without having to manually specify the bytes of the section. This makes for much easier to maintain tests. See the tests under lld/COFF in this patch for example. Before they just said SectionData: <blob> whereas now we can use meaningful record descriptions. Note that it still supports the SectionData yaml field, which could be useful for initializing a section to invalid bytes for testing, for example. Differential Revision: https://reviews.llvm.org/D34127 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305366 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
24 changed file(s) with 595 addition(s) and 311 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;
2929 class DebugSymbolRVASubsectionRef;
3030 class DebugSymbolsSubsectionRef;
3131 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 };
32 class StringsAndChecksumsRef;
8233
8334 class DebugSubsectionVisitor {
8435 public:
8839 return Error::success();
8940 }
9041 virtual Error visitLines(DebugLinesSubsectionRef &Lines,
91 const DebugSubsectionState &State) = 0;
42 const StringsAndChecksumsRef &State) = 0;
9243 virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
93 const DebugSubsectionState &State) = 0;
44 const StringsAndChecksumsRef &State) = 0;
9445 virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
95 const DebugSubsectionState &State) = 0;
46 const StringsAndChecksumsRef &State) = 0;
9647 virtual Error
9748 visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
98 const DebugSubsectionState &State) = 0;
49 const StringsAndChecksumsRef &State) = 0;
9950 virtual Error
10051 visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE,
101 const DebugSubsectionState &State) = 0;
52 const StringsAndChecksumsRef &State) = 0;
10253
10354 virtual Error visitStringTable(DebugStringTableSubsectionRef &ST,
104 const DebugSubsectionState &State) = 0;
55 const StringsAndChecksumsRef &State) = 0;
10556
10657 virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE,
107 const DebugSubsectionState &State) = 0;
58 const StringsAndChecksumsRef &State) = 0;
10859
10960 virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD,
110 const DebugSubsectionState &State) = 0;
61 const StringsAndChecksumsRef &State) = 0;
11162 virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs,
112 const DebugSubsectionState &State) = 0;
63 const StringsAndChecksumsRef &State) = 0;
11364 };
11465
11566 Error visitDebugSubsection(const DebugSubsectionRecord &R,
11667 DebugSubsectionVisitor &V,
117 const DebugSubsectionState &State);
68 const StringsAndChecksumsRef &State);
11869
11970 namespace detail {
12071 template
12172 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
122 DebugSubsectionState &State) {
73 StringsAndChecksumsRef &State) {
12374 State.initialize(std::forward(FragmentRange));
12475
12576 for (const DebugSubsectionRecord &L : FragmentRange) {
13283
13384 template
13485 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
135 DebugSubsectionState State;
86 StringsAndChecksumsRef State;
13687 return detail::visitDebugSubsections(std::forward(FragmentRange), V,
13788 State);
13889 }
14091 template
14192 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
14293 const DebugStringTableSubsectionRef &Strings) {
143 DebugSubsectionState State(Strings);
94 StringsAndChecksumsRef State(Strings);
14495 return detail::visitDebugSubsections(std::forward(FragmentRange), V,
14596 State);
14697 }
149100 Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
150101 const DebugStringTableSubsectionRef &Strings,
151102 const DebugChecksumsSubsectionRef &Checksums) {
152 DebugSubsectionState State(Strings, Checksums);
103 StringsAndChecksumsRef State(Strings, Checksums);
153104 return detail::visitDebugSubsections(std::forward(FragmentRange), V,
154105 State);
155106 }
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
14 #include
15
16 namespace llvm {
17 namespace codeview {
18
19 class DebugSubsectionRecord;
20 class DebugChecksumsSubsectionRef;
21 class DebugStringTableSubsectionRef;
22 class DebugChecksumsSubsection;
23 class DebugStringTableSubsection;
24
25 class StringsAndChecksumsRef {
26 public:
27 // If no subsections are known about initially, we find as much as we can.
28 StringsAndChecksumsRef();
29
30 // If only a string table subsection is given, we find a checksums subsection.
31 explicit StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings);
32
33 // If both subsections are given, we don't need to find anything.
34 StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings,
35 const DebugChecksumsSubsectionRef &Checksums);
36
37 template void initialize(T &&FragmentRange) {
38 for (const DebugSubsectionRecord &R : FragmentRange) {
39 if (Strings && Checksums)
40 return;
41 if (R.kind() == DebugSubsectionKind::FileChecksums) {
42 initializeChecksums(R);
43 continue;
44 }
45 if (R.kind() == DebugSubsectionKind::StringTable && !Strings) {
46 // While in practice we should never encounter a string table even
47 // though the string table is already initialized, in theory it's
48 // possible. PDBs are supposed to have one global string table and
49 // then this subsection should not appear. Whereas object files are
50 // supposed to have this subsection appear exactly once. However,
51 // for testing purposes it's nice to be able to test this subsection
52 // independently of one format or the other, so for some tests we
53 // manually construct a PDB that contains this subsection in addition
54 // to a global string table.
55 initializeStrings(R);
56 continue;
57 }
58 }
59 }
60
61 const DebugStringTableSubsectionRef &strings() const { return *Strings; }
62 const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; }
63
64 bool hasStrings() const { return Strings != nullptr; }
65 bool hasChecksums() const { return Checksums != nullptr; }
66
67 private:
68 void initializeStrings(const DebugSubsectionRecord &SR);
69 void initializeChecksums(const DebugSubsectionRecord &FCR);
70
71 std::unique_ptr OwnedStrings;
72 std::unique_ptr OwnedChecksums;
73
74 const DebugStringTableSubsectionRef *Strings = nullptr;
75 const DebugChecksumsSubsectionRef *Checksums = nullptr;
76 };
77
78 class StringsAndChecksums {
79 public:
80 using StringsPtr = std::shared_ptr;
81 using ChecksumsPtr = std::shared_ptr;
82 // If no subsections are known about initially, we find as much as we can.
83 StringsAndChecksums() {}
84
85 void setStrings(const StringsPtr &SP) { Strings = SP; }
86 void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; }
87
88 const StringsPtr &strings() const { return Strings; }
89 const ChecksumsPtr &checksums() const { return Checksums; }
90
91 bool hasStrings() const { return Strings != nullptr; }
92 bool hasChecksums() const { return Checksums != nullptr; }
93
94 private:
95 StringsPtr Strings;
96 ChecksumsPtr Checksums;
97 };
98
99 } // namespace codeview
100 } // namespace llvm
101
102 #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; }
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));
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
399390 return nullptr;
400391 }
401392
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);
393 std::shared_ptr YAMLChecksumsSubsection::toCodeViewSubsection(
394 BumpPtrAllocator &Allocator,
395 const codeview::StringsAndChecksums &SC) const {
396 assert(SC.hasStrings());
397 auto Result = std::make_shared(*SC.strings());
407398 for (const auto &CS : Checksums) {
408399 Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
409400 }
410401 return std::move(Result);
411402 }
412403
413 std::unique_ptr YAMLLinesSubsection::toCodeViewSubsection(
414 BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
415 DebugChecksumsSubsection *UseChecksums) const {
416 assert(UseStrings && UseChecksums);
404 std::shared_ptr YAMLLinesSubsection::toCodeViewSubsection(
405 BumpPtrAllocator &Allocator,
406 const codeview::StringsAndChecksums &SC) const {
407 assert(SC.hasStrings() && SC.hasChecksums());
417408 auto Result =
418 llvm::make_unique(*UseChecksums, *UseStrings);
409 std::make_shared(*SC.checksums(), *SC.strings());
419410 Result->setCodeSize(Lines.CodeSize);
420411 Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
421412 Result->setFlags(Lines.Flags);
437428 }
438429 }
439430 }
440 return llvm::cast(std::move(Result));
441 }
442
443 std::unique_ptr
431 return std::move(Result);
432 }
433
434 std::shared_ptr
444435 YAMLInlineeLinesSubsection::toCodeViewSubsection(
445 BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
446 DebugChecksumsSubsection *UseChecksums) const {
447 assert(UseChecksums);
448 auto Result = llvm::make_unique(
449 *UseChecksums, InlineeLines.HasExtraFiles);
436 BumpPtrAllocator &Allocator,
437 const codeview::StringsAndChecksums &SC) const {
438 assert(SC.hasChecksums());
439 auto Result = std::make_shared(
440 *SC.checksums(), InlineeLines.HasExtraFiles);
450441
451442 for (const auto &Site : InlineeLines.Sites) {
452443 Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
458449 Result->addExtraFile(EF);
459450 }
460451 }
461 return llvm::cast(std::move(Result));
462 }
463
464 std::unique_ptr
452 return std::move(Result);
453 }
454
455 std::shared_ptr
465456 YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
466 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
467 DebugChecksumsSubsection *Checksums) const {
468 auto Result = llvm::make_unique();
457 BumpPtrAllocator &Allocator,
458 const codeview::StringsAndChecksums &SC) const {
459 auto Result = std::make_shared();
469460 for (const auto &M : Exports)
470461 Result->addMapping(M.Local, M.Global);
471 return llvm::cast(std::move(Result));
472 }
473
474 std::unique_ptr
462 return std::move(Result);
463 }
464
465 std::shared_ptr
475466 YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
476 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
477 DebugChecksumsSubsection *Checksums) const {
478 auto Result = llvm::make_unique(*Strings);
467 BumpPtrAllocator &Allocator,
468 const codeview::StringsAndChecksums &SC) const {
469 assert(SC.hasStrings());
470
471 auto Result =
472 std::make_shared(*SC.strings());
479473 for (const auto &M : Imports) {
480474 for (const auto Id : M.ImportIds)
481475 Result->addImport(M.ModuleName, Id);
482476 }
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();
477 return std::move(Result);
478 }
479
480 std::shared_ptr YAMLSymbolsSubsection::toCodeViewSubsection(
481 BumpPtrAllocator &Allocator,
482 const codeview::StringsAndChecksums &SC) const {
483 auto Result = std::make_shared();
490484 for (const auto &Sym : Symbols)
491485 Result->addSymbol(
492486 Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
493487 return std::move(Result);
494488 }
495489
496 std::unique_ptr
490 std::shared_ptr
497491 YAMLStringTableSubsection::toCodeViewSubsection(
498 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
499 DebugChecksumsSubsection *Checksums) const {
500 auto Result = llvm::make_unique();
492 BumpPtrAllocator &Allocator,
493 const codeview::StringsAndChecksums &SC) const {
494 auto Result = std::make_shared();
501495 for (const auto &Str : this->Strings)
502496 Result->insert(Str);
503497 return std::move(Result);
504498 }
505499
506 std::unique_ptr YAMLFrameDataSubsection::toCodeViewSubsection(
507 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
508 DebugChecksumsSubsection *Checksums) const {
509 assert(Strings);
500 std::shared_ptr YAMLFrameDataSubsection::toCodeViewSubsection(
501 BumpPtrAllocator &Allocator,
502 const codeview::StringsAndChecksums &SC) const {
503 assert(SC.hasStrings());
504
510505 auto Result = llvm::make_unique();
511506 for (const auto &YF : Frames) {
512507 codeview::FrameData F;
518513 F.PrologSize = YF.PrologSize;
519514 F.RvaStart = YF.RvaStart;
520515 F.SavedRegsSize = YF.SavedRegsSize;
521 F.FrameFunc = Strings->insert(YF.FrameFunc);
516 F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
522517 Result->addFrameData(F);
523518 }
524519 return std::move(Result);
525520 }
526521
527 std::unique_ptr
522 std::shared_ptr
528523 YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
529 BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
530 DebugChecksumsSubsection *Checksums) const {
524 BumpPtrAllocator &Allocator,
525 const codeview::StringsAndChecksums &SC) const {
531526 auto Result = llvm::make_unique();
532527 for (const auto &RVA : RVAs)
533528 Result->addRVA(RVA);
740735 return Result;
741736 }
742737
743 Expectedunique_ptr>>
738 Expectedshared_ptr>>
744739 llvm::CodeViewYAML::toCodeViewSubsectionList(
745740 BumpPtrAllocator &Allocator, ArrayRef Subsections,
746 DebugStringTableSubsection &Strings) {
747 std::vector> Result;
741 const codeview::StringsAndChecksums &SC) {
742 std::vector> Result;
748743 if (Subsections.empty())
749744 return std::move(Result);
750745
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());
758746 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);
747 std::shared_ptr CVS;
748 CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
800749 assert(CVS != nullptr);
801750 Result.push_back(std::move(CVS));
802751 }
809758
810759 Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
811760 Error visitLines(DebugLinesSubsectionRef &Lines,
812 const DebugSubsectionState &State) override;
761 const StringsAndChecksumsRef &State) override;
813762 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
814 const DebugSubsectionState &State) override;
763 const StringsAndChecksumsRef &State) override;
815764 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
816 const DebugSubsectionState &State) override;
765 const StringsAndChecksumsRef &State) override;
817766 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
818 const DebugSubsectionState &State) override;
767 const StringsAndChecksumsRef &State) override;
819768 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
820 const DebugSubsectionState &State) override;
769 const StringsAndChecksumsRef &State) override;
821770 Error visitStringTable(DebugStringTableSubsectionRef &ST,
822 const DebugSubsectionState &State) override;
771 const StringsAndChecksumsRef &State) override;
823772 Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
824 const DebugSubsectionState &State) override;
773 const StringsAndChecksumsRef &State) override;
825774 Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
826 const DebugSubsectionState &State) override;
775 const StringsAndChecksumsRef &State) override;
827776 Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols,
828 const DebugSubsectionState &State) override;
777 const StringsAndChecksumsRef &State) override;
829778
830779 YAMLDebugSubsection Subsection;
831780 };
836785 }
837786
838787 Error SubsectionConversionVisitor::visitLines(
839 DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) {
788 DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) {
840789 auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
841790 State.strings(), State.checksums(), Lines);
842791 if (!Result)
846795 }
847796
848797 Error SubsectionConversionVisitor::visitFileChecksums(
849 DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) {
798 DebugChecksumsSubsectionRef &Checksums,
799 const StringsAndChecksumsRef &State) {
850800 auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
851801 Checksums);
852802 if (!Result)
857807
858808 Error SubsectionConversionVisitor::visitInlineeLines(
859809 DebugInlineeLinesSubsectionRef &Inlinees,
860 const DebugSubsectionState &State) {
810 const StringsAndChecksumsRef &State) {
861811 auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
862812 State.strings(), State.checksums(), Inlinees);
863813 if (!Result)
868818
869819 Error SubsectionConversionVisitor::visitCrossModuleExports(
870820 DebugCrossModuleExportsSubsectionRef &Exports,
871 const DebugSubsectionState &State) {
821 const StringsAndChecksumsRef &State) {
872822 auto Result =
873823 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
874824 if (!Result)
879829
880830 Error SubsectionConversionVisitor::visitCrossModuleImports(
881831 DebugCrossModuleImportsSubsectionRef &Imports,
882 const DebugSubsectionState &State) {
832 const StringsAndChecksumsRef &State) {
883833 auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
884834 State.strings(), Imports);
885835 if (!Result)
889839 }
890840
891841 Error SubsectionConversionVisitor::visitStringTable(
892 DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) {
842 DebugStringTableSubsectionRef &Strings,
843 const StringsAndChecksumsRef &State) {
893844 auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
894845 if (!Result)
895846 return Result.takeError();
898849 }
899850
900851 Error SubsectionConversionVisitor::visitSymbols(
901 DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) {
852 DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
902853 auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
903854 if (!Result)
904855 return Result.takeError();
907858 }
908859
909860 Error SubsectionConversionVisitor::visitFrameData(
910 DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) {
861 DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) {
911862 auto Result =
912863 YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
913864 if (!Result)
917868 }
918869
919870 Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
920 DebugSymbolRVASubsectionRef &RVAs, const DebugSubsectionState &State) {
871 DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) {
921872 auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs);
922873 if (!Result)
923874 return Result.takeError();
926877 }
927878 }
928879
929 Expected YAMLDebugSubsection::fromCodeViewSubection(
930 const DebugStringTableSubsectionRef &Strings,
931 const DebugChecksumsSubsectionRef &Checksums,
932 const DebugSubsectionRecord &SS) {
933 DebugSubsectionState State(Strings, Checksums);
880 Expected
881 YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC,
882 const DebugSubsectionRecord &SS) {
934883 SubsectionConversionVisitor V;
935 if (auto EC = visitDebugSubsection(SS, V, State))
884 if (auto EC = visitDebugSubsection(SS, V, SC))
936885 return std::move(EC);
937886
938887 return V.Subsection;
939888 }
940889
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 }
890 std::vector
891 llvm::CodeViewYAML::fromDebugS(ArrayRef Data,
892 const StringsAndChecksumsRef &SC) {
893 BinaryStreamReader Reader(Data, support::little);
894 uint32_t Magic;
895
896 ExitOnError Err("Invalid .debug$S section!");
897 Err(Reader.readInteger(Magic));
898 assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
899
900 DebugSubsectionArray Subsections;
901 Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
902
903 std::vector Result;
904
905 for (const auto &SS : Subsections) {
906 auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
907 Result.push_back(YamlSS);
908 }
909 return std::move(Result);
910 }
911
912 void llvm::CodeViewYAML::initializeStringsAndChecksums(
913 ArrayRef Sections, codeview::StringsAndChecksums &SC) {
914 // String Table and Checksums subsections don't use the allocator.
915 BumpPtrAllocator Allocator;
916
917 // It's possible for checksums and strings to even appear in different debug$S
918 // sections, so we have to make this a stateful function that can build up
919 // the strings and checksums field over multiple iterations.
920
921 // File Checksums require the string table, but may become before it, so we
922 // have to scan for strings first, then scan for checksums again from the
923 // beginning.
924 if (!SC.hasStrings()) {
925 for (const auto &SS : Sections) {
926 if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
927 continue;
928
929 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
930 SC.setStrings(
931 std::static_pointer_cast(Result));
932 break;
933 }
934 }
935
936 if (SC.hasStrings() && !SC.hasChecksums()) {
937 for (const auto &SS : Sections) {
938 if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
939 continue;
940
941 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
942 SC.setChecksums(
943 std::static_pointer_cast(Result));
944 break;
945 }
946 }
947 }
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 std::move(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 }
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()) {
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"
2527 #include
2628
2729 using namespace llvm;
30
31 namespace {
32 template struct WeakishPtr {
33 public:
34 WeakishPtr() : Ref(nullptr) {}
35
36 WeakishPtr(std::unique_ptr Value)
37 : Ref(Value.get()), UniquePtr(std::move(Value)) {}
38
39 WeakishPtr(std::unique_ptr &&Value)
40 : Ref(Value.get()), UniquePtr(std::move(Value)) {}
41
42 WeakishPtr &operator=(std::unique_ptr &&Value) {
43 Owned = std::move(Value);
44 Ref = Owned.get();
45 return *this;
46 }
47
48 T *get() { return Ref; }
49 T &operator*() { return *Ref; }
50
51 operator bool() const { return Ref != nullptr; }
52
53 T *Ref;
54 std::unique_ptr Owned;
55 };
56 } // namespace
2857
2958 /// This parses a yaml stream that represents a COFF object file.
3059 /// See docs/yaml2obj for the yaml scheema.
141170
142171 COFFYAML::Object &Obj;
143172
173 codeview::StringsAndChecksums StringsAndChecksums;
174 BumpPtrAllocator Allocator;
144175 StringMap StringTableMap;
145176 std::string StringTable;
146177 uint32_t SectionTableStart;
164195 enum { DOSStubSize = 128 };
165196 }
166197
198 static yaml::BinaryRef
199 toDebugS(ArrayRef Subsections,
200 const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator) {
201 using namespace codeview;
202 ExitOnError Err("Error occurred writing .debug$S section");
203 auto CVSS =
204 Err(CodeViewYAML::toCodeViewSubsectionList(Allocator, Subsections, SC));
205
206 std::vector Builders;
207 uint32_t Size = sizeof(uint32_t);
208 for (auto &SS : CVSS) {
209 DebugSubsectionRecordBuilder B(SS, CodeViewContainer::ObjectFile);
210 Size += B.calculateSerializedLength();
211 Builders.push_back(std::move(B));
212 }
213 uint8_t *Buffer = Allocator.Allocate(Size);
214 MutableArrayRef Output(Buffer, Size);
215 BinaryStreamWriter Writer(Output, support::little);
216
217 Err(Writer.writeInteger(COFF::DEBUG_SECTION_MAGIC));
218 for (const auto &B : Builders) {
219 Err(B.commit(Writer));
220 }
221 return {Output};
222 }
223
167224 // Take a CP and assign addresses and sizes to everything. Returns false if the
168225 // layout is not valid to do.
169226 static bool layoutCOFF(COFFParser &CP) {
178235 uint32_t CurrentSectionDataOffset =
179236 CP.SectionTableStart + CP.SectionTableSize;
180237
238 for (COFFYAML::Section &S : CP.Obj.Sections) {
239 // We support specifying exactly one of SectionData or Subsections. So if
240 // there is already some SectionData, then we don't need to do any of this.
241 if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) {
242 CodeViewYAML::initializeStringsAndChecksums(S.DebugS,
243 CP.StringsAndChecksums);
244 if (CP.StringsAndChecksums.hasChecksums() &&
245 CP.StringsAndChecksums.hasStrings())
246 break;
247 }
248 }
249
181250 // Assign each section data address consecutively.
182251 for (COFFYAML::Section &S : CP.Obj.Sections) {
252 if (S.Name == ".debug$S") {
253 if (S.SectionData.binary_size() == 0) {
254 assert(CP.StringsAndChecksums.hasStrings() &&
255 "Object file does not have debug string table!");
256
257 S.SectionData =
258 toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator);
259 }
260 } else if (S.Name == ".debug$T") {
261 if (S.SectionData.binary_size() == 0)
262 S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator);
263 }
264
183265 if (S.SectionData.binary_size() > 0) {
184266 CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset,
185267 CP.isPE() ? CP.getFileAlignment() : 4);
542624 errs() << "yaml2obj: Failed to layout optional header for COFF file!\n";
543625 return 1;
544626 }
627
545628 if (!layoutCOFF(CP)) {
546629 errs() << "yaml2obj: Failed to layout COFF file!\n";
547630 return 1;