Function scanAllUnwindInfo [src]
If .eh_frame_hdr is present, then only the header needs to be parsed. Otherwise, .eh_frame
and .debug_frame are scanned and a sorted list of FDEs is built for binary searching during
unwinding. Even if .eh_frame_hdr is used, we may find during unwinding that it's incomplete,
in which case we build the sorted list of FDEs at that point.
See also scanCieFdeInfo.
Prototype
pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void
Parameters
di: *Dwarf
allocator: Allocator
base_address: usize
Source
pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {
if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: {
var fbr: FixedBufferReader = .{ .buf = eh_frame_hdr, .endian = native_endian };
const version = try fbr.readByte();
if (version != 1) break :blk;
const eh_frame_ptr_enc = try fbr.readByte();
if (eh_frame_ptr_enc == EH.PE.omit) break :blk;
const fde_count_enc = try fbr.readByte();
if (fde_count_enc == EH.PE.omit) break :blk;
const table_enc = try fbr.readByte();
if (table_enc == EH.PE.omit) break :blk;
const eh_frame_ptr = cast(usize, try readEhPointer(&fbr, eh_frame_ptr_enc, @sizeOf(usize), .{
.pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
.follow_indirect = true,
}) orelse return bad()) orelse return bad();
const fde_count = cast(usize, try readEhPointer(&fbr, fde_count_enc, @sizeOf(usize), .{
.pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
.follow_indirect = true,
}) orelse return bad()) orelse return bad();
const entry_size = try ExceptionFrameHeader.entrySize(table_enc);
const entries_len = fde_count * entry_size;
if (entries_len > eh_frame_hdr.len - fbr.pos) return bad();
di.eh_frame_hdr = .{
.eh_frame_ptr = eh_frame_ptr,
.table_enc = table_enc,
.fde_count = fde_count,
.entries = eh_frame_hdr[fbr.pos..][0..entries_len],
};
// No need to scan .eh_frame, we have a binary search table already
return;
}
try di.scanCieFdeInfo(allocator, base_address);
}