blob: c7ba32b82bc6be11e9a6e62d17bcb428dfcb2add [file] [log] [blame]
Zachary Turnerf04d6e82017-01-20 22:41:15 +00001//===- NamedStreamMap.cpp - PDB Named Stream 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
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000010#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
Zachary Turner11036a92017-01-19 23:31:24 +000011
David Majnemer36b7b082016-06-04 22:47:39 +000012#include "llvm/ADT/SparseBitVector.h"
Eugene Zelenko570e39a2016-11-23 23:16:32 +000013#include "llvm/ADT/StringMap.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/iterator_range.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000016#include "llvm/DebugInfo/PDB/Native/HashTable.h"
17#include "llvm/DebugInfo/PDB/Native/RawError.h"
Zachary Turnerd9dc2822017-03-02 20:52:51 +000018#include "llvm/Support/BinaryStreamReader.h"
Eugene Zelenko570e39a2016-11-23 23:16:32 +000019#include "llvm/Support/Error.h"
20#include <algorithm>
21#include <cstdint>
Zachary Turnerf34e0162016-04-26 16:20:00 +000022
23using namespace llvm;
Zachary Turner2f09b502016-04-29 17:28:47 +000024using namespace llvm::pdb;
Zachary Turnerf34e0162016-04-26 16:20:00 +000025
Zachary Turnerf04d6e82017-01-20 22:41:15 +000026NamedStreamMap::NamedStreamMap() = default;
Zachary Turnerf34e0162016-04-26 16:20:00 +000027
Zachary Turner120faca2017-02-27 22:11:43 +000028Error NamedStreamMap::load(BinaryStreamReader &Stream) {
Zachary Turner60667ca2017-01-20 22:41:40 +000029 Mapping.clear();
30 FinalizedHashTable.clear();
31 FinalizedInfo.reset();
32
Zachary Turner11036a92017-01-19 23:31:24 +000033 uint32_t StringBufferSize;
Zachary Turner695ed562017-02-28 00:04:07 +000034 if (auto EC = Stream.readInteger(StringBufferSize))
David Majnemer836937e2016-05-27 16:16:56 +000035 return joinErrors(std::move(EC),
36 make_error<RawError>(raw_error_code::corrupt_file,
Zachary Turner11036a92017-01-19 23:31:24 +000037 "Expected string buffer size"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000038
Zachary Turner120faca2017-02-27 22:11:43 +000039 BinaryStreamRef StringsBuffer;
Zachary Turner11036a92017-01-19 23:31:24 +000040 if (auto EC = Stream.readStreamRef(StringsBuffer, StringBufferSize))
41 return EC;
Zachary Turnerf34e0162016-04-26 16:20:00 +000042
Zachary Turner11036a92017-01-19 23:31:24 +000043 HashTable OffsetIndexMap;
44 if (auto EC = OffsetIndexMap.load(Stream))
45 return EC;
Zachary Turnerf34e0162016-04-26 16:20:00 +000046
Zachary Turner11036a92017-01-19 23:31:24 +000047 uint32_t NameOffset;
48 uint32_t NameIndex;
49 for (const auto &Entry : OffsetIndexMap) {
50 std::tie(NameOffset, NameIndex) = Entry;
Zachary Turnerf34e0162016-04-26 16:20:00 +000051
52 // Compute the offset of the start of the string relative to the stream.
Zachary Turner120faca2017-02-27 22:11:43 +000053 BinaryStreamReader NameReader(StringsBuffer);
Zachary Turner11036a92017-01-19 23:31:24 +000054 NameReader.setOffset(NameOffset);
Zachary Turnerf34e0162016-04-26 16:20:00 +000055 // Pump out our c-string from the stream.
Zachary Turner8dbe3622016-05-27 01:54:44 +000056 StringRef Str;
Zachary Turner120faca2017-02-27 22:11:43 +000057 if (auto EC = NameReader.readCString(Str))
David Majnemer836937e2016-05-27 16:16:56 +000058 return joinErrors(std::move(EC),
59 make_error<RawError>(raw_error_code::corrupt_file,
60 "Expected name map name"));
Zachary Turnerf34e0162016-04-26 16:20:00 +000061
Zachary Turnerf34e0162016-04-26 16:20:00 +000062 // Add this to a string-map from name to stream number.
63 Mapping.insert({Str, NameIndex});
64 }
65
Zachary Turner819e77d2016-05-06 20:51:57 +000066 return Error::success();
Zachary Turnerf34e0162016-04-26 16:20:00 +000067}
68
Zachary Turner120faca2017-02-27 22:11:43 +000069Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
Zachary Turner60667ca2017-01-20 22:41:40 +000070 assert(FinalizedInfo.hasValue());
71
72 // The first field is the number of bytes of string data.
Zachary Turner695ed562017-02-28 00:04:07 +000073 if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes))
Zachary Turner60667ca2017-01-20 22:41:40 +000074 return EC;
75
76 // Now all of the string data itself.
77 for (const auto &Item : Mapping) {
Zachary Turner120faca2017-02-27 22:11:43 +000078 if (auto EC = Writer.writeCString(Item.getKey()))
Zachary Turner60667ca2017-01-20 22:41:40 +000079 return EC;
80 }
81
82 // And finally the Offset Index map.
83 if (auto EC = FinalizedHashTable.commit(Writer))
84 return EC;
85
86 return Error::success();
87}
88
89uint32_t NamedStreamMap::finalize() {
90 if (FinalizedInfo.hasValue())
91 return FinalizedInfo->SerializedLength;
92
93 // Build the finalized hash table.
94 FinalizedHashTable.clear();
95 FinalizedInfo.emplace();
96 for (const auto &Item : Mapping) {
97 FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item.getValue());
98 FinalizedInfo->StringDataBytes += Item.getKeyLength() + 1;
99 }
100
101 // Number of bytes of string data.
102 FinalizedInfo->SerializedLength += sizeof(support::ulittle32_t);
103 // Followed by that many actual bytes of string data.
104 FinalizedInfo->SerializedLength += FinalizedInfo->StringDataBytes;
105 // Followed by the mapping from Offset to Index.
106 FinalizedInfo->SerializedLength +=
107 FinalizedHashTable.calculateSerializedLength();
108 return FinalizedInfo->SerializedLength;
109}
110
Zachary Turnerf04d6e82017-01-20 22:41:15 +0000111iterator_range<StringMapConstIterator<uint32_t>>
112NamedStreamMap::entries() const {
Eugene Zelenko570e39a2016-11-23 23:16:32 +0000113 return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
114 Mapping.end());
Zachary Turner85ed80b2016-05-25 03:43:17 +0000115}
116
Zachary Turner02278ce2017-03-16 20:18:41 +0000117uint32_t NamedStreamMap::size() const { return Mapping.size(); }
118
Zachary Turner60667ca2017-01-20 22:41:40 +0000119bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
120 auto Iter = Mapping.find(Stream);
Zachary Turnerf34e0162016-04-26 16:20:00 +0000121 if (Iter == Mapping.end())
122 return false;
Zachary Turner60667ca2017-01-20 22:41:40 +0000123 StreamNo = Iter->second;
Zachary Turnerf34e0162016-04-26 16:20:00 +0000124 return true;
125}
Zachary Turner60667ca2017-01-20 22:41:40 +0000126
127void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
128 FinalizedInfo.reset();
129 Mapping[Stream] = StreamNo;
130}
131
132void NamedStreamMap::remove(StringRef Stream) {
133 FinalizedInfo.reset();
134 Mapping.erase(Stream);
135}