1*6b6b8c4fSAdrian McCarthy //===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
2*6b6b8c4fSAdrian McCarthy //
3*6b6b8c4fSAdrian McCarthy //                     The LLVM Compiler Infrastructure
4*6b6b8c4fSAdrian McCarthy //
5*6b6b8c4fSAdrian McCarthy // This file is distributed under the University of Illinois Open Source
6*6b6b8c4fSAdrian McCarthy // License. See LICENSE.TXT for details.
7*6b6b8c4fSAdrian McCarthy //
8*6b6b8c4fSAdrian McCarthy //===----------------------------------------------------------------------===//
9*6b6b8c4fSAdrian McCarthy 
10*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
11*6b6b8c4fSAdrian McCarthy 
12*6b6b8c4fSAdrian McCarthy #include "llvm/ADT/ArrayRef.h"
13*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MSFBuilder.h"
14*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
15*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/StreamWriter.h"
16*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
17*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawError.h"
18*6b6b8c4fSAdrian McCarthy #include "llvm/Object/COFF.h"
19*6b6b8c4fSAdrian McCarthy #include "llvm/Support/COFF.h"
20*6b6b8c4fSAdrian McCarthy 
21*6b6b8c4fSAdrian McCarthy using namespace llvm;
22*6b6b8c4fSAdrian McCarthy using namespace llvm::codeview;
23*6b6b8c4fSAdrian McCarthy using namespace llvm::msf;
24*6b6b8c4fSAdrian McCarthy using namespace llvm::pdb;
25*6b6b8c4fSAdrian McCarthy 
26*6b6b8c4fSAdrian McCarthy namespace {
27*6b6b8c4fSAdrian McCarthy class ModiSubstreamBuilder {};
28*6b6b8c4fSAdrian McCarthy }
29*6b6b8c4fSAdrian McCarthy 
30*6b6b8c4fSAdrian McCarthy DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf)
31*6b6b8c4fSAdrian McCarthy     : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0),
32*6b6b8c4fSAdrian McCarthy       PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86),
33*6b6b8c4fSAdrian McCarthy       Header(nullptr), DbgStreams((int)DbgHeaderType::Max) {}
34*6b6b8c4fSAdrian McCarthy 
35*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
36*6b6b8c4fSAdrian McCarthy 
37*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setAge(uint32_t A) { Age = A; }
38*6b6b8c4fSAdrian McCarthy 
39*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; }
40*6b6b8c4fSAdrian McCarthy 
41*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; }
42*6b6b8c4fSAdrian McCarthy 
43*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; }
44*6b6b8c4fSAdrian McCarthy 
45*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
46*6b6b8c4fSAdrian McCarthy 
47*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
48*6b6b8c4fSAdrian McCarthy 
49*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) {
50*6b6b8c4fSAdrian McCarthy   SectionContribs = Arr;
51*6b6b8c4fSAdrian McCarthy }
52*6b6b8c4fSAdrian McCarthy 
53*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
54*6b6b8c4fSAdrian McCarthy   SectionMap = SecMap;
55*6b6b8c4fSAdrian McCarthy }
56*6b6b8c4fSAdrian McCarthy 
57*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
58*6b6b8c4fSAdrian McCarthy                                      ArrayRef<uint8_t> Data) {
59*6b6b8c4fSAdrian McCarthy   if (DbgStreams[(int)Type].StreamNumber)
60*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::duplicate_entry,
61*6b6b8c4fSAdrian McCarthy                                 "The specified stream type already exists");
62*6b6b8c4fSAdrian McCarthy   auto ExpectedIndex = Msf.addStream(Data.size());
63*6b6b8c4fSAdrian McCarthy   if (!ExpectedIndex)
64*6b6b8c4fSAdrian McCarthy     return ExpectedIndex.takeError();
65*6b6b8c4fSAdrian McCarthy   uint32_t Index = std::move(*ExpectedIndex);
66*6b6b8c4fSAdrian McCarthy   DbgStreams[(int)Type].Data = Data;
67*6b6b8c4fSAdrian McCarthy   DbgStreams[(int)Type].StreamNumber = Index;
68*6b6b8c4fSAdrian McCarthy   return Error::success();
69*6b6b8c4fSAdrian McCarthy }
70*6b6b8c4fSAdrian McCarthy 
71*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateSerializedLength() const {
72*6b6b8c4fSAdrian McCarthy   // For now we only support serializing the header.
73*6b6b8c4fSAdrian McCarthy   return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() +
74*6b6b8c4fSAdrian McCarthy          calculateModiSubstreamSize() + calculateSectionContribsStreamSize() +
75*6b6b8c4fSAdrian McCarthy          calculateSectionMapStreamSize() + calculateDbgStreamsSize();
76*6b6b8c4fSAdrian McCarthy }
77*6b6b8c4fSAdrian McCarthy 
78*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::addModuleInfo(StringRef ObjFile, StringRef Module) {
79*6b6b8c4fSAdrian McCarthy   auto Entry = llvm::make_unique<ModuleInfo>();
80*6b6b8c4fSAdrian McCarthy   ModuleInfo *M = Entry.get();
81*6b6b8c4fSAdrian McCarthy   Entry->Mod = Module;
82*6b6b8c4fSAdrian McCarthy   Entry->Obj = ObjFile;
83*6b6b8c4fSAdrian McCarthy   auto Result = ModuleInfos.insert(std::make_pair(Module, std::move(Entry)));
84*6b6b8c4fSAdrian McCarthy   if (!Result.second)
85*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::duplicate_entry,
86*6b6b8c4fSAdrian McCarthy                                 "The specified module already exists");
87*6b6b8c4fSAdrian McCarthy   ModuleInfoList.push_back(M);
88*6b6b8c4fSAdrian McCarthy   return Error::success();
89*6b6b8c4fSAdrian McCarthy }
90*6b6b8c4fSAdrian McCarthy 
91*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) {
92*6b6b8c4fSAdrian McCarthy   auto ModIter = ModuleInfos.find(Module);
93*6b6b8c4fSAdrian McCarthy   if (ModIter == ModuleInfos.end())
94*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::no_entry,
95*6b6b8c4fSAdrian McCarthy                                 "The specified module was not found");
96*6b6b8c4fSAdrian McCarthy   uint32_t Index = SourceFileNames.size();
97*6b6b8c4fSAdrian McCarthy   SourceFileNames.insert(std::make_pair(File, Index));
98*6b6b8c4fSAdrian McCarthy   auto &ModEntry = *ModIter;
99*6b6b8c4fSAdrian McCarthy   ModEntry.second->SourceFiles.push_back(File);
100*6b6b8c4fSAdrian McCarthy   return Error::success();
101*6b6b8c4fSAdrian McCarthy }
102*6b6b8c4fSAdrian McCarthy 
103*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
104*6b6b8c4fSAdrian McCarthy   uint32_t Size = 0;
105*6b6b8c4fSAdrian McCarthy   for (const auto &M : ModuleInfoList) {
106*6b6b8c4fSAdrian McCarthy     Size += sizeof(ModuleInfoHeader);
107*6b6b8c4fSAdrian McCarthy     Size += M->Mod.size() + 1;
108*6b6b8c4fSAdrian McCarthy     Size += M->Obj.size() + 1;
109*6b6b8c4fSAdrian McCarthy   }
110*6b6b8c4fSAdrian McCarthy   return alignTo(Size, sizeof(uint32_t));
111*6b6b8c4fSAdrian McCarthy }
112*6b6b8c4fSAdrian McCarthy 
113*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const {
114*6b6b8c4fSAdrian McCarthy   if (SectionContribs.empty())
115*6b6b8c4fSAdrian McCarthy     return 0;
116*6b6b8c4fSAdrian McCarthy   return sizeof(enum PdbRaw_DbiSecContribVer) +
117*6b6b8c4fSAdrian McCarthy          sizeof(SectionContribs[0]) * SectionContribs.size();
118*6b6b8c4fSAdrian McCarthy }
119*6b6b8c4fSAdrian McCarthy 
120*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const {
121*6b6b8c4fSAdrian McCarthy   if (SectionMap.empty())
122*6b6b8c4fSAdrian McCarthy     return 0;
123*6b6b8c4fSAdrian McCarthy   return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size();
124*6b6b8c4fSAdrian McCarthy }
125*6b6b8c4fSAdrian McCarthy 
126*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const {
127*6b6b8c4fSAdrian McCarthy   uint32_t Size = 0;
128*6b6b8c4fSAdrian McCarthy   Size += sizeof(ulittle16_t);                         // NumModules
129*6b6b8c4fSAdrian McCarthy   Size += sizeof(ulittle16_t);                         // NumSourceFiles
130*6b6b8c4fSAdrian McCarthy   Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices
131*6b6b8c4fSAdrian McCarthy   Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts
132*6b6b8c4fSAdrian McCarthy   uint32_t NumFileInfos = 0;
133*6b6b8c4fSAdrian McCarthy   for (const auto &M : ModuleInfoList)
134*6b6b8c4fSAdrian McCarthy     NumFileInfos += M->SourceFiles.size();
135*6b6b8c4fSAdrian McCarthy   Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets
136*6b6b8c4fSAdrian McCarthy   Size += calculateNamesBufferSize();
137*6b6b8c4fSAdrian McCarthy   return alignTo(Size, sizeof(uint32_t));
138*6b6b8c4fSAdrian McCarthy }
139*6b6b8c4fSAdrian McCarthy 
140*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateNamesBufferSize() const {
141*6b6b8c4fSAdrian McCarthy   uint32_t Size = 0;
142*6b6b8c4fSAdrian McCarthy   for (const auto &F : SourceFileNames) {
143*6b6b8c4fSAdrian McCarthy     Size += F.getKeyLength() + 1; // Names[I];
144*6b6b8c4fSAdrian McCarthy   }
145*6b6b8c4fSAdrian McCarthy   return Size;
146*6b6b8c4fSAdrian McCarthy }
147*6b6b8c4fSAdrian McCarthy 
148*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const {
149*6b6b8c4fSAdrian McCarthy   return DbgStreams.size() * sizeof(uint16_t);
150*6b6b8c4fSAdrian McCarthy }
151*6b6b8c4fSAdrian McCarthy 
152*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::generateModiSubstream() {
153*6b6b8c4fSAdrian McCarthy   uint32_t Size = calculateModiSubstreamSize();
154*6b6b8c4fSAdrian McCarthy   auto Data = Allocator.Allocate<uint8_t>(Size);
155*6b6b8c4fSAdrian McCarthy 
156*6b6b8c4fSAdrian McCarthy   ModInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
157*6b6b8c4fSAdrian McCarthy 
158*6b6b8c4fSAdrian McCarthy   StreamWriter ModiWriter(ModInfoBuffer);
159*6b6b8c4fSAdrian McCarthy   for (const auto &M : ModuleInfoList) {
160*6b6b8c4fSAdrian McCarthy     ModuleInfoHeader Layout = {};
161*6b6b8c4fSAdrian McCarthy     Layout.ModDiStream = kInvalidStreamIndex;
162*6b6b8c4fSAdrian McCarthy     Layout.NumFiles = M->SourceFiles.size();
163*6b6b8c4fSAdrian McCarthy     if (auto EC = ModiWriter.writeObject(Layout))
164*6b6b8c4fSAdrian McCarthy       return EC;
165*6b6b8c4fSAdrian McCarthy     if (auto EC = ModiWriter.writeZeroString(M->Mod))
166*6b6b8c4fSAdrian McCarthy       return EC;
167*6b6b8c4fSAdrian McCarthy     if (auto EC = ModiWriter.writeZeroString(M->Obj))
168*6b6b8c4fSAdrian McCarthy       return EC;
169*6b6b8c4fSAdrian McCarthy   }
170*6b6b8c4fSAdrian McCarthy   if (ModiWriter.bytesRemaining() > sizeof(uint32_t))
171*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::invalid_format,
172*6b6b8c4fSAdrian McCarthy                                 "Unexpected bytes in Modi Stream Data");
173*6b6b8c4fSAdrian McCarthy   return Error::success();
174*6b6b8c4fSAdrian McCarthy }
175*6b6b8c4fSAdrian McCarthy 
176*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::generateFileInfoSubstream() {
177*6b6b8c4fSAdrian McCarthy   uint32_t Size = calculateFileInfoSubstreamSize();
178*6b6b8c4fSAdrian McCarthy   uint32_t NameSize = calculateNamesBufferSize();
179*6b6b8c4fSAdrian McCarthy   auto Data = Allocator.Allocate<uint8_t>(Size);
180*6b6b8c4fSAdrian McCarthy   uint32_t NamesOffset = Size - NameSize;
181*6b6b8c4fSAdrian McCarthy 
182*6b6b8c4fSAdrian McCarthy   FileInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
183*6b6b8c4fSAdrian McCarthy 
184*6b6b8c4fSAdrian McCarthy   WritableStreamRef MetadataBuffer =
185*6b6b8c4fSAdrian McCarthy       WritableStreamRef(FileInfoBuffer).keep_front(NamesOffset);
186*6b6b8c4fSAdrian McCarthy   StreamWriter MetadataWriter(MetadataBuffer);
187*6b6b8c4fSAdrian McCarthy 
188*6b6b8c4fSAdrian McCarthy   uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.size());
189*6b6b8c4fSAdrian McCarthy   uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
190*6b6b8c4fSAdrian McCarthy   if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules
191*6b6b8c4fSAdrian McCarthy     return EC;
192*6b6b8c4fSAdrian McCarthy   if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles
193*6b6b8c4fSAdrian McCarthy     return EC;
194*6b6b8c4fSAdrian McCarthy   for (uint16_t I = 0; I < ModiCount; ++I) {
195*6b6b8c4fSAdrian McCarthy     if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices
196*6b6b8c4fSAdrian McCarthy       return EC;
197*6b6b8c4fSAdrian McCarthy   }
198*6b6b8c4fSAdrian McCarthy   for (const auto MI : ModuleInfoList) {
199*6b6b8c4fSAdrian McCarthy     FileCount = static_cast<uint16_t>(MI->SourceFiles.size());
200*6b6b8c4fSAdrian McCarthy     if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts
201*6b6b8c4fSAdrian McCarthy       return EC;
202*6b6b8c4fSAdrian McCarthy   }
203*6b6b8c4fSAdrian McCarthy 
204*6b6b8c4fSAdrian McCarthy   // Before writing the FileNameOffsets array, write the NamesBuffer array.
205*6b6b8c4fSAdrian McCarthy   // A side effect of this is that this will actually compute the various
206*6b6b8c4fSAdrian McCarthy   // file name offsets, so we can then go back and write the FileNameOffsets
207*6b6b8c4fSAdrian McCarthy   // array to the other substream.
208*6b6b8c4fSAdrian McCarthy   NamesBuffer = WritableStreamRef(FileInfoBuffer).drop_front(NamesOffset);
209*6b6b8c4fSAdrian McCarthy   StreamWriter NameBufferWriter(NamesBuffer);
210*6b6b8c4fSAdrian McCarthy   for (auto &Name : SourceFileNames) {
211*6b6b8c4fSAdrian McCarthy     Name.second = NameBufferWriter.getOffset();
212*6b6b8c4fSAdrian McCarthy     if (auto EC = NameBufferWriter.writeZeroString(Name.getKey()))
213*6b6b8c4fSAdrian McCarthy       return EC;
214*6b6b8c4fSAdrian McCarthy   }
215*6b6b8c4fSAdrian McCarthy 
216*6b6b8c4fSAdrian McCarthy   for (const auto MI : ModuleInfoList) {
217*6b6b8c4fSAdrian McCarthy     for (StringRef Name : MI->SourceFiles) {
218*6b6b8c4fSAdrian McCarthy       auto Result = SourceFileNames.find(Name);
219*6b6b8c4fSAdrian McCarthy       if (Result == SourceFileNames.end())
220*6b6b8c4fSAdrian McCarthy         return make_error<RawError>(raw_error_code::no_entry,
221*6b6b8c4fSAdrian McCarthy                                     "The source file was not found.");
222*6b6b8c4fSAdrian McCarthy       if (auto EC = MetadataWriter.writeInteger(Result->second))
223*6b6b8c4fSAdrian McCarthy         return EC;
224*6b6b8c4fSAdrian McCarthy     }
225*6b6b8c4fSAdrian McCarthy   }
226*6b6b8c4fSAdrian McCarthy 
227*6b6b8c4fSAdrian McCarthy   if (NameBufferWriter.bytesRemaining() > 0)
228*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::invalid_format,
229*6b6b8c4fSAdrian McCarthy                                 "The names buffer contained unexpected data.");
230*6b6b8c4fSAdrian McCarthy 
231*6b6b8c4fSAdrian McCarthy   if (MetadataWriter.bytesRemaining() > sizeof(uint32_t))
232*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(
233*6b6b8c4fSAdrian McCarthy         raw_error_code::invalid_format,
234*6b6b8c4fSAdrian McCarthy         "The metadata buffer contained unexpected data.");
235*6b6b8c4fSAdrian McCarthy 
236*6b6b8c4fSAdrian McCarthy   return Error::success();
237*6b6b8c4fSAdrian McCarthy }
238*6b6b8c4fSAdrian McCarthy 
239*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::finalize() {
240*6b6b8c4fSAdrian McCarthy   if (Header)
241*6b6b8c4fSAdrian McCarthy     return Error::success();
242*6b6b8c4fSAdrian McCarthy 
243*6b6b8c4fSAdrian McCarthy   DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>();
244*6b6b8c4fSAdrian McCarthy 
245*6b6b8c4fSAdrian McCarthy   if (auto EC = generateModiSubstream())
246*6b6b8c4fSAdrian McCarthy     return EC;
247*6b6b8c4fSAdrian McCarthy   if (auto EC = generateFileInfoSubstream())
248*6b6b8c4fSAdrian McCarthy     return EC;
249*6b6b8c4fSAdrian McCarthy 
250*6b6b8c4fSAdrian McCarthy   H->VersionHeader = *VerHeader;
251*6b6b8c4fSAdrian McCarthy   H->VersionSignature = -1;
252*6b6b8c4fSAdrian McCarthy   H->Age = Age;
253*6b6b8c4fSAdrian McCarthy   H->BuildNumber = BuildNumber;
254*6b6b8c4fSAdrian McCarthy   H->Flags = Flags;
255*6b6b8c4fSAdrian McCarthy   H->PdbDllRbld = PdbDllRbld;
256*6b6b8c4fSAdrian McCarthy   H->PdbDllVersion = PdbDllVersion;
257*6b6b8c4fSAdrian McCarthy   H->MachineType = static_cast<uint16_t>(MachineType);
258*6b6b8c4fSAdrian McCarthy 
259*6b6b8c4fSAdrian McCarthy   H->ECSubstreamSize = 0;
260*6b6b8c4fSAdrian McCarthy   H->FileInfoSize = FileInfoBuffer.getLength();
261*6b6b8c4fSAdrian McCarthy   H->ModiSubstreamSize = ModInfoBuffer.getLength();
262*6b6b8c4fSAdrian McCarthy   H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t);
263*6b6b8c4fSAdrian McCarthy   H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
264*6b6b8c4fSAdrian McCarthy   H->SectionMapSize = calculateSectionMapStreamSize();
265*6b6b8c4fSAdrian McCarthy   H->TypeServerSize = 0;
266*6b6b8c4fSAdrian McCarthy   H->SymRecordStreamIndex = kInvalidStreamIndex;
267*6b6b8c4fSAdrian McCarthy   H->PublicSymbolStreamIndex = kInvalidStreamIndex;
268*6b6b8c4fSAdrian McCarthy   H->MFCTypeServerIndex = kInvalidStreamIndex;
269*6b6b8c4fSAdrian McCarthy   H->GlobalSymbolStreamIndex = kInvalidStreamIndex;
270*6b6b8c4fSAdrian McCarthy 
271*6b6b8c4fSAdrian McCarthy   Header = H;
272*6b6b8c4fSAdrian McCarthy   return Error::success();
273*6b6b8c4fSAdrian McCarthy }
274*6b6b8c4fSAdrian McCarthy 
275*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::finalizeMsfLayout() {
276*6b6b8c4fSAdrian McCarthy   uint32_t Length = calculateSerializedLength();
277*6b6b8c4fSAdrian McCarthy   if (auto EC = Msf.setStreamSize(StreamDBI, Length))
278*6b6b8c4fSAdrian McCarthy     return EC;
279*6b6b8c4fSAdrian McCarthy   return Error::success();
280*6b6b8c4fSAdrian McCarthy }
281*6b6b8c4fSAdrian McCarthy 
282*6b6b8c4fSAdrian McCarthy static uint16_t toSecMapFlags(uint32_t Flags) {
283*6b6b8c4fSAdrian McCarthy   uint16_t Ret = 0;
284*6b6b8c4fSAdrian McCarthy   if (Flags & COFF::IMAGE_SCN_MEM_READ)
285*6b6b8c4fSAdrian McCarthy     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read);
286*6b6b8c4fSAdrian McCarthy   if (Flags & COFF::IMAGE_SCN_MEM_WRITE)
287*6b6b8c4fSAdrian McCarthy     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write);
288*6b6b8c4fSAdrian McCarthy   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
289*6b6b8c4fSAdrian McCarthy     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
290*6b6b8c4fSAdrian McCarthy   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
291*6b6b8c4fSAdrian McCarthy     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
292*6b6b8c4fSAdrian McCarthy   if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT))
293*6b6b8c4fSAdrian McCarthy     Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit);
294*6b6b8c4fSAdrian McCarthy 
295*6b6b8c4fSAdrian McCarthy   // This seems always 1.
296*6b6b8c4fSAdrian McCarthy   Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector);
297*6b6b8c4fSAdrian McCarthy 
298*6b6b8c4fSAdrian McCarthy   return Ret;
299*6b6b8c4fSAdrian McCarthy }
300*6b6b8c4fSAdrian McCarthy 
301*6b6b8c4fSAdrian McCarthy // A utility function to create Section Contributions
302*6b6b8c4fSAdrian McCarthy // for a given input sections.
303*6b6b8c4fSAdrian McCarthy std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs(
304*6b6b8c4fSAdrian McCarthy     ArrayRef<object::coff_section> SecHdrs) {
305*6b6b8c4fSAdrian McCarthy   std::vector<SectionContrib> Ret;
306*6b6b8c4fSAdrian McCarthy 
307*6b6b8c4fSAdrian McCarthy   // Create a SectionContrib for each input section.
308*6b6b8c4fSAdrian McCarthy   for (auto &Sec : SecHdrs) {
309*6b6b8c4fSAdrian McCarthy     Ret.emplace_back();
310*6b6b8c4fSAdrian McCarthy     auto &Entry = Ret.back();
311*6b6b8c4fSAdrian McCarthy     memset(&Entry, 0, sizeof(Entry));
312*6b6b8c4fSAdrian McCarthy 
313*6b6b8c4fSAdrian McCarthy     Entry.Off = Sec.PointerToRawData;
314*6b6b8c4fSAdrian McCarthy     Entry.Size = Sec.SizeOfRawData;
315*6b6b8c4fSAdrian McCarthy     Entry.Characteristics = Sec.Characteristics;
316*6b6b8c4fSAdrian McCarthy   }
317*6b6b8c4fSAdrian McCarthy   return Ret;
318*6b6b8c4fSAdrian McCarthy }
319*6b6b8c4fSAdrian McCarthy 
320*6b6b8c4fSAdrian McCarthy // A utility function to create a Section Map for a given list of COFF sections.
321*6b6b8c4fSAdrian McCarthy //
322*6b6b8c4fSAdrian McCarthy // A Section Map seem to be a copy of a COFF section list in other format.
323*6b6b8c4fSAdrian McCarthy // I don't know why a PDB file contains both a COFF section header and
324*6b6b8c4fSAdrian McCarthy // a Section Map, but it seems it must be present in a PDB.
325*6b6b8c4fSAdrian McCarthy std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap(
326*6b6b8c4fSAdrian McCarthy     ArrayRef<llvm::object::coff_section> SecHdrs) {
327*6b6b8c4fSAdrian McCarthy   std::vector<SecMapEntry> Ret;
328*6b6b8c4fSAdrian McCarthy   int Idx = 0;
329*6b6b8c4fSAdrian McCarthy 
330*6b6b8c4fSAdrian McCarthy   auto Add = [&]() -> SecMapEntry & {
331*6b6b8c4fSAdrian McCarthy     Ret.emplace_back();
332*6b6b8c4fSAdrian McCarthy     auto &Entry = Ret.back();
333*6b6b8c4fSAdrian McCarthy     memset(&Entry, 0, sizeof(Entry));
334*6b6b8c4fSAdrian McCarthy 
335*6b6b8c4fSAdrian McCarthy     Entry.Frame = Idx + 1;
336*6b6b8c4fSAdrian McCarthy 
337*6b6b8c4fSAdrian McCarthy     // We don't know the meaning of these fields yet.
338*6b6b8c4fSAdrian McCarthy     Entry.SecName = UINT16_MAX;
339*6b6b8c4fSAdrian McCarthy     Entry.ClassName = UINT16_MAX;
340*6b6b8c4fSAdrian McCarthy 
341*6b6b8c4fSAdrian McCarthy     return Entry;
342*6b6b8c4fSAdrian McCarthy   };
343*6b6b8c4fSAdrian McCarthy 
344*6b6b8c4fSAdrian McCarthy   for (auto &Hdr : SecHdrs) {
345*6b6b8c4fSAdrian McCarthy     auto &Entry = Add();
346*6b6b8c4fSAdrian McCarthy     Entry.Flags = toSecMapFlags(Hdr.Characteristics);
347*6b6b8c4fSAdrian McCarthy     Entry.SecByteLength = Hdr.VirtualSize;
348*6b6b8c4fSAdrian McCarthy     ++Idx;
349*6b6b8c4fSAdrian McCarthy   }
350*6b6b8c4fSAdrian McCarthy 
351*6b6b8c4fSAdrian McCarthy   // The last entry is for absolute symbols.
352*6b6b8c4fSAdrian McCarthy   auto &Entry = Add();
353*6b6b8c4fSAdrian McCarthy   Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) |
354*6b6b8c4fSAdrian McCarthy                 static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress);
355*6b6b8c4fSAdrian McCarthy   Entry.SecByteLength = UINT32_MAX;
356*6b6b8c4fSAdrian McCarthy 
357*6b6b8c4fSAdrian McCarthy   return Ret;
358*6b6b8c4fSAdrian McCarthy }
359*6b6b8c4fSAdrian McCarthy 
360*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
361*6b6b8c4fSAdrian McCarthy                                const msf::WritableStream &Buffer) {
362*6b6b8c4fSAdrian McCarthy   if (auto EC = finalize())
363*6b6b8c4fSAdrian McCarthy     return EC;
364*6b6b8c4fSAdrian McCarthy 
365*6b6b8c4fSAdrian McCarthy   auto InfoS =
366*6b6b8c4fSAdrian McCarthy       WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI);
367*6b6b8c4fSAdrian McCarthy 
368*6b6b8c4fSAdrian McCarthy   StreamWriter Writer(*InfoS);
369*6b6b8c4fSAdrian McCarthy   if (auto EC = Writer.writeObject(*Header))
370*6b6b8c4fSAdrian McCarthy     return EC;
371*6b6b8c4fSAdrian McCarthy 
372*6b6b8c4fSAdrian McCarthy   if (auto EC = Writer.writeStreamRef(ModInfoBuffer))
373*6b6b8c4fSAdrian McCarthy     return EC;
374*6b6b8c4fSAdrian McCarthy 
375*6b6b8c4fSAdrian McCarthy   if (!SectionContribs.empty()) {
376*6b6b8c4fSAdrian McCarthy     if (auto EC = Writer.writeEnum(DbiSecContribVer60))
377*6b6b8c4fSAdrian McCarthy       return EC;
378*6b6b8c4fSAdrian McCarthy     if (auto EC = Writer.writeArray(SectionContribs))
379*6b6b8c4fSAdrian McCarthy       return EC;
380*6b6b8c4fSAdrian McCarthy   }
381*6b6b8c4fSAdrian McCarthy 
382*6b6b8c4fSAdrian McCarthy   if (!SectionMap.empty()) {
383*6b6b8c4fSAdrian McCarthy     ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size());
384*6b6b8c4fSAdrian McCarthy     SecMapHeader SMHeader = {Size, Size};
385*6b6b8c4fSAdrian McCarthy     if (auto EC = Writer.writeObject(SMHeader))
386*6b6b8c4fSAdrian McCarthy       return EC;
387*6b6b8c4fSAdrian McCarthy     if (auto EC = Writer.writeArray(SectionMap))
388*6b6b8c4fSAdrian McCarthy       return EC;
389*6b6b8c4fSAdrian McCarthy   }
390*6b6b8c4fSAdrian McCarthy 
391*6b6b8c4fSAdrian McCarthy   if (auto EC = Writer.writeStreamRef(FileInfoBuffer))
392*6b6b8c4fSAdrian McCarthy     return EC;
393*6b6b8c4fSAdrian McCarthy 
394*6b6b8c4fSAdrian McCarthy   for (auto &Stream : DbgStreams)
395*6b6b8c4fSAdrian McCarthy     if (auto EC = Writer.writeInteger(Stream.StreamNumber))
396*6b6b8c4fSAdrian McCarthy       return EC;
397*6b6b8c4fSAdrian McCarthy 
398*6b6b8c4fSAdrian McCarthy   for (auto &Stream : DbgStreams) {
399*6b6b8c4fSAdrian McCarthy     if (Stream.StreamNumber == kInvalidStreamIndex)
400*6b6b8c4fSAdrian McCarthy       continue;
401*6b6b8c4fSAdrian McCarthy     auto WritableStream = WritableMappedBlockStream::createIndexedStream(
402*6b6b8c4fSAdrian McCarthy         Layout, Buffer, Stream.StreamNumber);
403*6b6b8c4fSAdrian McCarthy     StreamWriter DbgStreamWriter(*WritableStream);
404*6b6b8c4fSAdrian McCarthy     if (auto EC = DbgStreamWriter.writeArray(Stream.Data))
405*6b6b8c4fSAdrian McCarthy       return EC;
406*6b6b8c4fSAdrian McCarthy   }
407*6b6b8c4fSAdrian McCarthy 
408*6b6b8c4fSAdrian McCarthy   if (Writer.bytesRemaining() > 0)
409*6b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::invalid_format,
410*6b6b8c4fSAdrian McCarthy                                 "Unexpected bytes found in DBI Stream");
411*6b6b8c4fSAdrian McCarthy   return Error::success();
412*6b6b8c4fSAdrian McCarthy }
413