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 = new LVAutoLocations();
70
71 // Create the location entry.
72 CurrentLocation = new LVLocationSymbol();
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,uint64_t Operand1,uint64_t Operand2)85 void LVSymbol::addLocationOperands(LVSmall Opcode, uint64_t Operand1,
86 uint64_t Operand2) {
87 if (CurrentLocation)
88 CurrentLocation->addObject(Opcode, Operand1, Operand2);
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,
101 /*Operand1=*/Constant, /*Operand2=*/0);
102 }
103
addLocationGap(LVLocations::iterator Pos,LVAddress LowPC,LVAddress HighPC)104 LVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos,
105 LVAddress LowPC,
106 LVAddress HighPC) {
107 // Create a location entry for the gap.
108 LVLocation *Gap = new LVLocationSymbol();
109 Gap->setParent(this);
110 Gap->setAttr(dwarf::DW_AT_location);
111 Gap->addObject(LowPC, HighPC,
112 /*section_offset=*/0,
113 /*locdesc_offset=*/0);
114
115 LVLocations::iterator Iter = Locations->insert(Pos, Gap);
116
117 // Add gap to Location Entry.
118 Gap->addObject(/*op=*/dwarf::DW_OP_hi_user,
119 /*opd1=*/0, /*opd2=*/0);
120
121 // Mark the entry as a gap.
122 Gap->setIsGapEntry();
123
124 return Iter;
125 }
126
fillLocationGaps()127 void LVSymbol::fillLocationGaps() {
128 // The symbol has locations records. Fill gaps in the location list.
129 if (!getHasLocation() || !getFillGaps())
130 return;
131
132 // Get the parent range information and add dummy location entries.
133 const LVLocations *Ranges = getParentScope()->getRanges();
134 if (!Ranges)
135 return;
136
137 for (const LVLocation *Entry : *Ranges) {
138 LVAddress ParentLowPC = Entry->getLowerAddress();
139 LVAddress ParentHighPC = Entry->getUpperAddress();
140
141 // Traverse the symbol locations and for each location contained in
142 // the current parent range, insert locations for any existing gap.
143 LVLocation *Location;
144 LVAddress LowPC = 0;
145 LVAddress Marker = ParentLowPC;
146 for (LVLocations::iterator Iter = Locations->begin();
147 Iter != Locations->end(); ++Iter) {
148 Location = *Iter;
149 LowPC = Location->getLowerAddress();
150 if (LowPC != Marker) {
151 // We have a gap at [Marker,LowPC - 1].
152 Iter = addLocationGap(Iter, Marker, LowPC - 1);
153 ++Iter;
154 }
155
156 // Move to the next item in the location list.
157 Marker = Location->getUpperAddress() + 1;
158 }
159
160 // Check any gap at the end.
161 if (Marker < ParentHighPC)
162 // We have a gap at [Marker,ParentHighPC].
163 addLocationGap(Locations->end(), Marker, ParentHighPC);
164 }
165 }
166
167 // Get all the locations based on the valid function.
getLocations(LVLocations & LocationList,LVValidLocation ValidLocation,bool RecordInvalid)168 void LVSymbol::getLocations(LVLocations &LocationList,
169 LVValidLocation ValidLocation, bool RecordInvalid) {
170 if (!Locations)
171 return;
172
173 for (LVLocation *Location : *Locations) {
174 // Add the invalid location object.
175 if (!(Location->*ValidLocation)() && RecordInvalid)
176 LocationList.push_back(Location);
177 }
178
179 // Calculate coverage factor.
180 calculateCoverage();
181 }
182
getLocations(LVLocations & LocationList) const183 void LVSymbol::getLocations(LVLocations &LocationList) const {
184 if (!Locations)
185 return;
186
187 for (LVLocation *Location : *Locations)
188 LocationList.push_back(Location);
189 }
190
191 // Calculate coverage factor.
calculateCoverage()192 void LVSymbol::calculateCoverage() {
193 if (!LVLocation::calculateCoverage(Locations, CoverageFactor,
194 CoveragePercentage)) {
195 LVScope *Parent = getParentScope();
196 if (Parent->getIsInlinedFunction()) {
197 // For symbols representing the inlined function parameters and its
198 // variables, get the outer most parent that contains their location
199 // lower address.
200 // The symbol can have a set of non-contiguous locations. We are using
201 // only the first location entry to get the outermost parent.
202 // If no scope contains the location, assume its enclosing parent.
203 LVScope *Scope =
204 Parent->outermostParent(Locations->front()->getLowerAddress());
205 if (Scope)
206 Parent = Scope;
207 }
208 unsigned CoverageParent = Parent->getCoverageFactor();
209 // Get a percentage rounded to two decimal digits. This avoids
210 // implementation-defined rounding inside printing functions.
211 CoveragePercentage =
212 CoverageParent
213 ? rint((double(CoverageFactor) / CoverageParent) * 100.0 * 100.0) /
214 100.0
215 : 0;
216 // Record invalid coverage entry.
217 if (options().getWarningCoverages() && CoveragePercentage > 100)
218 getReaderCompileUnit()->addInvalidCoverage(this);
219 }
220 }
221
resolveName()222 void LVSymbol::resolveName() {
223 if (getIsResolvedName())
224 return;
225 setIsResolvedName();
226
227 LVElement::resolveName();
228
229 // Resolve any given pattern.
230 patterns().resolvePatternMatch(this);
231 }
232
resolveReferences()233 void LVSymbol::resolveReferences() {
234 // The symbols can have the following references to other elements:
235 // A Type:
236 // DW_AT_type -> Type or Scope
237 // DW_AT_import -> Type
238 // A Reference:
239 // DW_AT_specification -> Symbol
240 // DW_AT_abstract_origin -> Symbol
241 // DW_AT_extension -> Symbol
242
243 // Resolve any referenced symbol.
244 LVSymbol *Reference = getReference();
245 if (Reference) {
246 Reference->resolve();
247 // Recursively resolve the symbol names.
248 resolveReferencesChain();
249 }
250
251 // Set the file/line information using the Debug Information entry.
252 setFile(Reference);
253
254 // Resolve symbol type.
255 if (LVElement *Element = getType()) {
256 Element->resolve();
257
258 // In the case of demoted typedefs, use the underlying type.
259 if (Element->getIsTypedefReduced()) {
260 Element = Element->getType();
261 Element->resolve();
262 }
263
264 // If the type is a template parameter, get its type, which can
265 // point to a type or scope, depending on the argument instance.
266 setGenericType(Element);
267 }
268
269 // Resolve the variable associated type.
270 if (!getType() && Reference)
271 setType(Reference->getType());
272 }
273
resolveReferencesChain()274 StringRef LVSymbol::resolveReferencesChain() {
275 // If the symbol have a DW_AT_specification or DW_AT_abstract_origin,
276 // follow the chain to resolve the name from those references.
277 if (getHasReference() && !isNamed())
278 setName(getReference()->resolveReferencesChain());
279
280 return getName();
281 }
282
markMissingParents(const LVSymbols * References,const LVSymbols * Targets)283 void LVSymbol::markMissingParents(const LVSymbols *References,
284 const LVSymbols *Targets) {
285 if (!(References && Targets))
286 return;
287
288 LLVM_DEBUG({
289 dbgs() << "\n[LVSymbol::markMissingParents]\n";
290 for (const LVSymbol *Reference : *References)
291 dbgs() << "References: "
292 << "Kind = " << formattedKind(Reference->kind()) << ", "
293 << "Name = " << formattedName(Reference->getName()) << "\n";
294 for (const LVSymbol *Target : *Targets)
295 dbgs() << "Targets : "
296 << "Kind = " << formattedKind(Target->kind()) << ", "
297 << "Name = " << formattedName(Target->getName()) << "\n";
298 });
299
300 for (LVSymbol *Reference : *References) {
301 LLVM_DEBUG({
302 dbgs() << "Search Reference: Name = "
303 << formattedName(Reference->getName()) << "\n";
304 });
305 if (!Reference->findIn(Targets))
306 Reference->markBranchAsMissing();
307 }
308 }
309
findIn(const LVSymbols * Targets) const310 LVSymbol *LVSymbol::findIn(const LVSymbols *Targets) const {
311 if (!Targets)
312 return nullptr;
313
314 LLVM_DEBUG({
315 dbgs() << "\n[LVSymbol::findIn]\n"
316 << "Reference: "
317 << "Level = " << getLevel() << ", "
318 << "Kind = " << formattedKind(kind()) << ", "
319 << "Name = " << formattedName(getName()) << "\n";
320 for (const LVSymbol *Target : *Targets)
321 dbgs() << "Target : "
322 << "Level = " << Target->getLevel() << ", "
323 << "Kind = " << formattedKind(Target->kind()) << ", "
324 << "Name = " << formattedName(Target->getName()) << "\n";
325 });
326
327 for (LVSymbol *Target : *Targets)
328 if (equals(Target))
329 return Target;
330
331 return nullptr;
332 }
333
334 // Check for a match on the arguments of a function.
parametersMatch(const LVSymbols * References,const LVSymbols * Targets)335 bool LVSymbol::parametersMatch(const LVSymbols *References,
336 const LVSymbols *Targets) {
337 if (!References && !Targets)
338 return true;
339 if (References && Targets) {
340 LVSymbols ReferenceParams;
341 getParameters(References, &ReferenceParams);
342 LVSymbols TargetParams;
343 getParameters(Targets, &TargetParams);
344 return LVSymbol::equals(&ReferenceParams, &TargetParams);
345 }
346 return false;
347 }
348
349 // Return the symbols which are parameters.
getParameters(const LVSymbols * Symbols,LVSymbols * Parameters)350 void LVSymbol::getParameters(const LVSymbols *Symbols, LVSymbols *Parameters) {
351 if (Symbols)
352 for (LVSymbol *Symbol : *Symbols)
353 if (Symbol->getIsParameter())
354 Parameters->push_back(Symbol);
355 }
356
equals(const LVSymbol * Symbol) const357 bool LVSymbol::equals(const LVSymbol *Symbol) const {
358 if (!LVElement::equals(Symbol))
359 return false;
360
361 // Check if any reference is the same.
362 if (!referenceMatch(Symbol))
363 return false;
364
365 if (getReference() && !getReference()->equals(Symbol->getReference()))
366 return false;
367
368 return true;
369 }
370
equals(const LVSymbols * References,const LVSymbols * Targets)371 bool LVSymbol::equals(const LVSymbols *References, const LVSymbols *Targets) {
372 if (!References && !Targets)
373 return true;
374 if (References && Targets && References->size() == Targets->size()) {
375 for (const LVSymbol *Reference : *References)
376 if (!Reference->findIn(Targets))
377 return false;
378 return true;
379 }
380 return false;
381 }
382
report(LVComparePass Pass)383 void LVSymbol::report(LVComparePass Pass) {
384 getComparator().printItem(this, Pass);
385 }
386
printLocations(raw_ostream & OS,bool Full) const387 void LVSymbol::printLocations(raw_ostream &OS, bool Full) const {
388 if (Locations)
389 for (const LVLocation *Location : *Locations)
390 Location->printRaw(OS, Full);
391 }
392
print(raw_ostream & OS,bool Full) const393 void LVSymbol::print(raw_ostream &OS, bool Full) const {
394 if (getIncludeInPrint() && getReader().doPrintSymbol(this)) {
395 getReaderCompileUnit()->incrementPrintedSymbols();
396 LVElement::print(OS, Full);
397 printExtra(OS, Full);
398 }
399 }
400
printExtra(raw_ostream & OS,bool Full) const401 void LVSymbol::printExtra(raw_ostream &OS, bool Full) const {
402 // Accessibility depends on the parent (class, structure).
403 uint32_t AccessCode = 0;
404 if (getIsMember() || getIsInheritance())
405 AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private
406 : dwarf::DW_ACCESS_public;
407
408 const LVSymbol *Symbol = getIsInlined() ? Reference : this;
409 std::string Attributes =
410 Symbol->getIsCallSiteParameter()
411 ? ""
412 : formatAttributes(Symbol->externalString(),
413 Symbol->accessibilityString(AccessCode),
414 virtualityString());
415
416 OS << formattedKind(Symbol->kind()) << " " << Attributes;
417 if (Symbol->getIsUnspecified())
418 OS << formattedName(Symbol->getName());
419 else {
420 if (Symbol->getIsInheritance())
421 OS << Symbol->typeOffsetAsString()
422 << formattedNames(Symbol->getTypeQualifiedName(),
423 Symbol->typeAsString());
424 else {
425 OS << formattedName(Symbol->getName());
426 // Print any bitfield information.
427 if (uint32_t Size = getBitSize())
428 OS << ":" << Size;
429 OS << " -> " << Symbol->typeOffsetAsString()
430 << formattedNames(Symbol->getTypeQualifiedName(),
431 Symbol->typeAsString());
432 }
433 }
434
435 // Print any initial value if any.
436 if (ValueIndex)
437 OS << " = " << formattedName(getValue());
438 OS << "\n";
439
440 if (Full && options().getPrintFormatting()) {
441 if (getLinkageNameIndex())
442 printLinkageName(OS, Full, const_cast<LVSymbol *>(this));
443 if (LVSymbol *Reference = getReference())
444 Reference->printReference(OS, Full, const_cast<LVSymbol *>(this));
445
446 // Print location information.
447 LVLocation::print(Locations, OS, Full);
448 }
449 }
450