blob: ad60a44a52d558504e9a6a81d7847e97b2e79267 [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 Turnerd5d37dc2016-05-25 20:37:03 +000012#include "llvm/DebugInfo/CodeView/StreamReader.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000013#include "llvm/DebugInfo/PDB/Raw/RawError.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 Turnerd5d37dc2016-05-25 20:37:03 +000020Error NameMap::load(codeview::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;
David Majnemer836937e2016-05-27 16:16:56 +000025 if (auto EC = Stream.readInteger(NumberOfBytes))
26 return joinErrors(std::move(EC),
27 make_error<RawError>(raw_error_code::corrupt_file,
28 "Expected name map length"));
Zachary Turner819e77d2016-05-06 20:51:57 +000029 if (Stream.bytesRemaining() < NumberOfBytes)
30 return make_error<RawError>(raw_error_code::corrupt_file,
31 "Invalid name map length");
Zachary Turnerf34e0162016-04-26 16:20:00 +000032
33 // Following that field is the starting offset of strings in the name table.
34 uint32_t StringsOffset = Stream.getOffset();
35 Stream.setOffset(StringsOffset + NumberOfBytes);
36
37 // This appears to be equivalent to the total number of strings *actually*
38 // in the name table.
39 uint32_t HashSize;
David Majnemer836937e2016-05-27 16:16:56 +000040 if (auto EC = Stream.readInteger(HashSize))
41 return joinErrors(std::move(EC),
42 make_error<RawError>(raw_error_code::corrupt_file,
43 "Expected name map hash size"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000044
45 // This appears to be an upper bound on the number of strings in the name
46 // table.
47 uint32_t MaxNumberOfStrings;
David Majnemer836937e2016-05-27 16:16:56 +000048 if (auto EC = Stream.readInteger(MaxNumberOfStrings))
49 return joinErrors(std::move(EC),
50 make_error<RawError>(raw_error_code::corrupt_file,
51 "Expected name map max strings"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000052
David Majnemer869631f2016-05-28 05:59:25 +000053 const uint32_t MaxNumberOfWords = UINT32_MAX / sizeof(uint32_t);
54
Zachary Turnerf34e0162016-04-26 16:20:00 +000055 // This appears to be a hash table which uses bitfields to determine whether
56 // or not a bucket is 'present'.
57 uint32_t NumPresentWords;
David Majnemer836937e2016-05-27 16:16:56 +000058 if (auto EC = Stream.readInteger(NumPresentWords))
59 return joinErrors(std::move(EC),
60 make_error<RawError>(raw_error_code::corrupt_file,
61 "Expected name map num words"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000062
David Majnemer869631f2016-05-28 05:59:25 +000063 if (NumPresentWords > MaxNumberOfWords)
64 return make_error<RawError>(raw_error_code::corrupt_file,
65 "Number of present words is too large");
66
Zachary Turnerf34e0162016-04-26 16:20:00 +000067 // Store all the 'present' bits in a vector for later processing.
68 SmallVector<uint32_t, 1> PresentWords;
69 for (uint32_t I = 0; I != NumPresentWords; ++I) {
70 uint32_t Word;
David Majnemer836937e2016-05-27 16:16:56 +000071 if (auto EC = Stream.readInteger(Word))
72 return joinErrors(std::move(EC),
73 make_error<RawError>(raw_error_code::corrupt_file,
74 "Expected name map word"));
Zachary Turner819e77d2016-05-06 20:51:57 +000075
Zachary Turnerf34e0162016-04-26 16:20:00 +000076 PresentWords.push_back(Word);
77 }
78
79 // This appears to be a hash table which uses bitfields to determine whether
80 // or not a bucket is 'deleted'.
81 uint32_t NumDeletedWords;
David Majnemer836937e2016-05-27 16:16:56 +000082 if (auto EC = Stream.readInteger(NumDeletedWords))
83 return joinErrors(
84 std::move(EC),
85 make_error<RawError>(raw_error_code::corrupt_file,
86 "Expected name map num deleted words"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000087
David Majnemer869631f2016-05-28 05:59:25 +000088 if (NumDeletedWords > MaxNumberOfWords)
89 return make_error<RawError>(raw_error_code::corrupt_file,
90 "Number of deleted words is too large");
91
Zachary Turnerf34e0162016-04-26 16:20:00 +000092 // Store all the 'deleted' bits in a vector for later processing.
93 SmallVector<uint32_t, 1> DeletedWords;
94 for (uint32_t I = 0; I != NumDeletedWords; ++I) {
95 uint32_t Word;
David Majnemer836937e2016-05-27 16:16:56 +000096 if (auto EC = Stream.readInteger(Word))
97 return joinErrors(std::move(EC),
98 make_error<RawError>(raw_error_code::corrupt_file,
99 "Expected name map deleted word"));
Zachary Turner819e77d2016-05-06 20:51:57 +0000100
Zachary Turnerf34e0162016-04-26 16:20:00 +0000101 DeletedWords.push_back(Word);
102 }
103
104 BitVector Present(MaxNumberOfStrings, false);
105 if (!PresentWords.empty())
106 Present.setBitsInMask(PresentWords.data(), PresentWords.size());
107 BitVector Deleted(MaxNumberOfStrings, false);
108 if (!DeletedWords.empty())
109 Deleted.setBitsInMask(DeletedWords.data(), DeletedWords.size());
110
111 for (uint32_t I = 0; I < MaxNumberOfStrings; ++I) {
112 if (!Present.test(I))
113 continue;
114
115 // For all present entries, dump out their mapping.
116
117 // This appears to be an offset relative to the start of the strings.
118 // It tells us where the null-terminated string begins.
119 uint32_t NameOffset;
David Majnemer836937e2016-05-27 16:16:56 +0000120 if (auto EC = Stream.readInteger(NameOffset))
121 return joinErrors(std::move(EC),
122 make_error<RawError>(raw_error_code::corrupt_file,
123 "Expected name map name offset"));
Zachary Turnerf34e0162016-04-26 16:20:00 +0000124
125 // This appears to be a stream number into the stream directory.
126 uint32_t NameIndex;
David Majnemer836937e2016-05-27 16:16:56 +0000127 if (auto EC = Stream.readInteger(NameIndex))
128 return joinErrors(std::move(EC),
129 make_error<RawError>(raw_error_code::corrupt_file,
130 "Expected name map name index"));
Zachary Turnerf34e0162016-04-26 16:20:00 +0000131
132 // Compute the offset of the start of the string relative to the stream.
133 uint32_t StringOffset = StringsOffset + NameOffset;
134 uint32_t OldOffset = Stream.getOffset();
135 // Pump out our c-string from the stream.
Zachary Turner8dbe3622016-05-27 01:54:44 +0000136 StringRef Str;
Zachary Turnerf34e0162016-04-26 16:20:00 +0000137 Stream.setOffset(StringOffset);
David Majnemer836937e2016-05-27 16:16:56 +0000138 if (auto EC = Stream.readZeroString(Str))
139 return joinErrors(std::move(EC),
140 make_error<RawError>(raw_error_code::corrupt_file,
141 "Expected name map name"));
Zachary Turnerf34e0162016-04-26 16:20:00 +0000142
143 Stream.setOffset(OldOffset);
144 // Add this to a string-map from name to stream number.
145 Mapping.insert({Str, NameIndex});
146 }
147
Zachary Turner819e77d2016-05-06 20:51:57 +0000148 return Error::success();
Zachary Turnerf34e0162016-04-26 16:20:00 +0000149}
150
Zachary Turner85ed80b2016-05-25 03:43:17 +0000151iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const {
152 return llvm::make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
153 Mapping.end());
154}
155
Zachary Turner2f09b502016-04-29 17:28:47 +0000156bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
Zachary Turnerf34e0162016-04-26 16:20:00 +0000157 auto Iter = Mapping.find(Name);
158 if (Iter == Mapping.end())
159 return false;
160 Value = Iter->second;
161 return true;
162}