Revert "[codeview] Make obj2yaml/yaml2obj support .debug$S..."
[lldb.git] / llvm / lib / DebugInfo / PDB / Native / DbiModuleDescriptorBuilder.cpp
1 //===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
11
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/BinaryFormat/COFF.h"
14 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
15 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
16 #include "llvm/DebugInfo/MSF/MSFCommon.h"
17 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
18 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
19 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
20 #include "llvm/DebugInfo/PDB/Native/RawError.h"
21 #include "llvm/Support/BinaryItemStream.h"
22 #include "llvm/Support/BinaryStreamWriter.h"
23
24 using namespace llvm;
25 using namespace llvm::codeview;
26 using namespace llvm::msf;
27 using namespace llvm::pdb;
28
29 namespace llvm {
30 template <> struct BinaryItemTraits<CVSymbol> {
31   static size_t length(const CVSymbol &Item) { return Item.RecordData.size(); }
32
33   static ArrayRef<uint8_t> bytes(const CVSymbol &Item) {
34     return Item.RecordData;
35   }
36 };
37 }
38
39 static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
40                                             uint32_t C13Size) {
41   uint32_t Size = sizeof(uint32_t);   // Signature
42   Size += alignTo(SymbolByteSize, 4); // Symbol Data
43   Size += 0;                          // TODO: Layout.C11Bytes
44   Size += C13Size;                    // C13 Debug Info Size
45   Size += sizeof(uint32_t);           // GlobalRefs substream size (always 0)
46   Size += 0;                          // GlobalRefs substream bytes
47   return Size;
48 }
49
50 DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
51                                                        uint32_t ModIndex,
52                                                        msf::MSFBuilder &Msf)
53     : MSF(Msf), ModuleName(ModuleName) {
54   Layout.Mod = ModIndex;
55 }
56
57 DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
58
59 uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
60   return Layout.ModDiStream;
61 }
62
63 void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) {
64   ObjFileName = Name;
65 }
66
67 void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
68   Symbols.push_back(Symbol);
69   // Symbols written to a PDB file are required to be 4 byte aligned.  The same
70   // is not true of object files.
71   assert(Symbol.length() % alignOf(CodeViewContainer::Pdb) == 0 &&
72          "Invalid Symbol alignment!");
73   SymbolByteSize += Symbol.length();
74 }
75
76 void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
77   SourceFiles.push_back(Path);
78 }
79
80 uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
81   uint32_t Result = 0;
82   for (const auto &Builder : C13Builders) {
83     assert(Builder && "Empty C13 Fragment Builder!");
84     Result += Builder->calculateSerializedLength();
85   }
86   return Result;
87 }
88
89 uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
90   uint32_t L = sizeof(Layout);
91   uint32_t M = ModuleName.size() + 1;
92   uint32_t O = ObjFileName.size() + 1;
93   return alignTo(L + M + O, sizeof(uint32_t));
94 }
95
96 template <typename T> struct Foo {
97   explicit Foo(T &&Answer) : Answer(Answer) {}
98
99   T Answer;
100 };
101
102 template <typename T> Foo<T> makeFoo(T &&t) { return Foo<T>(std::move(t)); }
103
104 void DbiModuleDescriptorBuilder::finalize() {
105   Layout.FileNameOffs = 0; // TODO: Fix this
106   Layout.Flags = 0;        // TODO: Fix this
107   Layout.C11Bytes = 0;
108   Layout.C13Bytes = calculateC13DebugInfoSize();
109   (void)Layout.Mod;         // Set in constructor
110   (void)Layout.ModDiStream; // Set in finalizeMsfLayout
111   Layout.NumFiles = SourceFiles.size();
112   Layout.PdbFilePathNI = 0;
113   Layout.SrcFileNameNI = 0;
114
115   // This value includes both the signature field as well as the record bytes
116   // from the symbol stream.
117   Layout.SymBytes = SymbolByteSize + sizeof(uint32_t);
118 }
119
120 Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
121   this->Layout.ModDiStream = kInvalidStreamIndex;
122   uint32_t C13Size = calculateC13DebugInfoSize();
123   auto ExpectedSN =
124       MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
125   if (!ExpectedSN)
126     return ExpectedSN.takeError();
127   Layout.ModDiStream = *ExpectedSN;
128   return Error::success();
129 }
130
131 Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
132                                          const msf::MSFLayout &MsfLayout,
133                                          WritableBinaryStreamRef MsfBuffer) {
134   // We write the Modi record to the `ModiWriter`, but we additionally write its
135   // symbol stream to a brand new stream.
136   if (auto EC = ModiWriter.writeObject(Layout))
137     return EC;
138   if (auto EC = ModiWriter.writeCString(ModuleName))
139     return EC;
140   if (auto EC = ModiWriter.writeCString(ObjFileName))
141     return EC;
142   if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
143     return EC;
144
145   if (Layout.ModDiStream != kInvalidStreamIndex) {
146     auto NS = WritableMappedBlockStream::createIndexedStream(
147         MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
148     WritableBinaryStreamRef Ref(*NS);
149     BinaryStreamWriter SymbolWriter(Ref);
150     // Write the symbols.
151     if (auto EC =
152             SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
153       return EC;
154     BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little);
155     Records.setItems(Symbols);
156     BinaryStreamRef RecordsRef(Records);
157     if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
158       return EC;
159     if (auto EC = SymbolWriter.padToAlignment(4))
160       return EC;
161     // TODO: Write C11 Line data
162     assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
163            "Invalid debug section alignment!");
164     for (const auto &Builder : C13Builders) {
165       assert(Builder && "Empty C13 Fragment Builder!");
166       if (auto EC = Builder->commit(SymbolWriter))
167         return EC;
168     }
169
170     // TODO: Figure out what GlobalRefs substream actually is and populate it.
171     if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
172       return EC;
173     if (SymbolWriter.bytesRemaining() > 0)
174       return make_error<RawError>(raw_error_code::stream_too_long);
175   }
176   return Error::success();
177 }
178
179 void DbiModuleDescriptorBuilder::addDebugSubsection(
180     std::unique_ptr<DebugSubsection> Subsection) {
181   assert(Subsection);
182   C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
183       std::move(Subsection), CodeViewContainer::Pdb));
184 }