blob: e84573fe07b8e28d495d226a602db15bcfe7e115 [file] [log] [blame]
Zachary Turnerc504ae32017-05-03 15:58:37 +00001//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//
Zachary Turner0eace0b2016-05-02 18:09:14 +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
Zachary Turnere204a6c2017-05-02 18:00:13 +000010#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
Zachary Turner0eace0b2016-05-02 18:09:14 +000011
12#include "llvm/ADT/ArrayRef.h"
Zachary Turnerc504ae32017-05-03 15:58:37 +000013#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000014#include "llvm/DebugInfo/PDB/Native/Hash.h"
15#include "llvm/DebugInfo/PDB/Native/RawError.h"
16#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
Zachary Turnerd9dc2822017-03-02 20:52:51 +000017#include "llvm/Support/BinaryStreamReader.h"
Zachary Turner0eace0b2016-05-02 18:09:14 +000018#include "llvm/Support/Endian.h"
19
20using namespace llvm;
21using namespace llvm::support;
22using namespace llvm::pdb;
23
Zachary Turnerc504ae32017-05-03 15:58:37 +000024uint32_t PDBStringTable::getByteSize() const { return ByteSize; }
25uint32_t PDBStringTable::getNameCount() const { return NameCount; }
26uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
27uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
Zachary Turner0eace0b2016-05-02 18:09:14 +000028
Zachary Turnerc504ae32017-05-03 15:58:37 +000029Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
30 if (auto EC = Reader.readObject(Header))
Zachary Turner819e77d2016-05-06 20:51:57 +000031 return EC;
32
Zachary Turnerc504ae32017-05-03 15:58:37 +000033 if (Header->Signature != PDBStringTableSignature)
Zachary Turner819e77d2016-05-06 20:51:57 +000034 return make_error<RawError>(raw_error_code::corrupt_file,
35 "Invalid hash table signature");
Zachary Turnerc504ae32017-05-03 15:58:37 +000036 if (Header->HashVersion != 1 && Header->HashVersion != 2)
Zachary Turner819e77d2016-05-06 20:51:57 +000037 return make_error<RawError>(raw_error_code::corrupt_file,
38 "Unsupported hash version");
Zachary Turner0eace0b2016-05-02 18:09:14 +000039
Zachary Turnerc504ae32017-05-03 15:58:37 +000040 assert(Reader.bytesRemaining() == 0);
41 return Error::success();
42}
43
44Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
Zachary Turner2d5c2cd2017-05-03 17:11:11 +000045 BinaryStreamRef Stream;
46 if (auto EC = Reader.readStreamRef(Stream))
47 return EC;
48
49 if (auto EC = Strings.initialize(Stream)) {
David Majnemer836937e2016-05-27 16:16:56 +000050 return joinErrors(std::move(EC),
51 make_error<RawError>(raw_error_code::corrupt_file,
52 "Invalid hash table byte length"));
Zachary Turnerc504ae32017-05-03 15:58:37 +000053 }
Zachary Turner0eace0b2016-05-02 18:09:14 +000054
Zachary Turnerc504ae32017-05-03 15:58:37 +000055 assert(Reader.bytesRemaining() == 0);
56 return Error::success();
57}
58
59Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000060 const support::ulittle32_t *HashCount;
Zachary Turnerc504ae32017-05-03 15:58:37 +000061 if (auto EC = Reader.readObject(HashCount))
Zachary Turner819e77d2016-05-06 20:51:57 +000062 return EC;
63
Zachary Turnerc504ae32017-05-03 15:58:37 +000064 if (auto EC = Reader.readArray(IDs, *HashCount)) {
David Majnemer836937e2016-05-27 16:16:56 +000065 return joinErrors(std::move(EC),
66 make_error<RawError>(raw_error_code::corrupt_file,
67 "Could not read bucket array"));
Zachary Turnerc504ae32017-05-03 15:58:37 +000068 }
Zachary Turnerf1220082017-03-15 22:19:30 +000069
Zachary Turner819e77d2016-05-06 20:51:57 +000070 return Error::success();
Zachary Turner0eace0b2016-05-02 18:09:14 +000071}
72
Zachary Turnerc504ae32017-05-03 15:58:37 +000073Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
74 if (auto EC = Reader.readInteger(NameCount))
75 return EC;
76
77 assert(Reader.bytesRemaining() == 0);
78 return Error::success();
79}
80
81Error PDBStringTable::reload(BinaryStreamReader &Reader) {
82
83 BinaryStreamReader SectionReader;
84
85 std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
86 if (auto EC = readHeader(SectionReader))
87 return EC;
88
89 std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
90 if (auto EC = readStrings(SectionReader))
91 return EC;
92
93 // We don't know how long the hash table is until we parse it, so let the
94 // function responsible for doing that figure it out.
95 if (auto EC = readHashTable(Reader))
96 return EC;
97
98 std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
99 if (auto EC = readEpilogue(SectionReader))
100 return EC;
101
102 assert(Reader.bytesRemaining() == 0);
103 return Error::success();
104}
Zachary Turnerf1220082017-03-15 22:19:30 +0000105
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000106Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
Zachary Turnerc504ae32017-05-03 15:58:37 +0000107 return Strings.getString(ID);
Zachary Turner0eace0b2016-05-02 18:09:14 +0000108}
109
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000110Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
Zachary Turnerc504ae32017-05-03 15:58:37 +0000111 uint32_t Hash =
112 (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
Zachary Turner0eace0b2016-05-02 18:09:14 +0000113 size_t Count = IDs.size();
114 uint32_t Start = Hash % Count;
115 for (size_t I = 0; I < Count; ++I) {
116 // The hash is just a starting point for the search, but if it
117 // doesn't work we should find the string no matter what, because
118 // we iterate the entire array.
119 uint32_t Index = (Start + I) % Count;
120
121 uint32_t ID = IDs[Index];
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000122 auto ExpectedStr = getStringForID(ID);
123 if (!ExpectedStr)
124 return ExpectedStr.takeError();
125
126 if (*ExpectedStr == Str)
Zachary Turner0eace0b2016-05-02 18:09:14 +0000127 return ID;
128 }
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000129 return make_error<RawError>(raw_error_code::no_entry);
Zachary Turner0eace0b2016-05-02 18:09:14 +0000130}
131
Zachary Turnere204a6c2017-05-02 18:00:13 +0000132FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
Zachary Turnerb393d952016-05-27 03:51:53 +0000133 return IDs;
134}