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