LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugAranges.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 45 46 97.8 %
Date: 2018-10-20 13:21:21 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         218 : void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
      24         218 :   if (!DebugArangesData.isValidOffset(0))
      25         170 :     return;
      26          48 :   uint32_t Offset = 0;
      27             :   DWARFDebugArangeSet Set;
      28             : 
      29        1012 :   while (Set.extract(DebugArangesData, &Offset)) {
      30         964 :     uint32_t CUOffset = Set.getCompileUnitDIEOffset();
      31       66466 :     for (const auto &Desc : Set.descriptors()) {
      32       65502 :       uint64_t LowPC = Desc.Address;
      33       65502 :       uint64_t HighPC = Desc.getEndAddress();
      34       65502 :       appendRange(CUOffset, LowPC, HighPC);
      35             :     }
      36             :     ParsedCUOffsets.insert(CUOffset);
      37             :   }
      38             : }
      39             : 
      40         218 : void DWARFDebugAranges::generate(DWARFContext *CTX) {
      41         218 :   clear();
      42         218 :   if (!CTX)
      43           0 :     return;
      44             : 
      45             :   // Extract aranges from .debug_aranges section.
      46         218 :   DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(),
      47         218 :                             CTX->isLittleEndian(), 0);
      48         218 :   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        3500 :   for (const auto &CU : CTX->compile_units()) {
      54        3282 :     uint32_t CUOffset = CU->getOffset();
      55        3282 :     if (ParsedCUOffsets.insert(CUOffset).second) {
      56             :       DWARFAddressRangesVector CURanges;
      57        2318 :       CU->collectAddressRanges(CURanges);
      58        9371 :       for (const auto &R : CURanges)
      59        7053 :         appendRange(CUOffset, R.LowPC, R.HighPC);
      60             :     }
      61             :   }
      62             : 
      63         218 :   construct();
      64             : }
      65             : 
      66         218 : void DWARFDebugAranges::clear() {
      67             :   Endpoints.clear();
      68             :   Aranges.clear();
      69             :   ParsedCUOffsets.clear();
      70         218 : }
      71             : 
      72       72555 : void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
      73             :                                     uint64_t HighPC) {
      74       72555 :   if (LowPC >= HighPC)
      75             :     return;
      76       72529 :   Endpoints.emplace_back(LowPC, CUOffset, true);
      77       72529 :   Endpoints.emplace_back(HighPC, CUOffset, false);
      78             : }
      79             : 
      80         218 : void DWARFDebugAranges::construct() {
      81             :   std::multiset<uint32_t> ValidCUs;  // Maintain the set of CUs describing
      82             :                                      // a current address range.
      83             :   llvm::sort(Endpoints);
      84         218 :   uint64_t PrevAddress = -1ULL;
      85      145276 :   for (const auto &E : Endpoints) {
      86      145058 :     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      145304 :       if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
      91             :           ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
      92             :         Aranges.back().setHighPC(E.Address);
      93             :       } else {
      94      136364 :         Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
      95             :       }
      96             :     }
      97             :     // Update the set of valid CUs.
      98      145058 :     if (E.IsRangeStart) {
      99       72529 :       ValidCUs.insert(E.CUOffset);
     100             :     } else {
     101             :       auto CUPos = ValidCUs.find(E.CUOffset);
     102             :       assert(CUPos != ValidCUs.end());
     103             :       ValidCUs.erase(CUPos);
     104             :     }
     105      145058 :     PrevAddress = E.Address;
     106             :   }
     107             :   assert(ValidCUs.empty());
     108             : 
     109             :   // Endpoints are not needed now.
     110             :   Endpoints.clear();
     111             :   Endpoints.shrink_to_fit();
     112         218 : }
     113             : 
     114        1374 : uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
     115        1374 :   if (!Aranges.empty()) {
     116             :     Range range(Address);
     117             :     RangeCollIterator begin = Aranges.begin();
     118             :     RangeCollIterator end = Aranges.end();
     119             :     RangeCollIterator pos =
     120             :         std::lower_bound(begin, end, range);
     121             : 
     122        1263 :     if (pos != end && pos->containsAddress(Address)) {
     123          48 :       return pos->CUOffset;
     124        1215 :     } else if (pos != begin) {
     125             :       --pos;
     126             :       if (pos->containsAddress(Address))
     127         687 :         return pos->CUOffset;
     128             :     }
     129             :   }
     130             :   return -1U;
     131             : }

Generated by: LCOV version 1.13