LLVM  9.0.0svn
DbiModuleDescriptorBuilder.cpp
Go to the documentation of this file.
1 //===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/BinaryFormat/COFF.h"
22 
23 using namespace llvm;
24 using namespace llvm::codeview;
25 using namespace llvm::msf;
26 using namespace llvm::pdb;
27 
29  uint32_t C13Size) {
30  uint32_t Size = sizeof(uint32_t); // Signature
31  Size += alignTo(SymbolByteSize, 4); // Symbol Data
32  Size += 0; // TODO: Layout.C11Bytes
33  Size += C13Size; // C13 Debug Info Size
34  Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
35  Size += 0; // GlobalRefs substream bytes
36  return Size;
37 }
38 
39 DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
40  uint32_t ModIndex,
41  msf::MSFBuilder &Msf)
42  : MSF(Msf), ModuleName(ModuleName) {
43  ::memset(&Layout, 0, sizeof(Layout));
44  Layout.Mod = ModIndex;
45 }
46 
48 
50  return Layout.ModDiStream;
51 }
52 
54  ObjFileName = Name;
55 }
56 
58  PdbFilePathNI = NI;
59 }
60 
62  const SectionContrib &SC) {
63  Layout.SC = SC;
64 }
65 
67  // Defer to the bulk API. It does the same thing.
68  addSymbolsInBulk(Symbol.data());
69 }
70 
72  ArrayRef<uint8_t> BulkSymbols) {
73  // Do nothing for empty runs of symbols.
74  if (BulkSymbols.empty())
75  return;
76 
77  Symbols.push_back(BulkSymbols);
78  // Symbols written to a PDB file are required to be 4 byte aligned. The same
79  // is not true of object files.
80  assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 &&
81  "Invalid Symbol alignment!");
82  SymbolByteSize += BulkSymbols.size();
83 }
84 
85 void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
86  SourceFiles.push_back(Path);
87 }
88 
89 uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
90  uint32_t Result = 0;
91  for (const auto &Builder : C13Builders) {
92  assert(Builder && "Empty C13 Fragment Builder!");
93  Result += Builder->calculateSerializedLength();
94  }
95  return Result;
96 }
97 
99  uint32_t L = sizeof(Layout);
100  uint32_t M = ModuleName.size() + 1;
101  uint32_t O = ObjFileName.size() + 1;
102  return alignTo(L + M + O, sizeof(uint32_t));
103 }
104 
106  Layout.FileNameOffs = 0; // TODO: Fix this
107  Layout.Flags = 0; // TODO: Fix this
108  Layout.C11Bytes = 0;
109  Layout.C13Bytes = calculateC13DebugInfoSize();
110  (void)Layout.Mod; // Set in constructor
111  (void)Layout.ModDiStream; // Set in finalizeMsfLayout
112  Layout.NumFiles = SourceFiles.size();
113  Layout.PdbFilePathNI = PdbFilePathNI;
114  Layout.SrcFileNameNI = 0;
115 
116  // This value includes both the signature field as well as the record bytes
117  // from the symbol stream.
118  Layout.SymBytes =
120 }
121 
123  this->Layout.ModDiStream = kInvalidStreamIndex;
124  uint32_t C13Size = calculateC13DebugInfoSize();
125  if (!C13Size && !SymbolByteSize)
126  return Error::success();
127  auto ExpectedSN =
128  MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
129  if (!ExpectedSN)
130  return ExpectedSN.takeError();
131  Layout.ModDiStream = *ExpectedSN;
132  return Error::success();
133 }
134 
136  const msf::MSFLayout &MsfLayout,
137  WritableBinaryStreamRef MsfBuffer) {
138  // We write the Modi record to the `ModiWriter`, but we additionally write its
139  // symbol stream to a brand new stream.
140  if (auto EC = ModiWriter.writeObject(Layout))
141  return EC;
142  if (auto EC = ModiWriter.writeCString(ModuleName))
143  return EC;
144  if (auto EC = ModiWriter.writeCString(ObjFileName))
145  return EC;
146  if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
147  return EC;
148 
149  if (Layout.ModDiStream != kInvalidStreamIndex) {
150  auto NS = WritableMappedBlockStream::createIndexedStream(
151  MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
153  BinaryStreamWriter SymbolWriter(Ref);
154  // Write the symbols.
155  if (auto EC =
157  return EC;
158  for (ArrayRef<uint8_t> Syms : Symbols) {
159  if (auto EC = SymbolWriter.writeBytes(Syms))
160  return EC;
161  }
162  assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
163  "Invalid debug section alignment!");
164  // TODO: Write C11 Line data
165  for (const auto &Builder : C13Builders) {
166  assert(Builder && "Empty C13 Fragment Builder!");
167  if (auto EC = Builder->commit(SymbolWriter))
168  return EC;
169  }
170 
171  // TODO: Figure out what GlobalRefs substream actually is and populate it.
172  if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
173  return EC;
174  if (SymbolWriter.bytesRemaining() > 0)
175  return make_error<RawError>(raw_error_code::stream_too_long);
176  }
177  return Error::success();
178 }
179 
181  std::shared_ptr<DebugSubsection> Subsection) {
182  assert(Subsection);
183  C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
184  std::move(Subsection), CodeViewContainer::Pdb));
185 }
186 
188  const DebugSubsectionRecord &SubsectionContents) {
189  C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
190  SubsectionContents, CodeViewContainer::Pdb));
191 }
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
Error writeBytes(ArrayRef< uint8_t > Buffer)
Write the bytes specified in Buffer to the underlying stream.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
support::ulittle16_t NumFiles
Number of files contributing to this module.
Definition: RawTypes.h:238
support::ulittle32_t SrcFileNameNI
Name Index for src file name.
Definition: RawTypes.h:252
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
Error commit(BinaryStreamWriter &ModiWriter, const msf::MSFLayout &MsfLayout, WritableBinaryStreamRef MsfBuffer)
support::ulittle32_t SymBytes
Size of local symbol debug info in above stream.
Definition: RawTypes.h:229
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:684
uint32_t alignOf(CodeViewContainer Container)
Definition: CodeView.h:606
The access may reference the value stored in memory.
support::ulittle32_t PdbFilePathNI
Name Index for path to compiler PDB.
Definition: RawTypes.h:255
support::ulittle16_t Flags
See ModInfoFlags definition.
Definition: RawTypes.h:223
SectionContrib SC
First section contribution of this module.
Definition: RawTypes.h:220
ArrayRef< uint8_t > data() const
Definition: CVRecord.h:50
void setFirstSectionContrib(const SectionContrib &SC)
support::ulittle32_t C13Bytes
Size of C13 line number info in above stream.
Definition: RawTypes.h:235
const uint16_t kInvalidStreamIndex
Definition: RawConstants.h:19
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
support::ulittle32_t FileNameOffs
Array of [0..NumFiles) DBI name buffer offsets.
Definition: RawTypes.h:249
Provides write only access to a subclass of WritableBinaryStream.
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
uint32_t bytesRemaining() const
Error writeCString(StringRef Str)
Write the string Str to the underlying stream followed by a null terminator.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
support::ulittle32_t Mod
Currently opened module.
Definition: RawTypes.h:217
CHAIN = SC CHAIN, Imm128 - System call.
Expected< uint32_t > addStream(uint32_t Size, ArrayRef< uint32_t > Blocks)
Add a stream to the MSF file with the given size, occupying the given list of blocks.
Definition: MSFBuilder.cpp:154
support::ulittle16_t ModDiStream
Stream Number of module debug info.
Definition: RawTypes.h:226
static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize, uint32_t C13Size)
support::ulittle32_t C11Bytes
Size of C11 line number info in above stream.
Definition: RawTypes.h:232
Error padToAlignment(uint32_t Align)
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
uint32_t getNextSymbolOffset() const
Return the offset within the module symbol stream of the next symbol record passed to addSymbol...
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
void addSymbolsInBulk(ArrayRef< uint8_t > BulkSymbols)
CVRecord is a fat pointer (base + size pair) to a symbol or type record.
Definition: CVRecord.h:30
BumpPtrAllocator & getAllocator()
Definition: MSFBuilder.h:118
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:143
void addDebugSubsection(std::shared_ptr< codeview::DebugSubsection > Subsection)