LCOV - code coverage report
Current view: top level - lib/DebugInfo - DWARFUnit.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 185 190 97.4 %
Date: 2015-01-30 11:55:44 Functions: 21 22 95.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- DWARFUnit.cpp -----------------------------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/DebugInfo/DWARFUnit.h"
      11             : #include "llvm/DebugInfo/DWARFContext.h"
      12             : #include "llvm/DebugInfo/DWARFFormValue.h"
      13             : #include "llvm/Support/Dwarf.h"
      14             : #include "llvm/Support/Path.h"
      15             : #include <cstdio>
      16             : 
      17             : using namespace llvm;
      18             : using namespace dwarf;
      19             : 
      20        1024 : void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
      21        1024 :   parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(),
      22        2048 :             C.getStringSection(), StringRef(), C.getAddrSection(),
      23        4096 :             C.isLittleEndian());
      24        1024 : }
      25             : 
      26         114 : void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
      27             :                                     const DWARFSection &DWOSection) {
      28         114 :   parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(),
      29         228 :             C.getStringDWOSection(), C.getStringOffsetDWOSection(),
      30         456 :             C.getAddrSection(), C.isLittleEndian());
      31         114 : }
      32             : 
      33       13315 : DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
      34             :                      const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
      35             :                      StringRef SOS, StringRef AOS, bool LE,
      36             :                      const DWARFUnitSectionBase &UnitSection)
      37             :     : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
      38             :       StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
      39       26630 :       isLittleEndian(LE), UnitSection(UnitSection) {
      40       13315 :   clear();
      41       13315 : }
      42             : 
      43       26630 : DWARFUnit::~DWARFUnit() {
      44       13315 : }
      45             : 
      46          24 : bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
      47             :                                                 uint64_t &Result) const {
      48          24 :   uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
      49          24 :   if (AddrOffsetSection.size() < Offset + AddrSize)
      50             :     return false;
      51          24 :   DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
      52          24 :   Result = DA.getAddress(&Offset);
      53          24 :   return true;
      54             : }
      55             : 
      56         151 : bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
      57             :                                                   uint32_t &Result) const {
      58             :   // FIXME: string offset section entries are 8-byte for DWARF64.
      59         151 :   const uint32_t ItemSize = 4;
      60         151 :   uint32_t Offset = Index * ItemSize;
      61         151 :   if (StringOffsetSection.size() < Offset + ItemSize)
      62             :     return false;
      63         151 :   DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
      64         151 :   Result = DA.getU32(&Offset);
      65         151 :   return true;
      66             : }
      67             : 
      68       13315 : bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
      69       13315 :   Length = debug_info.getU32(offset_ptr);
      70       13315 :   Version = debug_info.getU16(offset_ptr);
      71       13315 :   uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
      72       13315 :   AddrSize = debug_info.getU8(offset_ptr);
      73             : 
      74       39945 :   bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
      75       26630 :   bool VersionOK = DWARFContext::isSupportedVersion(Version);
      76       13315 :   bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;
      77             : 
      78       13315 :   if (!LengthOK || !VersionOK || !AddrSizeOK)
      79             :     return false;
      80             : 
      81       13315 :   Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
      82       13315 :   if (Abbrevs == nullptr)
      83             :     return false;
      84             : 
      85       13315 :   return true;
      86             : }
      87             : 
      88       13315 : bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
      89       13315 :   clear();
      90             : 
      91       13315 :   Offset = *offset_ptr;
      92             : 
      93       26630 :   if (debug_info.isValidOffset(*offset_ptr)) {
      94       13315 :     if (extractImpl(debug_info, offset_ptr))
      95             :       return true;
      96             : 
      97             :     // reset the offset to where we tried to parse from if anything went wrong
      98           0 :     *offset_ptr = Offset;
      99             :   }
     100             : 
     101             :   return false;
     102             : }
     103             : 
     104       11763 : bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
     105             :                                         DWARFDebugRangeList &RangeList) const {
     106             :   // Require that compile unit is extracted.
     107             :   assert(DieArray.size() > 0);
     108       11763 :   DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
     109       11763 :   uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
     110       11763 :   return RangeList.extract(RangesData, &ActualRangeListOffset);
     111             : }
     112             : 
     113       26630 : void DWARFUnit::clear() {
     114       26630 :   Offset = 0;
     115       26630 :   Length = 0;
     116       26630 :   Version = 0;
     117       26630 :   Abbrevs = nullptr;
     118       26630 :   AddrSize = 0;
     119       26630 :   BaseAddr = 0;
     120       26630 :   RangeSectionBase = 0;
     121       26630 :   AddrOffsetSectionBase = 0;
     122       26630 :   clearDIEs(false);
     123       26630 :   DWO.reset();
     124       26630 : }
     125             : 
     126        1392 : const char *DWARFUnit::getCompilationDir() {
     127        1392 :   extractDIEsIfNeeded(true);
     128        2784 :   if (DieArray.empty())
     129             :     return nullptr;
     130        1392 :   return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
     131             : }
     132             : 
     133           2 : uint64_t DWARFUnit::getDWOId() {
     134           2 :   extractDIEsIfNeeded(true);
     135           2 :   const uint64_t FailValue = -1ULL;
     136           4 :   if (DieArray.empty())
     137             :     return FailValue;
     138           2 :   return DieArray[0]
     139           2 :       .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
     140             : }
     141             : 
     142       10885 : void DWARFUnit::setDIERelations() {
     143       21770 :   if (DieArray.size() <= 1)
     144       10487 :     return;
     145             : 
     146             :   std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;
     147         398 :   DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
     148    10067565 :   for (auto &DIE : DieArray) {
     149    10065973 :     if (SiblingChain) {
     150             :       SiblingChain->setSibling(&DIE);
     151             :     }
     152    10065973 :     if (const DWARFAbbreviationDeclaration *AbbrDecl =
     153    10065973 :             DIE.getAbbreviationDeclarationPtr()) {
     154             :       // Normal DIE.
     155     7827081 :       if (AbbrDecl->hasChildren()) {
     156     4477784 :         ParentChain.push_back(&DIE);
     157     2238892 :         SiblingChain = nullptr;
     158             :       } else {
     159             :         SiblingChain = &DIE;
     160             :       }
     161             :     } else {
     162             :       // NULL entry terminates the sibling chain.
     163     2238892 :       SiblingChain = ParentChain.back();
     164     2238892 :       ParentChain.pop_back();
     165             :     }
     166             :   }
     167             :   assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]);
     168             :   assert(ParentChain.empty());
     169             : }
     170             : 
     171       10885 : void DWARFUnit::extractDIEsToVector(
     172             :     bool AppendCUDie, bool AppendNonCUDies,
     173             :     std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
     174       10885 :   if (!AppendCUDie && !AppendNonCUDies)
     175           0 :     return;
     176             : 
     177             :   // Set the offset to that of the first DIE and calculate the start of the
     178             :   // next compilation unit header.
     179       10885 :   uint32_t DIEOffset = Offset + getHeaderSize();
     180       21770 :   uint32_t NextCUOffset = getNextUnitOffset();
     181             :   DWARFDebugInfoEntryMinimal DIE;
     182       10885 :   uint32_t Depth = 0;
     183       10885 :   bool IsCUDie = true;
     184             : 
     185    10087366 :   while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) {
     186    10076460 :     if (IsCUDie) {
     187       10885 :       if (AppendCUDie)
     188       10796 :         Dies.push_back(DIE);
     189       10885 :       if (!AppendNonCUDies)
     190             :         break;
     191             :       // The average bytes per DIE entry has been seen to be
     192             :       // around 14-20 so let's pre-reserve the needed memory for
     193             :       // our DIE entries accordingly.
     194        1257 :       Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
     195         419 :       IsCUDie = false;
     196             :     } else {
     197    10065575 :       Dies.push_back(DIE);
     198             :     }
     199             : 
     200    10065994 :     if (const DWARFAbbreviationDeclaration *AbbrDecl =
     201    10065994 :             DIE.getAbbreviationDeclarationPtr()) {
     202             :       // Normal DIE
     203     7827102 :       if (AbbrDecl->hasChildren())
     204     2238892 :         ++Depth;
     205             :     } else {
     206             :       // NULL DIE.
     207     2238892 :       if (Depth > 0)
     208     2238892 :         --Depth;
     209     2238892 :       if (Depth == 0)
     210             :         break;  // We are done with this compile unit!
     211             :     }
     212             :   }
     213             : 
     214             :   // Give a little bit of info if we encounter corrupt DWARF (our offset
     215             :   // should always terminate at or before the start of the next compilation
     216             :   // unit header).
     217       10885 :   if (DIEOffset > NextCUOffset)
     218             :     fprintf(stderr, "warning: DWARF compile unit extends beyond its "
     219           0 :                     "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset);
     220             : }
     221             : 
     222       13874 : size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
     223       38214 :   if ((CUDieOnly && DieArray.size() > 0) ||
     224       10978 :       DieArray.size() > 1)
     225             :     return 0; // Already parsed.
     226             : 
     227       21770 :   bool HasCUDie = DieArray.size() > 0;
     228       10885 :   extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
     229             : 
     230       21770 :   if (DieArray.empty())
     231             :     return 0;
     232             : 
     233             :   // If CU DIE was just parsed, copy several attribute values from it.
     234       10885 :   if (!HasCUDie) {
     235             :     uint64_t BaseAddr =
     236       10796 :         DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
     237       10796 :     if (BaseAddr == -1ULL)
     238         107 :       BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
     239       10796 :     setBaseAddress(BaseAddr);
     240       10796 :     AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
     241       10796 :         this, DW_AT_GNU_addr_base, 0);
     242       10796 :     RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
     243       10796 :         this, DW_AT_ranges_base, 0);
     244             :     // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
     245             :     // skeleton CU DIE, so that DWARF users not aware of it are not broken.
     246             :   }
     247             : 
     248       10885 :   setDIERelations();
     249       21770 :   return DieArray.size();
     250             : }
     251             : 
     252           3 : DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath)
     253           9 :     : DWOFile(), DWOContext(), DWOU(nullptr) {
     254           3 :   auto Obj = object::ObjectFile::createObjectFile(DWOPath);
     255           3 :   if (!Obj)
     256           3 :     return;
     257           1 :   DWOFile = std::move(Obj.get());
     258             :   DWOContext.reset(
     259           3 :       cast<DWARFContext>(DIContext::getDWARFContext(*DWOFile.getBinary())));
     260           3 :   if (DWOContext->getNumDWOCompileUnits() > 0)
     261           3 :     DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
     262             : }
     263             : 
     264          46 : bool DWARFUnit::parseDWO() {
     265          92 :   if (DWO.get())
     266             :     return false;
     267          45 :   extractDIEsIfNeeded(true);
     268          90 :   if (DieArray.empty())
     269             :     return false;
     270             :   const char *DWOFileName =
     271          45 :       DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr);
     272          45 :   if (!DWOFileName)
     273             :     return false;
     274             :   const char *CompilationDir =
     275           3 :       DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
     276             :   SmallString<16> AbsolutePath;
     277           6 :   if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
     278           3 :     sys::path::append(AbsolutePath, CompilationDir);
     279             :   }
     280           3 :   sys::path::append(AbsolutePath, DWOFileName);
     281           6 :   DWO = llvm::make_unique<DWOHolder>(AbsolutePath);
     282           6 :   DWARFUnit *DWOCU = DWO->getUnit();
     283             :   // Verify that compile unit in .dwo file is valid.
     284           3 :   if (!DWOCU || DWOCU->getDWOId() != getDWOId()) {
     285           2 :     DWO.reset();
     286             :     return false;
     287             :   }
     288             :   // Share .debug_addr and .debug_ranges section with compile unit in .dwo
     289           1 :   DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
     290           1 :   uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0);
     291             :   DWOCU->setRangesSection(RangeSection, DWORangesBase);
     292           1 :   return true;
     293             : }
     294             : 
     295       26672 : void DWARFUnit::clearDIEs(bool KeepCUDie) {
     296       53344 :   if (DieArray.size() > (unsigned)KeepCUDie) {
     297             :     // std::vectors never get any smaller when resized to a smaller size,
     298             :     // or when clear() or erase() are called, the size will report that it
     299             :     // is smaller, but the memory allocated remains intact (call capacity()
     300             :     // to see this). So we need to create a temporary vector and swap the
     301             :     // contents which will cause just the internal pointers to be swapped
     302             :     // so that when temporary vector goes out of scope, it will destroy the
     303             :     // contents.
     304             :     std::vector<DWARFDebugInfoEntryMinimal> TmpArray;
     305          42 :     DieArray.swap(TmpArray);
     306             :     // Save at least the compile unit DIE
     307          42 :     if (KeepCUDie)
     308          42 :       DieArray.push_back(TmpArray.front());
     309             :   }
     310       26672 : }
     311             : 
     312       10454 : void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
     313             :   // First, check if CU DIE describes address ranges for the unit.
     314       10454 :   const auto &CUDIERanges = getCompileUnitDIE()->getAddressRanges(this);
     315       10454 :   if (!CUDIERanges.empty()) {
     316       41648 :     CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
     317       10454 :     return;
     318             :   }
     319             : 
     320             :   // This function is usually called if there in no .debug_aranges section
     321             :   // in order to produce a compile unit level set of address ranges that
     322             :   // is accurate. If the DIEs weren't parsed, then we don't want all dies for
     323             :   // all compile units to stay loaded when they weren't needed. So we can end
     324             :   // up parsing the DWARF and then throwing them all away to keep memory usage
     325             :   // down.
     326          42 :   const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
     327          42 :   DieArray[0].collectChildrenAddressRanges(this, CURanges);
     328             : 
     329             :   // Collect address ranges from DIEs in .dwo if necessary.
     330          42 :   bool DWOCreated = parseDWO();
     331          84 :   if (DWO.get())
     332           0 :     DWO->getUnit()->collectAddressRanges(CURanges);
     333          42 :   if (DWOCreated)
     334           0 :     DWO.reset();
     335             : 
     336             :   // Keep memory down by clearing DIEs if this generate function
     337             :   // caused them to be parsed.
     338          42 :   if (ClearDIEs)
     339          42 :     clearDIEs(true);
     340             : }
     341             : 
     342             : const DWARFDebugInfoEntryMinimal *
     343         221 : DWARFUnit::getSubprogramForAddress(uint64_t Address) {
     344         221 :   extractDIEsIfNeeded(false);
     345    16357496 :   for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) {
     346    19432880 :     if (DIE.isSubprogramDIE() &&
     347     3076051 :         DIE.addressRangeContainsAddress(this, Address)) {
     348         217 :       return &DIE;
     349             :     }
     350             :   }
     351             :   return nullptr;
     352             : }
     353             : 
     354             : DWARFDebugInfoEntryInlinedChain
     355         219 : DWARFUnit::getInlinedChainForAddress(uint64_t Address) {
     356             :   // First, find a subprogram that contains the given address (the root
     357             :   // of inlined chain).
     358         219 :   const DWARFUnit *ChainCU = nullptr;
     359             :   const DWARFDebugInfoEntryMinimal *SubprogramDIE =
     360         219 :       getSubprogramForAddress(Address);
     361         219 :   if (SubprogramDIE) {
     362             :     ChainCU = this;
     363             :   } else {
     364             :     // Try to look for subprogram DIEs in the DWO file.
     365           4 :     parseDWO();
     366           8 :     if (DWO.get()) {
     367           4 :       SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
     368           2 :       if (SubprogramDIE)
     369           4 :         ChainCU = DWO->getUnit();
     370             :     }
     371             :   }
     372             : 
     373             :   // Get inlined chain rooted at this subprogram DIE.
     374         219 :   if (!SubprogramDIE)
     375             :     return DWARFDebugInfoEntryInlinedChain();
     376         217 :   return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
     377             : }

Generated by: LCOV version 1.11