Given a program counter value, returns the offset of the corresponding FDE, or null if no
matching FDE was found. The returned offset can be passed to getFde to load the data
associated with the FDE.
Before calling this function, prepare must return successfully at least once, to ensure that
unwind.lookup is populated.
The return value may be a false positive. After loading the FDE with loadFde, the caller must
validate that pc is indeed in its range -- if it is not, then no FDE matches pc.
pub fn lookupPc(unwind: *const Unwind, pc: u64, addr_size_bytes: u8, endian: Endian) !?u64
pub fn lookupPc(unwind: *const Unwind, pc: u64, addr_size_bytes: u8, endian: Endian) !?u64 {
const sorted_fdes: []const SortedFdeEntry = switch (unwind.lookup.?) {
.eh_frame_hdr => |eh_frame_hdr| {
const fde_vaddr = try eh_frame_hdr.table.findEntry(
eh_frame_hdr.vaddr,
pc,
addr_size_bytes,
endian,
) orelse return null;
return std.math.sub(u64, fde_vaddr, unwind.frame_section.vaddr) catch bad(); // convert vaddr to offset
},
.sorted_fdes => |sorted_fdes| sorted_fdes,
};
if (sorted_fdes.len == 0) return null;
var start: usize = 0;
var len: usize = sorted_fdes.len;
while (len > 1) {
const half = len / 2;
if (pc < sorted_fdes[start + half].pc_begin) {
len = half;
} else {
start += half;
len -= half;
}
}
// If any FDE matches, it'll be the one at `start` (maybe false positive).
return sorted_fdes[start].fde_offset;
}