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
26namespace llvm {
27namespace dwarf {
28// Support for CodeView ModifierOptions::Unaligned.
29constexpr Tag DW_TAG_unaligned = Tag(dwarf::DW_TAG_hi_user + 1);
30} // namespace dwarf
31} // namespace llvm
32
33namespace llvm {
34namespace logicalview {
35
36using LVSectionIndex = uint64_t;
37using LVAddress = uint64_t;
38using LVHalf = uint16_t;
39using LVLevel = uint16_t;
40using LVOffset = uint64_t;
41using LVSigned = int64_t;
42using LVUnsigned = uint64_t;
43using LVSmall = uint8_t;
44
45class LVElement;
46class LVLine;
47class LVLocation;
48class LVLocationSymbol;
49class LVObject;
50class LVOperation;
51class LVScope;
52class LVSymbol;
53class LVType;
54
55class LVOptions;
56class LVPatterns;
57
58LLVM_ABI StringRef typeNone();
59LLVM_ABI StringRef typeVoid();
60LLVM_ABI StringRef typeInt();
61LLVM_ABI StringRef typeUnknown();
62LLVM_ABI StringRef emptyString();
63
64using LVElementSetFunction = void (LVElement::*)();
65using LVElementGetFunction = bool (LVElement::*)() const;
66using LVLineSetFunction = void (LVLine::*)();
67using LVLineGetFunction = bool (LVLine::*)() const;
68using LVObjectSetFunction = void (LVObject::*)();
69using LVObjectGetFunction = bool (LVObject::*)() const;
70using LVScopeSetFunction = void (LVScope::*)();
71using LVScopeGetFunction = bool (LVScope::*)() const;
72using LVSymbolSetFunction = void (LVSymbol::*)();
73using LVSymbolGetFunction = bool (LVSymbol::*)() const;
74using LVTypeSetFunction = void (LVType::*)();
75using LVTypeGetFunction = bool (LVType::*)() const;
76
77using LVElements = SmallVector<LVElement *, 8>;
78using LVLines = SmallVector<LVLine *, 8>;
79using LVLocations = SmallVector<LVLocation *, 8>;
80using LVOperations = SmallVector<LVOperation *, 8>;
81using LVScopes = SmallVector<LVScope *, 8>;
82using LVSymbols = SmallVector<LVSymbol *, 8>;
83using LVTypes = SmallVector<LVType *, 8>;
84
85using 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
95const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max();
96
97enum class LVBinaryType { NONE, ELF, COFF };
98enum class LVComparePass { Missing, Added };
99
100// Validate functions.
101using LVValidLocation = bool (LVLocation::*)();
102
103// Keep counters of objects.
104struct LVCounter {
105 unsigned Lines = 0;
106 unsigned Scopes = 0;
107 unsigned Symbols = 0;
108 unsigned Types = 0;
109 void reset() {
110 Lines = 0;
111 Scopes = 0;
112 Symbols = 0;
113 Types = 0;
114 }
115};
116
117class 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 = {.Tag: 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 = {.Element: 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.
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
181 void incID() {
182 ++GID;
183 ID = GID;
184 }
185
186protected:
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
199public:
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.
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 || static_cast<LVElement *>(Parent.Element)) &&
251 "Invalid element");
252 return Parent.Element;
253 }
254 LVScope *getParentScope() const {
255 assert((!Parent.Scope || static_cast<LVScope *>(Parent.Scope)) &&
256 "Invalid scope");
257 return Parent.Scope;
258 }
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);
266 void resetParent() { Parent = {.Element: nullptr}; }
267
268 virtual LVAddress getLowerAddress() const { return 0; }
269 virtual void setLowerAddress(LVAddress Address) {}
270 virtual LVAddress getUpperAddress() const { return 0; }
271 virtual void setUpperAddress(LVAddress Address) {}
272
273 uint32_t getLineNumber() const { return LineNumber; }
274 void setLineNumber(uint32_t Number) { LineNumber = Number; }
275
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(LineNumber: getLineNumber(), Discriminator: 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)
316 void dump() const { print(dbgs()); }
317#endif
318
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