authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-18 17:19:27+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-18 17:27:28+02:00
log26500dafe53d1e4215adb411045d1680f75da685
treeaee7300b340265badd4f57d5f1402b64f604e887
parent701b4e10c670e550a878ce9a0e422c61cf14c29a
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

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.

1 files changed, 5 insertions(+), 5 deletions(-)

lib/std/debug/SelfInfo/MachO.zig+5-5
......@@ -426,10 +426,10 @@ fn unwindFrameInner(si: *SelfInfo, io: Io, context: *UnwindContext) !usize {
426426 var reg_addr = fp - @sizeOf(usize);
427427 inline for (@typeInfo(@TypeOf(frame.x_reg_pairs)).@"struct".field_names, 0..) |field_name, i| {
428428 if (@field(frame.x_reg_pairs, field_name) != 0) {
429 (try dwarfRegNative(&context.cpu_state, 19 + i)).* = @as(*const usize, @ptrFromInt(reg_addr)).*;
430 reg_addr += @sizeOf(usize);
431 (try dwarfRegNative(&context.cpu_state, 20 + i)).* = @as(*const usize, @ptrFromInt(reg_addr)).*;
432 reg_addr += @sizeOf(usize);
429 (try dwarfRegNative(&context.cpu_state, 19 + i * 2)).* = @as(*const usize, @ptrFromInt(reg_addr)).*;
430 reg_addr -= @sizeOf(usize);
431 (try dwarfRegNative(&context.cpu_state, 20 + i * 2)).* = @as(*const usize, @ptrFromInt(reg_addr)).*;
432 reg_addr -= @sizeOf(usize);
433433 }
434434 }
435435
......@@ -437,7 +437,7 @@ fn unwindFrameInner(si: *SelfInfo, io: Io, context: *UnwindContext) !usize {
437437 // vector registers in the AArch64 `cpu_context` anyway, so there's no reason to
438438 // fail a legitimate unwind just because we're asked to restore the registers here.
439439 // If some weird/broken unwind info tells us to read them later, we will fail then.
440 reg_addr += 16 * @as(usize, @popCount(@as(u4, @bitCast(frame.d_reg_pairs))));
440 reg_addr -= 16 * @as(usize, @popCount(@as(u4, @bitCast(frame.d_reg_pairs))));
441441
442442 const new_ip = @as(*const usize, @ptrFromInt(ip_ptr)).*;
443443 const new_fp = @as(*const usize, @ptrFromInt(fp)).*;