brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.4 KiB · 44d0733 Raw
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