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