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