447 lines · cpp
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-exception6//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 19using namespace llvm;20using namespace llvm::logicalview;21 22#define DEBUG_TYPE "Symbol"23 24namespace {25const char *const KindCallSiteParameter = "CallSiteParameter";26const char *const KindConstant = "Constant";27const char *const KindInherits = "Inherits";28const char *const KindMember = "Member";29const char *const KindParameter = "Parameter";30const char *const KindUndefined = "Undefined";31const char *const KindUnspecified = "Unspecified";32const char *const KindVariable = "Variable";33} // end anonymous namespace34 35// Return a string representation for the symbol kind.36const 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 55LVSymbolDispatch 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.65void 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.85void LVSymbol::addLocationOperands(LVSmall Opcode,86 ArrayRef<uint64_t> Operands) {87 if (CurrentLocation)88 CurrentLocation->addObject(Opcode, Operands);89}90 91// Add a Location Entry.92void 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 103LVLocations::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 125void 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 in140 // 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.166void 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 181void LVSymbol::getLocations(LVLocations &LocationList) const {182 if (!Locations)183 return;184 185 llvm::append_range(LocationList, *Locations);186}187 188// Calculate coverage factor.189void LVSymbol::calculateCoverage() {190 if (!LVLocation::calculateCoverage(Locations.get(), CoverageFactor,191 CoveragePercentage)) {192 LVScope *Parent = getParentScope();193 if (Parent->getIsInlinedFunction()) {194 // For symbols representing the inlined function parameters and its195 // variables, get the outer most parent that contains their location196 // lower address.197 // The symbol can have a set of non-contiguous locations. We are using198 // only the first location entry to get the outermost parent.199 // If no scope contains the location, assume its enclosing parent.200 LVScope *Scope =201 Parent->outermostParent(Locations->front()->getLowerAddress());202 if (Scope)203 Parent = Scope;204 }205 unsigned CoverageParent = Parent->getCoverageFactor();206 // Get a percentage rounded to two decimal digits. This avoids207 // implementation-defined rounding inside printing functions.208 CoveragePercentage =209 CoverageParent210 ? rint((double(CoverageFactor) / CoverageParent) * 100.0 * 100.0) /211 100.0212 : 0;213 // Record invalid coverage entry.214 if (options().getWarningCoverages() && CoveragePercentage > 100)215 getReaderCompileUnit()->addInvalidCoverage(this);216 }217}218 219void LVSymbol::resolveName() {220 if (getIsResolvedName())221 return;222 setIsResolvedName();223 224 LVElement::resolveName();225 226 // Resolve any given pattern.227 patterns().resolvePatternMatch(this);228}229 230void LVSymbol::resolveReferences() {231 // The symbols can have the following references to other elements:232 // A Type:233 // DW_AT_type -> Type or Scope234 // DW_AT_import -> Type235 // A Reference:236 // DW_AT_specification -> Symbol237 // DW_AT_abstract_origin -> Symbol238 // DW_AT_extension -> Symbol239 240 // Resolve any referenced symbol.241 LVSymbol *Reference = getReference();242 if (Reference) {243 Reference->resolve();244 // Recursively resolve the symbol names.245 resolveReferencesChain();246 }247 248 // Set the file/line information using the Debug Information entry.249 setFile(Reference);250 251 // Resolve symbol type.252 if (LVElement *Element = getType()) {253 Element->resolve();254 255 // In the case of demoted typedefs, use the underlying type.256 if (Element->getIsTypedefReduced()) {257 Element = Element->getType();258 Element->resolve();259 }260 261 // If the type is a template parameter, get its type, which can262 // point to a type or scope, depending on the argument instance.263 setGenericType(Element);264 }265 266 // Resolve the variable associated type.267 if (!getType() && Reference)268 setType(Reference->getType());269}270 271StringRef LVSymbol::resolveReferencesChain() {272 // If the symbol have a DW_AT_specification or DW_AT_abstract_origin,273 // follow the chain to resolve the name from those references.274 if (getHasReference() && !isNamed())275 setName(getReference()->resolveReferencesChain());276 277 return getName();278}279 280void LVSymbol::markMissingParents(const LVSymbols *References,281 const LVSymbols *Targets) {282 if (!(References && Targets))283 return;284 285 LLVM_DEBUG({286 dbgs() << "\n[LVSymbol::markMissingParents]\n";287 for (const LVSymbol *Reference : *References)288 dbgs() << "References: "289 << "Kind = " << formattedKind(Reference->kind()) << ", "290 << "Name = " << formattedName(Reference->getName()) << "\n";291 for (const LVSymbol *Target : *Targets)292 dbgs() << "Targets : "293 << "Kind = " << formattedKind(Target->kind()) << ", "294 << "Name = " << formattedName(Target->getName()) << "\n";295 });296 297 for (LVSymbol *Reference : *References) {298 LLVM_DEBUG({299 dbgs() << "Search Reference: Name = "300 << formattedName(Reference->getName()) << "\n";301 });302 if (!Reference->findIn(Targets))303 Reference->markBranchAsMissing();304 }305}306 307LVSymbol *LVSymbol::findIn(const LVSymbols *Targets) const {308 if (!Targets)309 return nullptr;310 311 LLVM_DEBUG({312 dbgs() << "\n[LVSymbol::findIn]\n"313 << "Reference: "314 << "Level = " << getLevel() << ", "315 << "Kind = " << formattedKind(kind()) << ", "316 << "Name = " << formattedName(getName()) << "\n";317 for (const LVSymbol *Target : *Targets)318 dbgs() << "Target : "319 << "Level = " << Target->getLevel() << ", "320 << "Kind = " << formattedKind(Target->kind()) << ", "321 << "Name = " << formattedName(Target->getName()) << "\n";322 });323 324 for (LVSymbol *Target : *Targets)325 if (equals(Target))326 return Target;327 328 return nullptr;329}330 331// Check for a match on the arguments of a function.332bool LVSymbol::parametersMatch(const LVSymbols *References,333 const LVSymbols *Targets) {334 if (!References && !Targets)335 return true;336 if (References && Targets) {337 LVSymbols ReferenceParams;338 getParameters(References, &ReferenceParams);339 LVSymbols TargetParams;340 getParameters(Targets, &TargetParams);341 return LVSymbol::equals(&ReferenceParams, &TargetParams);342 }343 return false;344}345 346// Return the symbols which are parameters.347void LVSymbol::getParameters(const LVSymbols *Symbols, LVSymbols *Parameters) {348 if (Symbols)349 for (LVSymbol *Symbol : *Symbols)350 if (Symbol->getIsParameter())351 Parameters->push_back(Symbol);352}353 354bool LVSymbol::equals(const LVSymbol *Symbol) const {355 if (!LVElement::equals(Symbol))356 return false;357 358 // Check if any reference is the same.359 if (!referenceMatch(Symbol))360 return false;361 362 if (getReference() && !getReference()->equals(Symbol->getReference()))363 return false;364 365 return true;366}367 368bool LVSymbol::equals(const LVSymbols *References, const LVSymbols *Targets) {369 if (!References && !Targets)370 return true;371 if (References && Targets && References->size() == Targets->size()) {372 for (const LVSymbol *Reference : *References)373 if (!Reference->findIn(Targets))374 return false;375 return true;376 }377 return false;378}379 380void LVSymbol::report(LVComparePass Pass) {381 getComparator().printItem(this, Pass);382}383 384void LVSymbol::printLocations(raw_ostream &OS, bool Full) const {385 if (Locations)386 for (const LVLocation *Location : *Locations)387 Location->printRaw(OS, Full);388}389 390void LVSymbol::print(raw_ostream &OS, bool Full) const {391 if (getIncludeInPrint() && getReader().doPrintSymbol(this)) {392 getReaderCompileUnit()->incrementPrintedSymbols();393 LVElement::print(OS, Full);394 printExtra(OS, Full);395 }396}397 398void LVSymbol::printExtra(raw_ostream &OS, bool Full) const {399 // Accessibility depends on the parent (class, structure).400 uint32_t AccessCode = 0;401 if (getIsMember() || getIsInheritance())402 AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private403 : dwarf::DW_ACCESS_public;404 405 const LVSymbol *Symbol = getIsInlined() ? Reference : this;406 std::string Attributes =407 Symbol->getIsCallSiteParameter()408 ? ""409 : formatAttributes(Symbol->externalString(),410 Symbol->accessibilityString(AccessCode),411 virtualityString());412 413 OS << formattedKind(Symbol->kind()) << " " << Attributes;414 if (Symbol->getIsUnspecified())415 OS << formattedName(Symbol->getName());416 else {417 if (Symbol->getIsInheritance())418 OS << Symbol->typeOffsetAsString()419 << formattedNames(Symbol->getTypeQualifiedName(),420 Symbol->typeAsString());421 else {422 OS << formattedName(Symbol->getName());423 // Print any bitfield information.424 if (uint32_t Size = getBitSize())425 OS << ":" << Size;426 OS << " -> " << Symbol->typeOffsetAsString()427 << formattedNames(Symbol->getTypeQualifiedName(),428 Symbol->typeAsString());429 }430 }431 432 // Print any initial value if any.433 if (ValueIndex)434 OS << " = " << formattedName(getValue());435 OS << "\n";436 437 if (Full && options().getPrintFormatting()) {438 if (getLinkageNameIndex())439 printLinkageName(OS, Full, const_cast<LVSymbol *>(this));440 if (LVSymbol *Reference = getReference())441 Reference->printReference(OS, Full, const_cast<LVSymbol *>(this));442 443 // Print location information.444 LVLocation::print(Locations.get(), OS, Full);445 }446}447