| //===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" | |
| #include "llvm/ADT/iterator_range.h" | |
| #include "llvm/DebugInfo/CodeView/CodeView.h" | |
| #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" | |
| #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" | |
| #include "llvm/DebugInfo/MSF/MSFCommon.h" | |
| #include "llvm/DebugInfo/MSF/MappedBlockStream.h" | |
| #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" | |
| #include "llvm/DebugInfo/PDB/Native/RawConstants.h" | |
| #include "llvm/DebugInfo/PDB/Native/RawError.h" | |
| #include "llvm/DebugInfo/PDB/Native/RawTypes.h" | |
| #include "llvm/Support/BinaryStreamArray.h" | |
| #include "llvm/Support/BinaryStreamReader.h" | |
| #include "llvm/Support/BinaryStreamRef.h" | |
| #include "llvm/Support/Error.h" | |
| #include <cstdint> | |
| using namespace llvm; | |
| using namespace llvm::codeview; | |
| using namespace llvm::msf; | |
| using namespace llvm::pdb; | |
| ModuleDebugStreamRef::ModuleDebugStreamRef( | |
| const DbiModuleDescriptor &Module, | |
| std::unique_ptr<MappedBlockStream> Stream) | |
| : Mod(Module), Stream(std::move(Stream)) {} | |
| ModuleDebugStreamRef::~ModuleDebugStreamRef() = default; | |
| Error ModuleDebugStreamRef::reload() { | |
| BinaryStreamReader Reader(*Stream); | |
| if (Mod.getModuleStreamIndex() != llvm::pdb::kInvalidStreamIndex) { | |
| if (Error E = reloadSerialize(Reader)) | |
| return E; | |
| } | |
| if (Reader.bytesRemaining() > 0) | |
| return make_error<RawError>(raw_error_code::corrupt_file, | |
| "Unexpected bytes in module stream."); | |
| return Error::success(); | |
| } | |
| Error ModuleDebugStreamRef::reloadSerialize(BinaryStreamReader &Reader) { | |
| uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); | |
| uint32_t C11Size = Mod.getC11LineInfoByteSize(); | |
| uint32_t C13Size = Mod.getC13LineInfoByteSize(); | |
| if (C11Size > 0 && C13Size > 0) | |
| return make_error<RawError>(raw_error_code::corrupt_file, | |
| "Module has both C11 and C13 line info"); | |
| BinaryStreamRef S; | |
| if (auto EC = Reader.readInteger(Signature)) | |
| return EC; | |
| Reader.setOffset(0); | |
| if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize)) | |
| return EC; | |
| if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size)) | |
| return EC; | |
| if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size)) | |
| return EC; | |
| BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData); | |
| if (auto EC = SymbolReader.readArray( | |
| SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t))) | |
| return EC; | |
| BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData); | |
| if (auto EC = SubsectionsReader.readArray(Subsections, | |
| SubsectionsReader.bytesRemaining())) | |
| return EC; | |
| uint32_t GlobalRefsSize; | |
| if (auto EC = Reader.readInteger(GlobalRefsSize)) | |
| return EC; | |
| if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize)) | |
| return EC; | |
| return Error::success(); | |
| } | |
| const codeview::CVSymbolArray | |
| ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const { | |
| return limitSymbolArrayToScope(SymbolArray, ScopeBegin); | |
| } | |
| BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const { | |
| return SymbolsSubstream; | |
| } | |
| BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const { | |
| return C11LinesSubstream; | |
| } | |
| BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const { | |
| return C13LinesSubstream; | |
| } | |
| BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const { | |
| return GlobalRefsSubstream; | |
| } | |
| iterator_range<codeview::CVSymbolArray::Iterator> | |
| ModuleDebugStreamRef::symbols(bool *HadError) const { | |
| return make_range(SymbolArray.begin(HadError), SymbolArray.end()); | |
| } | |
| CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const { | |
| auto Iter = SymbolArray.at(Offset); | |
| assert(Iter != SymbolArray.end()); | |
| return *Iter; | |
| } | |
| iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator> | |
| ModuleDebugStreamRef::subsections() const { | |
| return make_range(Subsections.begin(), Subsections.end()); | |
| } | |
| bool ModuleDebugStreamRef::hasDebugSubsections() const { | |
| return !C13LinesSubstream.empty(); | |
| } | |
| Error ModuleDebugStreamRef::commit() { return Error::success(); } | |
| Expected<codeview::DebugChecksumsSubsectionRef> | |
| ModuleDebugStreamRef::findChecksumsSubsection() const { | |
| codeview::DebugChecksumsSubsectionRef Result; | |
| for (const auto &SS : subsections()) { | |
| if (SS.kind() != DebugSubsectionKind::FileChecksums) | |
| continue; | |
| if (auto EC = Result.initialize(SS.getRecordData())) | |
| return std::move(EC); | |
| return Result; | |
| } | |
| return Result; | |
| } |