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 
11*ed98c1b3Sserge-sans-paille #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
12*ed98c1b3Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/HashTable.h"
13d100b5ddSNico Weber #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
14d100b5ddSNico Weber #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
15*ed98c1b3Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
16d100b5ddSNico Weber 
17d100b5ddSNico Weber namespace llvm {
18d100b5ddSNico Weber namespace pdb {
19d100b5ddSNico Weber 
20d100b5ddSNico Weber namespace {
21d100b5ddSNico Weber 
readStreamData(BinaryStream & Stream,uint64_t Limit)22646299d1SNico Weber Expected<std::string> readStreamData(BinaryStream &Stream, uint64_t Limit) {
23646299d1SNico Weber   uint64_t Offset = 0, DataLength = std::min(Limit, Stream.getLength());
24d100b5ddSNico Weber   std::string Result;
25d100b5ddSNico Weber   Result.reserve(DataLength);
26d100b5ddSNico Weber   while (Offset < DataLength) {
27d100b5ddSNico Weber     ArrayRef<uint8_t> Data;
28d100b5ddSNico Weber     if (auto E = Stream.readLongestContiguousChunk(Offset, Data))
29c55cf4afSBill Wendling       return std::move(E);
307bb5fc05SNico Weber     Data = Data.take_front(DataLength - Offset);
31d100b5ddSNico Weber     Offset += Data.size();
32d100b5ddSNico Weber     Result += toStringRef(Data);
33d100b5ddSNico Weber   }
34d100b5ddSNico Weber   return Result;
35d100b5ddSNico Weber }
36d100b5ddSNico Weber 
37d100b5ddSNico Weber class NativeInjectedSource final : public IPDBInjectedSource {
38d100b5ddSNico Weber   const SrcHeaderBlockEntry &Entry;
39d100b5ddSNico Weber   const PDBStringTable &Strings;
40d100b5ddSNico Weber   PDBFile &File;
41d100b5ddSNico Weber 
42d100b5ddSNico Weber public:
NativeInjectedSource(const SrcHeaderBlockEntry & Entry,PDBFile & File,const PDBStringTable & Strings)43d100b5ddSNico Weber   NativeInjectedSource(const SrcHeaderBlockEntry &Entry,
44d100b5ddSNico Weber                        PDBFile &File, const PDBStringTable &Strings)
45d100b5ddSNico Weber       : Entry(Entry), Strings(Strings), File(File) {}
46d100b5ddSNico Weber 
getCrc32() const47d100b5ddSNico Weber   uint32_t getCrc32() const override { return Entry.CRC; }
getCodeByteSize() const48d100b5ddSNico Weber   uint64_t getCodeByteSize() const override { return Entry.FileSize; }
49d100b5ddSNico Weber 
getFileName() const50d100b5ddSNico Weber   std::string getFileName() const override {
5178d632d1SGeorge Rimar     StringRef Ret = cantFail(Strings.getStringForID(Entry.FileNI),
5278d632d1SGeorge Rimar                              "InjectedSourceStream should have rejected this");
53adcd0268SBenjamin Kramer     return std::string(Ret);
54d100b5ddSNico Weber   }
55d100b5ddSNico Weber 
getObjectFileName() const56d100b5ddSNico Weber   std::string getObjectFileName() const override {
5778d632d1SGeorge Rimar     StringRef Ret = cantFail(Strings.getStringForID(Entry.ObjNI),
5878d632d1SGeorge Rimar                              "InjectedSourceStream should have rejected this");
59adcd0268SBenjamin Kramer     return std::string(Ret);
60d100b5ddSNico Weber   }
61d100b5ddSNico Weber 
getVirtualFileName() const62d100b5ddSNico Weber   std::string getVirtualFileName() const override {
6378d632d1SGeorge Rimar     StringRef Ret = cantFail(Strings.getStringForID(Entry.VFileNI),
6478d632d1SGeorge Rimar                              "InjectedSourceStream should have rejected this");
65adcd0268SBenjamin Kramer     return std::string(Ret);
66d100b5ddSNico Weber   }
67d100b5ddSNico Weber 
getCompression() const687bb5fc05SNico Weber   uint32_t getCompression() const override { return Entry.Compression; }
69d100b5ddSNico Weber 
getCode() const70d100b5ddSNico Weber   std::string getCode() const override {
71d100b5ddSNico Weber     // Get name of stream storing the data.
7278d632d1SGeorge Rimar     StringRef VName =
7378d632d1SGeorge Rimar         cantFail(Strings.getStringForID(Entry.VFileNI),
7478d632d1SGeorge Rimar                  "InjectedSourceStream should have rejected this");
7578d632d1SGeorge Rimar     std::string StreamName = ("/src/files/" + VName).str();
76d100b5ddSNico Weber 
77d100b5ddSNico Weber     // Find stream with that name and read its data.
78d100b5ddSNico Weber     // FIXME: Consider validating (or even loading) all this in
79d100b5ddSNico Weber     // InjectedSourceStream so that no error can happen here.
80d100b5ddSNico Weber     auto ExpectedFileStream = File.safelyCreateNamedStream(StreamName);
81d100b5ddSNico Weber     if (!ExpectedFileStream) {
82d100b5ddSNico Weber       consumeError(ExpectedFileStream.takeError());
83d100b5ddSNico Weber       return "(failed to open data stream)";
84d100b5ddSNico Weber     }
85d100b5ddSNico Weber 
867bb5fc05SNico Weber     auto Data = readStreamData(**ExpectedFileStream, Entry.FileSize);
87d100b5ddSNico Weber     if (!Data) {
88d100b5ddSNico Weber       consumeError(Data.takeError());
89d100b5ddSNico Weber       return "(failed to read data)";
90d100b5ddSNico Weber     }
91d100b5ddSNico Weber     return *Data;
92d100b5ddSNico Weber   }
93d100b5ddSNico Weber };
94d100b5ddSNico Weber 
95d100b5ddSNico Weber } // namespace
96d100b5ddSNico Weber 
NativeEnumInjectedSources(PDBFile & File,const InjectedSourceStream & IJS,const PDBStringTable & Strings)97d100b5ddSNico Weber NativeEnumInjectedSources::NativeEnumInjectedSources(
98d100b5ddSNico Weber     PDBFile &File, const InjectedSourceStream &IJS,
99d100b5ddSNico Weber     const PDBStringTable &Strings)
100d100b5ddSNico Weber     : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {}
101d100b5ddSNico Weber 
getChildCount() const102d100b5ddSNico Weber uint32_t NativeEnumInjectedSources::getChildCount() const {
103d100b5ddSNico Weber   return static_cast<uint32_t>(Stream.size());
104d100b5ddSNico Weber }
105d100b5ddSNico Weber 
106d100b5ddSNico Weber std::unique_ptr<IPDBInjectedSource>
getChildAtIndex(uint32_t N) const107d100b5ddSNico Weber NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const {
108d100b5ddSNico Weber   if (N >= getChildCount())
109d100b5ddSNico Weber     return nullptr;
1100eaee545SJonas Devlieghere   return std::make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second,
111d100b5ddSNico Weber                                            File, Strings);
112d100b5ddSNico Weber }
113d100b5ddSNico Weber 
getNext()114d100b5ddSNico Weber std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() {
115d100b5ddSNico Weber   if (Cur == Stream.end())
116d100b5ddSNico Weber     return nullptr;
1170eaee545SJonas Devlieghere   return std::make_unique<NativeInjectedSource>((Cur++)->second, File, Strings);
118d100b5ddSNico Weber }
119d100b5ddSNico Weber 
reset()120d100b5ddSNico Weber void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); }
121d100b5ddSNico Weber 
122d100b5ddSNico Weber }
123d100b5ddSNico Weber }
124