xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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