Skip to content

Commit 1c489eb

Browse files
committed
wasm: clarify and test DWARF range repair
1 parent 0c439cc commit 1c489eb

5 files changed

Lines changed: 310 additions & 179 deletions

File tree

‎src/wasm/dwarf-ranges.h‎

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2026 WebAssembly Community Group participants
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef wasm_dwarf_ranges_h
18+
#define wasm_dwarf_ranges_h
19+
20+
#include <algorithm>
21+
#include <cassert>
22+
#include <cstddef>
23+
#include <cstdint>
24+
#include <initializer_list>
25+
#include <utility>
26+
#include <vector>
27+
28+
namespace wasm::Debug {
29+
30+
using DwarfRange = std::pair<uint64_t, uint64_t>;
31+
32+
// A set of nonempty, half-open DWARF address ranges. Call normalize before
33+
// querying containment or overlap; adding one set to another normalizes the
34+
// result automatically.
35+
class DwarfRanges {
36+
std::vector<DwarfRange> ranges;
37+
38+
void normalizeInPlace() {
39+
std::sort(ranges.begin(), ranges.end());
40+
size_t written = 0;
41+
for (auto range : ranges) {
42+
if (written && range.first <= ranges[written - 1].second) {
43+
ranges[written - 1].second =
44+
std::max(ranges[written - 1].second, range.second);
45+
} else {
46+
ranges[written++] = range;
47+
}
48+
}
49+
ranges.resize(written);
50+
}
51+
52+
public:
53+
DwarfRanges() = default;
54+
DwarfRanges(std::initializer_list<DwarfRange> ranges) : ranges(ranges) {}
55+
56+
bool empty() const { return ranges.empty(); }
57+
58+
const std::vector<DwarfRange>& get() const { return ranges; }
59+
60+
void add(uint64_t start, uint64_t end) {
61+
assert(start < end);
62+
ranges.emplace_back(start, end);
63+
}
64+
65+
// Returns whether normalization changed the range representation.
66+
bool normalize() {
67+
auto original = ranges;
68+
normalizeInPlace();
69+
return ranges != original;
70+
}
71+
72+
// Adds another set and returns whether the resulting union changed this set.
73+
bool add(const DwarfRanges& other) {
74+
if (other.empty()) {
75+
return false;
76+
}
77+
auto original = ranges;
78+
ranges.insert(ranges.end(), other.ranges.begin(), other.ranges.end());
79+
normalizeInPlace();
80+
return ranges != original;
81+
}
82+
83+
bool contains(const DwarfRanges& other) const {
84+
size_t index = 0;
85+
for (auto otherRange : other.ranges) {
86+
while (index < ranges.size() &&
87+
ranges[index].second <= otherRange.first) {
88+
++index;
89+
}
90+
if (index == ranges.size() || ranges[index].first > otherRange.first ||
91+
ranges[index].second < otherRange.second) {
92+
return false;
93+
}
94+
}
95+
return true;
96+
}
97+
98+
bool overlaps(const DwarfRanges& other) const {
99+
size_t left = 0, right = 0;
100+
while (left < ranges.size() && right < other.ranges.size()) {
101+
auto leftRange = ranges[left];
102+
auto rightRange = other.ranges[right];
103+
if (leftRange.first < rightRange.second &&
104+
rightRange.first < leftRange.second) {
105+
return true;
106+
}
107+
if (leftRange.second <= rightRange.first) {
108+
++left;
109+
} else {
110+
++right;
111+
}
112+
}
113+
return false;
114+
}
115+
};
116+
117+
} // namespace wasm::Debug
118+
119+
#endif // wasm_dwarf_ranges_h

0 commit comments

Comments
 (0)