121
|
1 //===- NamedStreamMap.cpp - PDB Named Stream Map --------------------------===//
|
|
2 //
|
147
|
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
|
121
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8
|
|
9 #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
|
|
10 #include "llvm/ADT/StringMap.h"
|
|
11 #include "llvm/ADT/StringRef.h"
|
|
12 #include "llvm/ADT/iterator_range.h"
|
147
|
13 #include "llvm/DebugInfo/PDB/Native/Hash.h"
|
121
|
14 #include "llvm/DebugInfo/PDB/Native/HashTable.h"
|
|
15 #include "llvm/DebugInfo/PDB/Native/RawError.h"
|
|
16 #include "llvm/Support/BinaryStreamReader.h"
|
|
17 #include "llvm/Support/BinaryStreamRef.h"
|
|
18 #include "llvm/Support/BinaryStreamWriter.h"
|
|
19 #include "llvm/Support/Endian.h"
|
|
20 #include "llvm/Support/Error.h"
|
|
21 #include <algorithm>
|
|
22 #include <cassert>
|
|
23 #include <cstdint>
|
|
24 #include <tuple>
|
|
25
|
|
26 using namespace llvm;
|
|
27 using namespace llvm::pdb;
|
|
28
|
147
|
29 NamedStreamMapTraits::NamedStreamMapTraits(NamedStreamMap &NS) : NS(&NS) {}
|
121
|
30
|
147
|
31 uint16_t NamedStreamMapTraits::hashLookupKey(StringRef S) const {
|
|
32 // In the reference implementation, this uses
|
|
33 // HASH Hasher<ULONG*, USHORT*>::hashPbCb(PB pb, size_t cb, ULONG ulMod).
|
|
34 // Here, the type HASH is a typedef of unsigned short.
|
|
35 // ** It is not a bug that we truncate the result of hashStringV1, in fact
|
|
36 // it is a bug if we do not! **
|
|
37 // See NMTNI::hash() in the reference implementation.
|
|
38 return static_cast<uint16_t>(hashStringV1(S));
|
|
39 }
|
|
40
|
|
41 StringRef NamedStreamMapTraits::storageKeyToLookupKey(uint32_t Offset) const {
|
|
42 return NS->getString(Offset);
|
|
43 }
|
|
44
|
|
45 uint32_t NamedStreamMapTraits::lookupKeyToStorageKey(StringRef S) {
|
|
46 return NS->appendStringData(S);
|
|
47 }
|
|
48
|
|
49 NamedStreamMap::NamedStreamMap() : HashTraits(*this), OffsetIndexMap(1) {}
|
121
|
50
|
|
51 Error NamedStreamMap::load(BinaryStreamReader &Stream) {
|
|
52 uint32_t StringBufferSize;
|
|
53 if (auto EC = Stream.readInteger(StringBufferSize))
|
|
54 return joinErrors(std::move(EC),
|
|
55 make_error<RawError>(raw_error_code::corrupt_file,
|
|
56 "Expected string buffer size"));
|
|
57
|
147
|
58 StringRef Buffer;
|
|
59 if (auto EC = Stream.readFixedString(Buffer, StringBufferSize))
|
121
|
60 return EC;
|
147
|
61 NamesBuffer.assign(Buffer.begin(), Buffer.end());
|
121
|
62
|
147
|
63 return OffsetIndexMap.load(Stream);
|
121
|
64 }
|
|
65
|
|
66 Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
|
|
67 // The first field is the number of bytes of string data.
|
147
|
68 if (auto EC = Writer.writeInteger<uint32_t>(NamesBuffer.size()))
|
121
|
69 return EC;
|
|
70
|
147
|
71 // Then the actual string data.
|
|
72 StringRef Data(NamesBuffer.data(), NamesBuffer.size());
|
|
73 if (auto EC = Writer.writeFixedString(Data))
|
|
74 return EC;
|
121
|
75
|
|
76 // And finally the Offset Index map.
|
147
|
77 if (auto EC = OffsetIndexMap.commit(Writer))
|
121
|
78 return EC;
|
|
79
|
|
80 return Error::success();
|
|
81 }
|
|
82
|
147
|
83 uint32_t NamedStreamMap::calculateSerializedLength() const {
|
|
84 return sizeof(uint32_t) // String data size
|
|
85 + NamesBuffer.size() // String data
|
|
86 + OffsetIndexMap.calculateSerializedLength(); // Offset Index Map
|
121
|
87 }
|
|
88
|
147
|
89 uint32_t NamedStreamMap::size() const { return OffsetIndexMap.size(); }
|
|
90
|
|
91 StringRef NamedStreamMap::getString(uint32_t Offset) const {
|
|
92 assert(NamesBuffer.size() > Offset);
|
|
93 return StringRef(NamesBuffer.data() + Offset);
|
121
|
94 }
|
|
95
|
147
|
96 uint32_t NamedStreamMap::hashString(uint32_t Offset) const {
|
|
97 return hashStringV1(getString(Offset));
|
|
98 }
|
121
|
99
|
|
100 bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
|
147
|
101 auto Iter = OffsetIndexMap.find_as(Stream, HashTraits);
|
|
102 if (Iter == OffsetIndexMap.end())
|
121
|
103 return false;
|
147
|
104 StreamNo = (*Iter).second;
|
121
|
105 return true;
|
|
106 }
|
|
107
|
147
|
108 StringMap<uint32_t> NamedStreamMap::entries() const {
|
|
109 StringMap<uint32_t> Result;
|
|
110 for (const auto &Entry : OffsetIndexMap) {
|
|
111 StringRef Stream(NamesBuffer.data() + Entry.first);
|
|
112 Result.try_emplace(Stream, Entry.second);
|
|
113 }
|
|
114 return Result;
|
121
|
115 }
|
|
116
|
147
|
117 uint32_t NamedStreamMap::appendStringData(StringRef S) {
|
|
118 uint32_t Offset = NamesBuffer.size();
|
|
119 NamesBuffer.insert(NamesBuffer.end(), S.begin(), S.end());
|
|
120 NamesBuffer.push_back('\0');
|
|
121 return Offset;
|
121
|
122 }
|
147
|
123
|
|
124 void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
|
|
125 OffsetIndexMap.set_as(Stream, support::ulittle32_t(StreamNo), HashTraits);
|
|
126 }
|