1f37b6182SDimitry Andric //===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- C++ -*-===//
2f37b6182SDimitry Andric //
3f37b6182SDimitry Andric // The LLVM Compiler Infrastructure
4f37b6182SDimitry Andric //
5f37b6182SDimitry Andric // This file is distributed under the University of Illinois Open Source
6f37b6182SDimitry Andric // License. See LICENSE.TXT for details.
7f37b6182SDimitry Andric //
8f37b6182SDimitry Andric //===----------------------------------------------------------------------===//
9f37b6182SDimitry Andric
10f37b6182SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
11f37b6182SDimitry Andric
12f37b6182SDimitry Andric #include "llvm/ADT/ArrayRef.h"
13db17bf38SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
1489cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
15f37b6182SDimitry Andric #include "llvm/DebugInfo/MSF/MSFBuilder.h"
16f37b6182SDimitry Andric #include "llvm/DebugInfo/MSF/MSFCommon.h"
17f37b6182SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
18f37b6182SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
192cab237bSDimitry Andric #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
20f37b6182SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
21f37b6182SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h"
22f37b6182SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
23f37b6182SDimitry Andric
24f37b6182SDimitry Andric using namespace llvm;
25f37b6182SDimitry Andric using namespace llvm::codeview;
26f37b6182SDimitry Andric using namespace llvm::msf;
27f37b6182SDimitry Andric using namespace llvm::pdb;
28f37b6182SDimitry Andric
calculateDiSymbolStreamSize(uint32_t SymbolByteSize,uint32_t C13Size)29f37b6182SDimitry Andric static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
30f37b6182SDimitry Andric uint32_t C13Size) {
31f37b6182SDimitry Andric uint32_t Size = sizeof(uint32_t); // Signature
32db17bf38SDimitry Andric Size += alignTo(SymbolByteSize, 4); // Symbol Data
33f37b6182SDimitry Andric Size += 0; // TODO: Layout.C11Bytes
34f37b6182SDimitry Andric Size += C13Size; // C13 Debug Info Size
35f37b6182SDimitry Andric Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
36f37b6182SDimitry Andric Size += 0; // GlobalRefs substream bytes
37f37b6182SDimitry Andric return Size;
38f37b6182SDimitry Andric }
39f37b6182SDimitry Andric
DbiModuleDescriptorBuilder(StringRef ModuleName,uint32_t ModIndex,msf::MSFBuilder & Msf)40f37b6182SDimitry Andric DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
41f37b6182SDimitry Andric uint32_t ModIndex,
42f37b6182SDimitry Andric msf::MSFBuilder &Msf)
43f37b6182SDimitry Andric : MSF(Msf), ModuleName(ModuleName) {
44edd7eaddSDimitry Andric ::memset(&Layout, 0, sizeof(Layout));
45f37b6182SDimitry Andric Layout.Mod = ModIndex;
46f37b6182SDimitry Andric }
47f37b6182SDimitry Andric
~DbiModuleDescriptorBuilder()48f37b6182SDimitry Andric DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
49f37b6182SDimitry Andric
getStreamIndex() const50f37b6182SDimitry Andric uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
51f37b6182SDimitry Andric return Layout.ModDiStream;
52f37b6182SDimitry Andric }
53f37b6182SDimitry Andric
setObjFileName(StringRef Name)54f37b6182SDimitry Andric void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) {
55f37b6182SDimitry Andric ObjFileName = Name;
56f37b6182SDimitry Andric }
57f37b6182SDimitry Andric
setPdbFilePathNI(uint32_t NI)58c4394386SDimitry Andric void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) {
59c4394386SDimitry Andric PdbFilePathNI = NI;
60c4394386SDimitry Andric }
61c4394386SDimitry Andric
setFirstSectionContrib(const SectionContrib & SC)624ba319b5SDimitry Andric void DbiModuleDescriptorBuilder::setFirstSectionContrib(
634ba319b5SDimitry Andric const SectionContrib &SC) {
644ba319b5SDimitry Andric Layout.SC = SC;
654ba319b5SDimitry Andric }
664ba319b5SDimitry Andric
addSymbol(CVSymbol Symbol)67f37b6182SDimitry Andric void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
68*b5893f02SDimitry Andric // Defer to the bulk API. It does the same thing.
69*b5893f02SDimitry Andric addSymbolsInBulk(Symbol.data());
70*b5893f02SDimitry Andric }
71*b5893f02SDimitry Andric
addSymbolsInBulk(ArrayRef<uint8_t> BulkSymbols)72*b5893f02SDimitry Andric void DbiModuleDescriptorBuilder::addSymbolsInBulk(
73*b5893f02SDimitry Andric ArrayRef<uint8_t> BulkSymbols) {
74*b5893f02SDimitry Andric // Do nothing for empty runs of symbols.
75*b5893f02SDimitry Andric if (BulkSymbols.empty())
76*b5893f02SDimitry Andric return;
77*b5893f02SDimitry Andric
78*b5893f02SDimitry Andric Symbols.push_back(BulkSymbols);
796d97bb29SDimitry Andric // Symbols written to a PDB file are required to be 4 byte aligned. The same
806d97bb29SDimitry Andric // is not true of object files.
81*b5893f02SDimitry Andric assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 &&
826d97bb29SDimitry Andric "Invalid Symbol alignment!");
83*b5893f02SDimitry Andric SymbolByteSize += BulkSymbols.size();
84f37b6182SDimitry Andric }
85f37b6182SDimitry Andric
addSourceFile(StringRef Path)86f37b6182SDimitry Andric void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
87f37b6182SDimitry Andric SourceFiles.push_back(Path);
88f37b6182SDimitry Andric }
89f37b6182SDimitry Andric
calculateC13DebugInfoSize() const90f37b6182SDimitry Andric uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
91f37b6182SDimitry Andric uint32_t Result = 0;
92f37b6182SDimitry Andric for (const auto &Builder : C13Builders) {
93f37b6182SDimitry Andric assert(Builder && "Empty C13 Fragment Builder!");
94f37b6182SDimitry Andric Result += Builder->calculateSerializedLength();
95f37b6182SDimitry Andric }
96f37b6182SDimitry Andric return Result;
97f37b6182SDimitry Andric }
98f37b6182SDimitry Andric
calculateSerializedLength() const99f37b6182SDimitry Andric uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
100f37b6182SDimitry Andric uint32_t L = sizeof(Layout);
101f37b6182SDimitry Andric uint32_t M = ModuleName.size() + 1;
102f37b6182SDimitry Andric uint32_t O = ObjFileName.size() + 1;
103f37b6182SDimitry Andric return alignTo(L + M + O, sizeof(uint32_t));
104f37b6182SDimitry Andric }
105f37b6182SDimitry Andric
finalize()106f37b6182SDimitry Andric void DbiModuleDescriptorBuilder::finalize() {
1074ba319b5SDimitry Andric Layout.SC.Imod = Layout.Mod;
108f37b6182SDimitry Andric Layout.FileNameOffs = 0; // TODO: Fix this
109f37b6182SDimitry Andric Layout.Flags = 0; // TODO: Fix this
110f37b6182SDimitry Andric Layout.C11Bytes = 0;
111f37b6182SDimitry Andric Layout.C13Bytes = calculateC13DebugInfoSize();
112f37b6182SDimitry Andric (void)Layout.Mod; // Set in constructor
113f37b6182SDimitry Andric (void)Layout.ModDiStream; // Set in finalizeMsfLayout
114f37b6182SDimitry Andric Layout.NumFiles = SourceFiles.size();
115c4394386SDimitry Andric Layout.PdbFilePathNI = PdbFilePathNI;
116f37b6182SDimitry Andric Layout.SrcFileNameNI = 0;
117f37b6182SDimitry Andric
118f37b6182SDimitry Andric // This value includes both the signature field as well as the record bytes
119f37b6182SDimitry Andric // from the symbol stream.
120f37b6182SDimitry Andric Layout.SymBytes = SymbolByteSize + sizeof(uint32_t);
121f37b6182SDimitry Andric }
122f37b6182SDimitry Andric
finalizeMsfLayout()123f37b6182SDimitry Andric Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
124f37b6182SDimitry Andric this->Layout.ModDiStream = kInvalidStreamIndex;
125f37b6182SDimitry Andric uint32_t C13Size = calculateC13DebugInfoSize();
126f37b6182SDimitry Andric auto ExpectedSN =
127f37b6182SDimitry Andric MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
128f37b6182SDimitry Andric if (!ExpectedSN)
129f37b6182SDimitry Andric return ExpectedSN.takeError();
130f37b6182SDimitry Andric Layout.ModDiStream = *ExpectedSN;
131f37b6182SDimitry Andric return Error::success();
132f37b6182SDimitry Andric }
133f37b6182SDimitry Andric
commit(BinaryStreamWriter & ModiWriter,const msf::MSFLayout & MsfLayout,WritableBinaryStreamRef MsfBuffer)134f37b6182SDimitry Andric Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
135f37b6182SDimitry Andric const msf::MSFLayout &MsfLayout,
136f37b6182SDimitry Andric WritableBinaryStreamRef MsfBuffer) {
137f37b6182SDimitry Andric // We write the Modi record to the `ModiWriter`, but we additionally write its
138f37b6182SDimitry Andric // symbol stream to a brand new stream.
139f37b6182SDimitry Andric if (auto EC = ModiWriter.writeObject(Layout))
140f37b6182SDimitry Andric return EC;
141f37b6182SDimitry Andric if (auto EC = ModiWriter.writeCString(ModuleName))
142f37b6182SDimitry Andric return EC;
143f37b6182SDimitry Andric if (auto EC = ModiWriter.writeCString(ObjFileName))
144f37b6182SDimitry Andric return EC;
145f37b6182SDimitry Andric if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
146f37b6182SDimitry Andric return EC;
147f37b6182SDimitry Andric
148f37b6182SDimitry Andric if (Layout.ModDiStream != kInvalidStreamIndex) {
149f37b6182SDimitry Andric auto NS = WritableMappedBlockStream::createIndexedStream(
1506d97bb29SDimitry Andric MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
151f37b6182SDimitry Andric WritableBinaryStreamRef Ref(*NS);
152f37b6182SDimitry Andric BinaryStreamWriter SymbolWriter(Ref);
153f37b6182SDimitry Andric // Write the symbols.
154f37b6182SDimitry Andric if (auto EC =
155f37b6182SDimitry Andric SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
156f37b6182SDimitry Andric return EC;
157*b5893f02SDimitry Andric for (ArrayRef<uint8_t> Syms : Symbols) {
158*b5893f02SDimitry Andric if (auto EC = SymbolWriter.writeBytes(Syms))
159f37b6182SDimitry Andric return EC;
160*b5893f02SDimitry Andric }
1616d97bb29SDimitry Andric assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
1626d97bb29SDimitry Andric "Invalid debug section alignment!");
163*b5893f02SDimitry Andric // TODO: Write C11 Line data
164f37b6182SDimitry Andric for (const auto &Builder : C13Builders) {
165f37b6182SDimitry Andric assert(Builder && "Empty C13 Fragment Builder!");
166f37b6182SDimitry Andric if (auto EC = Builder->commit(SymbolWriter))
167f37b6182SDimitry Andric return EC;
168f37b6182SDimitry Andric }
169f37b6182SDimitry Andric
170f37b6182SDimitry Andric // TODO: Figure out what GlobalRefs substream actually is and populate it.
171f37b6182SDimitry Andric if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
172f37b6182SDimitry Andric return EC;
173f37b6182SDimitry Andric if (SymbolWriter.bytesRemaining() > 0)
174f37b6182SDimitry Andric return make_error<RawError>(raw_error_code::stream_too_long);
175f37b6182SDimitry Andric }
176f37b6182SDimitry Andric return Error::success();
177f37b6182SDimitry Andric }
178f37b6182SDimitry Andric
addDebugSubsection(std::shared_ptr<DebugSubsection> Subsection)1796d97bb29SDimitry Andric void DbiModuleDescriptorBuilder::addDebugSubsection(
18024d58133SDimitry Andric std::shared_ptr<DebugSubsection> Subsection) {
1816d97bb29SDimitry Andric assert(Subsection);
1826d97bb29SDimitry Andric C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
1836d97bb29SDimitry Andric std::move(Subsection), CodeViewContainer::Pdb));
184f37b6182SDimitry Andric }
185edd7eaddSDimitry Andric
addDebugSubsection(const DebugSubsectionRecord & SubsectionContents)186edd7eaddSDimitry Andric void DbiModuleDescriptorBuilder::addDebugSubsection(
187edd7eaddSDimitry Andric const DebugSubsectionRecord &SubsectionContents) {
188edd7eaddSDimitry Andric C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
189edd7eaddSDimitry Andric SubsectionContents, CodeViewContainer::Pdb));
190edd7eaddSDimitry Andric }
191