LLVM  4.0.0
NameMap.cpp
Go to the documentation of this file.
1 //===- NameMap.cpp - PDB Name Map -------------------------------*- 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 #include "llvm/ADT/StringMap.h"
12 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Error.h"
18 #include <algorithm>
19 #include <cstdint>
20 
21 using namespace llvm;
22 using namespace llvm::msf;
23 using namespace llvm::pdb;
24 
25 NameMap::NameMap() = default;
26 
27 Error NameMap::load(StreamReader &Stream) {
28  // This is some sort of weird string-set/hash table encoded in the stream.
29  // It starts with the number of bytes in the table.
30  uint32_t NumberOfBytes;
31  if (auto EC = Stream.readInteger(NumberOfBytes))
32  return joinErrors(std::move(EC),
33  make_error<RawError>(raw_error_code::corrupt_file,
34  "Expected name map length"));
35  if (Stream.bytesRemaining() < NumberOfBytes)
36  return make_error<RawError>(raw_error_code::corrupt_file,
37  "Invalid name map length");
38 
39  // Following that field is the starting offset of strings in the name table.
40  uint32_t StringsOffset = Stream.getOffset();
41  Stream.setOffset(StringsOffset + NumberOfBytes);
42 
43  // This appears to be equivalent to the total number of strings *actually*
44  // in the name table.
45  uint32_t HashSize;
46  if (auto EC = Stream.readInteger(HashSize))
47  return joinErrors(std::move(EC),
48  make_error<RawError>(raw_error_code::corrupt_file,
49  "Expected name map hash size"));
50 
51  // This appears to be an upper bound on the number of strings in the name
52  // table.
53  uint32_t MaxNumberOfStrings;
54  if (auto EC = Stream.readInteger(MaxNumberOfStrings))
55  return joinErrors(std::move(EC),
56  make_error<RawError>(raw_error_code::corrupt_file,
57  "Expected name map max strings"));
58 
59  if (MaxNumberOfStrings > (UINT32_MAX / sizeof(uint32_t)))
60  return make_error<RawError>(raw_error_code::corrupt_file,
61  "Implausible number of strings");
62 
63  const uint32_t MaxNumberOfWords = UINT32_MAX / (sizeof(uint32_t) * 8);
64 
65  // This appears to be a hash table which uses bitfields to determine whether
66  // or not a bucket is 'present'.
67  uint32_t NumPresentWords;
68  if (auto EC = Stream.readInteger(NumPresentWords))
69  return joinErrors(std::move(EC),
70  make_error<RawError>(raw_error_code::corrupt_file,
71  "Expected name map num words"));
72 
73  if (NumPresentWords > MaxNumberOfWords)
74  return make_error<RawError>(raw_error_code::corrupt_file,
75  "Number of present words is too large");
76 
77  SparseBitVector<> Present;
78  for (uint32_t I = 0; I != NumPresentWords; ++I) {
79  uint32_t Word;
80  if (auto EC = Stream.readInteger(Word))
81  return joinErrors(std::move(EC),
82  make_error<RawError>(raw_error_code::corrupt_file,
83  "Expected name map word"));
84  for (unsigned Idx = 0; Idx < 32; ++Idx)
85  if (Word & (1U << Idx))
86  Present.set((I * 32) + Idx);
87  }
88 
89  // This appears to be a hash table which uses bitfields to determine whether
90  // or not a bucket is 'deleted'.
91  uint32_t NumDeletedWords;
92  if (auto EC = Stream.readInteger(NumDeletedWords))
93  return joinErrors(
94  std::move(EC),
95  make_error<RawError>(raw_error_code::corrupt_file,
96  "Expected name map num deleted words"));
97 
98  if (NumDeletedWords > MaxNumberOfWords)
99  return make_error<RawError>(raw_error_code::corrupt_file,
100  "Number of deleted words is too large");
101 
102  SparseBitVector<> Deleted;
103  for (uint32_t I = 0; I != NumDeletedWords; ++I) {
104  uint32_t Word;
105  if (auto EC = Stream.readInteger(Word))
106  return joinErrors(std::move(EC),
107  make_error<RawError>(raw_error_code::corrupt_file,
108  "Expected name map word"));
109  for (unsigned Idx = 0; Idx < 32; ++Idx)
110  if (Word & (1U << Idx))
111  Deleted.set((I * 32) + Idx);
112  }
113 
114  for (unsigned I : Present) {
115  // For all present entries, dump out their mapping.
116  (void)I;
117 
118  // This appears to be an offset relative to the start of the strings.
119  // It tells us where the null-terminated string begins.
120  uint32_t NameOffset;
121  if (auto EC = Stream.readInteger(NameOffset))
122  return joinErrors(std::move(EC),
123  make_error<RawError>(raw_error_code::corrupt_file,
124  "Expected name map name offset"));
125 
126  // This appears to be a stream number into the stream directory.
127  uint32_t NameIndex;
128  if (auto EC = Stream.readInteger(NameIndex))
129  return joinErrors(std::move(EC),
130  make_error<RawError>(raw_error_code::corrupt_file,
131  "Expected name map name index"));
132 
133  // Compute the offset of the start of the string relative to the stream.
134  uint32_t StringOffset = StringsOffset + NameOffset;
135  uint32_t OldOffset = Stream.getOffset();
136  // Pump out our c-string from the stream.
137  StringRef Str;
138  Stream.setOffset(StringOffset);
139  if (auto EC = Stream.readZeroString(Str))
140  return joinErrors(std::move(EC),
141  make_error<RawError>(raw_error_code::corrupt_file,
142  "Expected name map name"));
143 
144  Stream.setOffset(OldOffset);
145  // Add this to a string-map from name to stream number.
146  Mapping.insert({Str, NameIndex});
147  }
148 
149  return Error::success();
150 }
151 
153  return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
154  Mapping.end());
155 }
156 
157 bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
158  auto Iter = Mapping.find(Name);
159  if (Iter == Mapping.end())
160  return false;
161  Value = Iter->second;
162  return true;
163 }
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
void setOffset(uint32_t Off)
Definition: StreamReader.h:105
Error readZeroString(StringRef &Dest)
FixedWord< 27 > Word
Error readInteger(uint8_t &Dest)
uint32_t getOffset() const
Definition: StreamReader.h:106
static ErrorSuccess success()
Create a success value.
A range adaptor for a pair of iterators.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
#define I(x, y, z)
Definition: MD5.cpp:54
uint32_t bytesRemaining() const
Definition: StreamReader.h:108
LLVM Value Representation.
Definition: Value.h:71
Lightweight error class with error context and mandatory checking.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47