LCOV - code coverage report
Current view: top level - lib/DebugInfo - DWARFDebugAranges.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 59 60 98.3 %
Date: 2015-01-30 11:55:44 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
       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/DWARFDebugAranges.h"
      11             : #include "llvm/DebugInfo/DWARFCompileUnit.h"
      12             : #include "llvm/DebugInfo/DWARFContext.h"
      13             : #include "llvm/DebugInfo/DWARFDebugArangeSet.h"
      14             : #include "llvm/Support/Format.h"
      15             : #include "llvm/Support/raw_ostream.h"
      16             : #include <algorithm>
      17             : #include <cassert>
      18             : #include <set>
      19             : using namespace llvm;
      20             : 
      21         139 : void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
      22         139 :   if (!DebugArangesData.isValidOffset(0))
      23          75 :     return;
      24          64 :   uint32_t Offset = 0;
      25             :   DWARFDebugArangeSet Set;
      26             : 
      27        2670 :   while (Set.extract(DebugArangesData, &Offset)) {
      28        2606 :     uint32_t CUOffset = Set.getCompileUnitDIEOffset();
      29      207900 :     for (const auto &Desc : Set.descriptors()) {
      30      202688 :       uint64_t LowPC = Desc.Address;
      31      202688 :       uint64_t HighPC = Desc.getEndAddress();
      32      202688 :       appendRange(CUOffset, LowPC, HighPC);
      33             :     }
      34        2606 :     ParsedCUOffsets.insert(CUOffset);
      35             :   }
      36             : }
      37             : 
      38         139 : void DWARFDebugAranges::generate(DWARFContext *CTX) {
      39         139 :   clear();
      40         139 :   if (!CTX)
      41           0 :     return;
      42             : 
      43             :   // Extract aranges from .debug_aranges section.
      44         139 :   DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
      45         139 :   extract(ArangesData);
      46             : 
      47             :   // Generate aranges from DIEs: even if .debug_aranges section is present,
      48             :   // it may describe only a small subset of compilation units, so we need to
      49             :   // manually build aranges for the rest of them.
      50       13199 :   for (const auto &CU : CTX->compile_units()) {
      51       13060 :     uint32_t CUOffset = CU->getOffset();
      52       13060 :     if (ParsedCUOffsets.insert(CUOffset).second) {
      53             :       DWARFAddressRangesVector CURanges;
      54       10454 :       CU->collectAddressRanges(CURanges);
      55      538265 :       for (const auto &R : CURanges) {
      56      496449 :         appendRange(CUOffset, R.first, R.second);
      57             :       }
      58             :     }
      59             :   }
      60             : 
      61         139 :   construct();
      62             : }
      63             : 
      64         139 : void DWARFDebugAranges::clear() {
      65         139 :   Endpoints.clear();
      66         139 :   Aranges.clear();
      67         139 :   ParsedCUOffsets.clear();
      68         139 : }
      69             : 
      70      699137 : void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
      71             :                                     uint64_t HighPC) {
      72      699137 :   if (LowPC >= HighPC)
      73      699137 :     return;
      74      699137 :   Endpoints.emplace_back(LowPC, CUOffset, true);
      75      699137 :   Endpoints.emplace_back(HighPC, CUOffset, false);
      76             : }
      77             : 
      78         139 : void DWARFDebugAranges::construct() {
      79             :   std::multiset<uint32_t> ValidCUs;  // Maintain the set of CUs describing
      80             :                                      // a current address range.
      81         278 :   std::sort(Endpoints.begin(), Endpoints.end());
      82         139 :   uint64_t PrevAddress = -1ULL;
      83     1398830 :   for (const auto &E : Endpoints) {
      84     2439162 :     if (PrevAddress < E.Address && ValidCUs.size() > 0) {
      85             :       // If the address range between two endpoints is described by some
      86             :       // CU, first try to extend the last range in Aranges. If we can't
      87             :       // do it, start a new range.
      88     1679518 :       if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
      89       94518 :           ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
      90       93356 :         Aranges.back().setHighPC(E.Address);
      91             :       } else {
      92      994868 :         Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
      93             :       }
      94             :     }
      95             :     // Update the set of valid CUs.
      96     1398274 :     if (E.IsRangeStart) {
      97      699137 :       ValidCUs.insert(E.CUOffset);
      98             :     } else {
      99     1398274 :       auto CUPos = ValidCUs.find(E.CUOffset);
     100             :       assert(CUPos != ValidCUs.end());
     101      699137 :       ValidCUs.erase(CUPos);
     102             :     }
     103     1398274 :     PrevAddress = E.Address;
     104             :   }
     105             :   assert(ValidCUs.empty());
     106             : 
     107             :   // Endpoints are not needed now.
     108             :   std::vector<RangeEndpoint> EmptyEndpoints;
     109         139 :   EmptyEndpoints.swap(Endpoints);
     110         139 : }
     111             : 
     112         376 : uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
     113         752 :   if (!Aranges.empty()) {
     114             :     Range range(Address);
     115         546 :     RangeCollIterator begin = Aranges.begin();
     116         546 :     RangeCollIterator end = Aranges.end();
     117             :     RangeCollIterator pos =
     118         273 :         std::lower_bound(begin, end, range);
     119             : 
     120         531 :     if (pos != end && pos->containsAddress(Address)) {
     121          12 :       return pos->CUOffset;
     122         261 :     } else if (pos != begin) {
     123             :       --pos;
     124         518 :       if (pos->containsAddress(Address))
     125         213 :         return pos->CUOffset;
     126             :     }
     127             :   }
     128             :   return -1U;
     129             : }

Generated by: LCOV version 1.11