1 //===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===//
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
7 //===----------------------------------------------------------------------===//
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/RawConstants.h"
18 #include "llvm/DebugInfo/PDB/Native/RawError.h"
19 #include "llvm/Support/BinaryStreamReader.h"
20 #include "llvm/Support/BinaryStreamRef.h"
21 #include "llvm/Support/Error.h"
26 using namespace llvm::codeview
;
27 using namespace llvm::msf
;
28 using namespace llvm::pdb
;
30 ModuleDebugStreamRef::ModuleDebugStreamRef(
31 const DbiModuleDescriptor
&Module
,
32 std::unique_ptr
<MappedBlockStream
> Stream
)
33 : Mod(Module
), Stream(std::move(Stream
)) {}
35 ModuleDebugStreamRef::~ModuleDebugStreamRef() = default;
37 Error
ModuleDebugStreamRef::reload() {
38 BinaryStreamReader
Reader(*Stream
);
40 if (Mod
.getModuleStreamIndex() != llvm::pdb::kInvalidStreamIndex
) {
41 if (Error E
= reloadSerialize(Reader
))
44 if (Reader
.bytesRemaining() > 0)
45 return make_error
<RawError
>(raw_error_code::corrupt_file
,
46 "Unexpected bytes in module stream.");
47 return Error::success();
50 Error
ModuleDebugStreamRef::reloadSerialize(BinaryStreamReader
&Reader
) {
51 uint32_t SymbolSize
= Mod
.getSymbolDebugInfoByteSize();
52 uint32_t C11Size
= Mod
.getC11LineInfoByteSize();
53 uint32_t C13Size
= Mod
.getC13LineInfoByteSize();
55 if (C11Size
> 0 && C13Size
> 0)
56 return make_error
<RawError
>(raw_error_code::corrupt_file
,
57 "Module has both C11 and C13 line info");
61 if (auto EC
= Reader
.readInteger(Signature
))
64 if (auto EC
= Reader
.readSubstream(SymbolsSubstream
, SymbolSize
))
66 if (auto EC
= Reader
.readSubstream(C11LinesSubstream
, C11Size
))
68 if (auto EC
= Reader
.readSubstream(C13LinesSubstream
, C13Size
))
71 BinaryStreamReader
SymbolReader(SymbolsSubstream
.StreamData
);
72 if (auto EC
= SymbolReader
.readArray(
73 SymbolArray
, SymbolReader
.bytesRemaining(), sizeof(uint32_t)))
76 BinaryStreamReader
SubsectionsReader(C13LinesSubstream
.StreamData
);
77 if (auto EC
= SubsectionsReader
.readArray(Subsections
,
78 SubsectionsReader
.bytesRemaining()))
81 uint32_t GlobalRefsSize
;
82 if (auto EC
= Reader
.readInteger(GlobalRefsSize
))
84 if (auto EC
= Reader
.readSubstream(GlobalRefsSubstream
, GlobalRefsSize
))
86 return Error::success();
89 const codeview::CVSymbolArray
90 ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin
) const {
91 return limitSymbolArrayToScope(SymbolArray
, ScopeBegin
);
94 BinarySubstreamRef
ModuleDebugStreamRef::getSymbolsSubstream() const {
95 return SymbolsSubstream
;
98 BinarySubstreamRef
ModuleDebugStreamRef::getC11LinesSubstream() const {
99 return C11LinesSubstream
;
102 BinarySubstreamRef
ModuleDebugStreamRef::getC13LinesSubstream() const {
103 return C13LinesSubstream
;
106 BinarySubstreamRef
ModuleDebugStreamRef::getGlobalRefsSubstream() const {
107 return GlobalRefsSubstream
;
110 iterator_range
<codeview::CVSymbolArray::Iterator
>
111 ModuleDebugStreamRef::symbols(bool *HadError
) const {
112 return make_range(SymbolArray
.begin(HadError
), SymbolArray
.end());
115 CVSymbol
ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset
) const {
116 auto Iter
= SymbolArray
.at(Offset
);
117 assert(Iter
!= SymbolArray
.end());
121 iterator_range
<ModuleDebugStreamRef::DebugSubsectionIterator
>
122 ModuleDebugStreamRef::subsections() const {
123 return make_range(Subsections
.begin(), Subsections
.end());
126 bool ModuleDebugStreamRef::hasDebugSubsections() const {
127 return !C13LinesSubstream
.empty();
130 Error
ModuleDebugStreamRef::commit() { return Error::success(); }
132 Expected
<codeview::DebugChecksumsSubsectionRef
>
133 ModuleDebugStreamRef::findChecksumsSubsection() const {
134 codeview::DebugChecksumsSubsectionRef Result
;
135 for (const auto &SS
: subsections()) {
136 if (SS
.kind() != DebugSubsectionKind::FileChecksums
)
139 if (auto EC
= Result
.initialize(SS
.getRecordData()))
140 return std::move(EC
);