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