xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // The data structures defined in this file are based on the reference
100b57cec5SDimitry Andric // implementation which is available at
110b57cec5SDimitry Andric // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // When you are reading the reference source code, you'd find the
140b57cec5SDimitry Andric // information below useful.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //  - ppdb1->m_fMinimalDbgInfo seems to be always true.
170b57cec5SDimitry Andric //  - SMALLBUCKETS macro is defined.
180b57cec5SDimitry Andric //
190b57cec5SDimitry Andric // The reference doesn't compile, so I learned just by reading code.
200b57cec5SDimitry Andric // It's not guaranteed to be correct.
210b57cec5SDimitry Andric //
220b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
250b57cec5SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
260b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h"
27*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
280b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
290b57cec5SDimitry Andric #include "llvm/Support/Error.h"
300b57cec5SDimitry Andric #include <cstdint>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric using namespace llvm::msf;
340b57cec5SDimitry Andric using namespace llvm::support;
350b57cec5SDimitry Andric using namespace llvm::pdb;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric PublicsStream::PublicsStream(std::unique_ptr<MappedBlockStream> Stream)
380b57cec5SDimitry Andric     : Stream(std::move(Stream)) {}
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric PublicsStream::~PublicsStream() = default;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
430b57cec5SDimitry Andric uint16_t PublicsStream::getThunkTableSection() const {
440b57cec5SDimitry Andric   return Header->ISectThunkTable;
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric uint32_t PublicsStream::getThunkTableOffset() const {
470b57cec5SDimitry Andric   return Header->OffThunkTable;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric // Publics stream contains fixed-size headers and a serialized hash table.
510b57cec5SDimitry Andric // This implementation is not complete yet. It reads till the end of the
520b57cec5SDimitry Andric // stream so that we verify the stream is at least not corrupted. However,
530b57cec5SDimitry Andric // we skip over the hash table which we believe contains information about
540b57cec5SDimitry Andric // public symbols.
550b57cec5SDimitry Andric Error PublicsStream::reload() {
560b57cec5SDimitry Andric   BinaryStreamReader Reader(*Stream);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   // Check stream size.
590b57cec5SDimitry Andric   if (Reader.bytesRemaining() <
600b57cec5SDimitry Andric       sizeof(PublicsStreamHeader) + sizeof(GSIHashHeader))
610b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
620b57cec5SDimitry Andric                                 "Publics Stream does not contain a header.");
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   // Read PSGSIHDR struct.
650b57cec5SDimitry Andric   if (Reader.readObject(Header))
660b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
670b57cec5SDimitry Andric                                 "Publics Stream does not contain a header.");
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   // Read the hash table.
700b57cec5SDimitry Andric   if (auto E = PublicsTable.read(Reader))
710b57cec5SDimitry Andric     return E;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   // Something called "address map" follows.
740b57cec5SDimitry Andric   uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
750b57cec5SDimitry Andric   if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries))
760b57cec5SDimitry Andric     return joinErrors(std::move(EC),
770b57cec5SDimitry Andric                       make_error<RawError>(raw_error_code::corrupt_file,
780b57cec5SDimitry Andric                                            "Could not read an address map."));
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   // Something called "thunk map" follows.
810b57cec5SDimitry Andric   if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks))
820b57cec5SDimitry Andric     return joinErrors(std::move(EC),
830b57cec5SDimitry Andric                       make_error<RawError>(raw_error_code::corrupt_file,
840b57cec5SDimitry Andric                                            "Could not read a thunk map."));
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   // Something called "section map" follows.
870b57cec5SDimitry Andric   if (Reader.bytesRemaining() > 0) {
880b57cec5SDimitry Andric     if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
890b57cec5SDimitry Andric       return joinErrors(std::move(EC),
900b57cec5SDimitry Andric                         make_error<RawError>(raw_error_code::corrupt_file,
910b57cec5SDimitry Andric                                              "Could not read a section map."));
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   if (Reader.bytesRemaining() > 0)
950b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
960b57cec5SDimitry Andric                                 "Corrupted publics stream.");
970b57cec5SDimitry Andric   return Error::success();
980b57cec5SDimitry Andric }
99