blob: afeea32043dd652c9d8e3457dad3a77d4a71d77d [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"
Adrian McCarthy6b6b8c42017-01-25 22:38:55 +000013#include "llvm/DebugInfo/PDB/Native/Hash.h"
14#include "llvm/DebugInfo/PDB/Native/RawError.h"
15#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
Zachary Turnerd9dc2822017-03-02 20:52:51 +000016#include "llvm/Support/BinaryStreamReader.h"
Zachary Turner0eace0b2016-05-02 18:09:14 +000017#include "llvm/Support/Endian.h"
18
19using namespace llvm;
20using namespace llvm::support;
21using namespace llvm::pdb;
22
Zachary Turnerf3b4b2d2017-07-07 18:45:37 +000023uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; }
Zachary Turnerc504ae32017-05-03 15:58:37 +000024uint32_t PDBStringTable::getNameCount() const { return NameCount; }
25uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
26uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
Zachary Turner0eace0b2016-05-02 18:09:14 +000027
Zachary Turnerc504ae32017-05-03 15:58:37 +000028Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
29 if (auto EC = Reader.readObject(Header))
Zachary Turner819e77d2016-05-06 20:51:57 +000030 return EC;
31
Zachary Turnerc504ae32017-05-03 15:58:37 +000032 if (Header->Signature != PDBStringTableSignature)
Zachary Turner819e77d2016-05-06 20:51:57 +000033 return make_error<RawError>(raw_error_code::corrupt_file,
34 "Invalid hash table signature");
Zachary Turnerc504ae32017-05-03 15:58:37 +000035 if (Header->HashVersion != 1 && Header->HashVersion != 2)
Zachary Turner819e77d2016-05-06 20:51:57 +000036 return make_error<RawError>(raw_error_code::corrupt_file,
37 "Unsupported hash version");
Zachary Turner0eace0b2016-05-02 18:09:14 +000038
Zachary Turnerc504ae32017-05-03 15:58:37 +000039 assert(Reader.bytesRemaining() == 0);
40 return Error::success();
41}
42
43Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
Zachary Turner2d5c2cd2017-05-03 17:11:11 +000044 BinaryStreamRef Stream;
45 if (auto EC = Reader.readStreamRef(Stream))
46 return EC;
47
48 if (auto EC = Strings.initialize(Stream)) {
David Majnemer836937e2016-05-27 16:16:56 +000049 return joinErrors(std::move(EC),
50 make_error<RawError>(raw_error_code::corrupt_file,
51 "Invalid hash table byte length"));
Zachary Turnerc504ae32017-05-03 15:58:37 +000052 }
Zachary Turner0eace0b2016-05-02 18:09:14 +000053
Zachary Turnerc504ae32017-05-03 15:58:37 +000054 assert(Reader.bytesRemaining() == 0);
55 return Error::success();
56}
57
Zachary Turnera8cfc292017-06-14 15:59:27 +000058const codeview::DebugStringTableSubsectionRef &
59PDBStringTable::getStringTable() const {
Zachary Turner92dcdda2017-06-02 19:49:14 +000060 return Strings;
61}
62
Zachary Turnerc504ae32017-05-03 15:58:37 +000063Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000064 const support::ulittle32_t *HashCount;
Zachary Turnerc504ae32017-05-03 15:58:37 +000065 if (auto EC = Reader.readObject(HashCount))
Zachary Turner819e77d2016-05-06 20:51:57 +000066 return EC;
67
Zachary Turnerc504ae32017-05-03 15:58:37 +000068 if (auto EC = Reader.readArray(IDs, *HashCount)) {
David Majnemer836937e2016-05-27 16:16:56 +000069 return joinErrors(std::move(EC),
70 make_error<RawError>(raw_error_code::corrupt_file,
71 "Could not read bucket array"));
Zachary Turnerc504ae32017-05-03 15:58:37 +000072 }
Zachary Turnerf1220082017-03-15 22:19:30 +000073
Zachary Turner819e77d2016-05-06 20:51:57 +000074 return Error::success();
Zachary Turner0eace0b2016-05-02 18:09:14 +000075}
76
Zachary Turnerc504ae32017-05-03 15:58:37 +000077Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
78 if (auto EC = Reader.readInteger(NameCount))
79 return EC;
80
81 assert(Reader.bytesRemaining() == 0);
82 return Error::success();
83}
84
85Error PDBStringTable::reload(BinaryStreamReader &Reader) {
86
87 BinaryStreamReader SectionReader;
88
89 std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
90 if (auto EC = readHeader(SectionReader))
91 return EC;
92
93 std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
94 if (auto EC = readStrings(SectionReader))
95 return EC;
96
97 // We don't know how long the hash table is until we parse it, so let the
98 // function responsible for doing that figure it out.
99 if (auto EC = readHashTable(Reader))
100 return EC;
101
102 std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
103 if (auto EC = readEpilogue(SectionReader))
104 return EC;
105
106 assert(Reader.bytesRemaining() == 0);
107 return Error::success();
108}
Zachary Turnerf1220082017-03-15 22:19:30 +0000109
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000110Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
Zachary Turnerc504ae32017-05-03 15:58:37 +0000111 return Strings.getString(ID);
Zachary Turner0eace0b2016-05-02 18:09:14 +0000112}
113
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000114Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
Zachary Turnerc504ae32017-05-03 15:58:37 +0000115 uint32_t Hash =
116 (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
Zachary Turner0eace0b2016-05-02 18:09:14 +0000117 size_t Count = IDs.size();
118 uint32_t Start = Hash % Count;
119 for (size_t I = 0; I < Count; ++I) {
120 // The hash is just a starting point for the search, but if it
121 // doesn't work we should find the string no matter what, because
122 // we iterate the entire array.
123 uint32_t Index = (Start + I) % Count;
124
Zachary Turnereb629992018-03-21 22:23:59 +0000125 // If we find 0, it means the item isn't in the hash table.
Zachary Turner0eace0b2016-05-02 18:09:14 +0000126 uint32_t ID = IDs[Index];
Zachary Turnereb629992018-03-21 22:23:59 +0000127 if (ID == 0)
128 return make_error<RawError>(raw_error_code::no_entry);
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000129 auto ExpectedStr = getStringForID(ID);
130 if (!ExpectedStr)
131 return ExpectedStr.takeError();
132
133 if (*ExpectedStr == Str)
Zachary Turner0eace0b2016-05-02 18:09:14 +0000134 return ID;
135 }
Zachary Turner2d5c2cd2017-05-03 17:11:11 +0000136 return make_error<RawError>(raw_error_code::no_entry);
Zachary Turner0eace0b2016-05-02 18:09:14 +0000137}
138
Zachary Turnere204a6c2017-05-02 18:00:13 +0000139FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
Zachary Turnerb393d952016-05-27 03:51:53 +0000140 return IDs;
141}