xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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