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