Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
35269 views
1
//===- DWARFDebugAranges.cpp ----------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
10
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
11
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
12
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
13
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
14
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
15
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
16
#include <algorithm>
17
#include <cassert>
18
#include <cstdint>
19
#include <set>
20
21
using namespace llvm;
22
23
void DWARFDebugAranges::extract(
24
DWARFDataExtractor DebugArangesData,
25
function_ref<void(Error)> RecoverableErrorHandler,
26
function_ref<void(Error)> WarningHandler) {
27
if (!DebugArangesData.isValidOffset(0))
28
return;
29
uint64_t Offset = 0;
30
DWARFDebugArangeSet Set;
31
32
while (DebugArangesData.isValidOffset(Offset)) {
33
if (Error E = Set.extract(DebugArangesData, &Offset, WarningHandler)) {
34
RecoverableErrorHandler(std::move(E));
35
return;
36
}
37
uint64_t CUOffset = Set.getCompileUnitDIEOffset();
38
for (const auto &Desc : Set.descriptors()) {
39
uint64_t LowPC = Desc.Address;
40
uint64_t HighPC = Desc.getEndAddress();
41
appendRange(CUOffset, LowPC, HighPC);
42
}
43
ParsedCUOffsets.insert(CUOffset);
44
}
45
}
46
47
void DWARFDebugAranges::generate(DWARFContext *CTX) {
48
clear();
49
if (!CTX)
50
return;
51
52
// Extract aranges from .debug_aranges section.
53
DWARFDataExtractor ArangesData(CTX->getDWARFObj().getArangesSection(),
54
CTX->isLittleEndian(), 0);
55
extract(ArangesData, CTX->getRecoverableErrorHandler(),
56
CTX->getWarningHandler());
57
58
// Generate aranges from DIEs: even if .debug_aranges section is present,
59
// it may describe only a small subset of compilation units, so we need to
60
// manually build aranges for the rest of them.
61
for (const auto &CU : CTX->compile_units()) {
62
uint64_t CUOffset = CU->getOffset();
63
if (ParsedCUOffsets.insert(CUOffset).second) {
64
Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges();
65
if (!CURanges)
66
CTX->getRecoverableErrorHandler()(CURanges.takeError());
67
else
68
for (const auto &R : *CURanges)
69
appendRange(CUOffset, R.LowPC, R.HighPC);
70
}
71
}
72
73
construct();
74
}
75
76
void DWARFDebugAranges::clear() {
77
Endpoints.clear();
78
Aranges.clear();
79
ParsedCUOffsets.clear();
80
}
81
82
void DWARFDebugAranges::appendRange(uint64_t CUOffset, uint64_t LowPC,
83
uint64_t HighPC) {
84
if (LowPC >= HighPC)
85
return;
86
Endpoints.emplace_back(LowPC, CUOffset, true);
87
Endpoints.emplace_back(HighPC, CUOffset, false);
88
}
89
90
void DWARFDebugAranges::construct() {
91
std::multiset<uint64_t> ValidCUs; // Maintain the set of CUs describing
92
// a current address range.
93
llvm::sort(Endpoints);
94
uint64_t PrevAddress = -1ULL;
95
for (const auto &E : Endpoints) {
96
if (PrevAddress < E.Address && !ValidCUs.empty()) {
97
// If the address range between two endpoints is described by some
98
// CU, first try to extend the last range in Aranges. If we can't
99
// do it, start a new range.
100
if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
101
ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
102
Aranges.back().setHighPC(E.Address);
103
} else {
104
Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
105
}
106
}
107
// Update the set of valid CUs.
108
if (E.IsRangeStart) {
109
ValidCUs.insert(E.CUOffset);
110
} else {
111
auto CUPos = ValidCUs.find(E.CUOffset);
112
assert(CUPos != ValidCUs.end());
113
ValidCUs.erase(CUPos);
114
}
115
PrevAddress = E.Address;
116
}
117
assert(ValidCUs.empty());
118
119
// Endpoints are not needed now.
120
Endpoints.clear();
121
Endpoints.shrink_to_fit();
122
}
123
124
uint64_t DWARFDebugAranges::findAddress(uint64_t Address) const {
125
RangeCollIterator It =
126
partition_point(Aranges, [=](Range R) { return R.HighPC() <= Address; });
127
if (It != Aranges.end() && It->LowPC <= Address)
128
return It->CUOffset;
129
return -1ULL;
130
}
131
132