diff options
| author | kcbanner <kcbanner@gmail.com> | 2023-07-17 10:22:01 -0400 |
|---|---|---|
| committer | kcbanner <kcbanner@gmail.com> | 2023-07-20 22:58:16 -0400 |
| commit | 97bda56306622784b2f2e4f036d817bbe5f2025e (patch) | |
| tree | ecec2a45ed278bf105155049695526d9d32b4006 /lib/std/macho.zig | |
| parent | 774dc2fdb75dc7f6b7e0bd2cfe947fffb9829ba1 (diff) | |
| download | zig-97bda56306622784b2f2e4f036d817bbe5f2025e.tar.gz zig-97bda56306622784b2f2e4f036d817bbe5f2025e.zip | |
macho: don't scan all eh_frame entries, instead follow the offset from the __unwind_info directly
Diffstat (limited to 'lib/std/macho.zig')
| -rw-r--r-- | lib/std/macho.zig | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/lib/std/macho.zig b/lib/std/macho.zig index dbf49b5f3d..3c18e1f23c 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -2142,7 +2142,7 @@ fn dwarfRegNumber(unwind_reg_number: u3) !u8 { const dwarf = std.dwarf; const abi = dwarf.abi; -pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, module_base_address: usize) !usize { +pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, eh_frame: ?[]const u8, module_base_address: usize) !usize { const header = mem.bytesAsValue( unwind_info_section_header, unwind_info[0..@sizeOf(unwind_info_section_header)], @@ -2396,7 +2396,9 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul break :blk new_ip; }, - .DWARF => return error.RequiresDWARFUnwind, + .DWARF => { + return unwindFrameDwarf(context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf)); + }, }, .aarch64 => switch (encoding.mode.arm64) { .OLD => return error.UnimplementedUnwindEncoding, @@ -2408,8 +2410,10 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(reg_context), reg_context)).* = new_sp; break :blk new_ip; }, - .DWARF => return error.RequiresDWARFUnwind, - .FRAME => { + .DWARF => { + return unwindFrameDwarf(context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf)); + }, + .FRAME => blk: { const fp = (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).*; const new_sp = fp + 16; const ip_ptr = fp + @sizeOf(usize); @@ -2453,7 +2457,7 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).* = new_fp; (try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), reg_context)).* = new_ip; - return error.UnimplementedUnwindEncoding; + break :blk new_ip; }, }, else => return error.UnimplementedArch, @@ -2463,3 +2467,18 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul if (context.pc > 0) context.pc -= 1; return new_ip; } + +fn unwindFrameDwarf(context: *dwarf.UnwindContext, eh_frame: []const u8, fde_offset: usize) !usize { + var di = dwarf.DwarfInfo{ + .endian = builtin.cpu.arch.endian(), + .is_macho = true, + }; + defer di.deinit(context.allocator); + + di.sections[@intFromEnum(dwarf.DwarfSection.eh_frame)] = .{ + .data = eh_frame, + .owned = false, + }; + + return di.unwindFrame(context, fde_offset); +} |
