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