1 //===-- LVCodeViewVisitor.h -------------------------------------*- C++ -*-===// 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 // This file defines the LVCodeViewVisitor class, which is used to describe a 10 // debug information (CodeView) visitor. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H 15 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H 16 17 #include "llvm/ADT/iterator.h" 18 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" 19 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" 20 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 21 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" 22 #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h" 23 #include "llvm/DebugInfo/PDB/Native/InputFile.h" 24 #include "llvm/Object/Binary.h" 25 #include "llvm/Object/ObjectFile.h" 26 #include "llvm/Support/Error.h" 27 #include <stack> 28 #include <utility> 29 30 namespace llvm { 31 namespace logicalview { 32 33 using namespace llvm::codeview; 34 35 class LVCodeViewReader; 36 class LVLogicalVisitor; 37 struct LVShared; 38 39 class LVTypeVisitor final : public TypeVisitorCallbacks { 40 ScopedPrinter &W; 41 LVLogicalVisitor *LogicalVisitor; 42 LazyRandomTypeCollection &Types; 43 LazyRandomTypeCollection &Ids; 44 uint32_t StreamIdx; 45 LVShared *Shared = nullptr; 46 47 // In a PDB, a type index may refer to a type (TPI) or an item ID (IPI). 48 // In a COFF or PDB (/Z7), the type index always refer to a type (TPI). 49 // When creating logical elements, we must access the correct element 50 // table, while searching for a type index. 51 bool HasIds = false; 52 53 // Current type index during the types traversal. 54 TypeIndex CurrentTypeIndex = TypeIndex::None(); 55 56 void printTypeIndex(StringRef FieldName, TypeIndex TI, 57 uint32_t StreamIdx) const; 58 59 public: 60 LVTypeVisitor(ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor, 61 LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids, 62 uint32_t StreamIdx, LVShared *Shared) 63 : TypeVisitorCallbacks(), W(W), LogicalVisitor(LogicalVisitor), 64 Types(Types), Ids(Ids), StreamIdx(StreamIdx), Shared(Shared) { 65 HasIds = &Types != &Ids; 66 } 67 68 Error visitTypeBegin(CVType &Record) override; 69 Error visitTypeBegin(CVType &Record, TypeIndex TI) override; 70 Error visitMemberBegin(CVMemberRecord &Record) override; 71 Error visitMemberEnd(CVMemberRecord &Record) override; 72 Error visitUnknownMember(CVMemberRecord &Record) override; 73 74 Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override; 75 Error visitKnownRecord(CVType &Record, ClassRecord &Class) override; 76 Error visitKnownRecord(CVType &Record, EnumRecord &Enum) override; 77 Error visitKnownRecord(CVType &Record, FuncIdRecord &Func) override; 78 Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc) override; 79 Error visitKnownRecord(CVType &Record, StringIdRecord &String) override; 80 Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &Line) override; 81 Error visitKnownRecord(CVType &Record, UnionRecord &Union) override; 82 Error visitUnknownType(CVType &Record) override; 83 }; 84 85 class LVSymbolVisitorDelegate final : public SymbolVisitorDelegate { 86 LVCodeViewReader *Reader; 87 const llvm::object::coff_section *CoffSection; 88 StringRef SectionContents; 89 90 public: 91 LVSymbolVisitorDelegate(LVCodeViewReader *Reader, 92 const llvm::object::SectionRef &Section, 93 const llvm::object::COFFObjectFile *Obj, 94 StringRef SectionContents) 95 : Reader(Reader), SectionContents(SectionContents) { 96 CoffSection = Obj->getCOFFSection(Section); 97 } 98 99 uint32_t getRecordOffset(BinaryStreamReader Reader) override { 100 ArrayRef<uint8_t> Data; 101 if (Error Err = Reader.readLongestContiguousChunk(Data)) { 102 llvm::consumeError(std::move(Err)); 103 return 0; 104 } 105 return Data.data() - SectionContents.bytes_begin(); 106 } 107 108 void printRelocatedField(StringRef Label, uint32_t RelocOffset, 109 uint32_t Offset, StringRef *RelocSym = nullptr); 110 111 void getLinkageName(uint32_t RelocOffset, uint32_t Offset, 112 StringRef *RelocSym = nullptr); 113 114 StringRef getFileNameForFileOffset(uint32_t FileOffset) override; 115 DebugStringTableSubsectionRef getStringTable() override; 116 }; 117 118 class LVElement; 119 class LVScope; 120 class LVSymbol; 121 class LVType; 122 123 // Visitor for CodeView symbol streams found in COFF object files and PDB files. 124 class LVSymbolVisitor final : public SymbolVisitorCallbacks { 125 LVCodeViewReader *Reader; 126 ScopedPrinter &W; 127 LVLogicalVisitor *LogicalVisitor; 128 LazyRandomTypeCollection &Types; 129 LazyRandomTypeCollection &Ids; 130 LVSymbolVisitorDelegate *ObjDelegate; 131 LVShared *Shared; 132 133 // Symbol offset when processing PDB streams. 134 uint32_t CurrentOffset = 0; 135 // Current object name collected from S_OBJNAME. 136 StringRef CurrentObjectName; 137 // Last symbol processed by S_LOCAL. 138 LVSymbol *LocalSymbol = nullptr; 139 140 bool HasIds; 141 bool InFunctionScope = false; 142 bool IsCompileUnit = false; 143 144 // Register for the locals and parameters symbols in the current frame. 145 RegisterId LocalFrameRegister = RegisterId::NONE; 146 RegisterId ParamFrameRegister = RegisterId::NONE; 147 148 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, 149 uint32_t RelocationOffset); 150 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); 151 void printTypeIndex(StringRef FieldName, TypeIndex TI) const; 152 153 // Return true if this symbol is a Compile Unit. 154 bool symbolIsCompileUnit(SymbolKind Kind) { 155 switch (Kind) { 156 case SymbolKind::S_COMPILE2: 157 case SymbolKind::S_COMPILE3: 158 return true; 159 default: 160 return false; 161 } 162 } 163 164 // Determine symbol kind (local or parameter). 165 void determineSymbolKind(LVSymbol *Symbol, RegisterId Register) { 166 if (Register == LocalFrameRegister) { 167 Symbol->setIsVariable(); 168 return; 169 } 170 if (Register == ParamFrameRegister) { 171 Symbol->setIsParameter(); 172 return; 173 } 174 // Assume is a variable. 175 Symbol->setIsVariable(); 176 } 177 178 public: 179 LVSymbolVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, 180 LVLogicalVisitor *LogicalVisitor, 181 LazyRandomTypeCollection &Types, 182 LazyRandomTypeCollection &Ids, 183 LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared) 184 : Reader(Reader), W(W), LogicalVisitor(LogicalVisitor), Types(Types), 185 Ids(Ids), ObjDelegate(ObjDelegate), Shared(Shared) { 186 HasIds = &Types != &Ids; 187 } 188 189 Error visitSymbolBegin(CVSymbol &Record) override; 190 Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override; 191 Error visitSymbolEnd(CVSymbol &Record) override; 192 Error visitUnknownSymbol(CVSymbol &Record) override; 193 194 Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override; 195 Error visitKnownRecord(CVSymbol &Record, BPRelativeSym &Local) override; 196 Error visitKnownRecord(CVSymbol &Record, BuildInfoSym &BuildInfo) override; 197 Error visitKnownRecord(CVSymbol &Record, Compile2Sym &Compile2) override; 198 Error visitKnownRecord(CVSymbol &Record, Compile3Sym &Compile3) override; 199 Error visitKnownRecord(CVSymbol &Record, ConstantSym &Constant) override; 200 Error visitKnownRecord(CVSymbol &Record, DataSym &Data) override; 201 Error visitKnownRecord(CVSymbol &Record, 202 DefRangeFramePointerRelFullScopeSym 203 &DefRangeFramePointerRelFullScope) override; 204 Error visitKnownRecord( 205 CVSymbol &Record, 206 DefRangeFramePointerRelSym &DefRangeFramePointerRel) override; 207 Error visitKnownRecord(CVSymbol &Record, 208 DefRangeRegisterRelSym &DefRangeRegisterRel) override; 209 Error visitKnownRecord(CVSymbol &Record, 210 DefRangeRegisterSym &DefRangeRegister) override; 211 Error visitKnownRecord( 212 CVSymbol &Record, 213 DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) override; 214 Error visitKnownRecord(CVSymbol &Record, 215 DefRangeSubfieldSym &DefRangeSubfield) override; 216 Error visitKnownRecord(CVSymbol &Record, DefRangeSym &DefRange) override; 217 Error visitKnownRecord(CVSymbol &Record, FrameProcSym &FrameProc) override; 218 Error visitKnownRecord(CVSymbol &Record, InlineSiteSym &InlineSite) override; 219 Error visitKnownRecord(CVSymbol &Record, LocalSym &Local) override; 220 Error visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) override; 221 Error visitKnownRecord(CVSymbol &Record, ProcSym &Proc) override; 222 Error visitKnownRecord(CVSymbol &Record, RegRelativeSym &Local) override; 223 Error visitKnownRecord(CVSymbol &Record, ScopeEndSym &ScopeEnd) override; 224 Error visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) override; 225 Error visitKnownRecord(CVSymbol &Record, UDTSym &UDT) override; 226 Error visitKnownRecord(CVSymbol &Record, UsingNamespaceSym &UN) override; 227 Error visitKnownRecord(CVSymbol &Record, JumpTableSym &JumpTable) override; 228 Error visitKnownRecord(CVSymbol &Record, CallerSym &Caller) override; 229 }; 230 231 // Visitor for CodeView types and symbols to populate elements. 232 class LVLogicalVisitor final { 233 LVCodeViewReader *Reader; 234 ScopedPrinter &W; 235 236 // Encapsulates access to the input file and any dependent type server, 237 // including any precompiled header object. 238 llvm::pdb::InputFile &Input; 239 std::shared_ptr<llvm::pdb::InputFile> TypeServer = nullptr; 240 std::shared_ptr<LazyRandomTypeCollection> PrecompHeader = nullptr; 241 242 std::shared_ptr<LVShared> Shared; 243 244 // Object files have only one type stream that contains both types and ids. 245 // Precompiled header objects don't contain an IPI stream. Use the TPI. 246 LazyRandomTypeCollection &types() { 247 return TypeServer ? TypeServer->types() 248 : (PrecompHeader ? *PrecompHeader : Input.types()); 249 } 250 LazyRandomTypeCollection &ids() { 251 return TypeServer ? TypeServer->ids() 252 : (PrecompHeader ? *PrecompHeader : Input.ids()); 253 } 254 255 using LVScopeStack = std::stack<LVScope *>; 256 LVScopeStack ScopeStack; 257 LVScope *ReaderParent = nullptr; 258 LVScope *ReaderScope = nullptr; 259 bool InCompileUnitScope = false; 260 261 // Allow processing of argument list. 262 bool ProcessArgumentList = false; 263 StringRef OverloadedMethodName; 264 std::string CompileUnitName; 265 266 // Inlined functions source information. 267 using LVInlineeEntry = std::pair<uint32_t, StringRef>; 268 using LVInlineeInfo = std::map<TypeIndex, LVInlineeEntry>; 269 LVInlineeInfo InlineeInfo; 270 271 Error visitFieldListMemberStream(TypeIndex TI, LVElement *Element, 272 ArrayRef<uint8_t> FieldList); 273 274 LVType *createBaseType(TypeIndex TI, StringRef TypeName); 275 LVType *createPointerType(TypeIndex TI, StringRef TypeName); 276 LVSymbol *createParameter(TypeIndex TI, StringRef Name, LVScope *Parent); 277 LVSymbol *createParameter(LVElement *Element, StringRef Name, 278 LVScope *Parent); 279 void createDataMember(CVMemberRecord &Record, LVScope *Parent, StringRef Name, 280 TypeIndex Type, MemberAccess Access); 281 void createParents(StringRef ScopedName, LVElement *Element); 282 283 public: 284 LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, 285 llvm::pdb::InputFile &Input); 286 287 // Current elements during the processing of a RecordType or RecordSymbol. 288 // They are shared with the SymbolVisitor. 289 LVElement *CurrentElement = nullptr; 290 LVScope *CurrentScope = nullptr; 291 LVSymbol *CurrentSymbol = nullptr; 292 LVType *CurrentType = nullptr; 293 294 // Input source in the case of type server or precompiled header. 295 void setInput(std::shared_ptr<llvm::pdb::InputFile> TypeServer) { 296 this->TypeServer = TypeServer; 297 } 298 void setInput(std::shared_ptr<LazyRandomTypeCollection> PrecompHeader) { 299 this->PrecompHeader = PrecompHeader; 300 } 301 302 void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename) { 303 InlineeInfo.emplace(std::piecewise_construct, std::forward_as_tuple(TI), 304 std::forward_as_tuple(LineNumber, Filename)); 305 } 306 307 void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx); 308 void printMemberAttributes(MemberAttributes Attrs); 309 void printMemberAttributes(MemberAccess Access, MethodKind Kind, 310 MethodOptions Options); 311 312 LVElement *createElement(TypeLeafKind Kind); 313 LVElement *createElement(SymbolKind Kind); 314 LVElement *createElement(TypeIndex TI, TypeLeafKind Kind); 315 316 // Break down the annotation byte code and calculate code and line offsets. 317 Error inlineSiteAnnotation(LVScope *AbstractFunction, 318 LVScope *InlinedFunction, 319 InlineSiteSym &InlineSite); 320 321 void pushScope(LVScope *Scope) { 322 ScopeStack.push(ReaderParent); 323 ReaderParent = ReaderScope; 324 ReaderScope = Scope; 325 } 326 void popScope() { 327 ReaderScope = ReaderParent; 328 ReaderParent = ScopeStack.top(); 329 ScopeStack.pop(); 330 } 331 void closeScope() { 332 if (InCompileUnitScope) { 333 InCompileUnitScope = false; 334 popScope(); 335 } 336 } 337 void setRoot(LVScope *Root) { ReaderScope = Root; } 338 339 void addElement(LVScope *Scope, bool IsCompileUnit); 340 void addElement(LVSymbol *Symbol); 341 void addElement(LVType *Type); 342 343 std::string getCompileUnitName() { return CompileUnitName; } 344 void setCompileUnitName(std::string Name) { 345 CompileUnitName = std::move(Name); 346 } 347 348 LVElement *getElement(uint32_t StreamIdx, TypeIndex TI, 349 LVScope *Parent = nullptr); 350 LVShared *getShared() { return Shared.get(); } 351 352 LVScope *getReaderScope() const { return ReaderScope; } 353 354 void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element, 355 uint32_t StreamIdx); 356 void printTypeEnd(CVType &Record); 357 void printMemberBegin(CVMemberRecord &Record, TypeIndex TI, 358 LVElement *Element, uint32_t StreamIdx); 359 void printMemberEnd(CVMemberRecord &Record); 360 361 void startProcessArgumentList() { ProcessArgumentList = true; } 362 void stopProcessArgumentList() { ProcessArgumentList = false; } 363 364 void processFiles(); 365 void processLines(); 366 void processNamespaces(); 367 368 void printRecords(raw_ostream &OS) const; 369 370 Error visitUnknownType(CVType &Record, TypeIndex TI); 371 Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI, 372 LVElement *Element); 373 Error visitKnownRecord(CVType &Record, ArrayRecord &AT, TypeIndex TI, 374 LVElement *Element); 375 Error visitKnownRecord(CVType &Record, BitFieldRecord &BF, TypeIndex TI, 376 LVElement *Element); 377 Error visitKnownRecord(CVType &Record, BuildInfoRecord &BI, TypeIndex TI, 378 LVElement *Element); 379 Error visitKnownRecord(CVType &Record, ClassRecord &Class, TypeIndex TI, 380 LVElement *Element); 381 Error visitKnownRecord(CVType &Record, EnumRecord &Enum, TypeIndex TI, 382 LVElement *Element); 383 Error visitKnownRecord(CVType &Record, FieldListRecord &FieldList, 384 TypeIndex TI, LVElement *Element); 385 Error visitKnownRecord(CVType &Record, FuncIdRecord &Func, TypeIndex TI, 386 LVElement *Element); 387 Error visitKnownRecord(CVType &Record, LabelRecord &LR, TypeIndex TI, 388 LVElement *Element); 389 Error visitKnownRecord(CVType &Record, ModifierRecord &Mod, TypeIndex TI, 390 LVElement *Element); 391 Error visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id, TypeIndex TI, 392 LVElement *Element); 393 Error visitKnownRecord(CVType &Record, MemberFunctionRecord &MF, TypeIndex TI, 394 LVElement *Element); 395 Error visitKnownRecord(CVType &Record, MethodOverloadListRecord &Overloads, 396 TypeIndex TI, LVElement *Element); 397 Error visitKnownRecord(CVType &Record, PointerRecord &Ptr, TypeIndex TI, 398 LVElement *Element); 399 Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc, TypeIndex TI, 400 LVElement *Element); 401 Error visitKnownRecord(CVType &Record, UnionRecord &Union, TypeIndex TI, 402 LVElement *Element); 403 Error visitKnownRecord(CVType &Record, TypeServer2Record &TS, TypeIndex TI, 404 LVElement *Element); 405 Error visitKnownRecord(CVType &Record, VFTableRecord &VFT, TypeIndex TI, 406 LVElement *Element); 407 Error visitKnownRecord(CVType &Record, VFTableShapeRecord &Shape, 408 TypeIndex TI, LVElement *Element); 409 Error visitKnownRecord(CVType &Record, StringListRecord &Strings, 410 TypeIndex TI, LVElement *Element); 411 Error visitKnownRecord(CVType &Record, StringIdRecord &String, TypeIndex TI, 412 LVElement *Element); 413 Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &SourceLine, 414 TypeIndex TI, LVElement *Element); 415 Error visitKnownRecord(CVType &Record, UdtModSourceLineRecord &ModSourceLine, 416 TypeIndex TI, LVElement *Element); 417 Error visitKnownRecord(CVType &Record, PrecompRecord &Precomp, TypeIndex TI, 418 LVElement *Element); 419 Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp, 420 TypeIndex TI, LVElement *Element); 421 422 Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI); 423 Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base, 424 TypeIndex TI, LVElement *Element); 425 Error visitKnownMember(CVMemberRecord &Record, DataMemberRecord &Field, 426 TypeIndex TI, LVElement *Element); 427 Error visitKnownMember(CVMemberRecord &Record, EnumeratorRecord &Enum, 428 TypeIndex TI, LVElement *Element); 429 Error visitKnownMember(CVMemberRecord &Record, ListContinuationRecord &Cont, 430 TypeIndex TI, LVElement *Element); 431 Error visitKnownMember(CVMemberRecord &Record, NestedTypeRecord &Nested, 432 TypeIndex TI, LVElement *Element); 433 Error visitKnownMember(CVMemberRecord &Record, OneMethodRecord &Method, 434 TypeIndex TI, LVElement *Element); 435 Error visitKnownMember(CVMemberRecord &Record, OverloadedMethodRecord &Method, 436 TypeIndex TI, LVElement *Element); 437 Error visitKnownMember(CVMemberRecord &Record, StaticDataMemberRecord &Field, 438 TypeIndex TI, LVElement *Element); 439 Error visitKnownMember(CVMemberRecord &Record, VFPtrRecord &VFTable, 440 TypeIndex TI, LVElement *Element); 441 Error visitKnownMember(CVMemberRecord &Record, VirtualBaseClassRecord &Base, 442 TypeIndex TI, LVElement *Element); 443 444 template <typename T> 445 Error visitKnownMember(CVMemberRecord &Record, 446 TypeVisitorCallbacks &Callbacks, TypeIndex TI, 447 LVElement *Element) { 448 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind); 449 T KnownRecord(RK); 450 if (Error Err = Callbacks.visitKnownMember(Record, KnownRecord)) 451 return Err; 452 if (Error Err = visitKnownMember(Record, KnownRecord, TI, Element)) 453 return Err; 454 return Error::success(); 455 } 456 457 template <typename T> 458 Error visitKnownRecord(CVType &Record, TypeIndex TI, LVElement *Element) { 459 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind()); 460 T KnownRecord(RK); 461 if (Error Err = TypeDeserializer::deserializeAs( 462 const_cast<CVType &>(Record), KnownRecord)) 463 return Err; 464 if (Error Err = visitKnownRecord(Record, KnownRecord, TI, Element)) 465 return Err; 466 return Error::success(); 467 } 468 469 Error visitMemberRecord(CVMemberRecord &Record, 470 TypeVisitorCallbacks &Callbacks, TypeIndex TI, 471 LVElement *Element); 472 Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element); 473 }; 474 475 } // namespace logicalview 476 } // namespace llvm 477 478 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H 479