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.
36 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.
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.
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.
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 
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 
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.
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 
183 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.
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 
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 
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 
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 
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 
310 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.
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.
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 
357 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 
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 
383 void LVSymbol::report(LVComparePass Pass) {
384   getComparator().printItem(this, Pass);
385 }
386 
387 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 
393 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 
401 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