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 : }
|