1 //==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==// 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/NativeEnumInjectedSources.h" 10 11 #include "llvm/DebugInfo/MSF/MappedBlockStream.h" 12 #include "llvm/DebugInfo/PDB/Native/HashTable.h" 13 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 14 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" 15 #include "llvm/DebugInfo/PDB/Native/RawTypes.h" 16 17 namespace llvm { 18 namespace pdb { 19 20 namespace { 21 22 Expected<std::string> readStreamData(BinaryStream &Stream, uint64_t Limit) { 23 uint64_t Offset = 0, DataLength = std::min(Limit, Stream.getLength()); 24 std::string Result; 25 Result.reserve(DataLength); 26 while (Offset < DataLength) { 27 ArrayRef<uint8_t> Data; 28 if (auto E = Stream.readLongestContiguousChunk(Offset, Data)) 29 return std::move(E); 30 Data = Data.take_front(DataLength - Offset); 31 Offset += Data.size(); 32 Result += toStringRef(Data); 33 } 34 return Result; 35 } 36 37 class NativeInjectedSource final : public IPDBInjectedSource { 38 const SrcHeaderBlockEntry &Entry; 39 const PDBStringTable &Strings; 40 PDBFile &File; 41 42 public: 43 NativeInjectedSource(const SrcHeaderBlockEntry &Entry, 44 PDBFile &File, const PDBStringTable &Strings) 45 : Entry(Entry), Strings(Strings), File(File) {} 46 47 uint32_t getCrc32() const override { return Entry.CRC; } 48 uint64_t getCodeByteSize() const override { return Entry.FileSize; } 49 50 std::string getFileName() const override { 51 StringRef Ret = cantFail(Strings.getStringForID(Entry.FileNI), 52 "InjectedSourceStream should have rejected this"); 53 return std::string(Ret); 54 } 55 56 std::string getObjectFileName() const override { 57 StringRef Ret = cantFail(Strings.getStringForID(Entry.ObjNI), 58 "InjectedSourceStream should have rejected this"); 59 return std::string(Ret); 60 } 61 62 std::string getVirtualFileName() const override { 63 StringRef Ret = cantFail(Strings.getStringForID(Entry.VFileNI), 64 "InjectedSourceStream should have rejected this"); 65 return std::string(Ret); 66 } 67 68 uint32_t getCompression() const override { return Entry.Compression; } 69 70 std::string getCode() const override { 71 // Get name of stream storing the data. 72 StringRef VName = 73 cantFail(Strings.getStringForID(Entry.VFileNI), 74 "InjectedSourceStream should have rejected this"); 75 std::string StreamName = ("/src/files/" + VName).str(); 76 77 // Find stream with that name and read its data. 78 // FIXME: Consider validating (or even loading) all this in 79 // InjectedSourceStream so that no error can happen here. 80 auto ExpectedFileStream = File.safelyCreateNamedStream(StreamName); 81 if (!ExpectedFileStream) { 82 consumeError(ExpectedFileStream.takeError()); 83 return "(failed to open data stream)"; 84 } 85 86 auto Data = readStreamData(**ExpectedFileStream, Entry.FileSize); 87 if (!Data) { 88 consumeError(Data.takeError()); 89 return "(failed to read data)"; 90 } 91 return *Data; 92 } 93 }; 94 95 } // namespace 96 97 NativeEnumInjectedSources::NativeEnumInjectedSources( 98 PDBFile &File, const InjectedSourceStream &IJS, 99 const PDBStringTable &Strings) 100 : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {} 101 102 uint32_t NativeEnumInjectedSources::getChildCount() const { 103 return static_cast<uint32_t>(Stream.size()); 104 } 105 106 std::unique_ptr<IPDBInjectedSource> 107 NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const { 108 if (N >= getChildCount()) 109 return nullptr; 110 return std::make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second, 111 File, Strings); 112 } 113 114 std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() { 115 if (Cur == Stream.end()) 116 return nullptr; 117 return std::make_unique<NativeInjectedSource>((Cur++)->second, File, Strings); 118 } 119 120 void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); } 121 122 } 123 } 124