LLVM  8.0.1
PDBStringTable.cpp
Go to the documentation of this file.
1 //===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//
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 
12 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/Support/Endian.h"
18 
19 using namespace llvm;
20 using namespace llvm::support;
21 using namespace llvm::pdb;
22 
23 uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; }
24 uint32_t PDBStringTable::getNameCount() const { return NameCount; }
25 uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
26 uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
27 
28 Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
29  if (auto EC = Reader.readObject(Header))
30  return EC;
31 
32  if (Header->Signature != PDBStringTableSignature)
33  return make_error<RawError>(raw_error_code::corrupt_file,
34  "Invalid hash table signature");
35  if (Header->HashVersion != 1 && Header->HashVersion != 2)
36  return make_error<RawError>(raw_error_code::corrupt_file,
37  "Unsupported hash version");
38 
39  assert(Reader.bytesRemaining() == 0);
40  return Error::success();
41 }
42 
43 Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
44  BinaryStreamRef Stream;
45  if (auto EC = Reader.readStreamRef(Stream))
46  return EC;
47 
48  if (auto EC = Strings.initialize(Stream)) {
49  return joinErrors(std::move(EC),
50  make_error<RawError>(raw_error_code::corrupt_file,
51  "Invalid hash table byte length"));
52  }
53 
54  assert(Reader.bytesRemaining() == 0);
55  return Error::success();
56 }
57 
59 PDBStringTable::getStringTable() const {
60  return Strings;
61 }
62 
63 Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
64  const support::ulittle32_t *HashCount;
65  if (auto EC = Reader.readObject(HashCount))
66  return EC;
67 
68  if (auto EC = Reader.readArray(IDs, *HashCount)) {
69  return joinErrors(std::move(EC),
70  make_error<RawError>(raw_error_code::corrupt_file,
71  "Could not read bucket array"));
72  }
73 
74  return Error::success();
75 }
76 
77 Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
78  if (auto EC = Reader.readInteger(NameCount))
79  return EC;
80 
81  assert(Reader.bytesRemaining() == 0);
82  return Error::success();
83 }
84 
85 Error PDBStringTable::reload(BinaryStreamReader &Reader) {
86 
87  BinaryStreamReader SectionReader;
88 
89  std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
90  if (auto EC = readHeader(SectionReader))
91  return EC;
92 
93  std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
94  if (auto EC = readStrings(SectionReader))
95  return EC;
96 
97  // We don't know how long the hash table is until we parse it, so let the
98  // function responsible for doing that figure it out.
99  if (auto EC = readHashTable(Reader))
100  return EC;
101 
102  std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
103  if (auto EC = readEpilogue(SectionReader))
104  return EC;
105 
106  assert(Reader.bytesRemaining() == 0);
107  return Error::success();
108 }
109 
110 Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
111  return Strings.getString(ID);
112 }
113 
114 Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
115  uint32_t Hash =
116  (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
117  size_t Count = IDs.size();
118  uint32_t Start = Hash % Count;
119  for (size_t I = 0; I < Count; ++I) {
120  // The hash is just a starting point for the search, but if it
121  // doesn't work we should find the string no matter what, because
122  // we iterate the entire array.
123  uint32_t Index = (Start + I) % Count;
124 
125  // If we find 0, it means the item isn't in the hash table.
126  uint32_t ID = IDs[Index];
127  if (ID == 0)
128  return make_error<RawError>(raw_error_code::no_entry);
129  auto ExpectedStr = getStringForID(ID);
130  if (!ExpectedStr)
131  return ExpectedStr.takeError();
132 
133  if (*ExpectedStr == Str)
134  return ID;
135  }
136  return make_error<RawError>(raw_error_code::no_entry);
137 }
138 
139 FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
140  return IDs;
141 }
uint32_t hashStringV2(StringRef Str)
Definition: Hash.cpp:57
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream&#39;s offset.
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...
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
std::pair< BinaryStreamReader, BinaryStreamReader > split(uint32_t Offset) const
The header preceeding the /names stream.
Definition: RawTypes.h:313
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:21
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Represents a read-only view of a CodeView string table.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:424
#define I(x, y, z)
Definition: MD5.cpp:58
Error readStreamRef(BinaryStreamRef &Ref)
Read the entire remainder of the underlying stream into Ref.
uint32_t bytesRemaining() const
const uint32_t PDBStringTableSignature
Definition: RawTypes.h:319
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
Provides read only access to a subclass of BinaryStream.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
static std::string getSignature(FunctionType *FTy)
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 ...