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