From 26500dafe53d1e4215adb411045d1680f75da685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 18 Oct 2026 17:19:27 +0200 Subject: [PATCH] std.debug.SelfInfo.MachO: fix xreg/dreg restore logic in compact unwinding The old logic advanced in the wrong direction and also overwrote one register in consecutive pairs. I'm not aware of any case where this matters in practice since macOS mandates the use of an FP register on AArch64, but we should still get it right. --- lib/std/debug/SelfInfo/MachO.zig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig index 59b9a524b01d4f68d5b8854d1b64d70bbb4fba9f..f68572d1ca07fab3f0a9249f1bdf42c85ba9ee2e 100644 --- a/lib/std/debug/SelfInfo/MachO.zig +++ b/lib/std/debug/SelfInfo/MachO.zig @@ -426,10 +426,10 @@ fn unwindFrameInner(si: *SelfInfo, io: Io, context: *UnwindContext) !usize { var reg_addr = fp - @sizeOf(usize); inline for (@typeInfo(@TypeOf(frame.x_reg_pairs)).@"struct".field_names, 0..) |field_name, i| { if (@field(frame.x_reg_pairs, field_name) != 0) { - (try dwarfRegNative(&context.cpu_state, 19 + i)).* = @as(*const usize, @ptrFromInt(reg_addr)).*; - reg_addr += @sizeOf(usize); - (try dwarfRegNative(&context.cpu_state, 20 + i)).* = @as(*const usize, @ptrFromInt(reg_addr)).*; - reg_addr += @sizeOf(usize); + (try dwarfRegNative(&context.cpu_state, 19 + i * 2)).* = @as(*const usize, @ptrFromInt(reg_addr)).*; + reg_addr -= @sizeOf(usize); + (try dwarfRegNative(&context.cpu_state, 20 + i * 2)).* = @as(*const usize, @ptrFromInt(reg_addr)).*; + reg_addr -= @sizeOf(usize); } } @@ -437,7 +437,7 @@ fn unwindFrameInner(si: *SelfInfo, io: Io, context: *UnwindContext) !usize { // vector registers in the AArch64 `cpu_context` anyway, so there's no reason to // fail a legitimate unwind just because we're asked to restore the registers here. // If some weird/broken unwind info tells us to read them later, we will fail then. - reg_addr += 16 * @as(usize, @popCount(@as(u4, @bitCast(frame.d_reg_pairs)))); + reg_addr -= 16 * @as(usize, @popCount(@as(u4, @bitCast(frame.d_reg_pairs)))); const new_ip = @as(*const usize, @ptrFromInt(ip_ptr)).*; const new_fp = @as(*const usize, @ptrFromInt(fp)).*; -- 2.54.0