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 15namespace llvm { 16namespace pdb { 17 18namespace { 19 20Expected<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 35class NativeInjectedSource final : public IPDBInjectedSource { 36 const SrcHeaderBlockEntry &Entry; 37 const PDBStringTable &Strings; 38 PDBFile &File; 39 40public: 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 StringRef Ret = cantFail(Strings.getStringForID(Entry.FileNI), 50 "InjectedSourceStream should have rejected this"); 51 return Ret; 52 } 53 54 std::string getObjectFileName() const override { 55 StringRef Ret = cantFail(Strings.getStringForID(Entry.ObjNI), 56 "InjectedSourceStream should have rejected this"); 57 return Ret; 58 } 59 60 std::string getVirtualFileName() const override { 61 StringRef Ret = cantFail(Strings.getStringForID(Entry.VFileNI), 62 "InjectedSourceStream should have rejected this"); 63 return Ret; 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 StringRef VName = 71 cantFail(Strings.getStringForID(Entry.VFileNI), 72 "InjectedSourceStream should have rejected this"); 73 std::string StreamName = ("/src/files/" + VName).str(); 74 75 // Find stream with that name and read its data. 76 // FIXME: Consider validating (or even loading) all this in 77 // InjectedSourceStream so that no error can happen here. 78 auto ExpectedFileStream = File.safelyCreateNamedStream(StreamName); 79 if (!ExpectedFileStream) { 80 consumeError(ExpectedFileStream.takeError()); 81 return "(failed to open data stream)"; 82 } 83 84 auto Data = readStreamData(**ExpectedFileStream, Entry.FileSize); 85 if (!Data) { 86 consumeError(Data.takeError()); 87 return "(failed to read data)"; 88 } 89 return *Data; 90 } 91}; 92 93} // namespace 94 95NativeEnumInjectedSources::NativeEnumInjectedSources( 96 PDBFile &File, const InjectedSourceStream &IJS, 97 const PDBStringTable &Strings) 98 : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {} 99 100uint32_t NativeEnumInjectedSources::getChildCount() const { 101 return static_cast<uint32_t>(Stream.size()); 102} 103 104std::unique_ptr<IPDBInjectedSource> 105NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const { 106 if (N >= getChildCount()) 107 return nullptr; 108 return std::make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second, 109 File, Strings); 110} 111 112std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() { 113 if (Cur == Stream.end()) 114 return nullptr; 115 return std::make_unique<NativeInjectedSource>((Cur++)->second, File, Strings); 116} 117 118void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); } 119 120} 121} 122