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