1 //===-- LVObject.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 LVObject class, which is used to describe a debug 10 // information object. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H 15 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H 16 17 #include "llvm/BinaryFormat/Dwarf.h" 18 #include "llvm/DebugInfo/CodeView/CodeView.h" 19 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 20 #include "llvm/DebugInfo/LogicalView/Core/LVSupport.h" 21 #include <limits> 22 #include <list> 23 #include <map> 24 #include <string> 25 26 namespace llvm { 27 namespace dwarf { 28 // Support for CodeView ModifierOptions::Unaligned. 29 constexpr Tag DW_TAG_unaligned = Tag(dwarf::DW_TAG_hi_user + 1); 30 } // namespace dwarf 31 } // namespace llvm 32 33 namespace llvm { 34 namespace logicalview { 35 36 using LVSectionIndex = uint64_t; 37 using LVAddress = uint64_t; 38 using LVHalf = uint16_t; 39 using LVLevel = uint32_t; 40 using LVOffset = uint64_t; 41 using LVSigned = int64_t; 42 using LVUnsigned = uint64_t; 43 using LVSmall = uint8_t; 44 45 class LVElement; 46 class LVLine; 47 class LVLocation; 48 class LVLocationSymbol; 49 class LVObject; 50 class LVOperation; 51 class LVScope; 52 class LVSymbol; 53 class LVType; 54 55 class LVOptions; 56 class LVPatterns; 57 58 StringRef typeNone(); 59 StringRef typeVoid(); 60 StringRef typeInt(); 61 StringRef typeUnknown(); 62 StringRef emptyString(); 63 64 using LVElementSetFunction = void (LVElement::*)(); 65 using LVElementGetFunction = bool (LVElement::*)() const; 66 using LVLineSetFunction = void (LVLine::*)(); 67 using LVLineGetFunction = bool (LVLine::*)() const; 68 using LVObjectSetFunction = void (LVObject::*)(); 69 using LVObjectGetFunction = bool (LVObject::*)() const; 70 using LVScopeSetFunction = void (LVScope::*)(); 71 using LVScopeGetFunction = bool (LVScope::*)() const; 72 using LVSymbolSetFunction = void (LVSymbol::*)(); 73 using LVSymbolGetFunction = bool (LVSymbol::*)() const; 74 using LVTypeSetFunction = void (LVType::*)(); 75 using LVTypeGetFunction = bool (LVType::*)() const; 76 77 // The LVScope class represents a logical scope and uses vectors to store its 78 // children, which are pointers to other allocated logical elements (types, 79 // symbols, lines, scopes, ranges). On destruction, we have to traverse each 80 // vector and destroy its elements. The other case is LVSymbol. 81 // These definitions are intended to be used by the LVScope and LVSymbol 82 // to support automatic vector cleanup. 83 using LVAutoLines = LVAutoSmallVector<LVLine *>; 84 using LVAutoLocations = LVAutoSmallVector<LVLocation *>; 85 using LVAutoOperations = LVAutoSmallVector<LVOperation *, 8>; 86 using LVAutoScopes = LVAutoSmallVector<LVScope *>; 87 using LVAutoSymbols = LVAutoSmallVector<LVSymbol *>; 88 using LVAutoTypes = LVAutoSmallVector<LVType *>; 89 90 // These definitions are intended to be used when the vector will be used 91 // just a container, with no automatic destruction. 92 using LVElements = SmallVector<LVElement *, 8>; 93 using LVLines = SmallVector<LVLine *, 8>; 94 using LVLocations = SmallVector<LVLocation *, 8>; 95 using LVOperations = SmallVector<LVOperation *, 8>; 96 using LVScopes = SmallVector<LVScope *, 8>; 97 using LVSymbols = SmallVector<LVSymbol *, 8>; 98 using LVTypes = SmallVector<LVType *, 8>; 99 100 using LVOffsets = SmallVector<LVOffset, 8>; 101 102 const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max(); 103 104 enum class LVBinaryType { NONE, ELF, COFF }; 105 enum class LVComparePass { Missing, Added }; 106 107 // Validate functions. 108 using LVValidLocation = bool (LVLocation::*)(); 109 110 // Keep counters of objects. 111 struct LVCounter { 112 unsigned Lines = 0; 113 unsigned Scopes = 0; 114 unsigned Symbols = 0; 115 unsigned Types = 0; resetLVCounter116 void reset() { 117 Lines = 0; 118 Scopes = 0; 119 Symbols = 0; 120 Types = 0; 121 } 122 }; 123 124 class LVObject { 125 enum class Property { 126 IsLocation, // Location. 127 IsGlobalReference, // This object is being referenced from another CU. 128 IsGeneratedName, // The Object name was generated. 129 IsResolved, // Object has been resolved. 130 IsResolvedName, // Object name has been resolved. 131 IsDiscarded, // Object has been stripped by the linker. 132 IsOptimized, // Object has been optimized by the compiler. 133 IsAdded, // Object has been 'added'. 134 IsMatched, // Object has been matched to a given pattern. 135 IsMissing, // Object is 'missing'. 136 IsMissingLink, // Object is indirectly 'missing'. 137 IsInCompare, // In 'compare' mode. 138 IsFileFromReference, // File ID from specification. 139 IsLineFromReference, // Line No from specification. 140 HasMoved, // The object was moved from 'target' to 'reference'. 141 HasPattern, // The object has a pattern. 142 IsFinalized, // CodeView object is finalized. 143 IsReferenced, // CodeView object being referenced. 144 HasCodeViewLocation, // CodeView object with debug location. 145 LastEntry 146 }; 147 // Typed bitvector with properties for this object. 148 LVProperties<Property> Properties; 149 150 LVOffset Offset = 0; 151 uint32_t LineNumber = 0; 152 LVLevel ScopeLevel = 0; 153 union { 154 dwarf::Tag Tag; 155 dwarf::Attribute Attr; 156 LVSmall Opcode; 157 } TagAttrOpcode = {dwarf::DW_TAG_null}; 158 159 // The parent of this object (nullptr if the root scope). For locations, 160 // the parent is a symbol object; otherwise it is a scope object. 161 union { 162 LVElement *Element; 163 LVScope *Scope; 164 LVSymbol *Symbol; 165 } Parent = {nullptr}; 166 167 // We do not support any object duplication, as they are created by parsing 168 // the debug information. There is only the case where we need a very basic 169 // object, to manipulate its offset, line number and scope level. Allow the 170 // copy constructor to create that object; it is used to print a reference 171 // to another object and in the case of templates, to print its encoded args. LVObject(const LVObject & Object)172 LVObject(const LVObject &Object) { 173 #ifndef NDEBUG 174 incID(); 175 #endif 176 Properties = Object.Properties; 177 Offset = Object.Offset; 178 LineNumber = Object.LineNumber; 179 ScopeLevel = Object.ScopeLevel; 180 TagAttrOpcode = Object.TagAttrOpcode; 181 Parent = Object.Parent; 182 } 183 184 #ifndef NDEBUG 185 // This is an internal ID used for debugging logical elements. It is used 186 // for cases where an unique offset within the binary input file is not 187 // available. 188 static uint64_t GID; 189 uint64_t ID = 0; 190 incID()191 void incID() { 192 ++GID; 193 ID = GID; 194 } 195 #endif 196 197 protected: 198 // Get a string representation for the given number and discriminator. 199 std::string lineAsString(uint32_t LineNumber, LVHalf Discriminator, 200 bool ShowZero) const; 201 202 // Get a string representation for the given number. 203 std::string referenceAsString(uint32_t LineNumber, bool Spaces) const; 204 205 // Print the Filename or Pathname. 206 // Empty implementation for those objects that do not have any user 207 // source file references, such as debug locations. 208 virtual void printFileIndex(raw_ostream &OS, bool Full = true) const {} 209 210 public: LVObject()211 LVObject() { 212 #ifndef NDEBUG 213 incID(); 214 #endif 215 }; 216 LVObject &operator=(const LVObject &) = delete; 217 virtual ~LVObject() = default; 218 219 PROPERTY(Property, IsLocation); 220 PROPERTY(Property, IsGlobalReference); 221 PROPERTY(Property, IsGeneratedName); 222 PROPERTY(Property, IsResolved); 223 PROPERTY(Property, IsResolvedName); 224 PROPERTY(Property, IsDiscarded); 225 PROPERTY(Property, IsOptimized); 226 PROPERTY(Property, IsAdded); 227 PROPERTY(Property, IsMatched); 228 PROPERTY(Property, IsMissing); 229 PROPERTY(Property, IsMissingLink); 230 PROPERTY(Property, IsInCompare); 231 PROPERTY(Property, IsFileFromReference); 232 PROPERTY(Property, IsLineFromReference); 233 PROPERTY(Property, HasMoved); 234 PROPERTY(Property, HasPattern); 235 PROPERTY(Property, IsFinalized); 236 PROPERTY(Property, IsReferenced); 237 PROPERTY(Property, HasCodeViewLocation); 238 239 // True if the scope has been named or typed or with line number. isNamed()240 virtual bool isNamed() const { return false; } isTyped()241 virtual bool isTyped() const { return false; } isFiled()242 virtual bool isFiled() const { return false; } isLined()243 bool isLined() const { return LineNumber != 0; } 244 245 // DWARF tag, attribute or expression opcode. getTag()246 dwarf::Tag getTag() const { return TagAttrOpcode.Tag; } setTag(dwarf::Tag Tag)247 void setTag(dwarf::Tag Tag) { TagAttrOpcode.Tag = Tag; } getAttr()248 dwarf::Attribute getAttr() const { return TagAttrOpcode.Attr; } setAttr(dwarf::Attribute Attr)249 void setAttr(dwarf::Attribute Attr) { TagAttrOpcode.Attr = Attr; } getOpcode()250 LVSmall getOpcode() const { return TagAttrOpcode.Opcode; } setOpcode(LVSmall Opcode)251 void setOpcode(LVSmall Opcode) { TagAttrOpcode.Opcode = Opcode; } 252 253 // DIE offset. getOffset()254 LVOffset getOffset() const { return Offset; } setOffset(LVOffset DieOffset)255 void setOffset(LVOffset DieOffset) { Offset = DieOffset; } 256 257 // Level where this object is located. getLevel()258 LVLevel getLevel() const { return ScopeLevel; } setLevel(LVLevel Level)259 void setLevel(LVLevel Level) { ScopeLevel = Level; } 260 getName()261 virtual StringRef getName() const { return StringRef(); } setName(StringRef ObjectName)262 virtual void setName(StringRef ObjectName) {} 263 getParent()264 LVElement *getParent() const { 265 assert((!Parent.Element || 266 (Parent.Element && static_cast<LVElement *>(Parent.Element))) && 267 "Invalid element"); 268 return Parent.Element; 269 } getParentScope()270 LVScope *getParentScope() const { 271 assert((!Parent.Scope || 272 (Parent.Scope && static_cast<LVScope *>(Parent.Scope))) && 273 "Invalid scope"); 274 return Parent.Scope; 275 } getParentSymbol()276 LVSymbol *getParentSymbol() const { 277 assert((!Parent.Symbol || 278 (Parent.Symbol && static_cast<LVSymbol *>(Parent.Symbol))) && 279 "Invalid symbol"); 280 return Parent.Symbol; 281 } 282 void setParent(LVScope *Scope); 283 void setParent(LVSymbol *Symbol); resetParent()284 void resetParent() { Parent = {nullptr}; } 285 getLowerAddress()286 virtual LVAddress getLowerAddress() const { return 0; } setLowerAddress(LVAddress Address)287 virtual void setLowerAddress(LVAddress Address) {} getUpperAddress()288 virtual LVAddress getUpperAddress() const { return 0; } setUpperAddress(LVAddress Address)289 virtual void setUpperAddress(LVAddress Address) {} 290 getLineNumber()291 uint32_t getLineNumber() const { return LineNumber; } setLineNumber(uint32_t Number)292 void setLineNumber(uint32_t Number) { LineNumber = Number; } 293 kind()294 virtual const char *kind() const { return nullptr; } 295 296 std::string indentAsString() const; 297 std::string indentAsString(LVLevel Level) const; 298 299 // String used as padding for printing objects with no line number. 300 virtual std::string noLineAsString(bool ShowZero) const; 301 302 // Line number for display; in the case of inlined functions, we use the 303 // DW_AT_call_line attribute; otherwise use DW_AT_decl_line attribute. 304 virtual std::string lineNumberAsString(bool ShowZero = false) const { 305 return lineAsString(getLineNumber(), 0, ShowZero); 306 } 307 std::string lineNumberAsStringStripped(bool ShowZero = false) const; 308 309 // This function prints the logical view to an output stream. 310 // Split: Prints the compilation unit view to a file. 311 // Match: Prints the object only if it satisfies the patterns collected 312 // from the command line. See the '--select' option. 313 // Print: Print the object only if satisfies the conditions specified by 314 // the different '--print' options. 315 // Full: Prints full information for objects representing debug locations, 316 // aggregated scopes, compile unit, functions and namespaces. 317 virtual Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, 318 bool Full = true) const; 319 void printAttributes(raw_ostream &OS, bool Full = true) const; 320 void printAttributes(raw_ostream &OS, bool Full, StringRef Name, 321 LVObject *Parent, StringRef Value, 322 bool UseQuotes = false, bool PrintRef = false) const; 323 324 // Mark branch as missing (current element and parents). 325 void markBranchAsMissing(); 326 327 // Prints the common information for an object (name, type, etc). 328 virtual void print(raw_ostream &OS, bool Full = true) const; 329 // Prints additional information for an object, depending on its kind 330 // (class attributes, debug ranges, files, directories, etc). 331 virtual void printExtra(raw_ostream &OS, bool Full = true) const {} 332 333 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()334 virtual void dump() const { print(dbgs()); } 335 #endif 336 getID()337 uint64_t getID() const { 338 return 339 #ifndef NDEBUG 340 ID; 341 #else 342 0; 343 #endif 344 } 345 }; 346 347 } // end namespace logicalview 348 } // end namespace llvm 349 350 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H 351