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