1 //===-- LVScope.h -----------------------------------------------*- C++ -*-===// 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 file defines the LVScope class, which is used to describe a debug 10 // information scope. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H 15 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H 16 17 #include "llvm/DebugInfo/LogicalView/Core/LVElement.h" 18 #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h" 19 #include "llvm/DebugInfo/LogicalView/Core/LVSort.h" 20 #include "llvm/Object/ObjectFile.h" 21 #include <list> 22 #include <map> 23 #include <set> 24 25 namespace llvm { 26 namespace logicalview { 27 28 // Name address, Code size. 29 using LVNameInfo = std::pair<LVAddress, uint64_t>; 30 using LVPublicNames = std::map<LVScope *, LVNameInfo>; 31 using LVPublicAddresses = std::map<LVAddress, LVNameInfo>; 32 33 class LVRange; 34 35 enum class LVScopeKind { 36 IsAggregate, 37 IsArray, 38 IsBlock, 39 IsCallSite, 40 IsCatchBlock, 41 IsClass, 42 IsCompileUnit, 43 IsEntryPoint, 44 IsEnumeration, 45 IsFunction, 46 IsFunctionType, 47 IsInlinedFunction, 48 IsLabel, 49 IsLexicalBlock, 50 IsMember, 51 IsNamespace, 52 IsRoot, 53 IsStructure, 54 IsSubprogram, 55 IsTemplate, 56 IsTemplateAlias, 57 IsTemplatePack, 58 IsTryBlock, 59 IsUnion, 60 LastEntry 61 }; 62 using LVScopeKindSet = std::set<LVScopeKind>; 63 using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>; 64 using LVScopeRequest = std::vector<LVScopeGetFunction>; 65 66 using LVOffsetElementMap = std::map<LVOffset, LVElement *>; 67 using LVOffsetLinesMap = std::map<LVOffset, LVLines>; 68 using LVOffsetLocationsMap = std::map<LVOffset, LVLocations>; 69 using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>; 70 using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsets>; 71 72 // Class to represent a DWARF Scope. 73 class LVScope : public LVElement { 74 enum class Property { 75 HasDiscriminator, 76 CanHaveRanges, 77 CanHaveLines, 78 HasGlobals, 79 HasLocals, 80 HasLines, 81 HasScopes, 82 HasSymbols, 83 HasTypes, 84 IsComdat, 85 HasComdatScopes, // Compile Unit has comdat functions. 86 HasRanges, 87 AddedMissing, // Added missing referenced symbols. 88 LastEntry 89 }; 90 91 // Typed bitvector with kinds and properties for this scope. 92 LVProperties<LVScopeKind> Kinds; 93 LVProperties<Property> Properties; 94 static LVScopeDispatch Dispatch; 95 96 // Coverage factor in units (bytes). 97 unsigned CoverageFactor = 0; 98 99 // Calculate coverage factor. calculateCoverage()100 void calculateCoverage() { 101 float CoveragePercentage = 0; 102 LVLocation::calculateCoverage(Ranges.get(), CoverageFactor, 103 CoveragePercentage); 104 } 105 106 // Decide if the scope will be printed, using some conditions given by: 107 // only-globals, only-locals, a-pattern. 108 bool resolvePrinting() const; 109 110 // Find the current scope in the given 'Targets'. 111 LVScope *findIn(const LVScopes *Targets) const; 112 113 // Traverse the scope parent tree, executing the given callback function 114 // on each scope. 115 void traverseParents(LVScopeGetFunction GetFunction, 116 LVScopeSetFunction SetFunction); 117 118 protected: 119 // Types, Symbols, Scopes, Lines, Locations in this scope. 120 std::unique_ptr<LVTypes> Types; 121 std::unique_ptr<LVSymbols> Symbols; 122 std::unique_ptr<LVScopes> Scopes; 123 std::unique_ptr<LVLines> Lines; 124 std::unique_ptr<LVLocations> Ranges; 125 126 // Vector of elements (types, scopes and symbols). 127 // It is the union of (*Types, *Symbols and *Scopes) to be used for 128 // the following reasons: 129 // - Preserve the order the logical elements are read in. 130 // - To have a single container with all the logical elements, when 131 // the traversal does not require any specific element kind. 132 std::unique_ptr<LVElements> Children; 133 134 // Resolve the template parameters/arguments relationship. 135 void resolveTemplate(); 136 void printEncodedArgs(raw_ostream &OS, bool Full) const; 137 138 void printActiveRanges(raw_ostream &OS, bool Full = true) const; printSizes(raw_ostream & OS)139 virtual void printSizes(raw_ostream &OS) const {} printSummary(raw_ostream & OS)140 virtual void printSummary(raw_ostream &OS) const {} 141 142 // Encoded template arguments. getEncodedArgs()143 virtual StringRef getEncodedArgs() const { return StringRef(); } setEncodedArgs(StringRef EncodedArgs)144 virtual void setEncodedArgs(StringRef EncodedArgs) {} 145 146 public: LVScope()147 LVScope() : LVElement(LVSubclassID::LV_SCOPE) { 148 setIsScope(); 149 setIncludeInPrint(); 150 } 151 LVScope(const LVScope &) = delete; 152 LVScope &operator=(const LVScope &) = delete; 153 virtual ~LVScope() = default; 154 classof(const LVElement * Element)155 static bool classof(const LVElement *Element) { 156 return Element->getSubclassID() == LVSubclassID::LV_SCOPE; 157 } 158 159 KIND(LVScopeKind, IsAggregate); 160 KIND(LVScopeKind, IsArray); 161 KIND_2(LVScopeKind, IsBlock, CanHaveRanges, CanHaveLines); 162 KIND_1(LVScopeKind, IsCallSite, IsFunction); 163 KIND_1(LVScopeKind, IsCatchBlock, IsBlock); 164 KIND_1(LVScopeKind, IsClass, IsAggregate); 165 KIND_3(LVScopeKind, IsCompileUnit, CanHaveRanges, CanHaveLines, 166 TransformName); 167 KIND_1(LVScopeKind, IsEntryPoint, IsFunction); 168 KIND(LVScopeKind, IsEnumeration); 169 KIND_2(LVScopeKind, IsFunction, CanHaveRanges, CanHaveLines); 170 KIND_1(LVScopeKind, IsFunctionType, IsFunction); 171 KIND_2(LVScopeKind, IsInlinedFunction, IsFunction, IsInlined); 172 KIND_1(LVScopeKind, IsLabel, IsFunction); 173 KIND_1(LVScopeKind, IsLexicalBlock, IsBlock); 174 KIND(LVScopeKind, IsMember); 175 KIND(LVScopeKind, IsNamespace); 176 KIND_1(LVScopeKind, IsRoot, TransformName); 177 KIND_1(LVScopeKind, IsStructure, IsAggregate); 178 KIND_1(LVScopeKind, IsSubprogram, IsFunction); 179 KIND(LVScopeKind, IsTemplate); 180 KIND(LVScopeKind, IsTemplateAlias); 181 KIND(LVScopeKind, IsTemplatePack); 182 KIND_1(LVScopeKind, IsTryBlock, IsBlock); 183 KIND_1(LVScopeKind, IsUnion, IsAggregate); 184 185 PROPERTY(Property, HasDiscriminator); 186 PROPERTY(Property, CanHaveRanges); 187 PROPERTY(Property, CanHaveLines); 188 PROPERTY(Property, HasGlobals); 189 PROPERTY(Property, HasLocals); 190 PROPERTY(Property, HasLines); 191 PROPERTY(Property, HasScopes); 192 PROPERTY(Property, HasSymbols); 193 PROPERTY(Property, HasTypes); 194 PROPERTY(Property, IsComdat); 195 PROPERTY(Property, HasComdatScopes); 196 PROPERTY(Property, HasRanges); 197 PROPERTY(Property, AddedMissing); 198 isCompileUnit()199 bool isCompileUnit() const override { return getIsCompileUnit(); } isRoot()200 bool isRoot() const override { return getIsRoot(); } 201 202 const char *kind() const override; 203 204 // Get the specific children. getLines()205 const LVLines *getLines() const { return Lines.get(); } getRanges()206 const LVLocations *getRanges() const { return Ranges.get(); } getScopes()207 const LVScopes *getScopes() const { return Scopes.get(); } getSymbols()208 const LVSymbols *getSymbols() const { return Symbols.get(); } getTypes()209 const LVTypes *getTypes() const { return Types.get(); } getChildren()210 const LVElements *getChildren() const { return Children.get(); } 211 212 void addElement(LVElement *Element); 213 void addElement(LVLine *Line); 214 void addElement(LVScope *Scope); 215 void addElement(LVSymbol *Symbol); 216 void addElement(LVType *Type); 217 void addObject(LVLocation *Location); 218 void addObject(LVAddress LowerAddress, LVAddress UpperAddress); 219 void addToChildren(LVElement *Element); 220 221 // Add the missing elements from the given 'Reference', which is the 222 // scope associated with any DW_AT_specification, DW_AT_abstract_origin. 223 void addMissingElements(LVScope *Reference); 224 225 // Traverse the scope parent tree and the children, executing the given 226 // callback function on each element. 227 void traverseParentsAndChildren(LVObjectGetFunction GetFunction, 228 LVObjectSetFunction SetFunction); 229 230 // Get the size of specific children. lineCount()231 size_t lineCount() const { return Lines ? Lines->size() : 0; } rangeCount()232 size_t rangeCount() const { return Ranges ? Ranges->size() : 0; } scopeCount()233 size_t scopeCount() const { return Scopes ? Scopes->size() : 0; } symbolCount()234 size_t symbolCount() const { return Symbols ? Symbols->size() : 0; } typeCount()235 size_t typeCount() const { return Types ? Types->size() : 0; } 236 237 // Find containing parent for the given address. 238 LVScope *outermostParent(LVAddress Address); 239 240 // Get all the locations associated with symbols. 241 void getLocations(LVLocations &LocationList, LVValidLocation ValidLocation, 242 bool RecordInvalid = false); 243 void getRanges(LVLocations &LocationList, LVValidLocation ValidLocation, 244 bool RecordInvalid = false); 245 void getRanges(LVRange &RangeList); 246 getCoverageFactor()247 unsigned getCoverageFactor() const { return CoverageFactor; } 248 249 Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, 250 bool Full = true) const override; 251 // Sort the logical elements using the criteria specified by the 252 // command line option '--output-sort'. 253 void sort(); 254 255 // Get template parameter types. 256 bool getTemplateParameterTypes(LVTypes &Params); 257 258 // DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension. getReference()259 virtual LVScope *getReference() const { return nullptr; } 260 getCompileUnitParent()261 LVScope *getCompileUnitParent() const override { 262 return LVElement::getCompileUnitParent(); 263 } 264 265 // Follow a chain of references given by DW_AT_abstract_origin and/or 266 // DW_AT_specification and update the scope name. 267 StringRef resolveReferencesChain(); 268 269 bool removeElement(LVElement *Element) override; 270 void updateLevel(LVScope *Parent, bool Moved) override; 271 272 void resolve() override; 273 void resolveName() override; 274 void resolveReferences() override; 275 276 // Return the chain of parents as a string. 277 void getQualifiedName(std::string &QualifiedName) const; 278 // Encode the template arguments. 279 void encodeTemplateArguments(std::string &Name) const; 280 void encodeTemplateArguments(std::string &Name, const LVTypes *Types) const; 281 282 void resolveElements(); 283 284 // Iterate through the 'References' set and check that all its elements 285 // are present in the 'Targets' set. For a missing element, mark its 286 // parents as missing. 287 static void markMissingParents(const LVScopes *References, 288 const LVScopes *Targets, 289 bool TraverseChildren); 290 291 // Checks if the current scope is contained within the target scope. 292 // Depending on the result, the callback may be performed. 293 virtual void markMissingParents(const LVScope *Target, bool TraverseChildren); 294 295 // Returns true if the current scope and the given 'Scope' have the 296 // same number of children. 297 virtual bool equalNumberOfChildren(const LVScope *Scope) const; 298 299 // Returns true if current scope is logically equal to the given 'Scope'. 300 virtual bool equals(const LVScope *Scope) const; 301 302 // Returns true if the given 'References' are logically equal to the 303 // given 'Targets'. 304 static bool equals(const LVScopes *References, const LVScopes *Targets); 305 306 // For the given 'Scopes' returns a scope that is logically equal 307 // to the current scope; otherwise 'nullptr'. 308 virtual LVScope *findEqualScope(const LVScopes *Scopes) const; 309 310 // Report the current scope as missing or added during comparison. 311 void report(LVComparePass Pass) override; 312 getDispatch()313 static LVScopeDispatch &getDispatch() { return Dispatch; } 314 315 void print(raw_ostream &OS, bool Full = true) const override; 316 void printExtra(raw_ostream &OS, bool Full = true) const override; 317 virtual void printWarnings(raw_ostream &OS, bool Full = true) const {} printMatchedElements(raw_ostream & OS,bool UseMatchedElements)318 virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {} 319 320 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()321 void dump() const override { print(dbgs()); } 322 #endif 323 }; 324 325 // Class to represent a DWARF Union/Structure/Class. 326 class LVScopeAggregate final : public LVScope { 327 LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin. 328 size_t EncodedArgsIndex = 0; // Template encoded arguments. 329 330 public: LVScopeAggregate()331 LVScopeAggregate() : LVScope() {} 332 LVScopeAggregate(const LVScopeAggregate &) = delete; 333 LVScopeAggregate &operator=(const LVScopeAggregate &) = delete; 334 ~LVScopeAggregate() = default; 335 336 // DW_AT_specification, DW_AT_abstract_origin. getReference()337 LVScope *getReference() const override { return Reference; } setReference(LVScope * Scope)338 void setReference(LVScope *Scope) override { 339 Reference = Scope; 340 setHasReference(); 341 } setReference(LVElement * Element)342 void setReference(LVElement *Element) override { 343 setReference(static_cast<LVScope *>(Element)); 344 } 345 getEncodedArgs()346 StringRef getEncodedArgs() const override { 347 return getStringPool().getString(EncodedArgsIndex); 348 } setEncodedArgs(StringRef EncodedArgs)349 void setEncodedArgs(StringRef EncodedArgs) override { 350 EncodedArgsIndex = getStringPool().getIndex(EncodedArgs); 351 } 352 353 // Returns true if current scope is logically equal to the given 'Scope'. 354 bool equals(const LVScope *Scope) const override; 355 356 // For the given 'Scopes' returns a scope that is logically equal 357 // to the current scope; otherwise 'nullptr'. 358 LVScope *findEqualScope(const LVScopes *Scopes) const override; 359 360 void printExtra(raw_ostream &OS, bool Full = true) const override; 361 }; 362 363 // Class to represent a DWARF Template alias. 364 class LVScopeAlias final : public LVScope { 365 public: LVScopeAlias()366 LVScopeAlias() : LVScope() { 367 setIsTemplateAlias(); 368 setIsTemplate(); 369 } 370 LVScopeAlias(const LVScopeAlias &) = delete; 371 LVScopeAlias &operator=(const LVScopeAlias &) = delete; 372 ~LVScopeAlias() = default; 373 374 // Returns true if current scope is logically equal to the given 'Scope'. 375 bool equals(const LVScope *Scope) const override; 376 377 void printExtra(raw_ostream &OS, bool Full = true) const override; 378 }; 379 380 // Class to represent a DWARF array (DW_TAG_array_type). 381 class LVScopeArray final : public LVScope { 382 public: LVScopeArray()383 LVScopeArray() : LVScope() { setIsArray(); } 384 LVScopeArray(const LVScopeArray &) = delete; 385 LVScopeArray &operator=(const LVScopeArray &) = delete; 386 ~LVScopeArray() = default; 387 388 void resolveExtra() override; 389 390 // Returns true if current scope is logically equal to the given 'Scope'. 391 bool equals(const LVScope *Scope) const override; 392 393 void printExtra(raw_ostream &OS, bool Full = true) const override; 394 }; 395 396 // Class to represent a DWARF Compilation Unit (CU). 397 class LVScopeCompileUnit final : public LVScope { 398 // Names (files and directories) used by the Compile Unit. 399 std::vector<size_t> Filenames; 400 401 // As the .debug_pubnames section has been removed in DWARF5, we have a 402 // similar functionality, which is used by the decoded functions. We use 403 // the low-pc and high-pc for those scopes that are marked as public, in 404 // order to support DWARF and CodeView. 405 LVPublicNames PublicNames; 406 407 // Toolchain producer. 408 size_t ProducerIndex = 0; 409 410 // Compilation directory name. 411 size_t CompilationDirectoryIndex = 0; 412 413 // Used by the CodeView Reader. 414 codeview::CPUType CompilationCPUType = codeview::CPUType::X64; 415 416 // Keep record of elements. They are needed at the compilation unit level 417 // to print the summary at the end of the printing. 418 LVCounter Allocated; 419 LVCounter Found; 420 LVCounter Printed; 421 422 // Elements that match a given command line pattern. 423 LVElements MatchedElements; 424 LVScopes MatchedScopes; 425 426 // It records the mapping between logical lines representing a debug line 427 // entry and its address in the text section. It is used to find a line 428 // giving its exact or closest address. To support comdat functions, all 429 // addresses for the same section are recorded in the same map. 430 using LVAddressToLine = std::map<LVAddress, LVLine *>; 431 LVDoubleMap<LVSectionIndex, LVAddress, LVLine *> SectionMappings; 432 433 // DWARF Tags (Tag, Element list). 434 LVTagOffsetsMap DebugTags; 435 436 // Offsets associated with objects being flagged as having invalid data 437 // (ranges, locations, lines zero or coverages). 438 LVOffsetElementMap WarningOffsets; 439 440 // Symbols with invalid locations. (Symbol, Location List). 441 LVOffsetLocationsMap InvalidLocations; 442 443 // Symbols with invalid coverage values. 444 LVOffsetSymbolMap InvalidCoverages; 445 446 // Scopes with invalid ranges (Scope, Range list). 447 LVOffsetLocationsMap InvalidRanges; 448 449 // Scopes with lines zero (Scope, Line list). 450 LVOffsetLinesMap LinesZero; 451 452 // Record scopes contribution in bytes to the debug information. 453 using LVSizesMap = std::map<const LVScope *, LVOffset>; 454 LVSizesMap Sizes; 455 LVOffset CUContributionSize = 0; 456 457 // Helper function to add an invalid location/range. addInvalidLocationOrRange(LVLocation * Location,LVElement * Element,LVOffsetLocationsMap * Map)458 void addInvalidLocationOrRange(LVLocation *Location, LVElement *Element, 459 LVOffsetLocationsMap *Map) { 460 LVOffset Offset = Element->getOffset(); 461 addInvalidOffset(Offset, Element); 462 addItem<LVOffsetLocationsMap, LVOffset, LVLocation *>(Map, Offset, 463 Location); 464 } 465 466 // Record scope sizes indexed by lexical level. 467 // Setting an initial size that will cover a very deep nested scopes. 468 const size_t TotalInitialSize = 8; 469 using LVTotalsEntry = std::pair<unsigned, float>; 470 SmallVector<LVTotalsEntry> Totals; 471 // Maximum seen lexical level. It is used to control how many entries 472 // in the 'Totals' vector are valid values. 473 LVLevel MaxSeenLevel = 0; 474 475 // Get the line located at the given address. 476 LVLine *lineLowerBound(LVAddress Address, LVScope *Scope) const; 477 LVLine *lineUpperBound(LVAddress Address, LVScope *Scope) const; 478 479 void printScopeSize(const LVScope *Scope, raw_ostream &OS); printScopeSize(const LVScope * Scope,raw_ostream & OS)480 void printScopeSize(const LVScope *Scope, raw_ostream &OS) const { 481 (const_cast<LVScopeCompileUnit *>(this))->printScopeSize(Scope, OS); 482 } 483 void printTotals(raw_ostream &OS) const; 484 485 protected: 486 void printSizes(raw_ostream &OS) const override; 487 void printSummary(raw_ostream &OS) const override; 488 489 public: LVScopeCompileUnit()490 LVScopeCompileUnit() : LVScope(), Totals(TotalInitialSize, {0, 0.0}) { 491 setIsCompileUnit(); 492 } 493 LVScopeCompileUnit(const LVScopeCompileUnit &) = delete; 494 LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete; 495 ~LVScopeCompileUnit() = default; 496 getCompileUnitParent()497 LVScope *getCompileUnitParent() const override { 498 return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this)); 499 } 500 501 // Add line to address mapping. 502 void addMapping(LVLine *Line, LVSectionIndex SectionIndex); 503 LVLineRange lineRange(LVLocation *Location) const; 504 505 LVNameInfo NameNone = {UINT64_MAX, 0}; addPublicName(LVScope * Scope,LVAddress LowPC,LVAddress HighPC)506 void addPublicName(LVScope *Scope, LVAddress LowPC, LVAddress HighPC) { 507 PublicNames.emplace(std::piecewise_construct, std::forward_as_tuple(Scope), 508 std::forward_as_tuple(LowPC, HighPC - LowPC)); 509 } findPublicName(LVScope * Scope)510 const LVNameInfo &findPublicName(LVScope *Scope) { 511 LVPublicNames::iterator Iter = PublicNames.find(Scope); 512 return (Iter != PublicNames.end()) ? Iter->second : NameNone; 513 } getPublicNames()514 const LVPublicNames &getPublicNames() const { return PublicNames; } 515 516 // The base address of the scope for any of the debugging information 517 // entries listed, is given by either the DW_AT_low_pc attribute or the 518 // first address in the first range entry in the list of ranges given by 519 // the DW_AT_ranges attribute. getBaseAddress()520 LVAddress getBaseAddress() const { 521 return Ranges ? Ranges->front()->getLowerAddress() : 0; 522 } 523 getCompilationDirectory()524 StringRef getCompilationDirectory() const { 525 return getStringPool().getString(CompilationDirectoryIndex); 526 } setCompilationDirectory(StringRef CompilationDirectory)527 void setCompilationDirectory(StringRef CompilationDirectory) { 528 CompilationDirectoryIndex = getStringPool().getIndex(CompilationDirectory); 529 } 530 531 StringRef getFilename(size_t Index) const; addFilename(StringRef Name)532 void addFilename(StringRef Name) { 533 Filenames.push_back(getStringPool().getIndex(Name)); 534 } 535 getProducer()536 StringRef getProducer() const override { 537 return getStringPool().getString(ProducerIndex); 538 } setProducer(StringRef ProducerName)539 void setProducer(StringRef ProducerName) override { 540 ProducerIndex = getStringPool().getIndex(ProducerName); 541 } 542 setCPUType(codeview::CPUType Type)543 void setCPUType(codeview::CPUType Type) { CompilationCPUType = Type; } getCPUType()544 codeview::CPUType getCPUType() { return CompilationCPUType; } 545 546 // Record DWARF tags. 547 void addDebugTag(dwarf::Tag Target, LVOffset Offset); 548 // Record elements with invalid offsets. 549 void addInvalidOffset(LVOffset Offset, LVElement *Element); 550 // Record symbols with invalid coverage values. 551 void addInvalidCoverage(LVSymbol *Symbol); 552 // Record symbols with invalid locations. 553 void addInvalidLocation(LVLocation *Location); 554 // Record scopes with invalid ranges. 555 void addInvalidRange(LVLocation *Location); 556 // Record line zero. 557 void addLineZero(LVLine *Line); 558 getDebugTags()559 const LVTagOffsetsMap &getDebugTags() const { return DebugTags; } getWarningOffsets()560 const LVOffsetElementMap &getWarningOffsets() const { return WarningOffsets; } getInvalidLocations()561 const LVOffsetLocationsMap &getInvalidLocations() const { 562 return InvalidLocations; 563 } getInvalidCoverages()564 const LVOffsetSymbolMap &getInvalidCoverages() const { 565 return InvalidCoverages; 566 } getInvalidRanges()567 const LVOffsetLocationsMap &getInvalidRanges() const { return InvalidRanges; } getLinesZero()568 const LVOffsetLinesMap &getLinesZero() const { return LinesZero; } 569 570 // Process ranges, locations and calculate coverage. 571 void processRangeLocationCoverage( 572 LVValidLocation ValidLocation = &LVLocation::validateRanges); 573 574 // Add matched element. addMatched(LVElement * Element)575 void addMatched(LVElement *Element) { MatchedElements.push_back(Element); } addMatched(LVScope * Scope)576 void addMatched(LVScope *Scope) { MatchedScopes.push_back(Scope); } 577 void propagatePatternMatch(); 578 getMatchedElements()579 const LVElements &getMatchedElements() const { return MatchedElements; } getMatchedScopes()580 const LVScopes &getMatchedScopes() const { return MatchedScopes; } 581 582 void printLocalNames(raw_ostream &OS, bool Full = true) const; 583 void printSummary(raw_ostream &OS, const LVCounter &Counter, 584 const char *Header) const; 585 586 void incrementPrintedLines(); 587 void incrementPrintedScopes(); 588 void incrementPrintedSymbols(); 589 void incrementPrintedTypes(); 590 591 // Values are used by '--summary' option (allocated). 592 void increment(LVLine *Line); 593 void increment(LVScope *Scope); 594 void increment(LVSymbol *Symbol); 595 void increment(LVType *Type); 596 597 // A new element has been added to the scopes tree. Take the following steps: 598 // Increase the added element counters, for printing summary. 599 // During comparison notify the Reader of the new element. 600 void addedElement(LVLine *Line); 601 void addedElement(LVScope *Scope); 602 void addedElement(LVSymbol *Symbol); 603 void addedElement(LVType *Type); 604 605 void addSize(LVScope *Scope, LVOffset Lower, LVOffset Upper); 606 607 // Returns true if current scope is logically equal to the given 'Scope'. 608 bool equals(const LVScope *Scope) const override; 609 610 void print(raw_ostream &OS, bool Full = true) const override; 611 void printExtra(raw_ostream &OS, bool Full = true) const override; 612 void printWarnings(raw_ostream &OS, bool Full = true) const override; 613 void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) override; 614 }; 615 616 // Class to represent a DWARF enumerator (DW_TAG_enumeration_type). 617 class LVScopeEnumeration final : public LVScope { 618 public: LVScopeEnumeration()619 LVScopeEnumeration() : LVScope() { setIsEnumeration(); } 620 LVScopeEnumeration(const LVScopeEnumeration &) = delete; 621 LVScopeEnumeration &operator=(const LVScopeEnumeration &) = delete; 622 ~LVScopeEnumeration() = default; 623 624 // Returns true if current scope is logically equal to the given 'Scope'. 625 bool equals(const LVScope *Scope) const override; 626 627 void printExtra(raw_ostream &OS, bool Full = true) const override; 628 }; 629 630 // Class to represent a DWARF formal parameter pack 631 // (DW_TAG_GNU_formal_parameter_pack). 632 class LVScopeFormalPack final : public LVScope { 633 public: LVScopeFormalPack()634 LVScopeFormalPack() : LVScope() { setIsTemplatePack(); } 635 LVScopeFormalPack(const LVScopeFormalPack &) = delete; 636 LVScopeFormalPack &operator=(const LVScopeFormalPack &) = delete; 637 ~LVScopeFormalPack() = default; 638 639 // Returns true if current scope is logically equal to the given 'Scope'. 640 bool equals(const LVScope *Scope) const override; 641 642 void printExtra(raw_ostream &OS, bool Full = true) const override; 643 }; 644 645 // Class to represent a DWARF Function. 646 class LVScopeFunction : public LVScope { 647 LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin. 648 size_t LinkageNameIndex = 0; // Function DW_AT_linkage_name attribute. 649 size_t EncodedArgsIndex = 0; // Template encoded arguments. 650 651 public: LVScopeFunction()652 LVScopeFunction() : LVScope() {} 653 LVScopeFunction(const LVScopeFunction &) = delete; 654 LVScopeFunction &operator=(const LVScopeFunction &) = delete; 655 virtual ~LVScopeFunction() = default; 656 657 // DW_AT_specification, DW_AT_abstract_origin. getReference()658 LVScope *getReference() const override { return Reference; } setReference(LVScope * Scope)659 void setReference(LVScope *Scope) override { 660 Reference = Scope; 661 setHasReference(); 662 } setReference(LVElement * Element)663 void setReference(LVElement *Element) override { 664 setReference(static_cast<LVScope *>(Element)); 665 } 666 getEncodedArgs()667 StringRef getEncodedArgs() const override { 668 return getStringPool().getString(EncodedArgsIndex); 669 } setEncodedArgs(StringRef EncodedArgs)670 void setEncodedArgs(StringRef EncodedArgs) override { 671 EncodedArgsIndex = getStringPool().getIndex(EncodedArgs); 672 } 673 setLinkageName(StringRef LinkageName)674 void setLinkageName(StringRef LinkageName) override { 675 LinkageNameIndex = getStringPool().getIndex(LinkageName); 676 } getLinkageName()677 StringRef getLinkageName() const override { 678 return getStringPool().getString(LinkageNameIndex); 679 } getLinkageNameIndex()680 size_t getLinkageNameIndex() const override { return LinkageNameIndex; } 681 682 void setName(StringRef ObjectName) override; 683 684 void resolveExtra() override; 685 void resolveReferences() override; 686 687 // Returns true if current scope is logically equal to the given 'Scope'. 688 bool equals(const LVScope *Scope) const override; 689 690 // For the given 'Scopes' returns a scope that is logically equal 691 // to the current scope; otherwise 'nullptr'. 692 LVScope *findEqualScope(const LVScopes *Scopes) const override; 693 694 void printExtra(raw_ostream &OS, bool Full = true) const override; 695 }; 696 697 // Class to represent a DWARF inlined function. 698 class LVScopeFunctionInlined final : public LVScopeFunction { 699 size_t CallFilenameIndex = 0; 700 uint32_t CallLineNumber = 0; 701 uint32_t Discriminator = 0; 702 703 public: LVScopeFunctionInlined()704 LVScopeFunctionInlined() : LVScopeFunction() { setIsInlinedFunction(); } 705 LVScopeFunctionInlined(const LVScopeFunctionInlined &) = delete; 706 LVScopeFunctionInlined &operator=(const LVScopeFunctionInlined &) = delete; 707 ~LVScopeFunctionInlined() = default; 708 getDiscriminator()709 uint32_t getDiscriminator() const override { return Discriminator; } setDiscriminator(uint32_t Value)710 void setDiscriminator(uint32_t Value) override { 711 Discriminator = Value; 712 setHasDiscriminator(); 713 } 714 getCallLineNumber()715 uint32_t getCallLineNumber() const override { return CallLineNumber; } setCallLineNumber(uint32_t Number)716 void setCallLineNumber(uint32_t Number) override { CallLineNumber = Number; } getCallFilenameIndex()717 size_t getCallFilenameIndex() const override { return CallFilenameIndex; } setCallFilenameIndex(size_t Index)718 void setCallFilenameIndex(size_t Index) override { 719 CallFilenameIndex = Index; 720 } 721 722 // Line number for display; in the case of Inlined Functions, we use the 723 // DW_AT_call_line attribute; otherwise use DW_AT_decl_line attribute. 724 std::string lineNumberAsString(bool ShowZero = false) const override { 725 return lineAsString(getCallLineNumber(), getDiscriminator(), ShowZero); 726 } 727 728 void resolveExtra() override; 729 730 // Returns true if current scope is logically equal to the given 'Scope'. 731 bool equals(const LVScope *Scope) const override; 732 733 // For the given 'Scopes' returns a scope that is logically equal 734 // to the current scope; otherwise 'nullptr'. 735 LVScope *findEqualScope(const LVScopes *Scopes) const override; 736 737 void printExtra(raw_ostream &OS, bool Full = true) const override; 738 }; 739 740 // Class to represent a DWARF subroutine type. 741 class LVScopeFunctionType final : public LVScopeFunction { 742 public: LVScopeFunctionType()743 LVScopeFunctionType() : LVScopeFunction() { setIsFunctionType(); } 744 LVScopeFunctionType(const LVScopeFunctionType &) = delete; 745 LVScopeFunctionType &operator=(const LVScopeFunctionType &) = delete; 746 ~LVScopeFunctionType() = default; 747 748 void resolveExtra() override; 749 }; 750 751 // Class to represent a DWARF Namespace. 752 class LVScopeNamespace final : public LVScope { 753 LVScope *Reference = nullptr; // Reference to DW_AT_extension attribute. 754 755 public: LVScopeNamespace()756 LVScopeNamespace() : LVScope() { setIsNamespace(); } 757 LVScopeNamespace(const LVScopeNamespace &) = delete; 758 LVScopeNamespace &operator=(const LVScopeNamespace &) = delete; 759 ~LVScopeNamespace() = default; 760 761 // Access DW_AT_extension reference. getReference()762 LVScope *getReference() const override { return Reference; } setReference(LVScope * Scope)763 void setReference(LVScope *Scope) override { 764 Reference = Scope; 765 setHasReference(); 766 } setReference(LVElement * Element)767 void setReference(LVElement *Element) override { 768 setReference(static_cast<LVScope *>(Element)); 769 } 770 771 // Returns true if current scope is logically equal to the given 'Scope'. 772 bool equals(const LVScope *Scope) const override; 773 774 // For the given 'Scopes' returns a scope that is logically equal 775 // to the current scope; otherwise 'nullptr'. 776 LVScope *findEqualScope(const LVScopes *Scopes) const override; 777 778 void printExtra(raw_ostream &OS, bool Full = true) const override; 779 }; 780 781 // Class to represent the binary file being analyzed. 782 class LVScopeRoot final : public LVScope { 783 size_t FileFormatNameIndex = 0; 784 785 public: LVScopeRoot()786 LVScopeRoot() : LVScope() { setIsRoot(); } 787 LVScopeRoot(const LVScopeRoot &) = delete; 788 LVScopeRoot &operator=(const LVScopeRoot &) = delete; 789 ~LVScopeRoot() = default; 790 getFileFormatName()791 StringRef getFileFormatName() const { 792 return getStringPool().getString(FileFormatNameIndex); 793 } setFileFormatName(StringRef FileFormatName)794 void setFileFormatName(StringRef FileFormatName) { 795 FileFormatNameIndex = getStringPool().getIndex(FileFormatName); 796 } 797 798 // The CodeView Reader uses scoped names. Recursively transform the 799 // element name to use just the most inner component. 800 void transformScopedName(); 801 802 // Process the collected location, ranges and calculate coverage. 803 void processRangeInformation(); 804 805 // Returns true if current scope is logically equal to the given 'Scope'. 806 bool equals(const LVScope *Scope) const override; 807 808 void print(raw_ostream &OS, bool Full = true) const override; 809 void printExtra(raw_ostream &OS, bool Full = true) const override; 810 Error doPrintMatches(bool Split, raw_ostream &OS, 811 bool UseMatchedElements) const; 812 }; 813 814 // Class to represent a DWARF template parameter pack 815 // (DW_TAG_GNU_template_parameter_pack). 816 class LVScopeTemplatePack final : public LVScope { 817 public: LVScopeTemplatePack()818 LVScopeTemplatePack() : LVScope() { setIsTemplatePack(); } 819 LVScopeTemplatePack(const LVScopeTemplatePack &) = delete; 820 LVScopeTemplatePack &operator=(const LVScopeTemplatePack &) = delete; 821 ~LVScopeTemplatePack() = default; 822 823 // Returns true if current scope is logically equal to the given 'Scope'. 824 bool equals(const LVScope *Scope) const override; 825 826 void printExtra(raw_ostream &OS, bool Full = true) const override; 827 }; 828 829 } // end namespace logicalview 830 } // end namespace llvm 831 832 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H 833