File indexing completed on 2026-05-10 08:43:44
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_INPUTFILE_H
0010 #define LLVM_DEBUGINFO_PDB_NATIVE_INPUTFILE_H
0011
0012 #include "llvm/ADT/PointerUnion.h"
0013 #include "llvm/ADT/StringMap.h"
0014 #include "llvm/ADT/iterator.h"
0015 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
0016 #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
0017 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
0018 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
0019 #include "llvm/Object/Binary.h"
0020 #include "llvm/Object/ObjectFile.h"
0021 #include "llvm/Support/Error.h"
0022
0023 namespace llvm {
0024 namespace codeview {
0025 class LazyRandomTypeCollection;
0026 }
0027 namespace object {
0028 class COFFObjectFile;
0029 }
0030
0031 namespace pdb {
0032 class InputFile;
0033 class LinePrinter;
0034 class PDBFile;
0035 class NativeSession;
0036 class SymbolGroupIterator;
0037 class SymbolGroup;
0038
0039 class InputFile {
0040 InputFile();
0041
0042 std::unique_ptr<NativeSession> PdbSession;
0043 object::OwningBinary<object::Binary> CoffObject;
0044 std::unique_ptr<MemoryBuffer> UnknownFile;
0045 PointerUnion<PDBFile *, object::COFFObjectFile *, MemoryBuffer *> PdbOrObj;
0046
0047 using TypeCollectionPtr = std::unique_ptr<codeview::LazyRandomTypeCollection>;
0048
0049 TypeCollectionPtr Types;
0050 TypeCollectionPtr Ids;
0051
0052 enum TypeCollectionKind { kTypes, kIds };
0053 codeview::LazyRandomTypeCollection &
0054 getOrCreateTypeCollection(TypeCollectionKind Kind);
0055
0056 public:
0057 InputFile(PDBFile *Pdb) { PdbOrObj = Pdb; }
0058 InputFile(object::COFFObjectFile *Obj) { PdbOrObj = Obj; }
0059 InputFile(MemoryBuffer *Buffer) { PdbOrObj = Buffer; }
0060 ~InputFile();
0061 InputFile(InputFile &&Other) = default;
0062
0063 static Expected<InputFile> open(StringRef Path,
0064 bool AllowUnknownFile = false);
0065
0066 PDBFile &pdb();
0067 const PDBFile &pdb() const;
0068 object::COFFObjectFile &obj();
0069 const object::COFFObjectFile &obj() const;
0070 MemoryBuffer &unknown();
0071 const MemoryBuffer &unknown() const;
0072
0073 StringRef getFilePath() const;
0074
0075 bool hasTypes() const;
0076 bool hasIds() const;
0077
0078 codeview::LazyRandomTypeCollection &types();
0079 codeview::LazyRandomTypeCollection &ids();
0080
0081 iterator_range<SymbolGroupIterator> symbol_groups();
0082 SymbolGroupIterator symbol_groups_begin();
0083 SymbolGroupIterator symbol_groups_end();
0084
0085 bool isPdb() const;
0086 bool isObj() const;
0087 bool isUnknown() const;
0088 };
0089
0090 class SymbolGroup {
0091 friend class SymbolGroupIterator;
0092
0093 public:
0094 explicit SymbolGroup(InputFile *File, uint32_t GroupIndex = 0);
0095
0096 Expected<StringRef> getNameFromStringTable(uint32_t Offset) const;
0097 Expected<StringRef> getNameFromChecksums(uint32_t Offset) const;
0098
0099 void formatFromFileName(LinePrinter &Printer, StringRef File,
0100 bool Append = false) const;
0101
0102 void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
0103 bool Append = false) const;
0104
0105 StringRef name() const;
0106
0107 codeview::DebugSubsectionArray getDebugSubsections() const {
0108 return Subsections;
0109 }
0110 const ModuleDebugStreamRef &getPdbModuleStream() const;
0111
0112 const InputFile &getFile() const { return *File; }
0113 InputFile &getFile() { return *File; }
0114
0115 bool hasDebugStream() const { return DebugStream != nullptr; }
0116
0117 private:
0118 void initializeForPdb(uint32_t Modi);
0119 void updatePdbModi(uint32_t Modi);
0120 void updateDebugS(const codeview::DebugSubsectionArray &SS);
0121
0122 void rebuildChecksumMap();
0123 InputFile *File = nullptr;
0124 StringRef Name;
0125 codeview::DebugSubsectionArray Subsections;
0126 std::shared_ptr<ModuleDebugStreamRef> DebugStream;
0127 codeview::StringsAndChecksumsRef SC;
0128 StringMap<codeview::FileChecksumEntry> ChecksumsByFile;
0129 };
0130
0131 class SymbolGroupIterator
0132 : public iterator_facade_base<SymbolGroupIterator,
0133 std::forward_iterator_tag, SymbolGroup> {
0134 public:
0135 SymbolGroupIterator();
0136 explicit SymbolGroupIterator(InputFile &File);
0137 SymbolGroupIterator(const SymbolGroupIterator &Other) = default;
0138 SymbolGroupIterator &operator=(const SymbolGroupIterator &R) = default;
0139
0140 const SymbolGroup &operator*() const;
0141 SymbolGroup &operator*();
0142
0143 bool operator==(const SymbolGroupIterator &R) const;
0144 SymbolGroupIterator &operator++();
0145
0146 private:
0147 void scanToNextDebugS();
0148 bool isEnd() const;
0149
0150 uint32_t Index = 0;
0151 std::optional<object::section_iterator> SectionIter;
0152 SymbolGroup Value;
0153 };
0154
0155 Expected<ModuleDebugStreamRef>
0156 getModuleDebugStream(PDBFile &File, StringRef &ModuleName, uint32_t Index);
0157 Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
0158 uint32_t Index);
0159
0160 bool shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group,
0161 const FilterOptions &Filters);
0162
0163
0164 template <typename CallbackT>
0165 Error iterateOneModule(InputFile &File, const PrintScope &HeaderScope,
0166 const SymbolGroup &SG, uint32_t Modi,
0167 CallbackT Callback) {
0168 HeaderScope.P.formatLine(
0169 "Mod {0:4} | `{1}`: ",
0170 fmt_align(Modi, AlignStyle::Right, HeaderScope.LabelWidth), SG.name());
0171
0172 AutoIndent Indent(HeaderScope);
0173 return Callback(Modi, SG);
0174 }
0175
0176 template <typename CallbackT>
0177 Error iterateSymbolGroups(InputFile &Input, const PrintScope &HeaderScope,
0178 CallbackT Callback) {
0179 AutoIndent Indent(HeaderScope);
0180
0181 FilterOptions Filters = HeaderScope.P.getFilters();
0182 if (Filters.DumpModi) {
0183 uint32_t Modi = *Filters.DumpModi;
0184 SymbolGroup SG(&Input, Modi);
0185 return iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(Modi)),
0186 SG, Modi, Callback);
0187 }
0188
0189 uint32_t I = 0;
0190
0191 for (const auto &SG : Input.symbol_groups()) {
0192 if (shouldDumpSymbolGroup(I, SG, Filters))
0193 if (auto Err =
0194 iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(I)),
0195 SG, I, Callback))
0196 return Err;
0197
0198 ++I;
0199 }
0200 return Error::success();
0201 }
0202
0203 template <typename SubsectionT>
0204 Error iterateModuleSubsections(
0205 InputFile &File, const PrintScope &HeaderScope,
0206 llvm::function_ref<Error(uint32_t, const SymbolGroup &, SubsectionT &)>
0207 Callback) {
0208
0209 return iterateSymbolGroups(
0210 File, HeaderScope, [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
0211 for (const auto &SS : SG.getDebugSubsections()) {
0212 SubsectionT Subsection;
0213
0214 if (SS.kind() != Subsection.kind())
0215 continue;
0216
0217 BinaryStreamReader Reader(SS.getRecordData());
0218 if (auto Err = Subsection.initialize(Reader))
0219 continue;
0220 if (auto Err = Callback(Modi, SG, Subsection))
0221 return Err;
0222 }
0223 return Error::success();
0224 });
0225 }
0226
0227 }
0228 }
0229
0230 #endif