LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugAranges.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 65 66 98.5 %
Date: 2017-09-14 15:23:50 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFDebugAranges.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/DWARF/DWARFDebugAranges.h"
      11             : #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
      12             : #include "llvm/DebugInfo/DWARF/DWARFContext.h"
      13             : #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
      14             : #include "llvm/Support/DataExtractor.h"
      15             : #include <algorithm>
      16             : #include <cassert>
      17             : #include <cstdint>
      18             : #include <set>
      19             : #include <vector>
      20             : 
      21             : using namespace llvm;
      22             : 
      23         173 : void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
      24         173 :   if (!DebugArangesData.isValidOffset(0))
      25         132 :     return;
      26          41 :   uint32_t Offset = 0;
      27          41 :   DWARFDebugArangeSet Set;
      28             : 
      29        1475 :   while (Set.extract(DebugArangesData, &Offset)) {
      30         717 :     uint32_t CUOffset = Set.getCompileUnitDIEOffset();
      31       24072 :     for (const auto &Desc : Set.descriptors()) {
      32       22638 :       uint64_t LowPC = Desc.Address;
      33       22638 :       uint64_t HighPC = Desc.getEndAddress();
      34       22638 :       appendRange(CUOffset, LowPC, HighPC);
      35             :     }
      36        1434 :     ParsedCUOffsets.insert(CUOffset);
      37             :   }
      38             : }
      39             : 
      40         173 : void DWARFDebugAranges::generate(DWARFContext *CTX) {
      41         173 :   clear();
      42         173 :   if (!CTX)
      43           0 :     return;
      44             : 
      45             :   // Extract aranges from .debug_aranges section.
      46         173 :   DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(),
      47         519 :                             CTX->isLittleEndian(), 0);
      48         173 :   extract(ArangesData);
      49             : 
      50             :   // Generate aranges from DIEs: even if .debug_aranges section is present,
      51             :   // it may describe only a small subset of compilation units, so we need to
      52             :   // manually build aranges for the rest of them.
      53       26821 :   for (const auto &CU : CTX->compile_units()) {
      54       26648 :     uint32_t CUOffset = CU->getOffset();
      55       53296 :     if (ParsedCUOffsets.insert(CUOffset).second) {
      56       51862 :       DWARFAddressRangesVector CURanges;
      57       25931 :       CU->collectAddressRanges(CURanges);
      58     1659191 :       for (const auto &R : CURanges)
      59     1555467 :         appendRange(CUOffset, R.LowPC, R.HighPC);
      60             :     }
      61             :   }
      62             : 
      63         173 :   construct();
      64             : }
      65             : 
      66         173 : void DWARFDebugAranges::clear() {
      67         346 :   Endpoints.clear();
      68         346 :   Aranges.clear();
      69         346 :   ParsedCUOffsets.clear();
      70         173 : }
      71             : 
      72     1578105 : void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
      73             :                                     uint64_t HighPC) {
      74     1578105 :   if (LowPC >= HighPC)
      75             :     return;
      76     1578079 :   Endpoints.emplace_back(LowPC, CUOffset, true);
      77     1578079 :   Endpoints.emplace_back(HighPC, CUOffset, false);
      78             : }
      79             : 
      80         173 : void DWARFDebugAranges::construct() {
      81         346 :   std::multiset<uint32_t> ValidCUs;  // Maintain the set of CUs describing
      82             :                                      // a current address range.
      83         519 :   std::sort(Endpoints.begin(), Endpoints.end());
      84         173 :   uint64_t PrevAddress = -1ULL;
      85     3156850 :   for (const auto &E : Endpoints) {
      86     5263088 :     if (PrevAddress < E.Address && !ValidCUs.empty()) {
      87             :       // If the address range between two endpoints is described by some
      88             :       // CU, first try to extend the last range in Aranges. If we can't
      89             :       // do it, start a new range.
      90     4514865 :       if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
      91      301005 :           ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
      92      198534 :         Aranges.back().setHighPC(E.Address);
      93             :       } else {
      94     3013293 :         Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
      95             :       }
      96             :     }
      97             :     // Update the set of valid CUs.
      98     3156158 :     if (E.IsRangeStart) {
      99     1578079 :       ValidCUs.insert(E.CUOffset);
     100             :     } else {
     101     3156158 :       auto CUPos = ValidCUs.find(E.CUOffset);
     102             :       assert(CUPos != ValidCUs.end());
     103     1578079 :       ValidCUs.erase(CUPos);
     104             :     }
     105     3156158 :     PrevAddress = E.Address;
     106             :   }
     107             :   assert(ValidCUs.empty());
     108             : 
     109             :   // Endpoints are not needed now.
     110         346 :   Endpoints.clear();
     111         346 :   Endpoints.shrink_to_fit();
     112         173 : }
     113             : 
     114         992 : uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
     115        1984 :   if (!Aranges.empty()) {
     116         935 :     Range range(Address);
     117        1870 :     RangeCollIterator begin = Aranges.begin();
     118        1870 :     RangeCollIterator end = Aranges.end();
     119             :     RangeCollIterator pos =
     120         935 :         std::lower_bound(begin, end, range);
     121             : 
     122         975 :     if (pos != end && pos->containsAddress(Address)) {
     123         958 :       return pos->CUOffset;
     124         895 :     } else if (pos != begin) {
     125         891 :       --pos;
     126        1769 :       if (pos->containsAddress(Address))
     127         878 :         return pos->CUOffset;
     128             :     }
     129             :   }
     130             :   return -1U;
     131             : }

Generated by: LCOV version 1.13