1292236Sjhb//===-- LVSymbol.cpp ------------------------------------------------------===// 2292236Sjhb// 3292236Sjhb// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4292236Sjhb// See https://llvm.org/LICENSE.txt for license information. 5298107Sgjb// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6292236Sjhb// 7292236Sjhb//===----------------------------------------------------------------------===// 8311999Sjhb// 9292236Sjhb// This implements the LVSymbol class. 10292236Sjhb// 11311999Sjhb//===----------------------------------------------------------------------===// 12313538Sngie 13313538Sngie#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" 14294849Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h" 15311999Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h" 16295931Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVReader.h" 17311999Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVScope.h" 18332247Stuexen 19311999Sjhbusing namespace llvm; 20311999Sjhbusing namespace llvm::logicalview; 21328454Sjhb 22292622Sjhb#define DEBUG_TYPE "Symbol" 23311999Sjhb 24311999Sjhbnamespace { 25332244Stuexenconst char *const KindCallSiteParameter = "CallSiteParameter"; 26311999Sjhbconst char *const KindConstant = "Constant"; 27311999Sjhbconst char *const KindInherits = "Inherits"; 28319417Stuexenconst char *const KindMember = "Member"; 29294849Sjhbconst char *const KindParameter = "Parameter"; 30292236Sjhbconst char *const KindUndefined = "Undefined"; 31311999Sjhbconst char *const KindUnspecified = "Unspecified"; 32311999Sjhbconst char *const KindVariable = "Variable"; 33311999Sjhb} // end anonymous namespace 34311999Sjhb 35311999Sjhb// Return a string representation for the symbol kind. 36311999Sjhbconst char *LVSymbol::kind() const { 37311999Sjhb const char *Kind = KindUndefined; 38326044Sjhb if (getIsCallSiteParameter()) 39311999Sjhb Kind = KindCallSiteParameter; 40311999Sjhb else if (getIsConstant()) 41311999Sjhb Kind = KindConstant; 42311999Sjhb else if (getIsInheritance()) 43311999Sjhb Kind = KindInherits; 44311999Sjhb else if (getIsMember()) 45311999Sjhb Kind = KindMember; 46311999Sjhb else if (getIsParameter()) 47311999Sjhb Kind = KindParameter; 48326044Sjhb else if (getIsUnspecified()) 49311999Sjhb Kind = KindUnspecified; 50311999Sjhb else if (getIsVariable()) 51311999Sjhb Kind = KindVariable; 52311999Sjhb return Kind; 53311999Sjhb} 54311999Sjhb 55332243StuexenLVSymbolDispatch LVSymbol::Dispatch = { 56311999Sjhb {LVSymbolKind::IsCallSiteParameter, &LVSymbol::getIsCallSiteParameter}, 57311999Sjhb {LVSymbolKind::IsConstant, &LVSymbol::getIsConstant}, 58311999Sjhb {LVSymbolKind::IsInheritance, &LVSymbol::getIsInheritance}, 59311999Sjhb {LVSymbolKind::IsMember, &LVSymbol::getIsMember}, 60311999Sjhb {LVSymbolKind::IsParameter, &LVSymbol::getIsParameter}, 61311999Sjhb {LVSymbolKind::IsUnspecified, &LVSymbol::getIsUnspecified}, 62311999Sjhb {LVSymbolKind::IsVariable, &LVSymbol::getIsVariable}}; 63311999Sjhb 64311999Sjhb// Add a Location Entry. 65311999Sjhbvoid LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC, 66311999Sjhb LVAddress HighPC, LVUnsigned SectionOffset, 67311999Sjhb uint64_t LocDescOffset, bool CallSiteLocation) { 68311999Sjhb if (!Locations) 69311999Sjhb Locations = std::make_unique<LVLocations>(); 70311999Sjhb 71326044Sjhb // Create the location entry. 72311999Sjhb CurrentLocation = getReader().createLocationSymbol(); 73311999Sjhb CurrentLocation->setParent(this); 74311999Sjhb CurrentLocation->setAttr(Attr); 75311999Sjhb if (CallSiteLocation) 76328454Sjhb CurrentLocation->setIsCallSite(); 77328454Sjhb CurrentLocation->addObject(LowPC, HighPC, SectionOffset, LocDescOffset); 78328454Sjhb Locations->push_back(CurrentLocation); 79311999Sjhb 80326044Sjhb // Mark the symbol as having location information. 81311999Sjhb setHasLocation(); 82311999Sjhb} 83311999Sjhb 84311999Sjhb// Add a Location Record. 85311999Sjhbvoid LVSymbol::addLocationOperands(LVSmall Opcode, 86311999Sjhb ArrayRef<uint64_t> Operands) { 87311999Sjhb if (CurrentLocation) 88311999Sjhb CurrentLocation->addObject(Opcode, Operands); 89311999Sjhb} 90311999Sjhb 91311999Sjhb// Add a Location Entry. 92311999Sjhbvoid LVSymbol::addLocationConstant(dwarf::Attribute Attr, LVUnsigned Constant, 93311999Sjhb uint64_t LocDescOffset) { 94311999Sjhb // Create a Location Entry, with the global information. 95311999Sjhb addLocation(Attr, 96311999Sjhb /*LowPC=*/0, /*HighPC=*/-1, 97311999Sjhb /*SectionOffset=*/0, LocDescOffset); 98311999Sjhb 99332248Stuexen // Add records to Location Entry. 100332248Stuexen addLocationOperands(/*Opcode=*/LVLocationMemberOffset, {Constant}); 101332248Stuexen} 102311999Sjhb 103311999SjhbLVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos, 104311999Sjhb LVAddress LowPC, 105311999Sjhb LVAddress HighPC) { 106311999Sjhb // Create a location entry for the gap. 107311999Sjhb LVLocation *Gap = getReader().createLocationSymbol(); 108311999Sjhb Gap->setParent(this); 109292236Sjhb Gap->setAttr(dwarf::DW_AT_location); 110351891Sbdrewery Gap->addObject(LowPC, HighPC, 111292622Sjhb /*section_offset=*/0, 112292622Sjhb /*locdesc_offset=*/0); 113292622Sjhb 114292622Sjhb LVLocations::iterator Iter = Locations->insert(Pos, Gap); 115292622Sjhb 116292622Sjhb // Add gap to Location Entry. 117292622Sjhb Gap->addObject(dwarf::DW_OP_hi_user, {}); 118292622Sjhb 119292622Sjhb // Mark the entry as a gap. 120292622Sjhb Gap->setIsGapEntry(); 121292622Sjhb 122294849Sjhb return Iter; 123294849Sjhb} 124294849Sjhb 125294849Sjhbvoid LVSymbol::fillLocationGaps() { 126361020Sjhb // The symbol has locations records. Fill gaps in the location list. 127361020Sjhb if (!getHasLocation() || !getFillGaps()) 128361020Sjhb return; 129361020Sjhb 130361020Sjhb // Get the parent range information and add dummy location entries. 131361020Sjhb const LVLocations *Ranges = getParentScope()->getRanges(); 132361020Sjhb if (!Ranges) 133292622Sjhb return; 134292622Sjhb 135311999Sjhb for (const LVLocation *Entry : *Ranges) { 136311999Sjhb LVAddress ParentLowPC = Entry->getLowerAddress(); 137311999Sjhb LVAddress ParentHighPC = Entry->getUpperAddress(); 138311999Sjhb 139311999Sjhb // Traverse the symbol locations and for each location contained in 140311999Sjhb // the current parent range, insert locations for any existing gap. 141311999Sjhb LVLocation *Location; 142311999Sjhb LVAddress LowPC = 0; 143311999Sjhb LVAddress Marker = ParentLowPC; 144311999Sjhb for (LVLocations::iterator Iter = Locations->begin(); 145321687Skp Iter != Locations->end(); ++Iter) { 146292622Sjhb Location = *Iter; 147292622Sjhb LowPC = Location->getLowerAddress(); 148311999Sjhb if (LowPC != Marker) { 149292622Sjhb // We have a gap at [Marker,LowPC - 1]. 150292236Sjhb 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 for (LVLocation *Location : *Locations) 186 LocationList.push_back(Location); 187} 188 189// Calculate coverage factor. 190void 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 220void 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 231void 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 272StringRef 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 281void 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 308LVSymbol *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. 333bool 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. 348void 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 355bool 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 369bool 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 381void LVSymbol::report(LVComparePass Pass) { 382 getComparator().printItem(this, Pass); 383} 384 385void LVSymbol::printLocations(raw_ostream &OS, bool Full) const { 386 if (Locations) 387 for (const LVLocation *Location : *Locations) 388 Location->printRaw(OS, Full); 389} 390 391void 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 399void 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