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