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