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