1358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
2358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//
3358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//                     The LLVM Compiler Infrastructure
4358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//
5358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer// This file is distributed under the University of Illinois Open Source
6358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer// License. See LICENSE.TXT for details.
7358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//
8358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//===----------------------------------------------------------------------===//
9358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
10ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
11ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
12ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/DebugInfo/DWARF/DWARFContext.h"
13ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
14358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include "llvm/Support/Format.h"
15358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include "llvm/Support/raw_ostream.h"
16358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include <algorithm>
17358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include <cassert>
18c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include <set>
19358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramerusing namespace llvm;
20358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
21d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonovvoid DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
22d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonov  if (!DebugArangesData.isValidOffset(0))
23d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonov    return;
24041f7c8d65a653701cb9ed464911cd44b19ab47eAlexey Samsonov  uint32_t Offset = 0;
25041f7c8d65a653701cb9ed464911cd44b19ab47eAlexey Samsonov  DWARFDebugArangeSet Set;
26041f7c8d65a653701cb9ed464911cd44b19ab47eAlexey Samsonov
27041f7c8d65a653701cb9ed464911cd44b19ab47eAlexey Samsonov  while (Set.extract(DebugArangesData, &Offset)) {
28dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    uint32_t CUOffset = Set.getCompileUnitDIEOffset();
29dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (const auto &Desc : Set.descriptors()) {
3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      uint64_t LowPC = Desc.Address;
3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      uint64_t HighPC = Desc.getEndAddress();
32041f7c8d65a653701cb9ed464911cd44b19ab47eAlexey Samsonov      appendRange(CUOffset, LowPC, HighPC);
33041f7c8d65a653701cb9ed464911cd44b19ab47eAlexey Samsonov    }
34c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    ParsedCUOffsets.insert(CUOffset);
35358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  }
36358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
37358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
38d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonovvoid DWARFDebugAranges::generate(DWARFContext *CTX) {
393db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  clear();
403db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  if (!CTX)
413db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov    return;
423db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov
433db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  // Extract aranges from .debug_aranges section.
443db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
453db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  extract(ArangesData);
4610df80692cc1594fb06fc02cae6eba177123cfd9Benjamin Kramer
473db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  // Generate aranges from DIEs: even if .debug_aranges section is present,
483db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  // it may describe only a small subset of compilation units, so we need to
493db24f52c5c0404529b627688106e0fd11a64400Alexey Samsonov  // manually build aranges for the rest of them.
5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const auto &CU : CTX->compile_units()) {
5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint32_t CUOffset = CU->getOffset();
52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (ParsedCUOffsets.insert(CUOffset).second) {
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      DWARFAddressRangesVector CURanges;
54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      CU->collectAddressRanges(CURanges);
55dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      for (const auto &R : CURanges) {
56dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        appendRange(CUOffset, R.first, R.second);
57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      }
58dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
59358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  }
60358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
61c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  construct();
62358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
63358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid DWARFDebugAranges::clear() {
65c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  Endpoints.clear();
66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Aranges.clear();
67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  ParsedCUOffsets.clear();
68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
70d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonovvoid DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
71d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonov                                    uint64_t HighPC) {
72c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (LowPC >= HighPC)
73358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    return;
74c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  Endpoints.emplace_back(LowPC, CUOffset, true);
75c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  Endpoints.emplace_back(HighPC, CUOffset, false);
76c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
77358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
78c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesvoid DWARFDebugAranges::construct() {
79c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::multiset<uint32_t> ValidCUs;  // Maintain the set of CUs describing
80c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                     // a current address range.
81c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::sort(Endpoints.begin(), Endpoints.end());
82c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t PrevAddress = -1ULL;
83c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  for (const auto &E : Endpoints) {
84c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (PrevAddress < E.Address && ValidCUs.size() > 0) {
85c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // If the address range between two endpoints is described by some
86c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // CU, first try to extend the last range in Aranges. If we can't
87c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // do it, start a new range.
88c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
89c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
90c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        Aranges.back().setHighPC(E.Address);
91c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      } else {
92c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
93c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
94c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
95c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    // Update the set of valid CUs.
96c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (E.IsRangeStart) {
97c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      ValidCUs.insert(E.CUOffset);
98358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    } else {
99c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      auto CUPos = ValidCUs.find(E.CUOffset);
100c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      assert(CUPos != ValidCUs.end());
101c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      ValidCUs.erase(CUPos);
102358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    }
103c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    PrevAddress = E.Address;
104358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  }
105c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  assert(ValidCUs.empty());
106358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
107c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // Endpoints are not needed now.
108c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::vector<RangeEndpoint> EmptyEndpoints;
109c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  EmptyEndpoints.swap(Endpoints);
110358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
111358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
112d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonovuint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
113358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  if (!Aranges.empty()) {
114d1fc0f8d4ef32b4302338b8a3fd0d976e5bd8ae3Alexey Samsonov    Range range(Address);
115358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    RangeCollIterator begin = Aranges.begin();
116358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    RangeCollIterator end = Aranges.end();
11717f7d099e4a381a3876ce1e9412f0b0d76d71e8aAlexey Samsonov    RangeCollIterator pos =
11817f7d099e4a381a3876ce1e9412f0b0d76d71e8aAlexey Samsonov        std::lower_bound(begin, end, range);
119358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
12017f7d099e4a381a3876ce1e9412f0b0d76d71e8aAlexey Samsonov    if (pos != end && pos->containsAddress(Address)) {
12117f7d099e4a381a3876ce1e9412f0b0d76d71e8aAlexey Samsonov      return pos->CUOffset;
122358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    } else if (pos != begin) {
123358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer      --pos;
12417f7d099e4a381a3876ce1e9412f0b0d76d71e8aAlexey Samsonov      if (pos->containsAddress(Address))
12517f7d099e4a381a3876ce1e9412f0b0d76d71e8aAlexey Samsonov        return pos->CUOffset;
126358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    }
127358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  }
128358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  return -1U;
129358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
130