124 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"10 11#include "llvm/ADT/StringExtras.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 17namespace llvm {18namespace pdb {19 20namespace {21 22Expected<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 37class NativeInjectedSource final : public IPDBInjectedSource {38 const SrcHeaderBlockEntry &Entry;39 const PDBStringTable &Strings;40 PDBFile &File;41 42public: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 in79 // 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} // namespace96 97NativeEnumInjectedSources::NativeEnumInjectedSources(98 PDBFile &File, const InjectedSourceStream &IJS,99 const PDBStringTable &Strings)100 : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {}101 102uint32_t NativeEnumInjectedSources::getChildCount() const {103 return static_cast<uint32_t>(Stream.size());104}105 106std::unique_ptr<IPDBInjectedSource>107NativeEnumInjectedSources::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 114std::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 120void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); }121 122}123}124