LLVM  6.0.0svn
DbiStream.cpp
Go to the documentation of this file.
1 //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
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 
11 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Object/COFF.h"
24 #include "llvm/Support/Error.h"
25 #include <algorithm>
26 #include <cstddef>
27 #include <cstdint>
28 
29 using namespace llvm;
30 using namespace llvm::codeview;
31 using namespace llvm::msf;
32 using namespace llvm::pdb;
33 using namespace llvm::support;
34 
35 template <typename ContribType>
37  BinaryStreamReader &Reader) {
38  if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
39  return make_error<RawError>(
40  raw_error_code::corrupt_file,
41  "Invalid number of bytes of section contributions");
42 
43  uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
44  if (auto EC = Reader.readArray(Output, Count))
45  return EC;
46  return Error::success();
47 }
48 
49 DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
50  : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {}
51 
52 DbiStream::~DbiStream() = default;
53 
55  BinaryStreamReader Reader(*Stream);
56 
57  if (Stream->getLength() < sizeof(DbiStreamHeader))
58  return make_error<RawError>(raw_error_code::corrupt_file,
59  "DBI Stream does not contain a header.");
60  if (auto EC = Reader.readObject(Header))
61  return make_error<RawError>(raw_error_code::corrupt_file,
62  "DBI Stream does not contain a header.");
63 
64  if (Header->VersionSignature != -1)
65  return make_error<RawError>(raw_error_code::corrupt_file,
66  "Invalid DBI version signature.");
67 
68  // Require at least version 7, which should be present in all PDBs
69  // produced in the last decade and allows us to avoid having to
70  // special case all kinds of complicated arcane formats.
71  if (Header->VersionHeader < PdbDbiV70)
72  return make_error<RawError>(raw_error_code::feature_unsupported,
73  "Unsupported DBI version.");
74 
75  if (Stream->getLength() !=
76  sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
77  Header->SecContrSubstreamSize + Header->SectionMapSize +
78  Header->FileInfoSize + Header->TypeServerSize +
79  Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
80  return make_error<RawError>(raw_error_code::corrupt_file,
81  "DBI Length does not equal sum of substreams.");
82 
83  // Only certain substreams are guaranteed to be aligned. Validate
84  // them here.
85  if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
86  return make_error<RawError>(raw_error_code::corrupt_file,
87  "DBI MODI substream not aligned.");
88  if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
89  return make_error<RawError>(
90  raw_error_code::corrupt_file,
91  "DBI section contribution substream not aligned.");
92  if (Header->SectionMapSize % sizeof(uint32_t) != 0)
93  return make_error<RawError>(raw_error_code::corrupt_file,
94  "DBI section map substream not aligned.");
95  if (Header->FileInfoSize % sizeof(uint32_t) != 0)
96  return make_error<RawError>(raw_error_code::corrupt_file,
97  "DBI file info substream not aligned.");
98  if (Header->TypeServerSize % sizeof(uint32_t) != 0)
99  return make_error<RawError>(raw_error_code::corrupt_file,
100  "DBI type server substream not aligned.");
101 
102  if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
103  return EC;
104 
105  if (auto EC = Reader.readSubstream(SecContrSubstream,
106  Header->SecContrSubstreamSize))
107  return EC;
108  if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
109  return EC;
110  if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
111  return EC;
112  if (auto EC =
113  Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
114  return EC;
115  if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
116  return EC;
117  if (auto EC = Reader.readArray(
118  DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
119  return EC;
120 
121  if (auto EC = Modules.initialize(ModiSubstream.StreamData,
122  FileInfoSubstream.StreamData))
123  return EC;
124 
125  if (auto EC = initializeSectionContributionData())
126  return EC;
127  if (auto EC = initializeSectionHeadersData())
128  return EC;
129  if (auto EC = initializeSectionMapData())
130  return EC;
131  if (auto EC = initializeFpoRecords())
132  return EC;
133 
134  if (Reader.bytesRemaining() > 0)
135  return make_error<RawError>(raw_error_code::corrupt_file,
136  "Found unexpected bytes in DBI Stream.");
137 
138  if (!ECSubstream.empty()) {
139  BinaryStreamReader ECReader(ECSubstream.StreamData);
140  if (auto EC = ECNames.reload(ECReader))
141  return EC;
142  }
143 
144  return Error::success();
145 }
146 
148  uint32_t Value = Header->VersionHeader;
149  return static_cast<PdbRaw_DbiVer>(Value);
150 }
151 
152 uint32_t DbiStream::getAge() const { return Header->Age; }
153 
155  return Header->PublicSymbolStreamIndex;
156 }
157 
159  return Header->GlobalSymbolStreamIndex;
160 }
161 
162 uint16_t DbiStream::getFlags() const { return Header->Flags; }
163 
165  return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
166 }
167 
168 bool DbiStream::hasCTypes() const {
169  return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
170 }
171 
172 bool DbiStream::isStripped() const {
173  return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
174 }
175 
176 uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
177 
179  return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
181 }
182 
184  return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
186 }
187 
188 uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
189 
191 
193  return Header->SymRecordStreamIndex;
194 }
195 
197  uint16_t Machine = Header->MachineType;
198  return static_cast<PDB_Machine>(Machine);
199 }
200 
202  return SectionHeaders;
203 }
204 
206  return FpoRecords;
207 }
208 
209 const DbiModuleList &DbiStream::modules() const { return Modules; }
210 
212  return SectionMap;
213 }
214 
216  ISectionContribVisitor &Visitor) const {
217  if (!SectionContribs.empty()) {
218  assert(SectionContribVersion == DbiSecContribVer60);
219  for (auto &SC : SectionContribs)
220  Visitor.visit(SC);
221  } else if (!SectionContribs2.empty()) {
222  assert(SectionContribVersion == DbiSecContribV2);
223  for (auto &SC : SectionContribs2)
224  Visitor.visit(SC);
225  }
226 }
227 
229  return ECNames.getStringForID(NI);
230 }
231 
232 Error DbiStream::initializeSectionContributionData() {
233  if (SecContrSubstream.empty())
234  return Error::success();
235 
236  BinaryStreamReader SCReader(SecContrSubstream.StreamData);
237  if (auto EC = SCReader.readEnum(SectionContribVersion))
238  return EC;
239 
240  if (SectionContribVersion == DbiSecContribVer60)
241  return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
242  if (SectionContribVersion == DbiSecContribV2)
243  return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
244 
245  return make_error<RawError>(raw_error_code::feature_unsupported,
246  "Unsupported DBI Section Contribution version");
247 }
248 
249 // Initializes this->SectionHeaders.
250 Error DbiStream::initializeSectionHeadersData() {
251  if (DbgStreams.size() == 0)
252  return Error::success();
253 
255  if (StreamNum == kInvalidStreamIndex)
256  return Error::success();
257 
258  if (StreamNum >= Pdb.getNumStreams())
259  return make_error<RawError>(raw_error_code::no_stream);
260 
261  auto SHS = MappedBlockStream::createIndexedStream(
262  Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
263 
264  size_t StreamLen = SHS->getLength();
265  if (StreamLen % sizeof(object::coff_section))
266  return make_error<RawError>(raw_error_code::corrupt_file,
267  "Corrupted section header stream.");
268 
269  size_t NumSections = StreamLen / sizeof(object::coff_section);
270  BinaryStreamReader Reader(*SHS);
271  if (auto EC = Reader.readArray(SectionHeaders, NumSections))
272  return make_error<RawError>(raw_error_code::corrupt_file,
273  "Could not read a bitmap.");
274 
275  SectionHeaderStream = std::move(SHS);
276  return Error::success();
277 }
278 
279 // Initializes this->Fpos.
280 Error DbiStream::initializeFpoRecords() {
281  if (DbgStreams.size() == 0)
282  return Error::success();
283 
285 
286  // This means there is no FPO data.
287  if (StreamNum == kInvalidStreamIndex)
288  return Error::success();
289 
290  if (StreamNum >= Pdb.getNumStreams())
291  return make_error<RawError>(raw_error_code::no_stream);
292 
293  auto FS = MappedBlockStream::createIndexedStream(
294  Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
295 
296  size_t StreamLen = FS->getLength();
297  if (StreamLen % sizeof(object::FpoData))
298  return make_error<RawError>(raw_error_code::corrupt_file,
299  "Corrupted New FPO stream.");
300 
301  size_t NumRecords = StreamLen / sizeof(object::FpoData);
302  BinaryStreamReader Reader(*FS);
303  if (auto EC = Reader.readArray(FpoRecords, NumRecords))
304  return make_error<RawError>(raw_error_code::corrupt_file,
305  "Corrupted New FPO stream.");
306  FpoStream = std::move(FS);
307  return Error::success();
308 }
309 
311  return SecContrSubstream;
312 }
313 
315  return SecMapSubstream;
316 }
317 
319  return ModiSubstream;
320 }
321 
323  return FileInfoSubstream;
324 }
325 
327  return TypeServerMapSubstream;
328 }
329 
330 BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
331 
332 Error DbiStream::initializeSectionMapData() {
333  if (SecMapSubstream.empty())
334  return Error::success();
335 
336  BinaryStreamReader SMReader(SecMapSubstream.StreamData);
337  const SecMapHeader *Header;
338  if (auto EC = SMReader.readObject(Header))
339  return EC;
340  if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
341  return EC;
342  return Error::success();
343 }
344 
346  uint16_t T = static_cast<uint16_t>(Type);
347  if (T >= DbgStreams.size())
348  return kInvalidStreamIndex;
349  return DbgStreams[T];
350 }
support::little32_t FileInfoSize
Size of file info substream.
Definition: RawTypes.h:153
virtual void visit(const SectionContrib &C)=0
Error readSubstream(BinarySubstreamRef &Stream, uint32_t Size)
Read Length bytes from the underlying stream into Stream.
static const uint16_t FlagHasCTypesMask
Definition: RawTypes.h:103
static Error loadSectionContribs(FixedStreamArray< ContribType > &Output, BinaryStreamReader &Reader)
Definition: DbiStream.cpp:36
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
Expected< StringRef > getECName(uint32_t NI) const
Definition: DbiStream.cpp:228
BinarySubstreamRef getECSubstreamData() const
Definition: DbiStream.cpp:330
support::little32_t VersionSignature
Definition: RawTypes.h:119
static const uint16_t BuildMinorMask
uint16_t MinorVersion : 8; uint16_t MajorVersion : 7; uint16_t NewVersionFormat : 1; ...
Definition: RawTypes.h:110
Error readObject(const T *&Dest)
Get a pointer to an object of type T from the underlying stream, as if by memcpy, and store the resul...
support::ulittle16_t GlobalSymbolStreamIndex
Global symbol stream #.
Definition: RawTypes.h:126
Error reload(BinaryStreamReader &Reader)
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
uint16_t getGlobalSymbolStreamIndex() const
Definition: DbiStream.cpp:158
support::ulittle16_t BuildNumber
See DbiBuildNo structure.
Definition: RawTypes.h:129
uint32_t getNumStreams() const override
Definition: PDBFile.cpp:84
BinarySubstreamRef getSectionContributionData() const
Definition: DbiStream.cpp:310
Definition: BitVector.h:920
bool isStripped() const
Definition: DbiStream.cpp:172
support::little32_t TypeServerSize
Size of type server map.
Definition: RawTypes.h:156
support::little32_t SectionMapSize
Size of sec. map substream.
Definition: RawTypes.h:150
FixedStreamArray< object::FpoData > getFpoRecords()
Definition: DbiStream.cpp:205
PDB_Machine getMachineType() const
Definition: DbiStream.cpp:196
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
The fixed size header that appears at the beginning of the DBI Stream.
Definition: RawTypes.h:118
BinarySubstreamRef getSecMapSubstreamData() const
Definition: DbiStream.cpp:314
uint32_t getSymRecordStreamIndex() const
Definition: DbiStream.cpp:192
support::little32_t ECSubstreamSize
Size of EC stream (what is EC?)
Definition: RawTypes.h:165
FixedStreamArray< object::coff_section > getSectionHeaders()
Definition: DbiStream.cpp:201
Expected< StringRef > getStringForID(uint32_t ID) const
uint16_t getBuildNumber() const
Definition: DbiStream.cpp:176
#define T
BinaryStreamRef getMsfBuffer() const
Definition: PDBFile.h:83
COFF::MachineTypes Machine
Definition: COFFYAML.cpp:363
BinarySubstreamRef getTypeServerMapSubstreamData() const
Definition: DbiStream.cpp:326
const uint16_t kInvalidStreamIndex
Definition: RawConstants.h:20
BumpPtrAllocator & getAllocator()
Definition: PDBFile.h:104
support::ulittle16_t PdbDllRbld
rbld number of mspdbNNN.dll
Definition: RawTypes.h:141
static const uint16_t BuildMajorShift
Definition: RawTypes.h:114
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
uint32_t getAge() const
Definition: DbiStream.cpp:152
uint16_t getBuildMajorVersion() const
Definition: DbiStream.cpp:178
Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo)
uint32_t getDebugStreamIndex(DbgHeaderType Type) const
If the given stream type is present, returns its stream index.
Definition: DbiStream.cpp:345
uint16_t getBuildMinorVersion() const
Definition: DbiStream.cpp:183
const DbiModuleList & modules() const
Definition: DbiStream.cpp:209
uint32_t getPdbDllVersion() const
Definition: DbiStream.cpp:190
support::ulittle16_t PdbDllVersion
version of mspdbNNN.dll
Definition: RawTypes.h:135
BinaryStreamRef StreamData
static const uint16_t FlagIncrementalMask
uint16_t IncrementalLinking : 1; // True if linked incrementally uint16_t IsStripped : 1; // True if ...
Definition: RawTypes.h:101
support::little32_t OptionalDbgHdrSize
Size of DbgHeader info.
Definition: RawTypes.h:162
support::ulittle16_t Flags
See DbiFlags enum.
Definition: RawTypes.h:168
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
CHAIN = SC CHAIN, Imm128 - System call.
support::ulittle16_t SecCount
Definition: RawTypes.h:68
BinarySubstreamRef getFileInfoSubstreamData() const
Definition: DbiStream.cpp:322
static const uint16_t FlagStrippedMask
Definition: RawTypes.h:102
support::little32_t ModiSubstreamSize
Size of module info stream.
Definition: RawTypes.h:144
PdbRaw_DbiVer getDbiVersion() const
Definition: DbiStream.cpp:147
support::little32_t SecContrSubstreamSize
Size of sec. contrib stream.
Definition: RawTypes.h:147
static const uint16_t BuildMajorMask
Definition: RawTypes.h:113
support::ulittle32_t Age
How "old" is this DBI Stream. Should match the age of the PDB InfoStream.
Definition: RawTypes.h:123
support::ulittle16_t SymRecordStreamIndex
Symbol records stream #.
Definition: RawTypes.h:138
support::ulittle32_t VersionHeader
Definition: RawTypes.h:120
static const uint16_t BuildMinorShift
Definition: RawTypes.h:111
uint32_t bytesRemaining() const
uint16_t getPdbDllRbld() const
Definition: DbiStream.cpp:188
uint16_t getPublicSymbolStreamIndex() const
Definition: DbiStream.cpp:154
uint16_t getFlags() const
Definition: DbiStream.cpp:162
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const msf::MSFLayout & getMsfLayout() const
Definition: PDBFile.h:82
LLVM Value Representation.
Definition: Value.h:73
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
support::ulittle16_t PublicSymbolStreamIndex
Public symbols stream #.
Definition: RawTypes.h:132
Provides read only access to a subclass of BinaryStream.
BinarySubstreamRef getModiSubstreamData() const
Definition: DbiStream.cpp:318
Error readEnum(T &Dest)
Similar to readInteger.
void visitSectionContributions(ISectionContribVisitor &Visitor) const
Definition: DbiStream.cpp:215
support::ulittle16_t MachineType
See PDB_MachineType enum.
Definition: RawTypes.h:171
FixedStreamArray< SecMapEntry > getSectionMap() const
Definition: DbiStream.cpp:211
bool hasCTypes() const
Definition: DbiStream.cpp:168
bool isIncrementallyLinked() const
Definition: DbiStream.cpp:164
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...