1 //===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
10 #include "llvm/ADT/iterator_range.h"
11 #include "llvm/DebugInfo/CodeView/CodeView.h"
12 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
13 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
14 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
15 #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
16 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
17 #include "llvm/DebugInfo/PDB/Native/RawError.h"
18 #include "llvm/Support/BinaryStreamReader.h"
19 #include "llvm/Support/BinaryStreamRef.h"
20 #include "llvm/Support/Error.h"
21 #include <algorithm>
22 #include <cstdint>
23 
24 using namespace llvm;
25 using namespace llvm::codeview;
26 using namespace llvm::msf;
27 using namespace llvm::pdb;
28 
29 ModuleDebugStreamRef::ModuleDebugStreamRef(
30     const DbiModuleDescriptor &Module,
31     std::unique_ptr<MappedBlockStream> Stream)
32     : Mod(Module), Stream(std::move(Stream)) {}
33 
34 ModuleDebugStreamRef::~ModuleDebugStreamRef() = default;
35 
36 Error ModuleDebugStreamRef::reload() {
37   BinaryStreamReader Reader(*Stream);
38 
39   uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
40   uint32_t C11Size = Mod.getC11LineInfoByteSize();
41   uint32_t C13Size = Mod.getC13LineInfoByteSize();
42 
43   if (C11Size > 0 && C13Size > 0)
44     return make_error<RawError>(raw_error_code::corrupt_file,
45                                 "Module has both C11 and C13 line info");
46 
47   BinaryStreamRef S;
48 
49   if (auto EC = Reader.readInteger(Signature))
50     return EC;
51   Reader.setOffset(0);
52   if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize))
53     return EC;
54   if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size))
55     return EC;
56   if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size))
57     return EC;
58 
59   BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData);
60   if (auto EC = SymbolReader.readArray(
61           SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t)))
62     return EC;
63 
64   BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);
65   if (auto EC = SubsectionsReader.readArray(Subsections,
66                                             SubsectionsReader.bytesRemaining()))
67     return EC;
68 
69   uint32_t GlobalRefsSize;
70   if (auto EC = Reader.readInteger(GlobalRefsSize))
71     return EC;
72   if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize))
73     return EC;
74   if (Reader.bytesRemaining() > 0)
75     return make_error<RawError>(raw_error_code::corrupt_file,
76                                 "Unexpected bytes in module stream.");
77 
78   return Error::success();
79 }
80 
81 const codeview::CVSymbolArray
82 ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const {
83   return limitSymbolArrayToScope(SymbolArray, ScopeBegin);
84 }
85 
86 BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const {
87   return SymbolsSubstream;
88 }
89 
90 BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const {
91   return C11LinesSubstream;
92 }
93 
94 BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const {
95   return C13LinesSubstream;
96 }
97 
98 BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const {
99   return GlobalRefsSubstream;
100 }
101 
102 iterator_range<codeview::CVSymbolArray::Iterator>
103 ModuleDebugStreamRef::symbols(bool *HadError) const {
104   return make_range(SymbolArray.begin(HadError), SymbolArray.end());
105 }
106 
107 CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const {
108   auto Iter = SymbolArray.at(Offset);
109   assert(Iter != SymbolArray.end());
110   return *Iter;
111 }
112 
113 iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator>
114 ModuleDebugStreamRef::subsections() const {
115   return make_range(Subsections.begin(), Subsections.end());
116 }
117 
118 bool ModuleDebugStreamRef::hasDebugSubsections() const {
119   return !C13LinesSubstream.empty();
120 }
121 
122 Error ModuleDebugStreamRef::commit() { return Error::success(); }
123 
124 Expected<codeview::DebugChecksumsSubsectionRef>
125 ModuleDebugStreamRef::findChecksumsSubsection() const {
126   codeview::DebugChecksumsSubsectionRef Result;
127   for (const auto &SS : subsections()) {
128     if (SS.kind() != DebugSubsectionKind::FileChecksums)
129       continue;
130 
131     if (auto EC = Result.initialize(SS.getRecordData()))
132       return std::move(EC);
133     return Result;
134   }
135   return Result;
136 }
137