Line data Source code
1 : //===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
2 : //
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 : //
10 : // The data structures defined in this file are based on the reference
11 : // implementation which is available at
12 : // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
13 : //
14 : // When you are reading the reference source code, you'd find the
15 : // information below useful.
16 : //
17 : // - ppdb1->m_fMinimalDbgInfo seems to be always true.
18 : // - SMALLBUCKETS macro is defined.
19 : //
20 : // The reference doesn't compile, so I learned just by reading code.
21 : // It's not guaranteed to be correct.
22 : //
23 : //===----------------------------------------------------------------------===//
24 :
25 : #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
26 : #include "llvm/ADT/iterator_range.h"
27 : #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
28 : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
29 : #include "llvm/DebugInfo/PDB/Native/RawError.h"
30 : #include "llvm/Support/BinaryStreamReader.h"
31 : #include "llvm/Support/Endian.h"
32 : #include "llvm/Support/Error.h"
33 : #include <algorithm>
34 : #include <cstdint>
35 :
36 : using namespace llvm;
37 : using namespace llvm::msf;
38 : using namespace llvm::support;
39 : using namespace llvm::pdb;
40 :
41 3 : PublicsStream::PublicsStream(std::unique_ptr<MappedBlockStream> Stream)
42 3 : : Stream(std::move(Stream)) {}
43 :
44 : PublicsStream::~PublicsStream() = default;
45 :
46 2 : uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
47 1 : uint16_t PublicsStream::getThunkTableSection() const {
48 2 : return Header->ISectThunkTable;
49 : }
50 1 : uint32_t PublicsStream::getThunkTableOffset() const {
51 2 : return Header->OffThunkTable;
52 : }
53 :
54 : // Publics stream contains fixed-size headers and a serialized hash table.
55 : // This implementation is not complete yet. It reads till the end of the
56 : // stream so that we verify the stream is at least not corrupted. However,
57 : // we skip over the hash table which we believe contains information about
58 : // public symbols.
59 3 : Error PublicsStream::reload() {
60 3 : BinaryStreamReader Reader(*Stream);
61 :
62 : // Check stream size.
63 3 : if (Reader.bytesRemaining() <
64 : sizeof(PublicsStreamHeader) + sizeof(GSIHashHeader))
65 : return make_error<RawError>(raw_error_code::corrupt_file,
66 : "Publics Stream does not contain a header.");
67 :
68 : // Read PSGSIHDR struct.
69 6 : if (Reader.readObject(Header))
70 : return make_error<RawError>(raw_error_code::corrupt_file,
71 : "Publics Stream does not contain a header.");
72 :
73 : // Read the hash table.
74 6 : if (auto E = PublicsTable.read(Reader))
75 : return E;
76 :
77 : // Something called "address map" follows.
78 3 : uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
79 6 : if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries))
80 : return joinErrors(std::move(EC),
81 0 : make_error<RawError>(raw_error_code::corrupt_file,
82 0 : "Could not read an address map."));
83 :
84 : // Something called "thunk map" follows.
85 9 : if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks))
86 : return joinErrors(std::move(EC),
87 0 : make_error<RawError>(raw_error_code::corrupt_file,
88 0 : "Could not read a thunk map."));
89 :
90 : // Something called "section map" follows.
91 3 : if (Reader.bytesRemaining() > 0) {
92 3 : if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
93 : return joinErrors(std::move(EC),
94 0 : make_error<RawError>(raw_error_code::corrupt_file,
95 0 : "Could not read a section map."));
96 : }
97 :
98 3 : if (Reader.bytesRemaining() > 0)
99 : return make_error<RawError>(raw_error_code::corrupt_file,
100 : "Corrupted publics stream.");
101 : return Error::success();
102 : }
|