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