LLVM  4.0.0
NameHashTable.cpp
Go to the documentation of this file.
1 //===- NameHashTable.cpp - PDB Name Hash 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"
16 #include "llvm/Support/Endian.h"
17 
18 using namespace llvm;
19 using namespace llvm::msf;
20 using namespace llvm::support;
21 using namespace llvm::pdb;
22 
23 NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {}
24 
26  struct Header {
27  support::ulittle32_t Signature;
28  support::ulittle32_t HashVersion;
29  support::ulittle32_t ByteSize;
30  };
31 
32  const Header *H;
33  if (auto EC = Stream.readObject(H))
34  return EC;
35 
36  if (H->Signature != 0xEFFEEFFE)
37  return make_error<RawError>(raw_error_code::corrupt_file,
38  "Invalid hash table signature");
39  if (H->HashVersion != 1 && H->HashVersion != 2)
40  return make_error<RawError>(raw_error_code::corrupt_file,
41  "Unsupported hash version");
42 
43  Signature = H->Signature;
44  HashVersion = H->HashVersion;
45  if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize))
46  return joinErrors(std::move(EC),
47  make_error<RawError>(raw_error_code::corrupt_file,
48  "Invalid hash table byte length"));
49 
50  const support::ulittle32_t *HashCount;
51  if (auto EC = Stream.readObject(HashCount))
52  return EC;
53 
54  if (auto EC = Stream.readArray(IDs, *HashCount))
55  return joinErrors(std::move(EC),
56  make_error<RawError>(raw_error_code::corrupt_file,
57  "Could not read bucket array"));
58 
59  if (Stream.bytesRemaining() < sizeof(support::ulittle32_t))
60  return make_error<RawError>(raw_error_code::corrupt_file,
61  "Missing name count");
62 
63  if (auto EC = Stream.readInteger(NameCount))
64  return EC;
65  return Error::success();
66 }
67 
69  if (ID == IDs[0])
70  return StringRef();
71 
72  // NamesBuffer is a buffer of null terminated strings back to back. ID is
73  // the starting offset of the string we're looking for. So just seek into
74  // the desired offset and a read a null terminated stream from that offset.
75  StringRef Result;
76  StreamReader NameReader(NamesBuffer);
77  NameReader.setOffset(ID);
78  if (auto EC = NameReader.readZeroString(Result))
79  consumeError(std::move(EC));
80  return Result;
81 }
82 
84  uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
85  size_t Count = IDs.size();
86  uint32_t Start = Hash % Count;
87  for (size_t I = 0; I < Count; ++I) {
88  // The hash is just a starting point for the search, but if it
89  // doesn't work we should find the string no matter what, because
90  // we iterate the entire array.
91  uint32_t Index = (Start + I) % Count;
92 
93  uint32_t ID = IDs[Index];
94  StringRef S = getStringForID(ID);
95  if (S == Str)
96  return ID;
97  }
98  // IDs[0] contains the ID of the "invalid" entry.
99  return IDs[0];
100 }
101 
103  return IDs;
104 }
uint32_t hashStringV2(StringRef Str)
Definition: Hash.cpp:57
void setOffset(uint32_t Off)
Definition: StreamReader.h:105
Error readZeroString(StringRef &Dest)
uint32_t size() const
Definition: StreamArray.h:233
StringRef getStringForID(uint32_t ID) const
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:21
#define H(x, y, z)
Definition: MD5.cpp:53
Error readInteger(uint8_t &Dest)
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Definition: StreamReader.h:62
void consumeError(Error Err)
Consume a Error without doing anything.
static ErrorSuccess success()
Create a success value.
uint32_t getIDForString(StringRef Str) const
Error load(msf::StreamReader &Stream)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
#define I(x, y, z)
Definition: MD5.cpp:54
Error readStreamRef(ReadableStreamRef &Ref)
uint32_t bytesRemaining() const
Definition: StreamReader.h:108
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:235
Lightweight error class with error context and mandatory checking.
std::string Hash(const Unit &U)
Definition: FuzzerSHA1.cpp:216
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
msf::FixedStreamArray< support::ulittle32_t > name_ids() const
Error readObject(const T *&Dest)
Definition: StreamReader.h:53