Line data Source code
1 : //===- NamedStreamMap.cpp - PDB Named Stream 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 :
10 : #include "llvm/DebugInfo/PDB/Raw/NamedStreamMap.h"
11 :
12 : #include "llvm/ADT/SparseBitVector.h"
13 : #include "llvm/ADT/StringMap.h"
14 : #include "llvm/ADT/StringRef.h"
15 : #include "llvm/ADT/iterator_range.h"
16 : #include "llvm/DebugInfo/MSF/StreamReader.h"
17 : #include "llvm/DebugInfo/PDB/Raw/HashTable.h"
18 : #include "llvm/DebugInfo/PDB/Raw/RawError.h"
19 : #include "llvm/Support/Error.h"
20 : #include <algorithm>
21 : #include <cstdint>
22 :
23 : using namespace llvm;
24 : using namespace llvm::msf;
25 : using namespace llvm::pdb;
26 :
27 : NamedStreamMap::NamedStreamMap() = default;
28 :
29 15 : Error NamedStreamMap::load(StreamReader &Stream) {
30 15 : Mapping.clear();
31 15 : FinalizedHashTable.clear();
32 15 : FinalizedInfo.reset();
33 :
34 : uint32_t StringBufferSize;
35 45 : if (auto EC = Stream.readInteger(StringBufferSize))
36 0 : return joinErrors(std::move(EC),
37 0 : make_error<RawError>(raw_error_code::corrupt_file,
38 0 : "Expected string buffer size"));
39 :
40 15 : msf::ReadableStreamRef StringsBuffer;
41 45 : if (auto EC = Stream.readStreamRef(StringsBuffer, StringBufferSize))
42 0 : return EC;
43 :
44 30 : HashTable OffsetIndexMap;
45 45 : if (auto EC = OffsetIndexMap.load(Stream))
46 0 : return EC;
47 :
48 : uint32_t NameOffset;
49 : uint32_t NameIndex;
50 120 : for (const auto &Entry : OffsetIndexMap) {
51 90 : std::tie(NameOffset, NameIndex) = Entry;
52 :
53 : // Compute the offset of the start of the string relative to the stream.
54 45 : msf::StreamReader NameReader(StringsBuffer);
55 90 : NameReader.setOffset(NameOffset);
56 : // Pump out our c-string from the stream.
57 45 : StringRef Str;
58 135 : if (auto EC = NameReader.readZeroString(Str))
59 0 : return joinErrors(std::move(EC),
60 0 : make_error<RawError>(raw_error_code::corrupt_file,
61 0 : "Expected name map name"));
62 :
63 : // Add this to a string-map from name to stream number.
64 90 : Mapping.insert({Str, NameIndex});
65 : }
66 :
67 45 : return Error::success();
68 : }
69 :
70 4 : Error NamedStreamMap::commit(msf::StreamWriter &Writer) const {
71 : assert(FinalizedInfo.hasValue());
72 :
73 : // The first field is the number of bytes of string data.
74 4 : if (auto EC = Writer.writeInteger(
75 12 : FinalizedInfo->StringDataBytes)) // Number of bytes of string data
76 0 : return EC;
77 :
78 : // Now all of the string data itself.
79 24 : for (const auto &Item : Mapping) {
80 36 : if (auto EC = Writer.writeZeroString(Item.getKey()))
81 0 : return EC;
82 : }
83 :
84 : // And finally the Offset Index map.
85 12 : if (auto EC = FinalizedHashTable.commit(Writer))
86 0 : return EC;
87 :
88 12 : return Error::success();
89 : }
90 :
91 4 : uint32_t NamedStreamMap::finalize() {
92 4 : if (FinalizedInfo.hasValue())
93 0 : return FinalizedInfo->SerializedLength;
94 :
95 : // Build the finalized hash table.
96 4 : FinalizedHashTable.clear();
97 8 : FinalizedInfo.emplace();
98 24 : for (const auto &Item : Mapping) {
99 24 : FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item.getValue());
100 36 : FinalizedInfo->StringDataBytes += Item.getKeyLength() + 1;
101 : }
102 :
103 : // Number of bytes of string data.
104 8 : FinalizedInfo->SerializedLength += sizeof(support::ulittle32_t);
105 : // Followed by that many actual bytes of string data.
106 12 : FinalizedInfo->SerializedLength += FinalizedInfo->StringDataBytes;
107 : // Followed by the mapping from Offset to Index.
108 12 : FinalizedInfo->SerializedLength +=
109 8 : FinalizedHashTable.calculateSerializedLength();
110 8 : return FinalizedInfo->SerializedLength;
111 : }
112 :
113 : iterator_range<StringMapConstIterator<uint32_t>>
114 9 : NamedStreamMap::entries() const {
115 : return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
116 27 : Mapping.end());
117 : }
118 :
119 10 : bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
120 10 : auto Iter = Mapping.find(Stream);
121 20 : if (Iter == Mapping.end())
122 : return false;
123 10 : StreamNo = Iter->second;
124 10 : return true;
125 : }
126 :
127 12 : void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
128 12 : FinalizedInfo.reset();
129 24 : Mapping[Stream] = StreamNo;
130 12 : }
131 :
132 0 : void NamedStreamMap::remove(StringRef Stream) {
133 0 : FinalizedInfo.reset();
134 0 : Mapping.erase(Stream);
135 0 : }
|