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