PDBStringTable.cpp revision 341825
1217309Snwhitehorn//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//
2251843Sbapt//
3217309Snwhitehorn//                     The LLVM Compiler Infrastructure
4251843Sbapt//
5217309Snwhitehorn// This file is distributed under the University of Illinois Open Source
6217309Snwhitehorn// License. See LICENSE.TXT for details.
7217309Snwhitehorn//
8217309Snwhitehorn//===----------------------------------------------------------------------===//
9217309Snwhitehorn
10217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
11217309Snwhitehorn
12217309Snwhitehorn#include "llvm/ADT/ArrayRef.h"
13217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/Hash.h"
14217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/RawError.h"
15217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
16217309Snwhitehorn#include "llvm/Support/BinaryStreamReader.h"
17217309Snwhitehorn#include "llvm/Support/Endian.h"
18217309Snwhitehorn
19217309Snwhitehornusing namespace llvm;
20217309Snwhitehornusing namespace llvm::support;
21217309Snwhitehornusing namespace llvm::pdb;
22217309Snwhitehorn
23217309Snwhitehornuint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; }
24217309Snwhitehornuint32_t PDBStringTable::getNameCount() const { return NameCount; }
25217309Snwhitehornuint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
26217309Snwhitehornuint32_t PDBStringTable::getSignature() const { return Header->Signature; }
27217309Snwhitehorn
28217309SnwhitehornError PDBStringTable::readHeader(BinaryStreamReader &Reader) {
29217309Snwhitehorn  if (auto EC = Reader.readObject(Header))
30217309Snwhitehorn    return EC;
31217309Snwhitehorn
32217309Snwhitehorn  if (Header->Signature != PDBStringTableSignature)
33251843Sbapt    return make_error<RawError>(raw_error_code::corrupt_file,
34217309Snwhitehorn                                "Invalid hash table signature");
35217309Snwhitehorn  if (Header->HashVersion != 1 && Header->HashVersion != 2)
36217309Snwhitehorn    return make_error<RawError>(raw_error_code::corrupt_file,
37217309Snwhitehorn                                "Unsupported hash version");
38217309Snwhitehorn
39217309Snwhitehorn  assert(Reader.bytesRemaining() == 0);
40220749Snwhitehorn  return Error::success();
41217309Snwhitehorn}
42217309Snwhitehorn
43217309SnwhitehornError PDBStringTable::readStrings(BinaryStreamReader &Reader) {
44217309Snwhitehorn  BinaryStreamRef Stream;
45217309Snwhitehorn  if (auto EC = Reader.readStreamRef(Stream))
46217309Snwhitehorn    return EC;
47217309Snwhitehorn
48217309Snwhitehorn  if (auto EC = Strings.initialize(Stream)) {
49217309Snwhitehorn    return joinErrors(std::move(EC),
50217309Snwhitehorn                      make_error<RawError>(raw_error_code::corrupt_file,
51217309Snwhitehorn                                           "Invalid hash table byte length"));
52217309Snwhitehorn  }
53217309Snwhitehorn
54217309Snwhitehorn  assert(Reader.bytesRemaining() == 0);
55217309Snwhitehorn  return Error::success();
56217309Snwhitehorn}
57217309Snwhitehorn
58217309Snwhitehornconst codeview::DebugStringTableSubsectionRef &
59217309SnwhitehornPDBStringTable::getStringTable() const {
60217309Snwhitehorn  return Strings;
61217309Snwhitehorn}
62217309Snwhitehorn
63217309SnwhitehornError PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
64217309Snwhitehorn  const support::ulittle32_t *HashCount;
65217309Snwhitehorn  if (auto EC = Reader.readObject(HashCount))
66217309Snwhitehorn    return EC;
67217309Snwhitehorn
68217309Snwhitehorn  if (auto EC = Reader.readArray(IDs, *HashCount)) {
69217309Snwhitehorn    return joinErrors(std::move(EC),
70217309Snwhitehorn                      make_error<RawError>(raw_error_code::corrupt_file,
71217309Snwhitehorn                                           "Could not read bucket array"));
72217309Snwhitehorn  }
73217309Snwhitehorn
74217309Snwhitehorn  return Error::success();
75217309Snwhitehorn}
76217309Snwhitehorn
77217309SnwhitehornError PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
78217309Snwhitehorn  if (auto EC = Reader.readInteger(NameCount))
79217309Snwhitehorn    return EC;
80217309Snwhitehorn
81217309Snwhitehorn  assert(Reader.bytesRemaining() == 0);
82217309Snwhitehorn  return Error::success();
83217309Snwhitehorn}
84217309Snwhitehorn
85217309SnwhitehornError PDBStringTable::reload(BinaryStreamReader &Reader) {
86217309Snwhitehorn
87217309Snwhitehorn  BinaryStreamReader SectionReader;
88217309Snwhitehorn
89217309Snwhitehorn  std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
90217309Snwhitehorn  if (auto EC = readHeader(SectionReader))
91217309Snwhitehorn    return EC;
92217309Snwhitehorn
93217309Snwhitehorn  std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
94217309Snwhitehorn  if (auto EC = readStrings(SectionReader))
95217309Snwhitehorn    return EC;
96217309Snwhitehorn
97217309Snwhitehorn  // We don't know how long the hash table is until we parse it, so let the
98217309Snwhitehorn  // function responsible for doing that figure it out.
99217309Snwhitehorn  if (auto EC = readHashTable(Reader))
100217309Snwhitehorn    return EC;
101217309Snwhitehorn
102217309Snwhitehorn  std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
103217309Snwhitehorn  if (auto EC = readEpilogue(SectionReader))
104217309Snwhitehorn    return EC;
105217309Snwhitehorn
106217309Snwhitehorn  assert(Reader.bytesRemaining() == 0);
107217309Snwhitehorn  return Error::success();
108217309Snwhitehorn}
109217309Snwhitehorn
110217309SnwhitehornExpected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
111217309Snwhitehorn  return Strings.getString(ID);
112217309Snwhitehorn}
113217309Snwhitehorn
114217309SnwhitehornExpected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
115217309Snwhitehorn  uint32_t Hash =
116217309Snwhitehorn      (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
117217309Snwhitehorn  size_t Count = IDs.size();
118217309Snwhitehorn  uint32_t Start = Hash % Count;
119217309Snwhitehorn  for (size_t I = 0; I < Count; ++I) {
120217309Snwhitehorn    // The hash is just a starting point for the search, but if it
121217309Snwhitehorn    // doesn't work we should find the string no matter what, because
122217309Snwhitehorn    // we iterate the entire array.
123217309Snwhitehorn    uint32_t Index = (Start + I) % Count;
124217309Snwhitehorn
125217309Snwhitehorn    // If we find 0, it means the item isn't in the hash table.
126217309Snwhitehorn    uint32_t ID = IDs[Index];
127217309Snwhitehorn    if (ID == 0)
128217309Snwhitehorn      return make_error<RawError>(raw_error_code::no_entry);
129217309Snwhitehorn    auto ExpectedStr = getStringForID(ID);
130217309Snwhitehorn    if (!ExpectedStr)
131217309Snwhitehorn      return ExpectedStr.takeError();
132217309Snwhitehorn
133217309Snwhitehorn    if (*ExpectedStr == Str)
134217309Snwhitehorn      return ID;
135217309Snwhitehorn  }
136217309Snwhitehorn  return make_error<RawError>(raw_error_code::no_entry);
137}
138
139FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
140  return IDs;
141}
142