1 //==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
11 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
12 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
13 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
20 Expected
<std::string
> readStreamData(BinaryStream
&Stream
, uint32_t Limit
) {
21 uint32_t Offset
= 0, DataLength
= std::min(Limit
, Stream
.getLength());
23 Result
.reserve(DataLength
);
24 while (Offset
< DataLength
) {
25 ArrayRef
<uint8_t> Data
;
26 if (auto E
= Stream
.readLongestContiguousChunk(Offset
, Data
))
28 Data
= Data
.take_front(DataLength
- Offset
);
29 Offset
+= Data
.size();
30 Result
+= toStringRef(Data
);
35 class NativeInjectedSource final
: public IPDBInjectedSource
{
36 const SrcHeaderBlockEntry
&Entry
;
37 const PDBStringTable
&Strings
;
41 NativeInjectedSource(const SrcHeaderBlockEntry
&Entry
,
42 PDBFile
&File
, const PDBStringTable
&Strings
)
43 : Entry(Entry
), Strings(Strings
), File(File
) {}
45 uint32_t getCrc32() const override
{ return Entry
.CRC
; }
46 uint64_t getCodeByteSize() const override
{ return Entry
.FileSize
; }
48 std::string
getFileName() const override
{
49 auto Name
= Strings
.getStringForID(Entry
.FileNI
);
50 assert(Name
&& "InjectedSourceStream should have rejected this");
54 std::string
getObjectFileName() const override
{
55 auto ObjName
= Strings
.getStringForID(Entry
.ObjNI
);
56 assert(ObjName
&& "InjectedSourceStream should have rejected this");
60 std::string
getVirtualFileName() const override
{
61 auto VName
= Strings
.getStringForID(Entry
.VFileNI
);
62 assert(VName
&& "InjectedSourceStream should have rejected this");
66 uint32_t getCompression() const override
{ return Entry
.Compression
; }
68 std::string
getCode() const override
{
69 // Get name of stream storing the data.
70 auto VName
= Strings
.getStringForID(Entry
.VFileNI
);
71 assert(VName
&& "InjectedSourceStream should have rejected this");
72 std::string StreamName
= ("/src/files/" + *VName
).str();
74 // Find stream with that name and read its data.
75 // FIXME: Consider validating (or even loading) all this in
76 // InjectedSourceStream so that no error can happen here.
77 auto ExpectedFileStream
= File
.safelyCreateNamedStream(StreamName
);
78 if (!ExpectedFileStream
) {
79 consumeError(ExpectedFileStream
.takeError());
80 return "(failed to open data stream)";
83 auto Data
= readStreamData(**ExpectedFileStream
, Entry
.FileSize
);
85 consumeError(Data
.takeError());
86 return "(failed to read data)";
94 NativeEnumInjectedSources::NativeEnumInjectedSources(
95 PDBFile
&File
, const InjectedSourceStream
&IJS
,
96 const PDBStringTable
&Strings
)
97 : File(File
), Stream(IJS
), Strings(Strings
), Cur(Stream
.begin()) {}
99 uint32_t NativeEnumInjectedSources::getChildCount() const {
100 return static_cast<uint32_t>(Stream
.size());
103 std::unique_ptr
<IPDBInjectedSource
>
104 NativeEnumInjectedSources::getChildAtIndex(uint32_t N
) const {
105 if (N
>= getChildCount())
107 return std::make_unique
<NativeInjectedSource
>(std::next(Stream
.begin(), N
)->second
,
111 std::unique_ptr
<IPDBInjectedSource
> NativeEnumInjectedSources::getNext() {
112 if (Cur
== Stream
.end())
114 return std::make_unique
<NativeInjectedSource
>((Cur
++)->second
, File
, Strings
);
117 void NativeEnumInjectedSources::reset() { Cur
= Stream
.begin(); }