brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.0 KiB · 011321b Raw
566 lines · cpp
1//===- llvm/unittest/DebugInfo/LogicalView/WarningInternalTest.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#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"10#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"11#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"12#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"13#include "llvm/DebugInfo/LogicalView/Core/LVType.h"14#include "llvm/Support/ScopedPrinter.h"15#include "llvm/Support/ToolOutputFile.h"16#include "llvm/Testing/Support/Error.h"17 18#include "gtest/gtest.h"19 20using namespace llvm;21using namespace llvm::logicalview;22 23namespace {24 25class MyLocation : public LVLocation {26public:27  bool validateRanges();28};29 30// This code emulates the work done by the Readers when processing the31// binary files and the creation of the AddressToLine mapping is done32// automatically, using the text sections.33class MyAddressToLine {34  using LVAddressToLine = std::map<LVAddress, LVLine *>;35  LVAddressToLine AddressToLineData;36 37public:38  MyAddressToLine() = default;39 40  void insert(LVLine *Line) {41    AddressToLineData.emplace(Line->getOffset(), Line);42  }43 44  LVLine *lineLowerBound(LVAddress Address);45  LVLine *lineUpperBound(LVAddress Address);46};47 48LVLine *MyAddressToLine::lineLowerBound(LVAddress Address) {49  LVAddressToLine::const_iterator Iter = AddressToLineData.lower_bound(Address);50  return (Iter != AddressToLineData.end()) ? Iter->second : nullptr;51}52 53LVLine *MyAddressToLine::lineUpperBound(LVAddress Address) {54  if (AddressToLineData.empty())55    return nullptr;56  LVAddressToLine::const_iterator Iter = AddressToLineData.upper_bound(Address);57  if (Iter != AddressToLineData.begin())58    Iter = std::prev(Iter);59  return Iter->second;60}61 62MyAddressToLine AddressToLine;63 64class ReaderTestWarningInternal : public LVReader {65#define CREATE(VARIABLE, CREATE_FUNCTION)                                      \66  VARIABLE = CREATE_FUNCTION();                                                \67  EXPECT_NE(VARIABLE, nullptr);68 69#define CREATE_CUSTOM(VARIABLE, CREATE_FUNCTION)                               \70  VARIABLE = CREATE_FUNCTION();                                                \71  EXPECT_NE(VARIABLE, nullptr);72 73  // Types.74  LVType *IntegerType = nullptr;75 76  // Scopes.77  LVScope *NestedScope = nullptr;78  LVScopeFunction *Function = nullptr;79 80  // Symbols.81  LVSymbol *LocalVariable = nullptr;82  LVSymbol *NestedVariable = nullptr;83  LVSymbol *Parameter = nullptr;84 85  // Lines.86  LVLine *LineOne = nullptr;87  LVLine *LineTwo = nullptr;88  LVLine *LineThree = nullptr;89  LVLine *LineFour = nullptr;90  LVLine *LineFive = nullptr;91  LVLine *LineSix = nullptr;92 93  // Locations.94  MyLocation *LocationOne = nullptr;95  MyLocation *LocationTwo = nullptr;96  MyLocation *LocationThree = nullptr;97  MyLocation *LocationFour = nullptr;98  MyLocation *LocationFive = nullptr;99  MyLocation *LocationSix = nullptr;100 101  llvm::SpecificBumpPtrAllocator<MyLocation> AllocatedLocations;102 103protected:104  MyLocation *createCustomLocation() {105    return new (AllocatedLocations.Allocate()) MyLocation();106  }107 108  void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);109  void add(LVScope *Parent, LVElement *Element);110  void set(LVElement *Element, StringRef Name, LVOffset Offset,111           uint32_t LineNumber = 0, LVElement *Type = nullptr);112  void set(MyLocation *Location, LVLine *LowerLine, LVLine *UpperLine,113           LVAddress LowerAddress, LVAddress UpperAddress);114 115public:116  ReaderTestWarningInternal(ScopedPrinter &W) : LVReader("", "", W) {117    setInstance(this);118  }119 120  Error createScopes() override { return LVReader::createScopes(); }121 122  void setMapping();123  void createElements();124  void addElements();125  void initElements();126  void resolveElements();127  void checkWarnings();128};129 130bool MyLocation::validateRanges() {131  // Traverse the locations and validate them against the address to line132  // mapping in the current compile unit. Record those invalid ranges.133  // A valid range must meet the following conditions:134  // a) line(lopc) <= line(hipc)135  // b) line(lopc) and line(hipc) are valid.136 137  LVLine *LowLine = AddressToLine.lineLowerBound(getLowerAddress());138  LVLine *HighLine = AddressToLine.lineUpperBound(getUpperAddress());139  if (LowLine)140    setLowerLine(LowLine);141  else {142    setIsInvalidLower();143    return false;144  }145  if (HighLine)146    setUpperLine(HighLine);147  else {148    setIsInvalidUpper();149    return false;150  }151  // Check for a valid interval.152  if (LowLine->getLineNumber() > HighLine->getLineNumber()) {153    setIsInvalidRange();154    return false;155  }156 157  return true;158}159 160// Map all logical lines with their addresses.161void ReaderTestWarningInternal::setMapping() {162  AddressToLine.insert(LineOne);163  AddressToLine.insert(LineTwo);164  AddressToLine.insert(LineThree);165  AddressToLine.insert(LineFour);166  AddressToLine.insert(LineFive);167  AddressToLine.insert(LineSix);168}169 170// Helper function to add a logical element to a given scope.171void ReaderTestWarningInternal::add(LVScope *Parent, LVElement *Child) {172  Parent->addElement(Child);173  EXPECT_EQ(Child->getParent(), Parent);174  EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);175}176 177// Helper function to set the initial values for a given logical element.178void ReaderTestWarningInternal::set(LVElement *Element, StringRef Name,179                                    LVOffset Offset, uint32_t LineNumber,180                                    LVElement *Type) {181  Element->setName(Name);182  Element->setOffset(Offset);183  Element->setLineNumber(LineNumber);184  Element->setType(Type);185  EXPECT_EQ(Element->getName(), Name);186  EXPECT_EQ(Element->getOffset(), Offset);187  EXPECT_EQ(Element->getLineNumber(), LineNumber);188  EXPECT_EQ(Element->getType(), Type);189}190 191// Helper function to set the initial values for a given logical location.192void ReaderTestWarningInternal::set(MyLocation *Location, LVLine *LowerLine,193                                    LVLine *UpperLine, LVAddress LowerAddress,194                                    LVAddress UpperAddress) {195  Location->setLowerLine(LowerLine);196  Location->setUpperLine(UpperLine);197  Location->setLowerAddress(LowerAddress);198  Location->setUpperAddress(UpperAddress);199  EXPECT_EQ(Location->getLowerLine(), LowerLine);200  EXPECT_EQ(Location->getUpperLine(), UpperLine);201  EXPECT_EQ(Location->getLowerAddress(), LowerAddress);202  EXPECT_EQ(Location->getUpperAddress(), UpperAddress);203}204 205// Helper function to add a logical location to a logical symbol.206void ReaderTestWarningInternal::add(LVSymbol *Symbol, LVLine *LowerLine,207                                    LVLine *UpperLine) {208  dwarf::Attribute Attr = dwarf::DW_AT_location;209 210  Symbol->addLocation(Attr, LowerLine->getAddress(), UpperLine->getAddress(),211                      /*SectionOffset=*/0, /*LocDesOffset=*/0);212}213 214// Create the logical elements.215void ReaderTestWarningInternal::createElements() {216  // Create scope root.217  Error Err = createScopes();218  ASSERT_THAT_ERROR(std::move(Err), Succeeded());219  Root = getScopesRoot();220  EXPECT_NE(Root, nullptr);221 222  // Create the logical types.223  CREATE(IntegerType, createType);224 225  // Create the logical scopes.226  CREATE(NestedScope, createScope);227  CREATE(CompileUnit, createScopeCompileUnit);228  CREATE(Function, createScopeFunction);229 230  // Create the logical symbols.231  CREATE(LocalVariable, createSymbol);232  CREATE(NestedVariable, createSymbol);233  CREATE(Parameter, createSymbol);234 235  // Create the logical lines.236  CREATE(LineOne, createLine);237  CREATE(LineTwo, createLine);238  CREATE(LineThree, createLine);239  CREATE(LineFour, createLine);240  CREATE(LineFive, createLine);241  CREATE(LineSix, createLine);242 243  // Create the logical locations.244  CREATE_CUSTOM(LocationOne, createCustomLocation);245  CREATE_CUSTOM(LocationTwo, createCustomLocation);246  CREATE_CUSTOM(LocationThree, createCustomLocation);247  CREATE_CUSTOM(LocationFour, createCustomLocation);248  CREATE_CUSTOM(LocationFive, createCustomLocation);249  CREATE_CUSTOM(LocationSix, createCustomLocation);250}251 252// Create the logical view adding the created logical elements.253void ReaderTestWarningInternal::addElements() {254  setCompileUnit(CompileUnit);255 256  // Root257  //   CompileUnit258  //     IntegerType259  //     Function260  //       LocationOne261  //       LocationTwo262  //       LocationFive263  //       LocationSix264  //       Parameter265  //       LocalVariable266  //       LineOne267  //       LineTwo268  //       NestedScope269  //         LocationThree270  //         LocationFour271  //         NestedVariable272  //         LineThree273  //         LineFour274  //       LineFive275  //       LineSix276 277  // Add elements to Root.278  add(Root, CompileUnit);279 280  // Add elements to CompileUnit.281  add(CompileUnit, IntegerType);282  add(CompileUnit, Function);283 284  // Add elements to Function.285  add(Function, Parameter);286  add(Function, LocalVariable);287  add(Function, LineOne);288  add(Function, LineTwo);289  add(Function, LineFive);290  add(Function, LineSix);291  add(Function, NestedScope);292 293  // Add elements to NestedScope.294  add(NestedScope, NestedVariable);295  add(NestedScope, LineThree);296  add(NestedScope, LineFour);297}298 299void ReaderTestWarningInternal::resolveElements() {300  // Traverse the given scope and its children checking for any warnings.301  std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {302    auto Warnings = [&](auto *Entry) {303      if (Entry->getIsLine()) {304        LVLine *Line = (LVLine *)Entry;305        if (options().getWarningLines() && Line->getIsLineDebug() &&306            !Line->getLineNumber())307          CompileUnit->addLineZero(Line);308      }309    };310    auto Traverse = [&](const auto *Set) {311      if (Set)312        for (const auto &Entry : *Set) {313          Warnings(Entry);314        }315    };316 317    Warnings(Parent);318 319    Traverse(Parent->getSymbols());320    Traverse(Parent->getTypes());321    Traverse(Parent->getLines());322 323    if (const LVScopes *Scopes = Parent->getScopes())324      for (LVScope *Scope : *Scopes) {325        Warnings(Scope);326        TraverseScope(Scope);327      }328  };329 330  // Start traversing the scopes root and resolve the elements.331  TraverseScope(Root);332}333 334// Set initial values to logical elements.335void ReaderTestWarningInternal::initElements() {336  // Types.337  set(IntegerType, "int", 0x1000);338 339  // Scopes.340  set(CompileUnit, "foo.cpp", 0x2000);341  set(Function, "foo", 0x2010, 100, IntegerType);342  set(NestedScope, "", 0x2020, 300);343 344  // Symbols.345  set(Parameter, "Param", 0x3000, 110, IntegerType);346  set(LocalVariable, "LocalVariable", 0x3020, 120, IntegerType);347  set(NestedVariable, "NestedVariable", 0x3010, 310, IntegerType);348 349  // Lines.350  set(LineOne, "", 0x5000, 100);351  LineOne->setIsLineDebug();352  set(LineTwo, "", 0x5200, 000);353  LineTwo->setIsLineDebug();354  set(LineThree, "", 0x5400, 300);355  LineThree->setIsLineDebug();356  set(LineFour, "", 0x5600, 000);357  LineFour->setIsLineDebug();358  set(LineFive, "", 0x5800, 500);359  LineOne->setIsLineDebug();360  set(LineSix, "", 0x6000, 600);361  LineSix->setIsLineDebug();362 363  // Locations.364  set(LocationOne, LineOne, LineOne, 0x5000, 0x5100);365  EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),366               " Lines 100:100 [0x0000005000:0x0000005100]");367 368  // Uses a Line zero.369  set(LocationTwo, LineTwo, LineTwo, 0x5200, 0x5300);370  EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),371               " Lines -:- [0x0000005200:0x0000005300]");372 373  set(LocationThree, LineThree, LineThree, 0x5400, 0x5500);374  EXPECT_STREQ(LocationThree->getIntervalInfo().c_str(),375               " Lines 300:300 [0x0000005400:0x0000005500]");376 377  // Uses a Line zero.378  set(LocationFour, LineFour, LineFour, 0x5600, 0x5700);379  LocationFour->setIsAddressRange();380  EXPECT_STREQ(LocationFour->getIntervalInfo().c_str(),381               "{Range} Lines -:- [0x0000005600:0x0000005700]");382 383  // Invalid range.384  set(LocationFive, LineFive, LineFive, 0x7800, 0x5900);385  LocationFive->setIsAddressRange();386  EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),387               "{Range} Lines 500:500 [0x0000007800:0x0000005900]");388 389  set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);390  LocationSix->setIsAddressRange();391  EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),392               "{Range} Lines 600:600 [0x0000006000:0x0000006100]");393 394  // Add ranges to Function.395  // Function: LocationOne, LocationTwo, LocationFive, LocationSix396  Function->addObject(LocationOne);397  Function->addObject(LocationTwo);398  Function->addObject(LocationFive);399  Function->addObject(LocationSix);400  EXPECT_EQ(Function->rangeCount(), 4u);401 402  // Add ranges to NestedScope.403  // NestedScope: LocationThree, LocationFour404  NestedScope->addObject(LocationThree);405  NestedScope->addObject(LocationFour);406  EXPECT_EQ(NestedScope->rangeCount(), 2u);407 408  // Get all ranges.409  LVRange Ranges;410  CompileUnit->getRanges(Ranges);411  Ranges.startSearch();412  EXPECT_EQ(Ranges.getEntry(0x4000), nullptr);413 414  EXPECT_EQ(Ranges.getEntry(0x5060), Function);415  EXPECT_EQ(Ranges.getEntry(0x5850), nullptr);416  EXPECT_EQ(Ranges.getEntry(0x5010, 0x5090), Function);417  EXPECT_EQ(Ranges.getEntry(0x5210, 0x5290), Function);418  EXPECT_EQ(Ranges.getEntry(0x5810, 0x5890), nullptr);419  EXPECT_EQ(Ranges.getEntry(0x6010, 0x6090), Function);420 421  EXPECT_EQ(Ranges.getEntry(0x5400), NestedScope);422  EXPECT_EQ(Ranges.getEntry(0x5650), NestedScope);423  EXPECT_EQ(Ranges.getEntry(0x5410, 0x5490), NestedScope);424  EXPECT_EQ(Ranges.getEntry(0x5610, 0x5690), NestedScope);425 426  EXPECT_EQ(Ranges.getEntry(0x8000), nullptr);427  Ranges.endSearch();428 429  // Add locations to symbols.430  // Parameter:       [LineOne, LineSix]431  // LocalVariable:   [LineTwo, LineSix], [LineFour, LineFive]432  // NestedVariable:  [LineThree, LineFour]433  add(Parameter, LineOne, LineSix);434  add(LocalVariable, LineTwo, LineSix);435  add(LocalVariable, LineFour, LineFive);436  add(NestedVariable, LineThree, LineFour);437  add(NestedVariable, LineOne, LineSix);438}439 440// Check logical elements warnigs.441void ReaderTestWarningInternal::checkWarnings() {442  // Map all lines with their addresses.443  setMapping();444 445  // Check for lines with line zero.446  resolveElements();447 448  // Check invalid locations and ranges using a customized validation.449  CompileUnit->processRangeLocationCoverage(450      (LVValidLocation)(&MyLocation::validateRanges));451 452  // Get lines with line zero. [Parent, Line]453  //   Function, LineTwo454  //   NestedScope, LineFour455  LVOffsetLinesMap LinesZero = CompileUnit->getLinesZero();456  ASSERT_EQ(LinesZero.size(), 2u);457 458  LVOffsetLinesMap::iterator IterZero = LinesZero.begin();459  EXPECT_EQ(IterZero->first, Function->getOffset());460  LVLines *Lines = &IterZero->second;461  EXPECT_NE(Lines, nullptr);462  ASSERT_EQ(Lines->size(), 1u);463  LVLine *Line = *(Lines->begin());464  EXPECT_NE(Line, nullptr);465  EXPECT_EQ(Line, LineTwo);466 467  ++IterZero;468  EXPECT_EQ(IterZero->first, NestedScope->getOffset());469  Lines = &IterZero->second;470  EXPECT_NE(Lines, nullptr);471  ASSERT_EQ(Lines->size(), 1u);472  Line = *(Lines->begin());473  EXPECT_NE(Line, nullptr);474  EXPECT_EQ(Line, LineFour);475 476  // Elements with invalid offsets.477  //   Function (line zero)478  //   NestedScope (line zero)479  //   NestedVariable (invalid location)480  LVOffsetElementMap InvalidOffsets = CompileUnit->getWarningOffsets();481  ASSERT_EQ(InvalidOffsets.size(), 3u);482 483  LVOffsetElementMap::iterator IterOffset = InvalidOffsets.begin();484  EXPECT_EQ(IterOffset->second, Function);485  ++IterOffset;486  EXPECT_EQ(IterOffset->second, NestedScope);487  ++IterOffset;488  EXPECT_EQ(IterOffset->second, NestedVariable);489 490  // Invalid ranges.491  //   Function492  LVOffsetLocationsMap InvalidRanges = CompileUnit->getInvalidRanges();493  ASSERT_EQ(InvalidRanges.size(), 1u);494 495  LVOffsetLocationsMap::iterator IterRange = InvalidRanges.begin();496  EXPECT_EQ(IterRange->first, Function->getOffset());497  LVLocations *Locations = &IterRange->second;498  EXPECT_NE(Locations, nullptr);499  ASSERT_EQ(Locations->size(), 1u);500  LVLocation *Location = *(Locations->begin());501  EXPECT_NE(Location, nullptr);502  EXPECT_EQ(Location, LocationFive);503 504  // Invalid location.505  //   NestedVariable506  LVOffsetLocationsMap InvalidLocations = CompileUnit->getInvalidLocations();507  ASSERT_EQ(InvalidLocations.size(), 1u);508 509  LVOffsetLocationsMap::iterator IterLocations = InvalidLocations.begin();510  EXPECT_EQ(IterLocations->first, NestedVariable->getOffset());511  Locations = &IterLocations->second;512  EXPECT_NE(Locations, nullptr);513  ASSERT_EQ(Locations->size(), 1u);514  Location = *(Locations->begin());515  EXPECT_NE(Location, nullptr);516  EXPECT_EQ(Location->getLowerAddress(), LocationThree->getLowerAddress());517  EXPECT_EQ(Location->getUpperAddress(), LocationFour->getLowerAddress());518  EXPECT_EQ(Location->getLowerLine()->getLineNumber(),519            LineThree->getLineNumber());520  EXPECT_EQ(Location->getUpperLine()->getLineNumber(), 0u);521 522  // Invalid coverages.523  //   NestedVariable524  LVOffsetSymbolMap InvalidCoverages = CompileUnit->getInvalidCoverages();525  ASSERT_EQ(InvalidCoverages.size(), 1u);526 527  LVOffsetSymbolMap::iterator IterCoverages = InvalidCoverages.begin();528  EXPECT_EQ(IterCoverages->first, NestedVariable->getOffset());529  EXPECT_EQ(IterCoverages->second, NestedVariable);530  EXPECT_GE((int)NestedVariable->getCoveragePercentage(), 100);531  EXPECT_EQ((int)NestedVariable->getCoveragePercentage(), 900);532  EXPECT_EQ(NestedVariable->getCoverageFactor(), 0x1200u);533 534  EXPECT_EQ((unsigned)Parameter->getCoveragePercentage(), 100u);535  EXPECT_EQ(Parameter->getCoverageFactor(), 100u);536 537  EXPECT_EQ((unsigned)LocalVariable->getCoveragePercentage(), 47u);538  EXPECT_EQ(LocalVariable->getCoverageFactor(),539            LineSix->getAddress() - LineOne->getAddress());540}541 542TEST(LogicalViewTest, WarningInternal) {543  ScopedPrinter W(outs());544  ReaderTestWarningInternal Reader(W);545 546  // Reader options.547  LVOptions ReaderOptions;548  ReaderOptions.setAttributeOffset();549  ReaderOptions.setAttributeRange();550  ReaderOptions.setAttributeLocation();551  ReaderOptions.setPrintAll();552  ReaderOptions.setWarningCoverages();553  ReaderOptions.setWarningLines();554  ReaderOptions.setWarningLocations();555  ReaderOptions.setWarningRanges();556  ReaderOptions.resolveDependencies();557  options().setOptions(&ReaderOptions);558 559  Reader.createElements();560  Reader.addElements();561  Reader.initElements();562  Reader.checkWarnings();563}564 565} // namespace566