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