LLVM  14.0.0git
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 }
llvm::BinaryStreamReader::split
std::pair< BinaryStreamReader, BinaryStreamReader > split(uint64_t Offset) const
Definition: BinaryStreamReader.cpp:169
BinaryStreamReader.h
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::pdb::hashStringV2
uint32_t hashStringV2(StringRef Str)
Definition: Hash.cpp:56
llvm::support::detail::packed_endian_specific_integral
Definition: Endian.h:206
RawTypes.h
getSignature
static std::string getSignature(FunctionType *FTy)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:440
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::BinaryStreamReader::bytesRemaining
uint64_t bytesRemaining() const
Definition: BinaryStreamReader.h:257
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
RawError.h
llvm::FixedStreamArray< support::ulittle32_t >
llvm::pdb::PDBStringTableSignature
const uint32_t PDBStringTableSignature
Definition: RawTypes.h:318
llvm::BinaryStreamReader::readInteger
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
Definition: BinaryStreamReader.h:75
llvm::BinaryStreamReader::readStreamRef
Error readStreamRef(BinaryStreamRef &Ref)
Read the entire remainder of the underlying stream into Ref.
Definition: BinaryStreamReader.cpp:130
llvm::pdb
Definition: ConcreteSymbolEnumerator.h:20
llvm::BinaryStreamReader
Provides read only access to a subclass of BinaryStream.
Definition: BinaryStreamReader.h:31
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:428
ArrayRef.h
llvm::pdb::PDBStringTableHeader
The header preceding the /names stream.
Definition: RawTypes.h:312
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::BinaryStreamReader::readObject
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...
Definition: BinaryStreamReader.h:169
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::support
Definition: Endian.h:25
PDBStringTable.h
llvm::codeview::DebugStringTableSubsectionRef
Represents a read-only view of a CodeView string table.
Definition: DebugStringTableSubsection.h:31
Hash.h
Endian.h
llvm::BinaryStreamReader::readArray
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 ...
Definition: BinaryStreamReader.h:187
llvm::BinaryStreamRef
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Definition: BinaryStreamRef.h:156
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37
llvm::pdb::hashStringV1
uint32_t hashStringV1(StringRef Str)
Definition: Hash.cpp:20