LLVM  4.0.0
PublicsStream.cpp
Go to the documentation of this file.
1 //===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
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 // The data structures defined in this file are based on the reference
11 // implementation which is available at
12 // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
13 //
14 // When you are reading the reference source code, you'd find the
15 // information below useful.
16 //
17 // - ppdb1->m_fMinimalDbgInfo seems to be always true.
18 // - SMALLBUCKETS macro is defined.
19 //
20 // The reference doesn't compile, so I learned just by reading code.
21 // It's not guaranteed to be correct.
22 //
23 //===----------------------------------------------------------------------===//
24 
25 #include "GSI.h"
34 #include "llvm/Support/Endian.h"
35 #include "llvm/Support/Error.h"
36 #include <algorithm>
37 #include <cstdint>
38 
39 using namespace llvm;
40 using namespace llvm::msf;
41 using namespace llvm::support;
42 using namespace llvm::pdb;
43 
44 // This is PSGSIHDR struct defined in
45 // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
52  char Padding[2];
55 };
56 
57 PublicsStream::PublicsStream(PDBFile &File,
58  std::unique_ptr<MappedBlockStream> Stream)
59  : Pdb(File), Stream(std::move(Stream)) {}
60 
62 
63 uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
64 uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
65 
66 // Publics stream contains fixed-size headers and a serialized hash table.
67 // This implementation is not complete yet. It reads till the end of the
68 // stream so that we verify the stream is at least not corrupted. However,
69 // we skip over the hash table which we believe contains information about
70 // public symbols.
72  StreamReader Reader(*Stream);
73 
74  // Check stream size.
75  if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
76  return make_error<RawError>(raw_error_code::corrupt_file,
77  "Publics Stream does not contain a header.");
78 
79  // Read PSGSIHDR and GSIHashHdr structs.
80  if (Reader.readObject(Header))
81  return make_error<RawError>(raw_error_code::corrupt_file,
82  "Publics Stream does not contain a header.");
83 
84  if (auto EC = readGSIHashHeader(HashHdr, Reader))
85  return EC;
86 
87  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
88  return EC;
89 
90  if (auto EC = readGSIHashBuckets(HashBuckets, HashHdr, Reader))
91  return EC;
92  NumBuckets = HashBuckets.size();
93 
94  // Something called "address map" follows.
95  uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
96  if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries))
97  return joinErrors(std::move(EC),
98  make_error<RawError>(raw_error_code::corrupt_file,
99  "Could not read an address map."));
100 
101  // Something called "thunk map" follows.
102  if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks))
103  return joinErrors(std::move(EC),
104  make_error<RawError>(raw_error_code::corrupt_file,
105  "Could not read a thunk map."));
106 
107  // Something called "section map" follows.
108  if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
109  return joinErrors(std::move(EC),
110  make_error<RawError>(raw_error_code::corrupt_file,
111  "Could not read a section map."));
112 
113  if (Reader.bytesRemaining() > 0)
114  return make_error<RawError>(raw_error_code::corrupt_file,
115  "Corrupted publics stream.");
116  return Error::success();
117 }
118 
120 PublicsStream::getSymbols(bool *HadError) const {
121  auto SymbolS = Pdb.getPDBSymbolStream();
122  if (SymbolS.takeError()) {
124  return make_range(Iter, Iter);
125  }
126  SymbolStream &SS = SymbolS.get();
127 
128  return SS.getSymbols(HadError);
129 }
130 
VarStreamArray represents an array of variable length records backed by a stream. ...
Definition: StreamArray.h:75
iterator_range< codeview::CVSymbolArray::Iterator > getSymbols(bool *HadError) const
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
Error readGSIHashBuckets(msf::FixedStreamArray< support::ulittle32_t > &HashBuckets, const GSIHashHeader *HashHdr, msf::StreamReader &Reader)
Definition: GSI.cpp:31
Header of the hash tables found in the globals and publics sections.
Definition: GSI.h:48
uint32_t size() const
Definition: StreamArray.h:233
Expected< SymbolStream & > getPDBSymbolStream()
Definition: PDBFile.cpp:307
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Definition: StreamReader.h:62
Error readGSIHashHeader(const GSIHashHeader *&HashHdr, msf::StreamReader &Reader)
Definition: GSI.cpp:59
uint32_t getSymHash() const
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static ErrorSuccess success()
Create a success value.
A range adaptor for a pair of iterators.
iterator_range< codeview::CVSymbolArray::Iterator > getSymbols(bool *HadError) const
Error joinErrors(Error E1, Error E2)
Concatenate errors.
uint32_t getAddrMap() const
uint32_t bytesRemaining() const
Definition: StreamReader.h:108
Lightweight error class with error context and mandatory checking.
Error readGSIHashRecords(msf::FixedStreamArray< PSHashRecord > &HashRecords, const GSIHashHeader *HashHdr, msf::StreamReader &Reader)
Definition: GSI.cpp:73
Error readObject(const T *&Dest)
Definition: StreamReader.h:53