llvm.org GIT mirror llvm / 5d9d83f
Revert r301986 (and subsequent r301987). The patch is failing to add StringTableStreamBuilder.h, but that isn't even discovered because the corresponding StringTableStreamBuilder.cpp isn't added to any CMakeLists.txt file and thus never built. I think this patch is just incomplete. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302002 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Jasper 2 years ago
19 changed file(s) with 116 addition(s) and 482 deletion(s). Raw diff Collapse all Expand all
+0
-70
include/llvm/DebugInfo/CodeView/StringTable.h less more
None //===- StringTable.h - CodeView String Table Reader/Writer ------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H
10 #define LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H
11
12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/ADT/StringRef.h"
14
15 #include "llvm/Support/BinaryStreamRef.h"
16 #include "llvm/Support/Error.h"
17
18 #include
19
20 namespace llvm {
21
22 class BinaryStreamReader;
23 class BinaryStreamRef;
24 class BinaryStreamWriter;
25
26 namespace codeview {
27
28 /// Represents a read-only view of a CodeView string table. This is a very
29 /// simple flat buffer consisting of null-terminated strings, where strings
30 /// are retrieved by their offset in the buffer. StringTableRef does not own
31 /// the underlying storage for the buffer.
32 class StringTableRef {
33 public:
34 StringTableRef();
35
36 Error initialize(BinaryStreamReader &Stream);
37
38 StringRef getString(uint32_t Offset) const;
39
40 private:
41 BinaryStreamRef Stream;
42 };
43
44 /// Represents a read-write view of a CodeView string table. StringTable owns
45 /// the underlying storage for the table, and is capable of serializing the
46 /// string table into a format understood by StringTableRef.
47 class StringTable {
48 public:
49 // If string S does not exist in the string table, insert it.
50 // Returns the ID for S.
51 uint32_t insert(StringRef S);
52
53 uint32_t calculateSerializedSize() const;
54 Error commit(BinaryStreamWriter &Writer) const;
55
56 uint32_t size() const;
57
58 StringMap::const_iterator begin() const { return Strings.begin(); }
59
60 StringMap::const_iterator end() const { return Strings.end(); }
61
62 private:
63 StringMap Strings;
64 uint32_t StringSize = 1;
65 };
66 }
67 }
68
69 #endif
129129 std::unique_ptr Publics;
130130 std::unique_ptr Symbols;
131131 std::unique_ptr DirectoryStream;
132 std::unique_ptr StringTableStream;
132 std::unique_ptr PDBStringTableStream;
133133 std::unique_ptr Strings;
134134 };
135135 }
4949
5050 Error commit(StringRef Filename);
5151
52 Expected getNamedStreamIndex(StringRef Name) const;
52 private:
5353 Error addNamedStream(StringRef Name, uint32_t Size);
54
55 private:
5654 Expected finalizeMsfLayout();
5755
5856 BumpPtrAllocator &Allocator;
1212
1313 #include "llvm/ADT/ArrayRef.h"
1414 #include "llvm/ADT/StringRef.h"
15 #include "llvm/DebugInfo/CodeView/StringTable.h"
1615 #include "llvm/Support/BinaryStreamArray.h"
1716 #include "llvm/Support/BinaryStreamRef.h"
1817 #include "llvm/Support/Endian.h"
2322 namespace llvm {
2423 class BinaryStreamReader;
2524
26 namespace msf {
27 class MappedBlockStream;
28 }
29
3025 namespace pdb {
31
32 struct PDBStringTableHeader;
3326
3427 class PDBStringTable {
3528 public:
36 Error reload(BinaryStreamReader &Reader);
29 PDBStringTable();
30
31 Error load(BinaryStreamReader &Stream);
3732
3833 uint32_t getByteSize() const;
39 uint32_t getNameCount() const;
40 uint32_t getHashVersion() const;
41 uint32_t getSignature() const;
34
35 uint32_t getNameCount() const { return NameCount; }
36 uint32_t getHashVersion() const { return HashVersion; }
37 uint32_t getSignature() const { return Signature; }
4238
4339 StringRef getStringForID(uint32_t ID) const;
4440 uint32_t getIDForString(StringRef Str) const;
4642 FixedStreamArray name_ids() const;
4743
4844 private:
49 Error readHeader(BinaryStreamReader &Reader);
50 Error readStrings(BinaryStreamReader &Reader);
51 Error readHashTable(BinaryStreamReader &Reader);
52 Error readEpilogue(BinaryStreamReader &Reader);
53
54 const PDBStringTableHeader *Header = nullptr;
55 codeview::StringTableRef Strings;
45 BinaryStreamRef NamesBuffer;
5646 FixedStreamArray IDs;
5747 uint32_t ByteSize = 0;
48 uint32_t Signature = 0;
49 uint32_t HashVersion = 0;
5850 uint32_t NameCount = 0;
5951 };
6052
1515
1616 #include "llvm/ADT/DenseMap.h"
1717 #include "llvm/ADT/StringRef.h"
18 #include "llvm/DebugInfo/CodeView/StringTable.h"
1918 #include "llvm/Support/Error.h"
2019 #include
2120
2221 namespace llvm {
2322 class BinaryStreamWriter;
24 class WritableBinaryStreamRef;
25
26 namespace msf {
27 struct MSFLayout;
28 }
2923
3024 namespace pdb {
31
32 class PDBFileBuilder;
3325
3426 class PDBStringTableBuilder {
3527 public:
3628 // If string S does not exist in the string table, insert it.
3729 // Returns the ID for S.
3830 uint32_t insert(StringRef S);
31 uint32_t getStringIndex(StringRef S);
3932
40 uint32_t calculateSerializedSize() const;
33 uint32_t finalize();
4134 Error commit(BinaryStreamWriter &Writer) const;
4235
4336 private:
44 uint32_t calculateHashTableSize() const;
45 Error writeHeader(BinaryStreamWriter &Writer) const;
46 Error writeStrings(BinaryStreamWriter &Writer) const;
47 Error writeHashTable(BinaryStreamWriter &Writer) const;
48 Error writeEpilogue(BinaryStreamWriter &Writer) const;
49
50 codeview::StringTable Strings;
37 DenseMap Strings;
38 uint32_t StringSize = 1;
5139 };
5240
5341 } // end namespace pdb
307307
308308 /// The header preceeding the /names stream.
309309 struct PDBStringTableHeader {
310 support::ulittle32_t Signature; // PDBStringTableSignature
311 support::ulittle32_t HashVersion; // 1 or 2
312 support::ulittle32_t ByteSize; // Number of bytes of names buffer.
310 support::ulittle32_t Signature;
311 support::ulittle32_t HashVersion;
312 support::ulittle32_t ByteSize;
313313 };
314314
315315 const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
3030 /// are overridable.
3131 class BinaryStreamReader {
3232 public:
33 BinaryStreamReader() = default;
3433 explicit BinaryStreamReader(BinaryStreamRef Stream);
3534 virtual ~BinaryStreamReader() {}
3635
243242 /// \returns the next byte in the stream.
244243 uint8_t peek() const;
245244
246 std::pair
247 split(uint32_t Offset) const;
248
249245 private:
250246 BinaryStreamRef Stream;
251247 uint32_t Offset;
1919 #include "llvm/Support/Error.h"
2020 #include
2121 #include
22 #include
2322
2423 namespace llvm {
2524
3029 /// although no methods are overridable.
3130 class BinaryStreamWriter {
3231 public:
32 // FIXME: We should be able to slice and drop_front etc on Writers / Readers.
33
3334 BinaryStreamWriter() = default;
3435 explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
3536 virtual ~BinaryStreamWriter() {}
150151 return writeStreamRef(Array.getUnderlyingStream());
151152 }
152153
153 /// Splits the Writer into two Writers at a given offset.
154 std::pair split(uint32_t Off) const;
155
156154 void setOffset(uint32_t Off) { Offset = Off; }
157155 uint32_t getOffset() const { return Offset; }
158156 uint32_t getLength() const { return Stream.getLength(); }
1414 ModuleDebugLineFragment.cpp
1515 ModuleDebugUnknownFragment.cpp
1616 RecordSerialization.cpp
17 StringTable.cpp
1817 SymbolRecordMapping.cpp
1918 SymbolDumper.cpp
2019 SymbolSerializer.cpp
+0
-65
lib/DebugInfo/CodeView/StringTable.cpp less more
None //===- StringTable.cpp - CodeView String Table Reader/Writer ----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/CodeView/StringTable.h"
10
11 #include "llvm/Support/BinaryStream.h"
12 #include "llvm/Support/BinaryStreamReader.h"
13 #include "llvm/Support/BinaryStreamWriter.h"
14
15 using namespace llvm;
16 using namespace llvm::codeview;
17
18 StringTableRef::StringTableRef() {}
19
20 Error StringTableRef::initialize(BinaryStreamReader &Reader) {
21 return Reader.readStreamRef(Stream, Reader.bytesRemaining());
22 }
23
24 StringRef StringTableRef::getString(uint32_t Offset) const {
25 BinaryStreamReader Reader(Stream);
26 Reader.setOffset(Offset);
27 StringRef Result;
28 Error EC = Reader.readCString(Result);
29 assert(!EC);
30 consumeError(std::move(EC));
31 return Result;
32 }
33
34 uint32_t StringTable::insert(StringRef S) {
35 auto P = Strings.insert({S, StringSize});
36
37 // If a given string didn't exist in the string table, we want to increment
38 // the string table size.
39 if (P.second)
40 StringSize += S.size() + 1; // +1 for '\0'
41 return P.first->second;
42 }
43
44 uint32_t StringTable::calculateSerializedSize() const { return StringSize; }
45
46 Error StringTable::commit(BinaryStreamWriter &Writer) const {
47 assert(Writer.bytesRemaining() == StringSize);
48 uint32_t MaxOffset = 1;
49
50 for (auto &Pair : Strings) {
51 StringRef S = Pair.getKey();
52 uint32_t Offset = Pair.getValue();
53 Writer.setOffset(Offset);
54 if (auto EC = Writer.writeCString(S))
55 return EC;
56 MaxOffset = std::max(MaxOffset, Offset + S.size() + 1);
57 }
58
59 Writer.setOffset(MaxOffset);
60 assert(Writer.bytesRemaining() == 0);
61 return Error::success();
62 }
63
64 uint32_t StringTable::size() const { return Strings.size(); }
145145
146146 if (ECSubstream.getLength() > 0) {
147147 BinaryStreamReader ECReader(ECSubstream);
148 if (auto EC = ECNames.reload(ECReader))
148 if (auto EC = ECNames.load(ECReader))
149149 return EC;
150150 }
151151
337337 }
338338
339339 Expected PDBFile::getStringTable() {
340 if (!Strings) {
340 if (!Strings || !PDBStringTableStream) {
341341 auto IS = getPDBInfoStream();
342342 if (!IS)
343343 return IS.takeError();
349349 if (!NS)
350350 return NS.takeError();
351351
352 BinaryStreamReader Reader(**NS);
352353 auto N = llvm::make_unique();
353 BinaryStreamReader Reader(**NS);
354 if (auto EC = N->reload(Reader))
355 return std::move(EC);
356 assert(Reader.bytesRemaining() == 0);
357 StringTableStream = std::move(*NS);
354 if (auto EC = N->load(Reader))
355 return std::move(EC);
358356 Strings = std::move(N);
357 PDBStringTableStream = std::move(*NS);
359358 }
360359 return *Strings;
361360 }
7979 }
8080
8181 Expected PDBFileBuilder::finalizeMsfLayout() {
82 uint32_t StringsLen = Strings.calculateSerializedSize();
82 uint32_t PDBStringTableSize = Strings.finalize();
8383
84 if (auto EC = addNamedStream("/names", StringsLen))
84 if (auto EC = addNamedStream("/names", PDBStringTableSize))
8585 return std::move(EC);
8686 if (auto EC = addNamedStream("/LinkInfo", 0))
8787 return std::move(EC);
106106 }
107107
108108 return Msf->build();
109 }
110
111 Expected PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
112 uint32_t SN = 0;
113 if (!NamedStreams.get(Name, SN))
114 return llvm::make_error(raw_error_code::no_stream);
115 return SN;
116109 }
117110
118111 Error PDBFileBuilder::commit(StringRef Filename) {
152145 return EC;
153146 }
154147
155 auto ExpectedSN = getNamedStreamIndex("/names");
156 if (!ExpectedSN)
157 return ExpectedSN.takeError();
148 uint32_t PDBStringTableStreamNo = 0;
149 if (!NamedStreams.get("/names", PDBStringTableStreamNo))
150 return llvm::make_error(raw_error_code::no_stream);
158151
159 auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
160 *ExpectedSN);
152 auto NS = WritableMappedBlockStream::createIndexedStream(
153 Layout, Buffer, PDBStringTableStreamNo);
161154 BinaryStreamWriter NSWriter(*NS);
162155 if (auto EC = Strings.commit(NSWriter))
163156 return EC;
None //===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//
0 //===- PDBStringTable.cpp - PDB String Table -----------------------*- C++
1 //-*-===//
12 //
23 // The LLVM Compiler Infrastructure
34 //
910 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
1011
1112 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1313 #include "llvm/DebugInfo/PDB/Native/Hash.h"
1414 #include "llvm/DebugInfo/PDB/Native/RawError.h"
1515 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
2020 using namespace llvm::support;
2121 using namespace llvm::pdb;
2222
23 uint32_t PDBStringTable::getByteSize() const { return ByteSize; }
24 uint32_t PDBStringTable::getNameCount() const { return NameCount; }
25 uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
26 uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
23 PDBStringTable::PDBStringTable() {}
2724
28 Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
29 if (auto EC = Reader.readObject(Header))
25 Error PDBStringTable::load(BinaryStreamReader &Stream) {
26 ByteSize = Stream.getLength();
27
28 const PDBStringTableHeader *H;
29 if (auto EC = Stream.readObject(H))
3030 return EC;
3131
32 if (Header->Signature != PDBStringTableSignature)
32 if (H->Signature != PDBStringTableSignature)
3333 return make_error(raw_error_code::corrupt_file,
3434 "Invalid hash table signature");
35 if (Header->HashVersion != 1 && Header->HashVersion != 2)
35 if (H->HashVersion != 1 && H->HashVersion != 2)
3636 return make_error(raw_error_code::corrupt_file,
3737 "Unsupported hash version");
3838
39 assert(Reader.bytesRemaining() == 0);
40 return Error::success();
41 }
42
43 Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
44 if (auto EC = Strings.initialize(Reader)) {
39 Signature = H->Signature;
40 HashVersion = H->HashVersion;
41 if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize))
4542 return joinErrors(std::move(EC),
4643 make_error(raw_error_code::corrupt_file,
4744 "Invalid hash table byte length"));
48 }
4945
50 assert(Reader.bytesRemaining() == 0);
51 return Error::success();
52 }
53
54 Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
5546 const support::ulittle32_t *HashCount;
56 if (auto EC = Reader.readObject(HashCount))
47 if (auto EC = Stream.readObject(HashCount))
5748 return EC;
5849
59 if (auto EC = Reader.readArray(IDs, *HashCount)) {
50 if (auto EC = Stream.readArray(IDs, *HashCount))
6051 return joinErrors(std::move(EC),
6152 make_error(raw_error_code::corrupt_file,
6253 "Could not read bucket array"));
63 }
54
55 if (Stream.bytesRemaining() < sizeof(support::ulittle32_t))
56 return make_error(raw_error_code::corrupt_file,
57 "Missing name count");
58
59 if (auto EC = Stream.readInteger(NameCount))
60 return EC;
61
62 if (Stream.bytesRemaining() > 0)
63 return make_error(raw_error_code::stream_too_long,
64 "Unexpected bytes found in string table");
6465
6566 return Error::success();
6667 }
6768
68 Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
69 if (auto EC = Reader.readInteger(NameCount))
70 return EC;
71
72 assert(Reader.bytesRemaining() == 0);
73 return Error::success();
74 }
75
76 Error PDBStringTable::reload(BinaryStreamReader &Reader) {
77
78 BinaryStreamReader SectionReader;
79
80 std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
81 if (auto EC = readHeader(SectionReader))
82 return EC;
83
84 std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
85 if (auto EC = readStrings(SectionReader))
86 return EC;
87
88 // We don't know how long the hash table is until we parse it, so let the
89 // function responsible for doing that figure it out.
90 if (auto EC = readHashTable(Reader))
91 return EC;
92
93 std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
94 if (auto EC = readEpilogue(SectionReader))
95 return EC;
96
97 assert(Reader.bytesRemaining() == 0);
98 return Error::success();
99 }
69 uint32_t PDBStringTable::getByteSize() const { return ByteSize; }
10070
10171 StringRef PDBStringTable::getStringForID(uint32_t ID) const {
102 return Strings.getString(ID);
72 if (ID == IDs[0])
73 return StringRef();
74
75 // NamesBuffer is a buffer of null terminated strings back to back. ID is
76 // the starting offset of the string we're looking for. So just seek into
77 // the desired offset and a read a null terminated stream from that offset.
78 StringRef Result;
79 BinaryStreamReader NameReader(NamesBuffer);
80 NameReader.setOffset(ID);
81 if (auto EC = NameReader.readCString(Result))
82 consumeError(std::move(EC));
83 return Result;
10384 }
10485
10586 uint32_t PDBStringTable::getIDForString(StringRef Str) const {
106 uint32_t Hash =
107 (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
87 uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
10888 size_t Count = IDs.size();
10989 uint32_t Start = Hash % Count;
11090 for (size_t I = 0; I < Count; ++I) {
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
10
1110 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1311 #include "llvm/DebugInfo/PDB/Native/Hash.h"
14 #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
1512 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
1613 #include "llvm/Support/BinaryStreamWriter.h"
1714 #include "llvm/Support/Endian.h"
1815
1916 using namespace llvm;
20 using namespace llvm::msf;
2117 using namespace llvm::support;
2218 using namespace llvm::support::endian;
2319 using namespace llvm::pdb;
2420
2521 uint32_t PDBStringTableBuilder::insert(StringRef S) {
26 return Strings.insert(S);
22 auto P = Strings.insert({S, StringSize});
23
24 // If a given string didn't exist in the string table, we want to increment
25 // the string table size.
26 if (P.second)
27 StringSize += S.size() + 1; // +1 for '\0'
28 return P.first->second;
29 }
30
31 uint32_t PDBStringTableBuilder::getStringIndex(StringRef S) {
32 auto Iter = Strings.find(S);
33 assert(Iter != Strings.end());
34 return Iter->second;
2735 }
2836
2937 static uint32_t computeBucketCount(uint32_t NumStrings) {
3543 return (NumStrings + 1) * 1.25;
3644 }
3745
38 uint32_t PDBStringTableBuilder::calculateHashTableSize() const {
39 uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field.
40 Size += sizeof(uint32_t) * computeBucketCount(Strings.size());
46 uint32_t PDBStringTableBuilder::finalize() {
47 uint32_t Size = 0;
48 Size += sizeof(PDBStringTableHeader);
49 Size += StringSize;
50 Size += sizeof(uint32_t); // Hash table begins with 4-byte size field.
4151
52 uint32_t BucketCount = computeBucketCount(Strings.size());
53 Size += BucketCount * sizeof(uint32_t);
54
55 Size +=
56 sizeof(uint32_t); // The /names stream ends with the number of strings.
4257 return Size;
4358 }
4459
45 uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
46 uint32_t Size = 0;
47 Size += sizeof(PDBStringTableHeader);
48 Size += Strings.calculateSerializedSize();
49 Size += calculateHashTableSize();
50 Size += sizeof(uint32_t); // The /names stream ends with the string count.
51 return Size;
52 }
53
54 Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
60 Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
5561 // Write a header
5662 PDBStringTableHeader H;
5763 H.Signature = PDBStringTableSignature;
5864 H.HashVersion = 1;
59 H.ByteSize = Strings.calculateSerializedSize();
65 H.ByteSize = StringSize;
6066 if (auto EC = Writer.writeObject(H))
6167 return EC;
62 assert(Writer.bytesRemaining() == 0);
63 return Error::success();
64 }
6568
66 Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const {
67 if (auto EC = Strings.commit(Writer))
68 return EC;
69 // Write a string table.
70 uint32_t StringStart = Writer.getOffset();
71 for (auto Pair : Strings) {
72 StringRef S = Pair.first;
73 uint32_t Offset = Pair.second;
74 Writer.setOffset(StringStart + Offset);
75 if (auto EC = Writer.writeCString(S))
76 return EC;
77 }
78 Writer.setOffset(StringStart + StringSize);
6979
70 assert(Writer.bytesRemaining() == 0);
71 return Error::success();
72 }
73
74 Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
7580 // Write a hash table.
7681 uint32_t BucketCount = computeBucketCount(Strings.size());
7782 if (auto EC = Writer.writeInteger(BucketCount))
7883 return EC;
7984 std::vector Buckets(BucketCount);
8085
81 for (auto &Pair : Strings) {
82 StringRef S = Pair.getKey();
83 uint32_t Offset = Pair.getValue();
86 for (auto Pair : Strings) {
87 StringRef S = Pair.first;
88 uint32_t Offset = Pair.second;
8489 uint32_t Hash = hashStringV1(S);
8590
8691 for (uint32_t I = 0; I != BucketCount; ++I) {
96101
97102 if (auto EC = Writer.writeArray(ArrayRef(Buckets)))
98103 return EC;
99
100 assert(Writer.bytesRemaining() == 0);
104 if (auto EC = Writer.writeInteger(static_cast(Strings.size())))
105 return EC;
101106 return Error::success();
102107 }
103
104 Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const {
105 if (auto EC = Writer.writeInteger(Strings.size()))
106 return EC;
107 assert(Writer.bytesRemaining() == 0);
108 return Error::success();
109 }
110
111 Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
112 BinaryStreamWriter SectionWriter;
113
114 std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader));
115 if (auto EC = writeHeader(SectionWriter))
116 return EC;
117
118 std::tie(SectionWriter, Writer) =
119 Writer.split(Strings.calculateSerializedSize());
120 if (auto EC = writeStrings(SectionWriter))
121 return EC;
122
123 std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize());
124 if (auto EC = writeHashTable(SectionWriter))
125 return EC;
126
127 std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t));
128 if (auto EC = writeEpilogue(SectionWriter))
129 return EC;
130
131 return Error::success();
132 }
+0
-123
lib/DebugInfo/PDB/Native/StringTableStreamBuilder.cpp less more
None //===- StringTableStreamBuilder.cpp - PDB String Table ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/PDB/Native/StringTableStreamBuilder.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/DebugInfo/PDB/Native/Hash.h"
12 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
13 #include "llvm/Support/BinaryStreamWriter.h"
14 #include "llvm/Support/Endian.h"
15
16 using namespace llvm;
17 using namespace llvm::support;
18 using namespace llvm::support::endian;
19 using namespace llvm::pdb;
20
21 uint32_t StringTableStreamBuilder::insert(StringRef S) {
22 return Strings.insert(S);
23 }
24
25 static uint32_t computeBucketCount(uint32_t NumStrings) {
26 // The /names stream is basically an on-disk open-addressing hash table.
27 // Hash collisions are resolved by linear probing. We cannot make
28 // utilization 100% because it will make the linear probing extremely
29 // slow. But lower utilization wastes disk space. As a reasonable
30 // load factor, we choose 80%. We need +1 because slot 0 is reserved.
31 return (NumStrings + 1) * 1.25;
32 }
33
34 uint32_t StringTableStreamBuilder::hashTableSize() const {
35 uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field.
36
37 Size += computeBucketCount(Strings.size()) * sizeof(uint32_t);
38 return Size;
39 }
40
41 uint32_t StringTableStreamBuilder::calculateSerializedSize() const {
42 uint32_t Size = 0;
43 Size += sizeof(StringTableHeader);
44 Size += Strings.calculateSerializedSize();
45 Size += hashTableSize();
46 Size += sizeof(uint32_t); // The table ends with the number of strings.
47 return Size;
48 }
49
50 Error StringTableStreamBuilder::writeHeader(BinaryStreamWriter &Writer) const {
51 // Write a header
52 StringTableHeader H;
53 H.Signature = StringTableSignature;
54 H.HashVersion = 1;
55 H.ByteSize = Strings.calculateSerializedSize();
56 if (auto EC = Writer.writeObject(H))
57 return EC;
58
59 assert(Writer.bytesRemaining() == 0);
60 return Error::success();
61 }
62
63 Error StringTableStreamBuilder::writeStrings(BinaryStreamWriter &Writer) const {
64 if (auto EC = Strings.commit(Writer))
65 return EC;
66
67 assert(Writer.bytesRemaining() == 0);
68 return Error::success();
69 }
70
71 Error StringTableStreamBuilder::writeHashTable(
72 BinaryStreamWriter &Writer) const {
73 // Write a hash table.
74 uint32_t BucketCount = computeBucketCount(Strings.size());
75 if (auto EC = Writer.writeInteger(BucketCount))
76 return EC;
77
78 std::vector Buckets(BucketCount);
79
80 for (auto &Pair : Strings) {
81 StringRef S = Pair.getKey();
82 uint32_t Offset = Pair.getValue();
83 uint32_t Hash = hashStringV1(S);
84
85 for (uint32_t I = 0; I != BucketCount; ++I) {
86 uint32_t Slot = (Hash + I) % BucketCount;
87 if (Slot == 0)
88 continue; // Skip reserved slot
89 if (Buckets[Slot] != 0)
90 continue;
91 Buckets[Slot] = Offset;
92 break;
93 }
94 }
95
96 if (auto EC = Writer.writeArray(makeArrayRef(Buckets)))
97 return EC;
98 assert(Writer.bytesRemaining() == 0);
99 return Error::success();
100 }
101
102 Error StringTableStreamBuilder::commit(BinaryStreamWriter &Writer) const {
103 BinaryStreamWriter Section;
104
105 std::tie(Section, Writer) = Writer.split(sizeof(StringTableHeader));
106 if (auto EC = writeHeader(Section))
107 return EC;
108
109 std::tie(Section, Writer) = Writer.split(Strings.calculateSerializedSize());
110 if (auto EC = writeStrings(Section))
111 return EC;
112
113 std::tie(Section, Writer) = Writer.split(hashTableSize());
114 if (auto EC = writeHashTable(Section))
115 return EC;
116
117 if (auto EC = Writer.writeInteger(Strings.size()))
118 return EC;
119
120 assert(Writer.bytesRemaining() == 0);
121 return Error::success();
122 }
9292 llvm::consumeError(std::move(EC));
9393 return Buffer[0];
9494 }
95
96 std::pair
97 BinaryStreamReader::split(uint32_t Off) const {
98 assert(getLength() >= Off);
99
100 BinaryStreamRef First = Stream.drop_front(Offset);
101
102 BinaryStreamRef Second = First.drop_front(Off);
103 First = First.keep_front(Off);
104 BinaryStreamReader W1{First};
105 BinaryStreamReader W2{Second};
106 return std::make_pair(W1, W2);
107 }
5858 return Error::success();
5959 }
6060
61 std::pair
62 BinaryStreamWriter::split(uint32_t Off) const {
63 assert(getLength() >= Off);
64
65 WritableBinaryStreamRef First = Stream.drop_front(Offset);
66
67 WritableBinaryStreamRef Second = First.drop_front(Off);
68 First = First.keep_front(Off);
69 BinaryStreamWriter W1{First};
70 BinaryStreamWriter W2{Second};
71 return std::make_pair(W1, W2);
72 }
73
7461 Error BinaryStreamWriter::padToAlignment(uint32_t Align) {
7562 uint32_t NewOffset = alignTo(Offset, Align);
7663 if (NewOffset > getLength())
3232 EXPECT_EQ(1U, Builder.insert("foo"));
3333 EXPECT_EQ(9U, Builder.insert("baz"));
3434
35 std::vector Buffer(Builder.calculateSerializedSize());
35 std::vector Buffer(Builder.finalize());
3636 MutableBinaryByteStream OutStream(Buffer, little);
3737 BinaryStreamWriter Writer(OutStream);
3838 EXPECT_NO_ERROR(Builder.commit(Writer));
4141 BinaryByteStream InStream(Buffer, little);
4242 BinaryStreamReader Reader(InStream);
4343 PDBStringTable Table;
44 EXPECT_NO_ERROR(Table.reload(Reader));
44 EXPECT_NO_ERROR(Table.load(Reader));
4545
4646 EXPECT_EQ(3U, Table.getNameCount());
4747 EXPECT_EQ(1U, Table.getHashVersion());