diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp')
| -rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp | 129 | 
1 files changed, 129 insertions, 0 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp new file mode 100644 index 000000000000..27a02c4c50d0 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -0,0 +1,129 @@ +//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <set> +using namespace llvm; + +void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { +  if (!DebugArangesData.isValidOffset(0)) +    return; +  uint32_t Offset = 0; +  DWARFDebugArangeSet Set; + +  while (Set.extract(DebugArangesData, &Offset)) { +    uint32_t CUOffset = Set.getCompileUnitDIEOffset(); +    for (const auto &Desc : Set.descriptors()) { +      uint64_t LowPC = Desc.Address; +      uint64_t HighPC = Desc.getEndAddress(); +      appendRange(CUOffset, LowPC, HighPC); +    } +    ParsedCUOffsets.insert(CUOffset); +  } +} + +void DWARFDebugAranges::generate(DWARFContext *CTX) { +  clear(); +  if (!CTX) +    return; + +  // Extract aranges from .debug_aranges section. +  DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0); +  extract(ArangesData); + +  // Generate aranges from DIEs: even if .debug_aranges section is present, +  // it may describe only a small subset of compilation units, so we need to +  // manually build aranges for the rest of them. +  for (const auto &CU : CTX->compile_units()) { +    uint32_t CUOffset = CU->getOffset(); +    if (ParsedCUOffsets.insert(CUOffset).second) { +      DWARFAddressRangesVector CURanges; +      CU->collectAddressRanges(CURanges); +      for (const auto &R : CURanges) { +        appendRange(CUOffset, R.first, R.second); +      } +    } +  } + +  construct(); +} + +void DWARFDebugAranges::clear() { +  Endpoints.clear(); +  Aranges.clear(); +  ParsedCUOffsets.clear(); +} + +void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, +                                    uint64_t HighPC) { +  if (LowPC >= HighPC) +    return; +  Endpoints.emplace_back(LowPC, CUOffset, true); +  Endpoints.emplace_back(HighPC, CUOffset, false); +} + +void DWARFDebugAranges::construct() { +  std::multiset<uint32_t> ValidCUs;  // Maintain the set of CUs describing +                                     // a current address range. +  std::sort(Endpoints.begin(), Endpoints.end()); +  uint64_t PrevAddress = -1ULL; +  for (const auto &E : Endpoints) { +    if (PrevAddress < E.Address && ValidCUs.size() > 0) { +      // If the address range between two endpoints is described by some +      // CU, first try to extend the last range in Aranges. If we can't +      // do it, start a new range. +      if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress && +          ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) { +        Aranges.back().setHighPC(E.Address); +      } else { +        Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin()); +      } +    } +    // Update the set of valid CUs. +    if (E.IsRangeStart) { +      ValidCUs.insert(E.CUOffset); +    } else { +      auto CUPos = ValidCUs.find(E.CUOffset); +      assert(CUPos != ValidCUs.end()); +      ValidCUs.erase(CUPos); +    } +    PrevAddress = E.Address; +  } +  assert(ValidCUs.empty()); + +  // Endpoints are not needed now. +  std::vector<RangeEndpoint> EmptyEndpoints; +  EmptyEndpoints.swap(Endpoints); +} + +uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const { +  if (!Aranges.empty()) { +    Range range(Address); +    RangeCollIterator begin = Aranges.begin(); +    RangeCollIterator end = Aranges.end(); +    RangeCollIterator pos = +        std::lower_bound(begin, end, range); + +    if (pos != end && pos->containsAddress(Address)) { +      return pos->CUOffset; +    } else if (pos != begin) { +      --pos; +      if (pos->containsAddress(Address)) +        return pos->CUOffset; +    } +  } +  return -1U; +}  | 
