blob: e1a248a609f92f97eb88c9bd2408062f44c07f15 [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
53 // This appears to be a hash table which uses bitfields to determine whether
54 // or not a bucket is 'present'.
55 uint32_t NumPresentWords;
David Majnemer836937e2016-05-27 16:16:56 +000056 if (auto EC = Stream.readInteger(NumPresentWords))
57 return joinErrors(std::move(EC),
58 make_error<RawError>(raw_error_code::corrupt_file,
59 "Expected name map num words"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000060
61 // Store all the 'present' bits in a vector for later processing.
62 SmallVector<uint32_t, 1> PresentWords;
63 for (uint32_t I = 0; I != NumPresentWords; ++I) {
64 uint32_t Word;
David Majnemer836937e2016-05-27 16:16:56 +000065 if (auto EC = Stream.readInteger(Word))
66 return joinErrors(std::move(EC),
67 make_error<RawError>(raw_error_code::corrupt_file,
68 "Expected name map word"));
Zachary Turner819e77d2016-05-06 20:51:57 +000069
Zachary Turnerf34e0162016-04-26 16:20:00 +000070 PresentWords.push_back(Word);
71 }
72
73 // This appears to be a hash table which uses bitfields to determine whether
74 // or not a bucket is 'deleted'.
75 uint32_t NumDeletedWords;
David Majnemer836937e2016-05-27 16:16:56 +000076 if (auto EC = Stream.readInteger(NumDeletedWords))
77 return joinErrors(
78 std::move(EC),
79 make_error<RawError>(raw_error_code::corrupt_file,
80 "Expected name map num deleted words"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000081
82 // Store all the 'deleted' bits in a vector for later processing.
83 SmallVector<uint32_t, 1> DeletedWords;
84 for (uint32_t I = 0; I != NumDeletedWords; ++I) {
85 uint32_t Word;
David Majnemer836937e2016-05-27 16:16:56 +000086 if (auto EC = Stream.readInteger(Word))
87 return joinErrors(std::move(EC),
88 make_error<RawError>(raw_error_code::corrupt_file,
89 "Expected name map deleted word"));
Zachary Turner819e77d2016-05-06 20:51:57 +000090
Zachary Turnerf34e0162016-04-26 16:20:00 +000091 DeletedWords.push_back(Word);
92 }
93
94 BitVector Present(MaxNumberOfStrings, false);
95 if (!PresentWords.empty())
96 Present.setBitsInMask(PresentWords.data(), PresentWords.size());
97 BitVector Deleted(MaxNumberOfStrings, false);
98 if (!DeletedWords.empty())
99 Deleted.setBitsInMask(DeletedWords.data(), DeletedWords.size());
100
101 for (uint32_t I = 0; I < MaxNumberOfStrings; ++I) {
102 if (!Present.test(I))
103 continue;
104
105 // For all present entries, dump out their mapping.
106
107 // This appears to be an offset relative to the start of the strings.
108 // It tells us where the null-terminated string begins.
109 uint32_t NameOffset;
David Majnemer836937e2016-05-27 16:16:56 +0000110 if (auto EC = Stream.readInteger(NameOffset))
111 return joinErrors(std::move(EC),
112 make_error<RawError>(raw_error_code::corrupt_file,
113 "Expected name map name offset"));
Zachary Turnerf34e0162016-04-26 16:20:00 +0000114
115 // This appears to be a stream number into the stream directory.
116 uint32_t NameIndex;
David Majnemer836937e2016-05-27 16:16:56 +0000117 if (auto EC = Stream.readInteger(NameIndex))
118 return joinErrors(std::move(EC),
119 make_error<RawError>(raw_error_code::corrupt_file,
120 "Expected name map name index"));
Zachary Turnerf34e0162016-04-26 16:20:00 +0000121
122 // Compute the offset of the start of the string relative to the stream.
123 uint32_t StringOffset = StringsOffset + NameOffset;
124 uint32_t OldOffset = Stream.getOffset();
125 // Pump out our c-string from the stream.
Zachary Turner8dbe3622016-05-27 01:54:44 +0000126 StringRef Str;
Zachary Turnerf34e0162016-04-26 16:20:00 +0000127 Stream.setOffset(StringOffset);
David Majnemer836937e2016-05-27 16:16:56 +0000128 if (auto EC = Stream.readZeroString(Str))
129 return joinErrors(std::move(EC),
130 make_error<RawError>(raw_error_code::corrupt_file,
131 "Expected name map name"));
Zachary Turnerf34e0162016-04-26 16:20:00 +0000132
133 Stream.setOffset(OldOffset);
134 // Add this to a string-map from name to stream number.
135 Mapping.insert({Str, NameIndex});
136 }
137
Zachary Turner819e77d2016-05-06 20:51:57 +0000138 return Error::success();
Zachary Turnerf34e0162016-04-26 16:20:00 +0000139}
140
Zachary Turner85ed80b2016-05-25 03:43:17 +0000141iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const {
142 return llvm::make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
143 Mapping.end());
144}
145
Zachary Turner2f09b502016-04-29 17:28:47 +0000146bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
Zachary Turnerf34e0162016-04-26 16:20:00 +0000147 auto Iter = Mapping.find(Name);
148 if (Iter == Mapping.end())
149 return false;
150 Value = Iter->second;
151 return true;
152}