std.debug: work around latest SPARC register window not being spilled on signal

I have no idea if this is a QEMU bug or real kernel behavior. Either way, the
register save area specifically exists for asynchronous spilling of incoming and
local registers, so there should be no harm in doing this.
This commit is contained in:
Alex Rønne Petersen 2025-10-14 09:49:20 +02:00
parent 78bc5d46e0
commit 6de2d61a0c
No known key found for this signature in database

View file

@ -1438,6 +1438,22 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
break :info .{ addr, name }; break :info .{ addr, name };
}; };
const opt_cpu_context: ?cpu_context.Native = cpu_context.fromPosixSignalContext(ctx_ptr); const opt_cpu_context: ?cpu_context.Native = cpu_context.fromPosixSignalContext(ctx_ptr);
if (native_arch.isSPARC()) {
// It's unclear to me whether this is a QEMU bug or also real kernel behavior, but in the
// former, I observed that the most recent register window wasn't getting spilled on the
// stack as expected when a signal arrived. A `flushw` from the signal handler does not
// appear to be sufficient either. On the other hand, when doing a synchronous stack trace
// and using `flushw`, this all appears to work as expected. So, *probably* a QEMU bug, but
// someone with real SPARC hardware should verify.
//
// In any case, the register save area exists specifically so that register windows can be
// spilled asynchronously. This means that it should be perfectly fine for us to manually do
// so here.
const ctx = opt_cpu_context.?;
@as(*[16]usize, @ptrFromInt(ctx.o[6] + StackIterator.stack_bias)).* = ctx.l ++ ctx.i;
}
handleSegfault(addr, name, if (opt_cpu_context) |*ctx| ctx else null); handleSegfault(addr, name, if (opt_cpu_context) |*ctx| ctx else null);
} }