xref: /src/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1a303c417SDimitry Andric //===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric 
9a303c417SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
10b915e9e0SDimitry Andric #include "llvm/ADT/iterator_range.h"
119df3605dSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
129df3605dSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
13d8e91e46SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
14145449b1SDimitry Andric #include "llvm/DebugInfo/MSF/MSFCommon.h"
15145449b1SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
16a303c417SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
17e6d15924SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
1871d5a254SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h"
19145449b1SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
20145449b1SDimitry Andric #include "llvm/Support/BinaryStreamArray.h"
2171d5a254SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
2271d5a254SDimitry Andric #include "llvm/Support/BinaryStreamRef.h"
23b915e9e0SDimitry Andric #include "llvm/Support/Error.h"
24b915e9e0SDimitry Andric #include <cstdint>
2501095a5dSDimitry Andric 
2601095a5dSDimitry Andric using namespace llvm;
27a303c417SDimitry Andric using namespace llvm::codeview;
28b915e9e0SDimitry Andric using namespace llvm::msf;
2901095a5dSDimitry Andric using namespace llvm::pdb;
3001095a5dSDimitry Andric 
ModuleDebugStreamRef(const DbiModuleDescriptor & Module,std::unique_ptr<MappedBlockStream> Stream)31a303c417SDimitry Andric ModuleDebugStreamRef::ModuleDebugStreamRef(
32a303c417SDimitry Andric     const DbiModuleDescriptor &Module,
3301095a5dSDimitry Andric     std::unique_ptr<MappedBlockStream> Stream)
3401095a5dSDimitry Andric     : Mod(Module), Stream(std::move(Stream)) {}
3501095a5dSDimitry Andric 
36a303c417SDimitry Andric ModuleDebugStreamRef::~ModuleDebugStreamRef() = default;
3701095a5dSDimitry Andric 
reload()38a303c417SDimitry Andric Error ModuleDebugStreamRef::reload() {
3971d5a254SDimitry Andric   BinaryStreamReader Reader(*Stream);
4001095a5dSDimitry Andric 
41e6d15924SDimitry Andric   if (Mod.getModuleStreamIndex() != llvm::pdb::kInvalidStreamIndex) {
42e6d15924SDimitry Andric     if (Error E = reloadSerialize(Reader))
43e6d15924SDimitry Andric       return E;
44e6d15924SDimitry Andric   }
45e6d15924SDimitry Andric   if (Reader.bytesRemaining() > 0)
46e6d15924SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
47e6d15924SDimitry Andric                                 "Unexpected bytes in module stream.");
48e6d15924SDimitry Andric   return Error::success();
49e6d15924SDimitry Andric }
50e6d15924SDimitry Andric 
reloadSerialize(BinaryStreamReader & Reader)51e6d15924SDimitry Andric Error ModuleDebugStreamRef::reloadSerialize(BinaryStreamReader &Reader) {
5201095a5dSDimitry Andric   uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
53a303c417SDimitry Andric   uint32_t C11Size = Mod.getC11LineInfoByteSize();
5401095a5dSDimitry Andric   uint32_t C13Size = Mod.getC13LineInfoByteSize();
5501095a5dSDimitry Andric 
5601095a5dSDimitry Andric   if (C11Size > 0 && C13Size > 0)
57b915e9e0SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
5801095a5dSDimitry Andric                                 "Module has both C11 and C13 line info");
5901095a5dSDimitry Andric 
6071d5a254SDimitry Andric   BinaryStreamRef S;
6101095a5dSDimitry Andric 
62b915e9e0SDimitry Andric   if (auto EC = Reader.readInteger(Signature))
6301095a5dSDimitry Andric     return EC;
64d8e91e46SDimitry Andric   Reader.setOffset(0);
65d8e91e46SDimitry Andric   if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize))
6608bbd35aSDimitry Andric     return EC;
6708bbd35aSDimitry Andric   if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size))
6808bbd35aSDimitry Andric     return EC;
6908bbd35aSDimitry Andric   if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size))
7001095a5dSDimitry Andric     return EC;
7101095a5dSDimitry Andric 
7208bbd35aSDimitry Andric   BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData);
73d8e91e46SDimitry Andric   if (auto EC = SymbolReader.readArray(
74d8e91e46SDimitry Andric           SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t)))
7501095a5dSDimitry Andric     return EC;
7601095a5dSDimitry Andric 
7708bbd35aSDimitry Andric   BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);
78d288ef4cSDimitry Andric   if (auto EC = SubsectionsReader.readArray(Subsections,
79d288ef4cSDimitry Andric                                             SubsectionsReader.bytesRemaining()))
8001095a5dSDimitry Andric     return EC;
8101095a5dSDimitry Andric 
8201095a5dSDimitry Andric   uint32_t GlobalRefsSize;
8301095a5dSDimitry Andric   if (auto EC = Reader.readInteger(GlobalRefsSize))
8401095a5dSDimitry Andric     return EC;
8508bbd35aSDimitry Andric   if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize))
8601095a5dSDimitry Andric     return EC;
8701095a5dSDimitry Andric   return Error::success();
8801095a5dSDimitry Andric }
8901095a5dSDimitry Andric 
90d8e91e46SDimitry Andric const codeview::CVSymbolArray
getSymbolArrayForScope(uint32_t ScopeBegin) const91d8e91e46SDimitry Andric ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const {
92d8e91e46SDimitry Andric   return limitSymbolArrayToScope(SymbolArray, ScopeBegin);
93d8e91e46SDimitry Andric }
94d8e91e46SDimitry Andric 
getSymbolsSubstream() const9508bbd35aSDimitry Andric BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const {
9608bbd35aSDimitry Andric   return SymbolsSubstream;
9708bbd35aSDimitry Andric }
9808bbd35aSDimitry Andric 
getC11LinesSubstream() const9908bbd35aSDimitry Andric BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const {
10008bbd35aSDimitry Andric   return C11LinesSubstream;
10108bbd35aSDimitry Andric }
10208bbd35aSDimitry Andric 
getC13LinesSubstream() const10308bbd35aSDimitry Andric BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const {
10408bbd35aSDimitry Andric   return C13LinesSubstream;
10508bbd35aSDimitry Andric }
10608bbd35aSDimitry Andric 
getGlobalRefsSubstream() const10708bbd35aSDimitry Andric BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const {
10808bbd35aSDimitry Andric   return GlobalRefsSubstream;
10908bbd35aSDimitry Andric }
11008bbd35aSDimitry Andric 
11101095a5dSDimitry Andric iterator_range<codeview::CVSymbolArray::Iterator>
symbols(bool * HadError) const112a303c417SDimitry Andric ModuleDebugStreamRef::symbols(bool *HadError) const {
11308bbd35aSDimitry Andric   return make_range(SymbolArray.begin(HadError), SymbolArray.end());
11401095a5dSDimitry Andric }
11501095a5dSDimitry Andric 
readSymbolAtOffset(uint32_t Offset) const116d8e91e46SDimitry Andric CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const {
117d8e91e46SDimitry Andric   auto Iter = SymbolArray.at(Offset);
118d8e91e46SDimitry Andric   assert(Iter != SymbolArray.end());
119d8e91e46SDimitry Andric   return *Iter;
120d8e91e46SDimitry Andric }
121d8e91e46SDimitry Andric 
1229df3605dSDimitry Andric iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator>
subsections() const123d288ef4cSDimitry Andric ModuleDebugStreamRef::subsections() const {
124d288ef4cSDimitry Andric   return make_range(Subsections.begin(), Subsections.end());
12501095a5dSDimitry Andric }
12601095a5dSDimitry Andric 
hasDebugSubsections() const127d288ef4cSDimitry Andric bool ModuleDebugStreamRef::hasDebugSubsections() const {
12808bbd35aSDimitry Andric   return !C13LinesSubstream.empty();
12912f3ca4cSDimitry Andric }
13012f3ca4cSDimitry Andric 
commit()131a303c417SDimitry Andric Error ModuleDebugStreamRef::commit() { return Error::success(); }
132d288ef4cSDimitry Andric 
133d288ef4cSDimitry Andric Expected<codeview::DebugChecksumsSubsectionRef>
findChecksumsSubsection() const134d288ef4cSDimitry Andric ModuleDebugStreamRef::findChecksumsSubsection() const {
1357ab83427SDimitry Andric   codeview::DebugChecksumsSubsectionRef Result;
136d288ef4cSDimitry Andric   for (const auto &SS : subsections()) {
137d288ef4cSDimitry Andric     if (SS.kind() != DebugSubsectionKind::FileChecksums)
138d288ef4cSDimitry Andric       continue;
139d288ef4cSDimitry Andric 
140d288ef4cSDimitry Andric     if (auto EC = Result.initialize(SS.getRecordData()))
141d288ef4cSDimitry Andric       return std::move(EC);
142d288ef4cSDimitry Andric     return Result;
143d288ef4cSDimitry Andric   }
1447ab83427SDimitry Andric   return Result;
145d288ef4cSDimitry Andric }
146