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