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