| ... | ... | @@ -1086,10 +1086,12 @@ const StackIterator = union(enum) { |
| 1086 | 1086 | switch (it.*) { |
| 1087 | 1087 | .ctx_first => |context_ptr| { |
| 1088 | 1088 | // After the first frame, start actually unwinding. |
| 1089 | | it.* = if (SelfInfo != void and SelfInfo.can_unwind and fp_usability != .ideal) |
| 1090 | | .{ .di = .init(context_ptr) } |
| 1091 | | else |
| 1092 | | .{ .fp = context_ptr.getFp() }; |
| 1089 | if (SelfInfo != void and SelfInfo.can_unwind and fp_usability != .ideal) { |
| 1090 | it.* = .{ .di = .init(context_ptr) }; |
| 1091 | } else { |
| 1092 | const fp = applyOffset(context_ptr.getFp(), stack_bias) orelse return .end; |
| 1093 | it.* = .{ .fp = fp }; |
| 1094 | } |
| 1093 | 1095 | |
| 1094 | 1096 | // The caller expects *return* addresses, where they will subtract 1 to find the address of the call. |
| 1095 | 1097 | // However, we have the actual current PC, which should not be adjusted. Compensate by adding 1. |
| ... | ... | @@ -1099,7 +1101,7 @@ const StackIterator = union(enum) { |
| 1099 | 1101 | const di = getSelfDebugInfo() catch unreachable; |
| 1100 | 1102 | const ret_addr = di.unwindFrame(io, unwind_context) catch |err| { |
| 1101 | 1103 | const pc = unwind_context.pc; |
| 1102 | | const fp = unwind_context.getFp(); |
| 1104 | const fp = applyOffset(unwind_context.getFp(), stack_bias) orelse return .end; |
| 1103 | 1105 | unwind_context.deinit(); |
| 1104 | 1106 | it.* = .{ .fp = fp }; |
| 1105 | 1107 | return .{ .switch_to_fp = .{ |
| ... | ... | @@ -1647,21 +1649,6 @@ fn handleSegfaultPosix(sig: posix.SIG, info: *const posix.siginfo_t, ctx_ptr: ?* |
| 1647 | 1649 | }; |
| 1648 | 1650 | const opt_cpu_context: ?cpu_context.Native = cpu_context.fromPosixSignalContext(ctx_ptr); |
| 1649 | 1651 | |
| 1650 | | if (native_arch.isSPARC()) { |
| 1651 | | // It's unclear to me whether this is a QEMU bug or also real kernel behavior, but in the |
| 1652 | | // former, I observed that the most recent register window wasn't getting spilled on the |
| 1653 | | // stack as expected when a signal arrived. A `flushw` from the signal handler does not |
| 1654 | | // appear to be sufficient either. On the other hand, when doing a synchronous stack trace |
| 1655 | | // and using `flushw`, this all appears to work as expected. So, *probably* a QEMU bug, but |
| 1656 | | // someone with real SPARC hardware should verify. |
| 1657 | | // |
| 1658 | | // In any case, the register save area exists specifically so that register windows can be |
| 1659 | | // spilled asynchronously. This means that it should be perfectly fine for us to manually do |
| 1660 | | // so here. |
| 1661 | | const ctx = opt_cpu_context.?; |
| 1662 | | @as(*[16]usize, @ptrFromInt(ctx.o[6] + StackIterator.stack_bias)).* = ctx.l ++ ctx.i; |
| 1663 | | } |
| 1664 | | |
| 1665 | 1652 | handleSegfault(addr, name, if (opt_cpu_context) |*ctx| ctx else null); |
| 1666 | 1653 | } |
| 1667 | 1654 | |