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