diff options
Diffstat (limited to 'lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp')
-rw-r--r-- | lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp b/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp new file mode 100644 index 000000000000..f17ff5bb01f2 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp @@ -0,0 +1,120 @@ +//==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h" + +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" + +namespace llvm { +namespace pdb { + +namespace { + +Expected<std::string> readStreamData(BinaryStream &Stream, uint32_t Limit) { + uint32_t Offset = 0, DataLength = std::min(Limit, Stream.getLength()); + std::string Result; + Result.reserve(DataLength); + while (Offset < DataLength) { + ArrayRef<uint8_t> Data; + if (auto E = Stream.readLongestContiguousChunk(Offset, Data)) + return std::move(E); + Data = Data.take_front(DataLength - Offset); + Offset += Data.size(); + Result += toStringRef(Data); + } + return Result; +} + +class NativeInjectedSource final : public IPDBInjectedSource { + const SrcHeaderBlockEntry &Entry; + const PDBStringTable &Strings; + PDBFile &File; + +public: + NativeInjectedSource(const SrcHeaderBlockEntry &Entry, + PDBFile &File, const PDBStringTable &Strings) + : Entry(Entry), Strings(Strings), File(File) {} + + uint32_t getCrc32() const override { return Entry.CRC; } + uint64_t getCodeByteSize() const override { return Entry.FileSize; } + + std::string getFileName() const override { + auto Name = Strings.getStringForID(Entry.FileNI); + assert(Name && "InjectedSourceStream should have rejected this"); + return *Name; + } + + std::string getObjectFileName() const override { + auto ObjName = Strings.getStringForID(Entry.ObjNI); + assert(ObjName && "InjectedSourceStream should have rejected this"); + return *ObjName; + } + + std::string getVirtualFileName() const override { + auto VName = Strings.getStringForID(Entry.VFileNI); + assert(VName && "InjectedSourceStream should have rejected this"); + return *VName; + } + + uint32_t getCompression() const override { return Entry.Compression; } + + std::string getCode() const override { + // Get name of stream storing the data. + auto VName = Strings.getStringForID(Entry.VFileNI); + assert(VName && "InjectedSourceStream should have rejected this"); + std::string StreamName = ("/src/files/" + *VName).str(); + + // Find stream with that name and read its data. + // FIXME: Consider validating (or even loading) all this in + // InjectedSourceStream so that no error can happen here. + auto ExpectedFileStream = File.safelyCreateNamedStream(StreamName); + if (!ExpectedFileStream) { + consumeError(ExpectedFileStream.takeError()); + return "(failed to open data stream)"; + } + + auto Data = readStreamData(**ExpectedFileStream, Entry.FileSize); + if (!Data) { + consumeError(Data.takeError()); + return "(failed to read data)"; + } + return *Data; + } +}; + +} // namespace + +NativeEnumInjectedSources::NativeEnumInjectedSources( + PDBFile &File, const InjectedSourceStream &IJS, + const PDBStringTable &Strings) + : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {} + +uint32_t NativeEnumInjectedSources::getChildCount() const { + return static_cast<uint32_t>(Stream.size()); +} + +std::unique_ptr<IPDBInjectedSource> +NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const { + if (N >= getChildCount()) + return nullptr; + return make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second, + File, Strings); +} + +std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() { + if (Cur == Stream.end()) + return nullptr; + return make_unique<NativeInjectedSource>((Cur++)->second, File, Strings); +} + +void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); } + +} +} |