1 //===-- LVSymbol.cpp ------------------------------------------------------===//
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 implements the LVSymbol class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
15 #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
16 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
17 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
18
19 using namespace llvm;
20 using namespace llvm::logicalview;
21
22 #define DEBUG_TYPE "Symbol"
23
24 namespace {
25 const char *const KindCallSiteParameter = "CallSiteParameter";
26 const char *const KindConstant = "Constant";
27 const char *const KindInherits = "Inherits";
28 const char *const KindMember = "Member";
29 const char *const KindParameter = "Parameter";
30 const char *const KindUndefined = "Undefined";
31 const char *const KindUnspecified = "Unspecified";
32 const char *const KindVariable = "Variable";
33 } // end anonymous namespace
34
35 // Return a string representation for the symbol kind.
kind() const36 const char *LVSymbol::kind() const {
37 const char *Kind = KindUndefined;
38 if (getIsCallSiteParameter())
39 Kind = KindCallSiteParameter;
40 else if (getIsConstant())
41 Kind = KindConstant;
42 else if (getIsInheritance())
43 Kind = KindInherits;
44 else if (getIsMember())
45 Kind = KindMember;
46 else if (getIsParameter())
47 Kind = KindParameter;
48 else if (getIsUnspecified())
49 Kind = KindUnspecified;
50 else if (getIsVariable())
51 Kind = KindVariable;
52 return Kind;
53 }
54
55 LVSymbolDispatch LVSymbol::Dispatch = {
56 {LVSymbolKind::IsCallSiteParameter, &LVSymbol::getIsCallSiteParameter},
57 {LVSymbolKind::IsConstant, &LVSymbol::getIsConstant},
58 {LVSymbolKind::IsInheritance, &LVSymbol::getIsInheritance},
59 {LVSymbolKind::IsMember, &LVSymbol::getIsMember},
60 {LVSymbolKind::IsParameter, &LVSymbol::getIsParameter},
61 {LVSymbolKind::IsUnspecified, &LVSymbol::getIsUnspecified},
62 {LVSymbolKind::IsVariable, &LVSymbol::getIsVariable}};
63
64 // Add a Location Entry.
addLocation(dwarf::Attribute Attr,LVAddress LowPC,LVAddress HighPC,LVUnsigned SectionOffset,uint64_t LocDescOffset,bool CallSiteLocation)65 void LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC,
66 LVAddress HighPC, LVUnsigned SectionOffset,
67 uint64_t LocDescOffset, bool CallSiteLocation) {
68 if (!Locations)
69 Locations = std::make_unique<LVLocations>();
70
71 // Create the location entry.
72 CurrentLocation = getReader().createLocationSymbol();
73 CurrentLocation->setParent(this);
74 CurrentLocation->setAttr(Attr);
75 if (CallSiteLocation)
76 CurrentLocation->setIsCallSite();
77 CurrentLocation->addObject(LowPC, HighPC, SectionOffset, LocDescOffset);
78 Locations->push_back(CurrentLocation);
79
80 // Mark the symbol as having location information.
81 setHasLocation();
82 }
83
84 // Add a Location Record.
addLocationOperands(LVSmall Opcode,ArrayRef<uint64_t> Operands)85 void LVSymbol::addLocationOperands(LVSmall Opcode,
86 ArrayRef<uint64_t> Operands) {
87 if (CurrentLocation)
88 CurrentLocation->addObject(Opcode, Operands);
89 }
90
91 // Add a Location Entry.
addLocationConstant(dwarf::Attribute Attr,LVUnsigned Constant,uint64_t LocDescOffset)92 void LVSymbol::addLocationConstant(dwarf::Attribute Attr, LVUnsigned Constant,
93 uint64_t LocDescOffset) {
94 // Create a Location Entry, with the global information.
95 addLocation(Attr,
96 /*LowPC=*/0, /*HighPC=*/-1,
97 /*SectionOffset=*/0, LocDescOffset);
98
99 // Add records to Location Entry.
100 addLocationOperands(/*Opcode=*/LVLocationMemberOffset, {Constant});
101 }
102
addLocationGap(LVLocations::iterator Pos,LVAddress LowPC,LVAddress HighPC)103 LVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos,
104 LVAddress LowPC,
105 LVAddress HighPC) {
106 // Create a location entry for the gap.
107 LVLocation *Gap = getReader().createLocationSymbol();
108 Gap->setParent(this);
109 Gap->setAttr(dwarf::DW_AT_location);
110 Gap->addObject(LowPC, HighPC,
111 /*section_offset=*/0,
112 /*locdesc_offset=*/0);
113
114 LVLocations::iterator Iter = Locations->insert(Pos, Gap);
115
116 // Add gap to Location Entry.
117 Gap->addObject(dwarf::DW_OP_hi_user, {});
118
119 // Mark the entry as a gap.
120 Gap->setIsGapEntry();
121
122 return Iter;
123 }
124
fillLocationGaps()125 void LVSymbol::fillLocationGaps() {
126 // The symbol has locations records. Fill gaps in the location list.
127 if (!getHasLocation() || !getFillGaps())
128 return;
129
130 // Get the parent range information and add dummy location entries.
131 const LVLocations *Ranges = getParentScope()->getRanges();
132 if (!Ranges)
133 return;
134
135 for (const LVLocation *Entry : *Ranges) {
136 LVAddress ParentLowPC = Entry->getLowerAddress();
137 LVAddress ParentHighPC = Entry->getUpperAddress();
138
139 // Traverse the symbol locations and for each location contained in
140 // the current parent range, insert locations for any existing gap.
141 LVLocation *Location;
142 LVAddress LowPC = 0;
143 LVAddress Marker = ParentLowPC;
144 for (LVLocations::iterator Iter = Locations->begin();
145 Iter != Locations->end(); ++Iter) {
146 Location = *Iter;
147 LowPC = Location->getLowerAddress();
148 if (LowPC != Marker) {
149 // We have a gap at [Marker,LowPC - 1].
150 Iter = addLocationGap(Iter, Marker, LowPC - 1);
151 ++Iter;
152 }
153
154 // Move to the next item in the location list.
155 Marker = Location->getUpperAddress() + 1;
156 }
157
158 // Check any gap at the end.
159 if (Marker < ParentHighPC)
160 // We have a gap at [Marker,ParentHighPC].
161 addLocationGap(Locations->end(), Marker, ParentHighPC);
162 }
163 }
164
165 // Get all the locations based on the valid function.
getLocations(LVLocations & LocationList,LVValidLocation ValidLocation,bool RecordInvalid)166 void LVSymbol::getLocations(LVLocations &LocationList,
167 LVValidLocation ValidLocation, bool RecordInvalid) {
168 if (!Locations)
169 return;
170
171 for (LVLocation *Location : *Locations) {
172 // Add the invalid location object.
173 if (!(Location->*ValidLocation)() && RecordInvalid)
174 LocationList.push_back(Location);
175 }
176
177 // Calculate coverage factor.
178 calculateCoverage();
179 }
180
getLocations(LVLocations & LocationList) const181 void LVSymbol::getLocations(LVLocations &LocationList) const {
182 if (!Locations)
183 return;
184
185 for (LVLocation *Location : *Locations)
186 LocationList.push_back(Location);
187 }
188
189 // Calculate coverage factor.
calculateCoverage()190 void LVSymbol::calculateCoverage() {
191 if (!LVLocation::calculateCoverage(Locations.get(), CoverageFactor,
192 CoveragePercentage)) {
193 LVScope *Parent = getParentScope();
194 if (Parent->getIsInlinedFunction()) {
195 // For symbols representing the inlined function parameters and its
196 // variables, get the outer most parent that contains their location
197 // lower address.
198 // The symbol can have a set of non-contiguous locations. We are using
199 // only the first location entry to get the outermost parent.
200 // If no scope contains the location, assume its enclosing parent.
201 LVScope *Scope =
202 Parent->outermostParent(Locations->front()->getLowerAddress());
203 if (Scope)
204 Parent = Scope;
205 }
206 unsigned CoverageParent = Parent->getCoverageFactor();
207 // Get a percentage rounded to two decimal digits. This avoids
208 // implementation-defined rounding inside printing functions.
209 CoveragePercentage =
210 CoverageParent
211 ? rint((double(CoverageFactor) / CoverageParent) * 100.0 * 100.0) /
212 100.0
213 : 0;
214 // Record invalid coverage entry.
215 if (options().getWarningCoverages() && CoveragePercentage > 100)
216 getReaderCompileUnit()->addInvalidCoverage(this);
217 }
218 }
219
resolveName()220 void LVSymbol::resolveName() {
221 if (getIsResolvedName())
222 return;
223 setIsResolvedName();
224
225 LVElement::resolveName();
226
227 // Resolve any given pattern.
228 patterns().resolvePatternMatch(this);
229 }
230
resolveReferences()231 void LVSymbol::resolveReferences() {
232 // The symbols can have the following references to other elements:
233 // A Type:
234 // DW_AT_type -> Type or Scope
235 // DW_AT_import -> Type
236 // A Reference:
237 // DW_AT_specification -> Symbol
238 // DW_AT_abstract_origin -> Symbol
239 // DW_AT_extension -> Symbol
240
241 // Resolve any referenced symbol.
242 LVSymbol *Reference = getReference();
243 if (Reference) {
244 Reference->resolve();
245 // Recursively resolve the symbol names.
246 resolveReferencesChain();
247 }
248
249 // Set the file/line information using the Debug Information entry.
250 setFile(Reference);
251
252 // Resolve symbol type.
253 if (LVElement *Element = getType()) {
254 Element->resolve();
255
256 // In the case of demoted typedefs, use the underlying type.
257 if (Element->getIsTypedefReduced()) {
258 Element = Element->getType();
259 Element->resolve();
260 }
261
262 // If the type is a template parameter, get its type, which can
263 // point to a type or scope, depending on the argument instance.
264 setGenericType(Element);
265 }
266
267 // Resolve the variable associated type.
268 if (!getType() && Reference)
269 setType(Reference->getType());
270 }
271
resolveReferencesChain()272 StringRef LVSymbol::resolveReferencesChain() {
273 // If the symbol have a DW_AT_specification or DW_AT_abstract_origin,
274 // follow the chain to resolve the name from those references.
275 if (getHasReference() && !isNamed())
276 setName(getReference()->resolveReferencesChain());
277
278 return getName();
279 }
280
markMissingParents(const LVSymbols * References,const LVSymbols * Targets)281 void LVSymbol::markMissingParents(const LVSymbols *References,
282 const LVSymbols *Targets) {
283 if (!(References && Targets))
284 return;
285
286 LLVM_DEBUG({
287 dbgs() << "\n[LVSymbol::markMissingParents]\n";
288 for (const LVSymbol *Reference : *References)
289 dbgs() << "References: "
290 << "Kind = " << formattedKind(Reference->kind()) << ", "
291 << "Name = " << formattedName(Reference->getName()) << "\n";
292 for (const LVSymbol *Target : *Targets)
293 dbgs() << "Targets : "
294 << "Kind = " << formattedKind(Target->kind()) << ", "
295 << "Name = " << formattedName(Target->getName()) << "\n";
296 });
297
298 for (LVSymbol *Reference : *References) {
299 LLVM_DEBUG({
300 dbgs() << "Search Reference: Name = "
301 << formattedName(Reference->getName()) << "\n";
302 });
303 if (!Reference->findIn(Targets))
304 Reference->markBranchAsMissing();
305 }
306 }
307
findIn(const LVSymbols * Targets) const308 LVSymbol *LVSymbol::findIn(const LVSymbols *Targets) const {
309 if (!Targets)
310 return nullptr;
311
312 LLVM_DEBUG({
313 dbgs() << "\n[LVSymbol::findIn]\n"
314 << "Reference: "
315 << "Level = " << getLevel() << ", "
316 << "Kind = " << formattedKind(kind()) << ", "
317 << "Name = " << formattedName(getName()) << "\n";
318 for (const LVSymbol *Target : *Targets)
319 dbgs() << "Target : "
320 << "Level = " << Target->getLevel() << ", "
321 << "Kind = " << formattedKind(Target->kind()) << ", "
322 << "Name = " << formattedName(Target->getName()) << "\n";
323 });
324
325 for (LVSymbol *Target : *Targets)
326 if (equals(Target))
327 return Target;
328
329 return nullptr;
330 }
331
332 // Check for a match on the arguments of a function.
parametersMatch(const LVSymbols * References,const LVSymbols * Targets)333 bool LVSymbol::parametersMatch(const LVSymbols *References,
334 const LVSymbols *Targets) {
335 if (!References && !Targets)
336 return true;
337 if (References && Targets) {
338 LVSymbols ReferenceParams;
339 getParameters(References, &ReferenceParams);
340 LVSymbols TargetParams;
341 getParameters(Targets, &TargetParams);
342 return LVSymbol::equals(&ReferenceParams, &TargetParams);
343 }
344 return false;
345 }
346
347 // Return the symbols which are parameters.
getParameters(const LVSymbols * Symbols,LVSymbols * Parameters)348 void LVSymbol::getParameters(const LVSymbols *Symbols, LVSymbols *Parameters) {
349 if (Symbols)
350 for (LVSymbol *Symbol : *Symbols)
351 if (Symbol->getIsParameter())
352 Parameters->push_back(Symbol);
353 }
354
equals(const LVSymbol * Symbol) const355 bool LVSymbol::equals(const LVSymbol *Symbol) const {
356 if (!LVElement::equals(Symbol))
357 return false;
358
359 // Check if any reference is the same.
360 if (!referenceMatch(Symbol))
361 return false;
362
363 if (getReference() && !getReference()->equals(Symbol->getReference()))
364 return false;
365
366 return true;
367 }
368
equals(const LVSymbols * References,const LVSymbols * Targets)369 bool LVSymbol::equals(const LVSymbols *References, const LVSymbols *Targets) {
370 if (!References && !Targets)
371 return true;
372 if (References && Targets && References->size() == Targets->size()) {
373 for (const LVSymbol *Reference : *References)
374 if (!Reference->findIn(Targets))
375 return false;
376 return true;
377 }
378 return false;
379 }
380
report(LVComparePass Pass)381 void LVSymbol::report(LVComparePass Pass) {
382 getComparator().printItem(this, Pass);
383 }
384
printLocations(raw_ostream & OS,bool Full) const385 void LVSymbol::printLocations(raw_ostream &OS, bool Full) const {
386 if (Locations)
387 for (const LVLocation *Location : *Locations)
388 Location->printRaw(OS, Full);
389 }
390
print(raw_ostream & OS,bool Full) const391 void LVSymbol::print(raw_ostream &OS, bool Full) const {
392 if (getIncludeInPrint() && getReader().doPrintSymbol(this)) {
393 getReaderCompileUnit()->incrementPrintedSymbols();
394 LVElement::print(OS, Full);
395 printExtra(OS, Full);
396 }
397 }
398
printExtra(raw_ostream & OS,bool Full) const399 void LVSymbol::printExtra(raw_ostream &OS, bool Full) const {
400 // Accessibility depends on the parent (class, structure).
401 uint32_t AccessCode = 0;
402 if (getIsMember() || getIsInheritance())
403 AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private
404 : dwarf::DW_ACCESS_public;
405
406 const LVSymbol *Symbol = getIsInlined() ? Reference : this;
407 std::string Attributes =
408 Symbol->getIsCallSiteParameter()
409 ? ""
410 : formatAttributes(Symbol->externalString(),
411 Symbol->accessibilityString(AccessCode),
412 virtualityString());
413
414 OS << formattedKind(Symbol->kind()) << " " << Attributes;
415 if (Symbol->getIsUnspecified())
416 OS << formattedName(Symbol->getName());
417 else {
418 if (Symbol->getIsInheritance())
419 OS << Symbol->typeOffsetAsString()
420 << formattedNames(Symbol->getTypeQualifiedName(),
421 Symbol->typeAsString());
422 else {
423 OS << formattedName(Symbol->getName());
424 // Print any bitfield information.
425 if (uint32_t Size = getBitSize())
426 OS << ":" << Size;
427 OS << " -> " << Symbol->typeOffsetAsString()
428 << formattedNames(Symbol->getTypeQualifiedName(),
429 Symbol->typeAsString());
430 }
431 }
432
433 // Print any initial value if any.
434 if (ValueIndex)
435 OS << " = " << formattedName(getValue());
436 OS << "\n";
437
438 if (Full && options().getPrintFormatting()) {
439 if (getLinkageNameIndex())
440 printLinkageName(OS, Full, const_cast<LVSymbol *>(this));
441 if (LVSymbol *Reference = getReference())
442 Reference->printReference(OS, Full, const_cast<LVSymbol *>(this));
443
444 // Print location information.
445 LVLocation::print(Locations.get(), OS, Full);
446 }
447 }
448