xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
100b57cec5SDimitry Andric 
11*06c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
1281ad6265SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1381ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/HashTable.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
150b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
1681ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace llvm {
190b57cec5SDimitry Andric namespace pdb {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace {
220b57cec5SDimitry Andric 
readStreamData(BinaryStream & Stream,uint64_t Limit)23349cc55cSDimitry Andric Expected<std::string> readStreamData(BinaryStream &Stream, uint64_t Limit) {
24349cc55cSDimitry Andric   uint64_t Offset = 0, DataLength = std::min(Limit, Stream.getLength());
250b57cec5SDimitry Andric   std::string Result;
260b57cec5SDimitry Andric   Result.reserve(DataLength);
270b57cec5SDimitry Andric   while (Offset < DataLength) {
280b57cec5SDimitry Andric     ArrayRef<uint8_t> Data;
290b57cec5SDimitry Andric     if (auto E = Stream.readLongestContiguousChunk(Offset, Data))
300b57cec5SDimitry Andric       return std::move(E);
310b57cec5SDimitry Andric     Data = Data.take_front(DataLength - Offset);
320b57cec5SDimitry Andric     Offset += Data.size();
330b57cec5SDimitry Andric     Result += toStringRef(Data);
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric   return Result;
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric class NativeInjectedSource final : public IPDBInjectedSource {
390b57cec5SDimitry Andric   const SrcHeaderBlockEntry &Entry;
400b57cec5SDimitry Andric   const PDBStringTable &Strings;
410b57cec5SDimitry Andric   PDBFile &File;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric public:
NativeInjectedSource(const SrcHeaderBlockEntry & Entry,PDBFile & File,const PDBStringTable & Strings)440b57cec5SDimitry Andric   NativeInjectedSource(const SrcHeaderBlockEntry &Entry,
450b57cec5SDimitry Andric                        PDBFile &File, const PDBStringTable &Strings)
460b57cec5SDimitry Andric       : Entry(Entry), Strings(Strings), File(File) {}
470b57cec5SDimitry Andric 
getCrc32() const480b57cec5SDimitry Andric   uint32_t getCrc32() const override { return Entry.CRC; }
getCodeByteSize() const490b57cec5SDimitry Andric   uint64_t getCodeByteSize() const override { return Entry.FileSize; }
500b57cec5SDimitry Andric 
getFileName() const510b57cec5SDimitry Andric   std::string getFileName() const override {
528bcb0991SDimitry Andric     StringRef Ret = cantFail(Strings.getStringForID(Entry.FileNI),
538bcb0991SDimitry Andric                              "InjectedSourceStream should have rejected this");
545ffd83dbSDimitry Andric     return std::string(Ret);
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric 
getObjectFileName() const570b57cec5SDimitry Andric   std::string getObjectFileName() const override {
588bcb0991SDimitry Andric     StringRef Ret = cantFail(Strings.getStringForID(Entry.ObjNI),
598bcb0991SDimitry Andric                              "InjectedSourceStream should have rejected this");
605ffd83dbSDimitry Andric     return std::string(Ret);
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric 
getVirtualFileName() const630b57cec5SDimitry Andric   std::string getVirtualFileName() const override {
648bcb0991SDimitry Andric     StringRef Ret = cantFail(Strings.getStringForID(Entry.VFileNI),
658bcb0991SDimitry Andric                              "InjectedSourceStream should have rejected this");
665ffd83dbSDimitry Andric     return std::string(Ret);
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
getCompression() const690b57cec5SDimitry Andric   uint32_t getCompression() const override { return Entry.Compression; }
700b57cec5SDimitry Andric 
getCode() const710b57cec5SDimitry Andric   std::string getCode() const override {
720b57cec5SDimitry Andric     // Get name of stream storing the data.
738bcb0991SDimitry Andric     StringRef VName =
748bcb0991SDimitry Andric         cantFail(Strings.getStringForID(Entry.VFileNI),
758bcb0991SDimitry Andric                  "InjectedSourceStream should have rejected this");
768bcb0991SDimitry Andric     std::string StreamName = ("/src/files/" + VName).str();
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric     // Find stream with that name and read its data.
790b57cec5SDimitry Andric     // FIXME: Consider validating (or even loading) all this in
800b57cec5SDimitry Andric     // InjectedSourceStream so that no error can happen here.
810b57cec5SDimitry Andric     auto ExpectedFileStream = File.safelyCreateNamedStream(StreamName);
820b57cec5SDimitry Andric     if (!ExpectedFileStream) {
830b57cec5SDimitry Andric       consumeError(ExpectedFileStream.takeError());
840b57cec5SDimitry Andric       return "(failed to open data stream)";
850b57cec5SDimitry Andric     }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric     auto Data = readStreamData(**ExpectedFileStream, Entry.FileSize);
880b57cec5SDimitry Andric     if (!Data) {
890b57cec5SDimitry Andric       consumeError(Data.takeError());
900b57cec5SDimitry Andric       return "(failed to read data)";
910b57cec5SDimitry Andric     }
920b57cec5SDimitry Andric     return *Data;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric };
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric } // namespace
970b57cec5SDimitry Andric 
NativeEnumInjectedSources(PDBFile & File,const InjectedSourceStream & IJS,const PDBStringTable & Strings)980b57cec5SDimitry Andric NativeEnumInjectedSources::NativeEnumInjectedSources(
990b57cec5SDimitry Andric     PDBFile &File, const InjectedSourceStream &IJS,
1000b57cec5SDimitry Andric     const PDBStringTable &Strings)
1010b57cec5SDimitry Andric     : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {}
1020b57cec5SDimitry Andric 
getChildCount() const1030b57cec5SDimitry Andric uint32_t NativeEnumInjectedSources::getChildCount() const {
1040b57cec5SDimitry Andric   return static_cast<uint32_t>(Stream.size());
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric std::unique_ptr<IPDBInjectedSource>
getChildAtIndex(uint32_t N) const1080b57cec5SDimitry Andric NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const {
1090b57cec5SDimitry Andric   if (N >= getChildCount())
1100b57cec5SDimitry Andric     return nullptr;
1118bcb0991SDimitry Andric   return std::make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second,
1120b57cec5SDimitry Andric                                            File, Strings);
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
getNext()1150b57cec5SDimitry Andric std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() {
1160b57cec5SDimitry Andric   if (Cur == Stream.end())
1170b57cec5SDimitry Andric     return nullptr;
1188bcb0991SDimitry Andric   return std::make_unique<NativeInjectedSource>((Cur++)->second, File, Strings);
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
reset()1210b57cec5SDimitry Andric void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric }
125