pub fn next(self: *@This()) !?PcRange {
const endian = self.endian;
const addr_size_bytes = self.compile_unit.addr_size_bytes;
switch (self.section_type) {
.debug_rnglists => {
const kind = try self.fr.takeByte();
switch (kind) {
RLE.end_of_list => return null,
RLE.base_addressx => {
const index = try self.fr.takeLeb128(u64);
self.base_address = try self.di.readDebugAddr(endian, self.compile_unit, index);
return try self.next();
},
RLE.startx_endx => {
const start_index = try self.fr.takeLeb128(u64);
const start_addr = try self.di.readDebugAddr(endian, self.compile_unit, start_index);
const end_index = try self.fr.takeLeb128(u64);
const end_addr = try self.di.readDebugAddr(endian, self.compile_unit, end_index);
return .{
.start = start_addr,
.end = end_addr,
};
},
RLE.startx_length => {
const start_index = try self.fr.takeLeb128(u64);
const start_addr = try self.di.readDebugAddr(endian, self.compile_unit, start_index);
const len = try self.fr.takeLeb128(u64);
const end_addr = start_addr + len;
return .{
.start = start_addr,
.end = end_addr,
};
},
RLE.offset_pair => {
const start_addr = try self.fr.takeLeb128(u64);
const end_addr = try self.fr.takeLeb128(u64);
// This is the only kind that uses the base address
return .{
.start = self.base_address + start_addr,
.end = self.base_address + end_addr,
};
},
RLE.base_address => {
self.base_address = try readAddress(&self.fr, endian, addr_size_bytes);
return try self.next();
},
RLE.start_end => {
const start_addr = try readAddress(&self.fr, endian, addr_size_bytes);
const end_addr = try readAddress(&self.fr, endian, addr_size_bytes);
return .{
.start = start_addr,
.end = end_addr,
};
},
RLE.start_length => {
const start_addr = try readAddress(&self.fr, endian, addr_size_bytes);
const len = try self.fr.takeLeb128(u64);
const end_addr = start_addr + len;
return .{
.start = start_addr,
.end = end_addr,
};
},
else => return bad(),
}
},
.debug_ranges => {
const start_addr = try readAddress(&self.fr, endian, addr_size_bytes);
const end_addr = try readAddress(&self.fr, endian, addr_size_bytes);
if (start_addr == 0 and end_addr == 0) return null;
// The entry with start_addr = max_representable_address selects a new value for the base address
const max_representable_address = ~@as(u64, 0) >> @intCast(64 - addr_size_bytes);
if (start_addr == max_representable_address) {
self.base_address = end_addr;
return try self.next();
}
return .{
.start = self.base_address + start_addr,
.end = self.base_address + end_addr,
};
},
else => unreachable,
}
}