1*09467b48Spatrick //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
2*09467b48Spatrick //
3*09467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*09467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*09467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*09467b48Spatrick //
7*09467b48Spatrick //===----------------------------------------------------------------------===//
8*09467b48Spatrick
9*09467b48Spatrick #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
10*09467b48Spatrick #include "llvm/ADT/StringRef.h"
11*09467b48Spatrick #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
12*09467b48Spatrick #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
13*09467b48Spatrick #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
14*09467b48Spatrick #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
15*09467b48Spatrick #include "llvm/DebugInfo/PDB/Native/RawError.h"
16*09467b48Spatrick #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
17*09467b48Spatrick #include "llvm/DebugInfo/PDB/PDBTypes.h"
18*09467b48Spatrick #include "llvm/Object/COFF.h"
19*09467b48Spatrick #include "llvm/Support/BinaryStreamArray.h"
20*09467b48Spatrick #include "llvm/Support/BinaryStreamReader.h"
21*09467b48Spatrick #include "llvm/Support/Error.h"
22*09467b48Spatrick #include <cstddef>
23*09467b48Spatrick #include <cstdint>
24*09467b48Spatrick
25*09467b48Spatrick using namespace llvm;
26*09467b48Spatrick using namespace llvm::codeview;
27*09467b48Spatrick using namespace llvm::msf;
28*09467b48Spatrick using namespace llvm::pdb;
29*09467b48Spatrick using namespace llvm::support;
30*09467b48Spatrick
31*09467b48Spatrick template <typename ContribType>
loadSectionContribs(FixedStreamArray<ContribType> & Output,BinaryStreamReader & Reader)32*09467b48Spatrick static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
33*09467b48Spatrick BinaryStreamReader &Reader) {
34*09467b48Spatrick if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
35*09467b48Spatrick return make_error<RawError>(
36*09467b48Spatrick raw_error_code::corrupt_file,
37*09467b48Spatrick "Invalid number of bytes of section contributions");
38*09467b48Spatrick
39*09467b48Spatrick uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
40*09467b48Spatrick if (auto EC = Reader.readArray(Output, Count))
41*09467b48Spatrick return EC;
42*09467b48Spatrick return Error::success();
43*09467b48Spatrick }
44*09467b48Spatrick
DbiStream(std::unique_ptr<BinaryStream> Stream)45*09467b48Spatrick DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
46*09467b48Spatrick : Stream(std::move(Stream)), Header(nullptr) {}
47*09467b48Spatrick
48*09467b48Spatrick DbiStream::~DbiStream() = default;
49*09467b48Spatrick
reload(PDBFile * Pdb)50*09467b48Spatrick Error DbiStream::reload(PDBFile *Pdb) {
51*09467b48Spatrick BinaryStreamReader Reader(*Stream);
52*09467b48Spatrick
53*09467b48Spatrick if (Stream->getLength() < sizeof(DbiStreamHeader))
54*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
55*09467b48Spatrick "DBI Stream does not contain a header.");
56*09467b48Spatrick if (auto EC = Reader.readObject(Header))
57*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
58*09467b48Spatrick "DBI Stream does not contain a header.");
59*09467b48Spatrick
60*09467b48Spatrick if (Header->VersionSignature != -1)
61*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
62*09467b48Spatrick "Invalid DBI version signature.");
63*09467b48Spatrick
64*09467b48Spatrick // Require at least version 7, which should be present in all PDBs
65*09467b48Spatrick // produced in the last decade and allows us to avoid having to
66*09467b48Spatrick // special case all kinds of complicated arcane formats.
67*09467b48Spatrick if (Header->VersionHeader < PdbDbiV70)
68*09467b48Spatrick return make_error<RawError>(raw_error_code::feature_unsupported,
69*09467b48Spatrick "Unsupported DBI version.");
70*09467b48Spatrick
71*09467b48Spatrick if (Stream->getLength() !=
72*09467b48Spatrick sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
73*09467b48Spatrick Header->SecContrSubstreamSize + Header->SectionMapSize +
74*09467b48Spatrick Header->FileInfoSize + Header->TypeServerSize +
75*09467b48Spatrick Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
76*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
77*09467b48Spatrick "DBI Length does not equal sum of substreams.");
78*09467b48Spatrick
79*09467b48Spatrick // Only certain substreams are guaranteed to be aligned. Validate
80*09467b48Spatrick // them here.
81*09467b48Spatrick if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
82*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
83*09467b48Spatrick "DBI MODI substream not aligned.");
84*09467b48Spatrick if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
85*09467b48Spatrick return make_error<RawError>(
86*09467b48Spatrick raw_error_code::corrupt_file,
87*09467b48Spatrick "DBI section contribution substream not aligned.");
88*09467b48Spatrick if (Header->SectionMapSize % sizeof(uint32_t) != 0)
89*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
90*09467b48Spatrick "DBI section map substream not aligned.");
91*09467b48Spatrick if (Header->FileInfoSize % sizeof(uint32_t) != 0)
92*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
93*09467b48Spatrick "DBI file info substream not aligned.");
94*09467b48Spatrick if (Header->TypeServerSize % sizeof(uint32_t) != 0)
95*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
96*09467b48Spatrick "DBI type server substream not aligned.");
97*09467b48Spatrick
98*09467b48Spatrick if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
99*09467b48Spatrick return EC;
100*09467b48Spatrick
101*09467b48Spatrick if (auto EC = Reader.readSubstream(SecContrSubstream,
102*09467b48Spatrick Header->SecContrSubstreamSize))
103*09467b48Spatrick return EC;
104*09467b48Spatrick if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
105*09467b48Spatrick return EC;
106*09467b48Spatrick if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
107*09467b48Spatrick return EC;
108*09467b48Spatrick if (auto EC =
109*09467b48Spatrick Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
110*09467b48Spatrick return EC;
111*09467b48Spatrick if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
112*09467b48Spatrick return EC;
113*09467b48Spatrick if (auto EC = Reader.readArray(
114*09467b48Spatrick DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
115*09467b48Spatrick return EC;
116*09467b48Spatrick
117*09467b48Spatrick if (auto EC = Modules.initialize(ModiSubstream.StreamData,
118*09467b48Spatrick FileInfoSubstream.StreamData))
119*09467b48Spatrick return EC;
120*09467b48Spatrick
121*09467b48Spatrick if (auto EC = initializeSectionContributionData())
122*09467b48Spatrick return EC;
123*09467b48Spatrick if (auto EC = initializeSectionHeadersData(Pdb))
124*09467b48Spatrick return EC;
125*09467b48Spatrick if (auto EC = initializeSectionMapData())
126*09467b48Spatrick return EC;
127*09467b48Spatrick if (auto EC = initializeOldFpoRecords(Pdb))
128*09467b48Spatrick return EC;
129*09467b48Spatrick if (auto EC = initializeNewFpoRecords(Pdb))
130*09467b48Spatrick return EC;
131*09467b48Spatrick
132*09467b48Spatrick if (Reader.bytesRemaining() > 0)
133*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
134*09467b48Spatrick "Found unexpected bytes in DBI Stream.");
135*09467b48Spatrick
136*09467b48Spatrick if (!ECSubstream.empty()) {
137*09467b48Spatrick BinaryStreamReader ECReader(ECSubstream.StreamData);
138*09467b48Spatrick if (auto EC = ECNames.reload(ECReader))
139*09467b48Spatrick return EC;
140*09467b48Spatrick }
141*09467b48Spatrick
142*09467b48Spatrick return Error::success();
143*09467b48Spatrick }
144*09467b48Spatrick
getDbiVersion() const145*09467b48Spatrick PdbRaw_DbiVer DbiStream::getDbiVersion() const {
146*09467b48Spatrick uint32_t Value = Header->VersionHeader;
147*09467b48Spatrick return static_cast<PdbRaw_DbiVer>(Value);
148*09467b48Spatrick }
149*09467b48Spatrick
getAge() const150*09467b48Spatrick uint32_t DbiStream::getAge() const { return Header->Age; }
151*09467b48Spatrick
getPublicSymbolStreamIndex() const152*09467b48Spatrick uint16_t DbiStream::getPublicSymbolStreamIndex() const {
153*09467b48Spatrick return Header->PublicSymbolStreamIndex;
154*09467b48Spatrick }
155*09467b48Spatrick
getGlobalSymbolStreamIndex() const156*09467b48Spatrick uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
157*09467b48Spatrick return Header->GlobalSymbolStreamIndex;
158*09467b48Spatrick }
159*09467b48Spatrick
getFlags() const160*09467b48Spatrick uint16_t DbiStream::getFlags() const { return Header->Flags; }
161*09467b48Spatrick
isIncrementallyLinked() const162*09467b48Spatrick bool DbiStream::isIncrementallyLinked() const {
163*09467b48Spatrick return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
164*09467b48Spatrick }
165*09467b48Spatrick
hasCTypes() const166*09467b48Spatrick bool DbiStream::hasCTypes() const {
167*09467b48Spatrick return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
168*09467b48Spatrick }
169*09467b48Spatrick
isStripped() const170*09467b48Spatrick bool DbiStream::isStripped() const {
171*09467b48Spatrick return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
172*09467b48Spatrick }
173*09467b48Spatrick
getBuildNumber() const174*09467b48Spatrick uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
175*09467b48Spatrick
getBuildMajorVersion() const176*09467b48Spatrick uint16_t DbiStream::getBuildMajorVersion() const {
177*09467b48Spatrick return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
178*09467b48Spatrick DbiBuildNo::BuildMajorShift;
179*09467b48Spatrick }
180*09467b48Spatrick
getBuildMinorVersion() const181*09467b48Spatrick uint16_t DbiStream::getBuildMinorVersion() const {
182*09467b48Spatrick return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
183*09467b48Spatrick DbiBuildNo::BuildMinorShift;
184*09467b48Spatrick }
185*09467b48Spatrick
getPdbDllRbld() const186*09467b48Spatrick uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
187*09467b48Spatrick
getPdbDllVersion() const188*09467b48Spatrick uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
189*09467b48Spatrick
getSymRecordStreamIndex() const190*09467b48Spatrick uint32_t DbiStream::getSymRecordStreamIndex() const {
191*09467b48Spatrick return Header->SymRecordStreamIndex;
192*09467b48Spatrick }
193*09467b48Spatrick
getMachineType() const194*09467b48Spatrick PDB_Machine DbiStream::getMachineType() const {
195*09467b48Spatrick uint16_t Machine = Header->MachineType;
196*09467b48Spatrick return static_cast<PDB_Machine>(Machine);
197*09467b48Spatrick }
198*09467b48Spatrick
getSectionHeaders() const199*09467b48Spatrick FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
200*09467b48Spatrick return SectionHeaders;
201*09467b48Spatrick }
202*09467b48Spatrick
hasOldFpoRecords() const203*09467b48Spatrick bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }
204*09467b48Spatrick
getOldFpoRecords() const205*09467b48Spatrick FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {
206*09467b48Spatrick return OldFpoRecords;
207*09467b48Spatrick }
208*09467b48Spatrick
hasNewFpoRecords() const209*09467b48Spatrick bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }
210*09467b48Spatrick
getNewFpoRecords() const211*09467b48Spatrick const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {
212*09467b48Spatrick return NewFpoRecords;
213*09467b48Spatrick }
214*09467b48Spatrick
modules() const215*09467b48Spatrick const DbiModuleList &DbiStream::modules() const { return Modules; }
216*09467b48Spatrick
getSectionMap() const217*09467b48Spatrick FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
218*09467b48Spatrick return SectionMap;
219*09467b48Spatrick }
220*09467b48Spatrick
visitSectionContributions(ISectionContribVisitor & Visitor) const221*09467b48Spatrick void DbiStream::visitSectionContributions(
222*09467b48Spatrick ISectionContribVisitor &Visitor) const {
223*09467b48Spatrick if (!SectionContribs.empty()) {
224*09467b48Spatrick assert(SectionContribVersion == DbiSecContribVer60);
225*09467b48Spatrick for (auto &SC : SectionContribs)
226*09467b48Spatrick Visitor.visit(SC);
227*09467b48Spatrick } else if (!SectionContribs2.empty()) {
228*09467b48Spatrick assert(SectionContribVersion == DbiSecContribV2);
229*09467b48Spatrick for (auto &SC : SectionContribs2)
230*09467b48Spatrick Visitor.visit(SC);
231*09467b48Spatrick }
232*09467b48Spatrick }
233*09467b48Spatrick
getECName(uint32_t NI) const234*09467b48Spatrick Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
235*09467b48Spatrick return ECNames.getStringForID(NI);
236*09467b48Spatrick }
237*09467b48Spatrick
initializeSectionContributionData()238*09467b48Spatrick Error DbiStream::initializeSectionContributionData() {
239*09467b48Spatrick if (SecContrSubstream.empty())
240*09467b48Spatrick return Error::success();
241*09467b48Spatrick
242*09467b48Spatrick BinaryStreamReader SCReader(SecContrSubstream.StreamData);
243*09467b48Spatrick if (auto EC = SCReader.readEnum(SectionContribVersion))
244*09467b48Spatrick return EC;
245*09467b48Spatrick
246*09467b48Spatrick if (SectionContribVersion == DbiSecContribVer60)
247*09467b48Spatrick return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
248*09467b48Spatrick if (SectionContribVersion == DbiSecContribV2)
249*09467b48Spatrick return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
250*09467b48Spatrick
251*09467b48Spatrick return make_error<RawError>(raw_error_code::feature_unsupported,
252*09467b48Spatrick "Unsupported DBI Section Contribution version");
253*09467b48Spatrick }
254*09467b48Spatrick
255*09467b48Spatrick // Initializes this->SectionHeaders.
initializeSectionHeadersData(PDBFile * Pdb)256*09467b48Spatrick Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
257*09467b48Spatrick Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
258*09467b48Spatrick createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);
259*09467b48Spatrick if (auto EC = ExpectedStream.takeError())
260*09467b48Spatrick return EC;
261*09467b48Spatrick
262*09467b48Spatrick auto &SHS = *ExpectedStream;
263*09467b48Spatrick if (!SHS)
264*09467b48Spatrick return Error::success();
265*09467b48Spatrick
266*09467b48Spatrick size_t StreamLen = SHS->getLength();
267*09467b48Spatrick if (StreamLen % sizeof(object::coff_section))
268*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
269*09467b48Spatrick "Corrupted section header stream.");
270*09467b48Spatrick
271*09467b48Spatrick size_t NumSections = StreamLen / sizeof(object::coff_section);
272*09467b48Spatrick BinaryStreamReader Reader(*SHS);
273*09467b48Spatrick if (auto EC = Reader.readArray(SectionHeaders, NumSections))
274*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
275*09467b48Spatrick "Could not read a bitmap.");
276*09467b48Spatrick
277*09467b48Spatrick SectionHeaderStream = std::move(SHS);
278*09467b48Spatrick return Error::success();
279*09467b48Spatrick }
280*09467b48Spatrick
281*09467b48Spatrick // Initializes this->Fpos.
initializeOldFpoRecords(PDBFile * Pdb)282*09467b48Spatrick Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {
283*09467b48Spatrick Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
284*09467b48Spatrick createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);
285*09467b48Spatrick if (auto EC = ExpectedStream.takeError())
286*09467b48Spatrick return EC;
287*09467b48Spatrick
288*09467b48Spatrick auto &FS = *ExpectedStream;
289*09467b48Spatrick if (!FS)
290*09467b48Spatrick return Error::success();
291*09467b48Spatrick
292*09467b48Spatrick size_t StreamLen = FS->getLength();
293*09467b48Spatrick if (StreamLen % sizeof(object::FpoData))
294*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
295*09467b48Spatrick "Corrupted Old FPO stream.");
296*09467b48Spatrick
297*09467b48Spatrick size_t NumRecords = StreamLen / sizeof(object::FpoData);
298*09467b48Spatrick BinaryStreamReader Reader(*FS);
299*09467b48Spatrick if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))
300*09467b48Spatrick return make_error<RawError>(raw_error_code::corrupt_file,
301*09467b48Spatrick "Corrupted Old FPO stream.");
302*09467b48Spatrick OldFpoStream = std::move(FS);
303*09467b48Spatrick return Error::success();
304*09467b48Spatrick }
305*09467b48Spatrick
initializeNewFpoRecords(PDBFile * Pdb)306*09467b48Spatrick Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {
307*09467b48Spatrick Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
308*09467b48Spatrick createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);
309*09467b48Spatrick if (auto EC = ExpectedStream.takeError())
310*09467b48Spatrick return EC;
311*09467b48Spatrick
312*09467b48Spatrick auto &FS = *ExpectedStream;
313*09467b48Spatrick if (!FS)
314*09467b48Spatrick return Error::success();
315*09467b48Spatrick
316*09467b48Spatrick if (auto EC = NewFpoRecords.initialize(*FS))
317*09467b48Spatrick return EC;
318*09467b48Spatrick
319*09467b48Spatrick NewFpoStream = std::move(FS);
320*09467b48Spatrick return Error::success();
321*09467b48Spatrick }
322*09467b48Spatrick
323*09467b48Spatrick Expected<std::unique_ptr<msf::MappedBlockStream>>
createIndexedStreamForHeaderType(PDBFile * Pdb,DbgHeaderType Type) const324*09467b48Spatrick DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,
325*09467b48Spatrick DbgHeaderType Type) const {
326*09467b48Spatrick if (!Pdb)
327*09467b48Spatrick return nullptr;
328*09467b48Spatrick
329*09467b48Spatrick if (DbgStreams.empty())
330*09467b48Spatrick return nullptr;
331*09467b48Spatrick
332*09467b48Spatrick uint32_t StreamNum = getDebugStreamIndex(Type);
333*09467b48Spatrick
334*09467b48Spatrick // This means there is no such stream.
335*09467b48Spatrick if (StreamNum == kInvalidStreamIndex)
336*09467b48Spatrick return nullptr;
337*09467b48Spatrick
338*09467b48Spatrick return Pdb->safelyCreateIndexedStream(StreamNum);
339*09467b48Spatrick }
340*09467b48Spatrick
getSectionContributionData() const341*09467b48Spatrick BinarySubstreamRef DbiStream::getSectionContributionData() const {
342*09467b48Spatrick return SecContrSubstream;
343*09467b48Spatrick }
344*09467b48Spatrick
getSecMapSubstreamData() const345*09467b48Spatrick BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
346*09467b48Spatrick return SecMapSubstream;
347*09467b48Spatrick }
348*09467b48Spatrick
getModiSubstreamData() const349*09467b48Spatrick BinarySubstreamRef DbiStream::getModiSubstreamData() const {
350*09467b48Spatrick return ModiSubstream;
351*09467b48Spatrick }
352*09467b48Spatrick
getFileInfoSubstreamData() const353*09467b48Spatrick BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
354*09467b48Spatrick return FileInfoSubstream;
355*09467b48Spatrick }
356*09467b48Spatrick
getTypeServerMapSubstreamData() const357*09467b48Spatrick BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
358*09467b48Spatrick return TypeServerMapSubstream;
359*09467b48Spatrick }
360*09467b48Spatrick
getECSubstreamData() const361*09467b48Spatrick BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
362*09467b48Spatrick
initializeSectionMapData()363*09467b48Spatrick Error DbiStream::initializeSectionMapData() {
364*09467b48Spatrick if (SecMapSubstream.empty())
365*09467b48Spatrick return Error::success();
366*09467b48Spatrick
367*09467b48Spatrick BinaryStreamReader SMReader(SecMapSubstream.StreamData);
368*09467b48Spatrick const SecMapHeader *Header;
369*09467b48Spatrick if (auto EC = SMReader.readObject(Header))
370*09467b48Spatrick return EC;
371*09467b48Spatrick if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
372*09467b48Spatrick return EC;
373*09467b48Spatrick return Error::success();
374*09467b48Spatrick }
375*09467b48Spatrick
getDebugStreamIndex(DbgHeaderType Type) const376*09467b48Spatrick uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
377*09467b48Spatrick uint16_t T = static_cast<uint16_t>(Type);
378*09467b48Spatrick if (T >= DbgStreams.size())
379*09467b48Spatrick return kInvalidStreamIndex;
380*09467b48Spatrick return DbgStreams[T];
381*09467b48Spatrick }
382