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 = 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. 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. 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 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 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. 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 181 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. 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 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 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 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 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 308 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. 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. 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 355 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 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 381 void LVSymbol::report(LVComparePass Pass) { 382 getComparator().printItem(this, Pass); 383 } 384 385 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 391 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 399 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