File indexing completed on 2026-05-10 08:43:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
0015 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
0016
0017 #include "llvm/ADT/iterator.h"
0018 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
0019 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
0020 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
0021 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
0022 #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
0023 #include "llvm/DebugInfo/PDB/Native/InputFile.h"
0024 #include "llvm/Object/Binary.h"
0025 #include "llvm/Object/ObjectFile.h"
0026 #include "llvm/Support/Error.h"
0027 #include <stack>
0028 #include <utility>
0029
0030 namespace llvm {
0031 namespace logicalview {
0032
0033 using namespace llvm::codeview;
0034
0035 class LVCodeViewReader;
0036 class LVLogicalVisitor;
0037 struct LVShared;
0038
0039 class LVTypeVisitor final : public TypeVisitorCallbacks {
0040 ScopedPrinter &W;
0041 LVLogicalVisitor *LogicalVisitor;
0042 LazyRandomTypeCollection &Types;
0043 LazyRandomTypeCollection &Ids;
0044 uint32_t StreamIdx;
0045 LVShared *Shared = nullptr;
0046
0047
0048
0049
0050
0051 bool HasIds = false;
0052
0053
0054 TypeIndex CurrentTypeIndex = TypeIndex::None();
0055
0056 void printTypeIndex(StringRef FieldName, TypeIndex TI,
0057 uint32_t StreamIdx) const;
0058
0059 public:
0060 LVTypeVisitor(ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor,
0061 LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids,
0062 uint32_t StreamIdx, LVShared *Shared)
0063 : TypeVisitorCallbacks(), W(W), LogicalVisitor(LogicalVisitor),
0064 Types(Types), Ids(Ids), StreamIdx(StreamIdx), Shared(Shared) {
0065 HasIds = &Types != &Ids;
0066 }
0067
0068 Error visitTypeBegin(CVType &Record) override;
0069 Error visitTypeBegin(CVType &Record, TypeIndex TI) override;
0070 Error visitMemberBegin(CVMemberRecord &Record) override;
0071 Error visitMemberEnd(CVMemberRecord &Record) override;
0072 Error visitUnknownMember(CVMemberRecord &Record) override;
0073
0074 Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override;
0075 Error visitKnownRecord(CVType &Record, ClassRecord &Class) override;
0076 Error visitKnownRecord(CVType &Record, EnumRecord &Enum) override;
0077 Error visitKnownRecord(CVType &Record, FuncIdRecord &Func) override;
0078 Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc) override;
0079 Error visitKnownRecord(CVType &Record, StringIdRecord &String) override;
0080 Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &Line) override;
0081 Error visitKnownRecord(CVType &Record, UnionRecord &Union) override;
0082 Error visitUnknownType(CVType &Record) override;
0083 };
0084
0085 class LVSymbolVisitorDelegate final : public SymbolVisitorDelegate {
0086 LVCodeViewReader *Reader;
0087 const llvm::object::coff_section *CoffSection;
0088 StringRef SectionContents;
0089
0090 public:
0091 LVSymbolVisitorDelegate(LVCodeViewReader *Reader,
0092 const llvm::object::SectionRef &Section,
0093 const llvm::object::COFFObjectFile *Obj,
0094 StringRef SectionContents)
0095 : Reader(Reader), SectionContents(SectionContents) {
0096 CoffSection = Obj->getCOFFSection(Section);
0097 }
0098
0099 uint32_t getRecordOffset(BinaryStreamReader Reader) override {
0100 ArrayRef<uint8_t> Data;
0101 if (Error Err = Reader.readLongestContiguousChunk(Data)) {
0102 llvm::consumeError(std::move(Err));
0103 return 0;
0104 }
0105 return Data.data() - SectionContents.bytes_begin();
0106 }
0107
0108 void printRelocatedField(StringRef Label, uint32_t RelocOffset,
0109 uint32_t Offset, StringRef *RelocSym = nullptr);
0110
0111 void getLinkageName(uint32_t RelocOffset, uint32_t Offset,
0112 StringRef *RelocSym = nullptr);
0113
0114 StringRef getFileNameForFileOffset(uint32_t FileOffset) override;
0115 DebugStringTableSubsectionRef getStringTable() override;
0116 };
0117
0118 class LVElement;
0119 class LVScope;
0120 class LVSymbol;
0121 class LVType;
0122
0123
0124 class LVSymbolVisitor final : public SymbolVisitorCallbacks {
0125 LVCodeViewReader *Reader;
0126 ScopedPrinter &W;
0127 LVLogicalVisitor *LogicalVisitor;
0128 LazyRandomTypeCollection &Types;
0129 LazyRandomTypeCollection &Ids;
0130 LVSymbolVisitorDelegate *ObjDelegate;
0131 LVShared *Shared;
0132
0133
0134 uint32_t CurrentOffset = 0;
0135
0136 StringRef CurrentObjectName;
0137
0138 LVSymbol *LocalSymbol = nullptr;
0139
0140 bool HasIds;
0141 bool InFunctionScope = false;
0142 bool IsCompileUnit = false;
0143
0144
0145 RegisterId LocalFrameRegister = RegisterId::NONE;
0146 RegisterId ParamFrameRegister = RegisterId::NONE;
0147
0148 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
0149 uint32_t RelocationOffset);
0150 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
0151 void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
0152
0153
0154 bool symbolIsCompileUnit(SymbolKind Kind) {
0155 switch (Kind) {
0156 case SymbolKind::S_COMPILE2:
0157 case SymbolKind::S_COMPILE3:
0158 return true;
0159 default:
0160 return false;
0161 }
0162 }
0163
0164
0165 void determineSymbolKind(LVSymbol *Symbol, RegisterId Register) {
0166 if (Register == LocalFrameRegister) {
0167 Symbol->setIsVariable();
0168 return;
0169 }
0170 if (Register == ParamFrameRegister) {
0171 Symbol->setIsParameter();
0172 return;
0173 }
0174
0175 Symbol->setIsVariable();
0176 }
0177
0178 public:
0179 LVSymbolVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
0180 LVLogicalVisitor *LogicalVisitor,
0181 LazyRandomTypeCollection &Types,
0182 LazyRandomTypeCollection &Ids,
0183 LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared)
0184 : Reader(Reader), W(W), LogicalVisitor(LogicalVisitor), Types(Types),
0185 Ids(Ids), ObjDelegate(ObjDelegate), Shared(Shared) {
0186 HasIds = &Types != &Ids;
0187 }
0188
0189 Error visitSymbolBegin(CVSymbol &Record) override;
0190 Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override;
0191 Error visitSymbolEnd(CVSymbol &Record) override;
0192 Error visitUnknownSymbol(CVSymbol &Record) override;
0193
0194 Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override;
0195 Error visitKnownRecord(CVSymbol &Record, BPRelativeSym &Local) override;
0196 Error visitKnownRecord(CVSymbol &Record, BuildInfoSym &BuildInfo) override;
0197 Error visitKnownRecord(CVSymbol &Record, Compile2Sym &Compile2) override;
0198 Error visitKnownRecord(CVSymbol &Record, Compile3Sym &Compile3) override;
0199 Error visitKnownRecord(CVSymbol &Record, ConstantSym &Constant) override;
0200 Error visitKnownRecord(CVSymbol &Record, DataSym &Data) override;
0201 Error visitKnownRecord(CVSymbol &Record,
0202 DefRangeFramePointerRelFullScopeSym
0203 &DefRangeFramePointerRelFullScope) override;
0204 Error visitKnownRecord(
0205 CVSymbol &Record,
0206 DefRangeFramePointerRelSym &DefRangeFramePointerRel) override;
0207 Error visitKnownRecord(CVSymbol &Record,
0208 DefRangeRegisterRelSym &DefRangeRegisterRel) override;
0209 Error visitKnownRecord(CVSymbol &Record,
0210 DefRangeRegisterSym &DefRangeRegister) override;
0211 Error visitKnownRecord(
0212 CVSymbol &Record,
0213 DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) override;
0214 Error visitKnownRecord(CVSymbol &Record,
0215 DefRangeSubfieldSym &DefRangeSubfield) override;
0216 Error visitKnownRecord(CVSymbol &Record, DefRangeSym &DefRange) override;
0217 Error visitKnownRecord(CVSymbol &Record, FrameProcSym &FrameProc) override;
0218 Error visitKnownRecord(CVSymbol &Record, InlineSiteSym &InlineSite) override;
0219 Error visitKnownRecord(CVSymbol &Record, LocalSym &Local) override;
0220 Error visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) override;
0221 Error visitKnownRecord(CVSymbol &Record, ProcSym &Proc) override;
0222 Error visitKnownRecord(CVSymbol &Record, RegRelativeSym &Local) override;
0223 Error visitKnownRecord(CVSymbol &Record, ScopeEndSym &ScopeEnd) override;
0224 Error visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) override;
0225 Error visitKnownRecord(CVSymbol &Record, UDTSym &UDT) override;
0226 Error visitKnownRecord(CVSymbol &Record, UsingNamespaceSym &UN) override;
0227 Error visitKnownRecord(CVSymbol &Record, JumpTableSym &JumpTable) override;
0228 Error visitKnownRecord(CVSymbol &Record, CallerSym &Caller) override;
0229 };
0230
0231
0232 class LVLogicalVisitor final {
0233 LVCodeViewReader *Reader;
0234 ScopedPrinter &W;
0235
0236
0237
0238 llvm::pdb::InputFile &Input;
0239 std::shared_ptr<llvm::pdb::InputFile> TypeServer = nullptr;
0240 std::shared_ptr<LazyRandomTypeCollection> PrecompHeader = nullptr;
0241
0242 std::shared_ptr<LVShared> Shared;
0243
0244
0245
0246 LazyRandomTypeCollection &types() {
0247 return TypeServer ? TypeServer->types()
0248 : (PrecompHeader ? *PrecompHeader : Input.types());
0249 }
0250 LazyRandomTypeCollection &ids() {
0251 return TypeServer ? TypeServer->ids()
0252 : (PrecompHeader ? *PrecompHeader : Input.ids());
0253 }
0254
0255 using LVScopeStack = std::stack<LVScope *>;
0256 LVScopeStack ScopeStack;
0257 LVScope *ReaderParent = nullptr;
0258 LVScope *ReaderScope = nullptr;
0259 bool InCompileUnitScope = false;
0260
0261
0262 bool ProcessArgumentList = false;
0263 StringRef OverloadedMethodName;
0264 std::string CompileUnitName;
0265
0266
0267 using LVInlineeEntry = std::pair<uint32_t, StringRef>;
0268 using LVInlineeInfo = std::map<TypeIndex, LVInlineeEntry>;
0269 LVInlineeInfo InlineeInfo;
0270
0271 Error visitFieldListMemberStream(TypeIndex TI, LVElement *Element,
0272 ArrayRef<uint8_t> FieldList);
0273
0274 LVType *createBaseType(TypeIndex TI, StringRef TypeName);
0275 LVType *createPointerType(TypeIndex TI, StringRef TypeName);
0276 LVSymbol *createParameter(TypeIndex TI, StringRef Name, LVScope *Parent);
0277 LVSymbol *createParameter(LVElement *Element, StringRef Name,
0278 LVScope *Parent);
0279 void createDataMember(CVMemberRecord &Record, LVScope *Parent, StringRef Name,
0280 TypeIndex Type, MemberAccess Access);
0281 void createParents(StringRef ScopedName, LVElement *Element);
0282
0283 public:
0284 LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
0285 llvm::pdb::InputFile &Input);
0286
0287
0288
0289 LVElement *CurrentElement = nullptr;
0290 LVScope *CurrentScope = nullptr;
0291 LVSymbol *CurrentSymbol = nullptr;
0292 LVType *CurrentType = nullptr;
0293
0294
0295 void setInput(std::shared_ptr<llvm::pdb::InputFile> TypeServer) {
0296 this->TypeServer = TypeServer;
0297 }
0298 void setInput(std::shared_ptr<LazyRandomTypeCollection> PrecompHeader) {
0299 this->PrecompHeader = PrecompHeader;
0300 }
0301
0302 void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename) {
0303 InlineeInfo.emplace(std::piecewise_construct, std::forward_as_tuple(TI),
0304 std::forward_as_tuple(LineNumber, Filename));
0305 }
0306
0307 void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx);
0308 void printMemberAttributes(MemberAttributes Attrs);
0309 void printMemberAttributes(MemberAccess Access, MethodKind Kind,
0310 MethodOptions Options);
0311
0312 LVElement *createElement(TypeLeafKind Kind);
0313 LVElement *createElement(SymbolKind Kind);
0314 LVElement *createElement(TypeIndex TI, TypeLeafKind Kind);
0315
0316
0317 Error inlineSiteAnnotation(LVScope *AbstractFunction,
0318 LVScope *InlinedFunction,
0319 InlineSiteSym &InlineSite);
0320
0321 void pushScope(LVScope *Scope) {
0322 ScopeStack.push(ReaderParent);
0323 ReaderParent = ReaderScope;
0324 ReaderScope = Scope;
0325 }
0326 void popScope() {
0327 ReaderScope = ReaderParent;
0328 ReaderParent = ScopeStack.top();
0329 ScopeStack.pop();
0330 }
0331 void closeScope() {
0332 if (InCompileUnitScope) {
0333 InCompileUnitScope = false;
0334 popScope();
0335 }
0336 }
0337 void setRoot(LVScope *Root) { ReaderScope = Root; }
0338
0339 void addElement(LVScope *Scope, bool IsCompileUnit);
0340 void addElement(LVSymbol *Symbol);
0341 void addElement(LVType *Type);
0342
0343 std::string getCompileUnitName() { return CompileUnitName; }
0344 void setCompileUnitName(std::string Name) {
0345 CompileUnitName = std::move(Name);
0346 }
0347
0348 LVElement *getElement(uint32_t StreamIdx, TypeIndex TI,
0349 LVScope *Parent = nullptr);
0350 LVShared *getShared() { return Shared.get(); }
0351
0352 LVScope *getReaderScope() const { return ReaderScope; }
0353
0354 void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element,
0355 uint32_t StreamIdx);
0356 void printTypeEnd(CVType &Record);
0357 void printMemberBegin(CVMemberRecord &Record, TypeIndex TI,
0358 LVElement *Element, uint32_t StreamIdx);
0359 void printMemberEnd(CVMemberRecord &Record);
0360
0361 void startProcessArgumentList() { ProcessArgumentList = true; }
0362 void stopProcessArgumentList() { ProcessArgumentList = false; }
0363
0364 void processFiles();
0365 void processLines();
0366 void processNamespaces();
0367
0368 void printRecords(raw_ostream &OS) const;
0369
0370 Error visitUnknownType(CVType &Record, TypeIndex TI);
0371 Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI,
0372 LVElement *Element);
0373 Error visitKnownRecord(CVType &Record, ArrayRecord &AT, TypeIndex TI,
0374 LVElement *Element);
0375 Error visitKnownRecord(CVType &Record, BitFieldRecord &BF, TypeIndex TI,
0376 LVElement *Element);
0377 Error visitKnownRecord(CVType &Record, BuildInfoRecord &BI, TypeIndex TI,
0378 LVElement *Element);
0379 Error visitKnownRecord(CVType &Record, ClassRecord &Class, TypeIndex TI,
0380 LVElement *Element);
0381 Error visitKnownRecord(CVType &Record, EnumRecord &Enum, TypeIndex TI,
0382 LVElement *Element);
0383 Error visitKnownRecord(CVType &Record, FieldListRecord &FieldList,
0384 TypeIndex TI, LVElement *Element);
0385 Error visitKnownRecord(CVType &Record, FuncIdRecord &Func, TypeIndex TI,
0386 LVElement *Element);
0387 Error visitKnownRecord(CVType &Record, LabelRecord &LR, TypeIndex TI,
0388 LVElement *Element);
0389 Error visitKnownRecord(CVType &Record, ModifierRecord &Mod, TypeIndex TI,
0390 LVElement *Element);
0391 Error visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id, TypeIndex TI,
0392 LVElement *Element);
0393 Error visitKnownRecord(CVType &Record, MemberFunctionRecord &MF, TypeIndex TI,
0394 LVElement *Element);
0395 Error visitKnownRecord(CVType &Record, MethodOverloadListRecord &Overloads,
0396 TypeIndex TI, LVElement *Element);
0397 Error visitKnownRecord(CVType &Record, PointerRecord &Ptr, TypeIndex TI,
0398 LVElement *Element);
0399 Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc, TypeIndex TI,
0400 LVElement *Element);
0401 Error visitKnownRecord(CVType &Record, UnionRecord &Union, TypeIndex TI,
0402 LVElement *Element);
0403 Error visitKnownRecord(CVType &Record, TypeServer2Record &TS, TypeIndex TI,
0404 LVElement *Element);
0405 Error visitKnownRecord(CVType &Record, VFTableRecord &VFT, TypeIndex TI,
0406 LVElement *Element);
0407 Error visitKnownRecord(CVType &Record, VFTableShapeRecord &Shape,
0408 TypeIndex TI, LVElement *Element);
0409 Error visitKnownRecord(CVType &Record, StringListRecord &Strings,
0410 TypeIndex TI, LVElement *Element);
0411 Error visitKnownRecord(CVType &Record, StringIdRecord &String, TypeIndex TI,
0412 LVElement *Element);
0413 Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &SourceLine,
0414 TypeIndex TI, LVElement *Element);
0415 Error visitKnownRecord(CVType &Record, UdtModSourceLineRecord &ModSourceLine,
0416 TypeIndex TI, LVElement *Element);
0417 Error visitKnownRecord(CVType &Record, PrecompRecord &Precomp, TypeIndex TI,
0418 LVElement *Element);
0419 Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp,
0420 TypeIndex TI, LVElement *Element);
0421
0422 Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI);
0423 Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base,
0424 TypeIndex TI, LVElement *Element);
0425 Error visitKnownMember(CVMemberRecord &Record, DataMemberRecord &Field,
0426 TypeIndex TI, LVElement *Element);
0427 Error visitKnownMember(CVMemberRecord &Record, EnumeratorRecord &Enum,
0428 TypeIndex TI, LVElement *Element);
0429 Error visitKnownMember(CVMemberRecord &Record, ListContinuationRecord &Cont,
0430 TypeIndex TI, LVElement *Element);
0431 Error visitKnownMember(CVMemberRecord &Record, NestedTypeRecord &Nested,
0432 TypeIndex TI, LVElement *Element);
0433 Error visitKnownMember(CVMemberRecord &Record, OneMethodRecord &Method,
0434 TypeIndex TI, LVElement *Element);
0435 Error visitKnownMember(CVMemberRecord &Record, OverloadedMethodRecord &Method,
0436 TypeIndex TI, LVElement *Element);
0437 Error visitKnownMember(CVMemberRecord &Record, StaticDataMemberRecord &Field,
0438 TypeIndex TI, LVElement *Element);
0439 Error visitKnownMember(CVMemberRecord &Record, VFPtrRecord &VFTable,
0440 TypeIndex TI, LVElement *Element);
0441 Error visitKnownMember(CVMemberRecord &Record, VirtualBaseClassRecord &Base,
0442 TypeIndex TI, LVElement *Element);
0443
0444 template <typename T>
0445 Error visitKnownMember(CVMemberRecord &Record,
0446 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
0447 LVElement *Element) {
0448 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
0449 T KnownRecord(RK);
0450 if (Error Err = Callbacks.visitKnownMember(Record, KnownRecord))
0451 return Err;
0452 if (Error Err = visitKnownMember(Record, KnownRecord, TI, Element))
0453 return Err;
0454 return Error::success();
0455 }
0456
0457 template <typename T>
0458 Error visitKnownRecord(CVType &Record, TypeIndex TI, LVElement *Element) {
0459 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
0460 T KnownRecord(RK);
0461 if (Error Err = TypeDeserializer::deserializeAs(
0462 const_cast<CVType &>(Record), KnownRecord))
0463 return Err;
0464 if (Error Err = visitKnownRecord(Record, KnownRecord, TI, Element))
0465 return Err;
0466 return Error::success();
0467 }
0468
0469 Error visitMemberRecord(CVMemberRecord &Record,
0470 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
0471 LVElement *Element);
0472 Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element);
0473 };
0474
0475 }
0476 }
0477
0478 #endif