blob: 91cbf4bca07651edde0938e86e4c17d79d24eaa5 [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"
Zachary Turnerd2684b72017-02-25 00:33:34 +000016#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000017#include "llvm/DebugInfo/PDB/Native/HashTable.h"
18#include "llvm/DebugInfo/PDB/Native/RawError.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;
NAKAMURA Takumi05a75e42017-02-25 17:04:23 +000034 if (auto EC = Stream.readInteger(StringBufferSize, llvm::support::little))
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.
NAKAMURA Takumi05a75e42017-02-25 17:04:23 +000073 if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes,
74 llvm::support::little))
Zachary Turner60667ca2017-01-20 22:41:40 +000075 return EC;
76
77 // Now all of the string data itself.
78 for (const auto &Item : Mapping) {
Zachary Turner120faca2017-02-27 22:11:43 +000079 if (auto EC = Writer.writeCString(Item.getKey()))
Zachary Turner60667ca2017-01-20 22:41:40 +000080 return EC;
81 }
82
83 // And finally the Offset Index map.
84 if (auto EC = FinalizedHashTable.commit(Writer))
85 return EC;
86
87 return Error::success();
88}
89
90uint32_t NamedStreamMap::finalize() {
91 if (FinalizedInfo.hasValue())
92 return FinalizedInfo->SerializedLength;
93
94 // Build the finalized hash table.
95 FinalizedHashTable.clear();
96 FinalizedInfo.emplace();
97 for (const auto &Item : Mapping) {
98 FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item.getValue());
99 FinalizedInfo->StringDataBytes += Item.getKeyLength() + 1;
100 }
101
102 // Number of bytes of string data.
103 FinalizedInfo->SerializedLength += sizeof(support::ulittle32_t);
104 // Followed by that many actual bytes of string data.
105 FinalizedInfo->SerializedLength += FinalizedInfo->StringDataBytes;
106 // Followed by the mapping from Offset to Index.
107 FinalizedInfo->SerializedLength +=
108 FinalizedHashTable.calculateSerializedLength();
109 return FinalizedInfo->SerializedLength;
110}
111
Zachary Turnerf04d6e82017-01-20 22:41:15 +0000112iterator_range<StringMapConstIterator<uint32_t>>
113NamedStreamMap::entries() const {
Eugene Zelenko570e39a2016-11-23 23:16:32 +0000114 return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
115 Mapping.end());
Zachary Turner85ed80b2016-05-25 03:43:17 +0000116}
117
Zachary Turner60667ca2017-01-20 22:41:40 +0000118bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
119 auto Iter = Mapping.find(Stream);
Zachary Turnerf34e0162016-04-26 16:20:00 +0000120 if (Iter == Mapping.end())
121 return false;
Zachary Turner60667ca2017-01-20 22:41:40 +0000122 StreamNo = Iter->second;
Zachary Turnerf34e0162016-04-26 16:20:00 +0000123 return true;
124}
Zachary Turner60667ca2017-01-20 22:41:40 +0000125
126void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
127 FinalizedInfo.reset();
128 Mapping[Stream] = StreamNo;
129}
130
131void NamedStreamMap::remove(StringRef Stream) {
132 FinalizedInfo.reset();
133 Mapping.erase(Stream);
134}