blob: 202e7173b0ef75d582d9741cd11e5c30ee5cca68 [file] [log] [blame]
Zachary Turner2f09b502016-04-29 17:28:47 +00001//===- NameMap.cpp - PDB Name Map -------------------------------*- C++ -*-===//
Zachary Turnerf34e0162016-04-26 16:20:00 +00002//
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
Zachary Turner2f09b502016-04-29 17:28:47 +000010#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
Zachary Turnerf34e0162016-04-26 16:20:00 +000011#include "llvm/ADT/BitVector.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000012#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000013#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"
Zachary Turnerf34e0162016-04-26 16:20:00 +000014
15using namespace llvm;
Zachary Turner2f09b502016-04-29 17:28:47 +000016using namespace llvm::pdb;
Zachary Turnerf34e0162016-04-26 16:20:00 +000017
Zachary Turner2f09b502016-04-29 17:28:47 +000018NameMap::NameMap() {}
Zachary Turnerf34e0162016-04-26 16:20:00 +000019
Zachary Turner819e77d2016-05-06 20:51:57 +000020Error NameMap::load(StreamReader &Stream) {
Zachary Turner6ba65de2016-04-29 17:22:58 +000021
Zachary Turnerf34e0162016-04-26 16:20:00 +000022 // This is some sort of weird string-set/hash table encoded in the stream.
23 // It starts with the number of bytes in the table.
24 uint32_t NumberOfBytes;
Zachary Turner819e77d2016-05-06 20:51:57 +000025 if (Stream.readInteger(NumberOfBytes))
26 return make_error<RawError>(raw_error_code::corrupt_file,
27 "Expected name map length");
28 if (Stream.bytesRemaining() < NumberOfBytes)
29 return make_error<RawError>(raw_error_code::corrupt_file,
30 "Invalid name map length");
Zachary Turnerf34e0162016-04-26 16:20:00 +000031
32 // Following that field is the starting offset of strings in the name table.
33 uint32_t StringsOffset = Stream.getOffset();
34 Stream.setOffset(StringsOffset + NumberOfBytes);
35
36 // This appears to be equivalent to the total number of strings *actually*
37 // in the name table.
38 uint32_t HashSize;
Zachary Turner819e77d2016-05-06 20:51:57 +000039 if (Stream.readInteger(HashSize))
40 return make_error<RawError>(raw_error_code::corrupt_file,
41 "Expected name map hash size");
Zachary Turnerf34e0162016-04-26 16:20:00 +000042
43 // This appears to be an upper bound on the number of strings in the name
44 // table.
45 uint32_t MaxNumberOfStrings;
Zachary Turner819e77d2016-05-06 20:51:57 +000046 if (Stream.readInteger(MaxNumberOfStrings))
47 return make_error<RawError>(raw_error_code::corrupt_file,
48 "Expected name map max strings");
Zachary Turnerf34e0162016-04-26 16:20:00 +000049
50 // This appears to be a hash table which uses bitfields to determine whether
51 // or not a bucket is 'present'.
52 uint32_t NumPresentWords;
Zachary Turner819e77d2016-05-06 20:51:57 +000053 if (Stream.readInteger(NumPresentWords))
54 return make_error<RawError>(raw_error_code::corrupt_file,
55 "Expected name map num words");
Zachary Turnerf34e0162016-04-26 16:20:00 +000056
57 // Store all the 'present' bits in a vector for later processing.
58 SmallVector<uint32_t, 1> PresentWords;
59 for (uint32_t I = 0; I != NumPresentWords; ++I) {
60 uint32_t Word;
Zachary Turner819e77d2016-05-06 20:51:57 +000061 if (Stream.readInteger(Word))
62 return make_error<RawError>(raw_error_code::corrupt_file,
63 "Expected name map word");
64
Zachary Turnerf34e0162016-04-26 16:20:00 +000065 PresentWords.push_back(Word);
66 }
67
68 // This appears to be a hash table which uses bitfields to determine whether
69 // or not a bucket is 'deleted'.
70 uint32_t NumDeletedWords;
Zachary Turner819e77d2016-05-06 20:51:57 +000071 if (Stream.readInteger(NumDeletedWords))
72 return make_error<RawError>(raw_error_code::corrupt_file,
73 "Expected name map num deleted words");
Zachary Turnerf34e0162016-04-26 16:20:00 +000074
75 // Store all the 'deleted' bits in a vector for later processing.
76 SmallVector<uint32_t, 1> DeletedWords;
77 for (uint32_t I = 0; I != NumDeletedWords; ++I) {
78 uint32_t Word;
Zachary Turner819e77d2016-05-06 20:51:57 +000079 if (Stream.readInteger(Word))
80 return make_error<RawError>(raw_error_code::corrupt_file,
81 "Expected name map deleted word");
82
Zachary Turnerf34e0162016-04-26 16:20:00 +000083 DeletedWords.push_back(Word);
84 }
85
86 BitVector Present(MaxNumberOfStrings, false);
87 if (!PresentWords.empty())
88 Present.setBitsInMask(PresentWords.data(), PresentWords.size());
89 BitVector Deleted(MaxNumberOfStrings, false);
90 if (!DeletedWords.empty())
91 Deleted.setBitsInMask(DeletedWords.data(), DeletedWords.size());
92
93 for (uint32_t I = 0; I < MaxNumberOfStrings; ++I) {
94 if (!Present.test(I))
95 continue;
96
97 // For all present entries, dump out their mapping.
98
99 // This appears to be an offset relative to the start of the strings.
100 // It tells us where the null-terminated string begins.
101 uint32_t NameOffset;
Zachary Turner819e77d2016-05-06 20:51:57 +0000102 if (Stream.readInteger(NameOffset))
103 return make_error<RawError>(raw_error_code::corrupt_file,
104 "Expected name map name offset");
Zachary Turnerf34e0162016-04-26 16:20:00 +0000105
106 // This appears to be a stream number into the stream directory.
107 uint32_t NameIndex;
Zachary Turner819e77d2016-05-06 20:51:57 +0000108 if (Stream.readInteger(NameIndex))
109 return make_error<RawError>(raw_error_code::corrupt_file,
110 "Expected name map name index");
Zachary Turnerf34e0162016-04-26 16:20:00 +0000111
112 // Compute the offset of the start of the string relative to the stream.
113 uint32_t StringOffset = StringsOffset + NameOffset;
114 uint32_t OldOffset = Stream.getOffset();
115 // Pump out our c-string from the stream.
116 std::string Str;
117 Stream.setOffset(StringOffset);
Zachary Turner819e77d2016-05-06 20:51:57 +0000118 if (Stream.readZeroString(Str))
119 return make_error<RawError>(raw_error_code::corrupt_file,
120 "Expected name map name");
Zachary Turnerf34e0162016-04-26 16:20:00 +0000121
122 Stream.setOffset(OldOffset);
123 // Add this to a string-map from name to stream number.
124 Mapping.insert({Str, NameIndex});
125 }
126
Zachary Turner819e77d2016-05-06 20:51:57 +0000127 return Error::success();
Zachary Turnerf34e0162016-04-26 16:20:00 +0000128}
129
Zachary Turner85ed80b2016-05-25 03:43:17 +0000130iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const {
131 return llvm::make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
132 Mapping.end());
133}
134
Zachary Turner2f09b502016-04-29 17:28:47 +0000135bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
Zachary Turnerf34e0162016-04-26 16:20:00 +0000136 auto Iter = Mapping.find(Name);
137 if (Iter == Mapping.end())
138 return false;
139 Value = Iter->second;
140 return true;
141}