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/SymbolRecordHelpers.h" 14 #include "llvm/DebugInfo/MSF/MSFCommon.h" 15 #include "llvm/DebugInfo/MSF/MappedBlockStream.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/DebugInfo/PDB/Native/RawTypes.h" 20 #include "llvm/Support/BinaryStreamArray.h" 21 #include "llvm/Support/BinaryStreamReader.h" 22 #include "llvm/Support/BinaryStreamRef.h" 23 #include "llvm/Support/Error.h" 24 #include <cstdint> 25 26 using namespace llvm; 27 using namespace llvm::codeview; 28 using namespace llvm::msf; 29 using namespace llvm::pdb; 30 31 ModuleDebugStreamRef::ModuleDebugStreamRef( 32 const DbiModuleDescriptor &Module, 33 std::unique_ptr<MappedBlockStream> Stream) 34 : Mod(Module), Stream(std::move(Stream)) {} 35 36 ModuleDebugStreamRef::~ModuleDebugStreamRef() = default; 37 38 Error ModuleDebugStreamRef::reload() { 39 BinaryStreamReader Reader(*Stream); 40 41 if (Mod.getModuleStreamIndex() != llvm::pdb::kInvalidStreamIndex) { 42 if (Error E = reloadSerialize(Reader)) 43 return E; 44 } 45 if (Reader.bytesRemaining() > 0) 46 return make_error<RawError>(raw_error_code::corrupt_file, 47 "Unexpected bytes in module stream."); 48 return Error::success(); 49 } 50 51 Error ModuleDebugStreamRef::reloadSerialize(BinaryStreamReader &Reader) { 52 uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); 53 uint32_t C11Size = Mod.getC11LineInfoByteSize(); 54 uint32_t C13Size = Mod.getC13LineInfoByteSize(); 55 56 if (C11Size > 0 && C13Size > 0) 57 return make_error<RawError>(raw_error_code::corrupt_file, 58 "Module has both C11 and C13 line info"); 59 60 BinaryStreamRef S; 61 62 if (auto EC = Reader.readInteger(Signature)) 63 return EC; 64 Reader.setOffset(0); 65 if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize)) 66 return EC; 67 if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size)) 68 return EC; 69 if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size)) 70 return EC; 71 72 BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData); 73 if (auto EC = SymbolReader.readArray( 74 SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t))) 75 return EC; 76 77 BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData); 78 if (auto EC = SubsectionsReader.readArray(Subsections, 79 SubsectionsReader.bytesRemaining())) 80 return EC; 81 82 uint32_t GlobalRefsSize; 83 if (auto EC = Reader.readInteger(GlobalRefsSize)) 84 return EC; 85 if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize)) 86 return EC; 87 return Error::success(); 88 } 89 90 const codeview::CVSymbolArray 91 ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const { 92 return limitSymbolArrayToScope(SymbolArray, ScopeBegin); 93 } 94 95 BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const { 96 return SymbolsSubstream; 97 } 98 99 BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const { 100 return C11LinesSubstream; 101 } 102 103 BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const { 104 return C13LinesSubstream; 105 } 106 107 BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const { 108 return GlobalRefsSubstream; 109 } 110 111 iterator_range<codeview::CVSymbolArray::Iterator> 112 ModuleDebugStreamRef::symbols(bool *HadError) const { 113 return make_range(SymbolArray.begin(HadError), SymbolArray.end()); 114 } 115 116 CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const { 117 auto Iter = SymbolArray.at(Offset); 118 assert(Iter != SymbolArray.end()); 119 return *Iter; 120 } 121 122 iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator> 123 ModuleDebugStreamRef::subsections() const { 124 return make_range(Subsections.begin(), Subsections.end()); 125 } 126 127 bool ModuleDebugStreamRef::hasDebugSubsections() const { 128 return !C13LinesSubstream.empty(); 129 } 130 131 Error ModuleDebugStreamRef::commit() { return Error::success(); } 132 133 Expected<codeview::DebugChecksumsSubsectionRef> 134 ModuleDebugStreamRef::findChecksumsSubsection() const { 135 codeview::DebugChecksumsSubsectionRef Result; 136 for (const auto &SS : subsections()) { 137 if (SS.kind() != DebugSubsectionKind::FileChecksums) 138 continue; 139 140 if (auto EC = Result.initialize(SS.getRecordData())) 141 return std::move(EC); 142 return Result; 143 } 144 return Result; 145 } 146