diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-09-17 18:38:11 +0100 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2025-09-30 13:44:54 +0100 |
| commit | a18fd41064493e742eacebc88e2afeadd54ff6f0 (patch) | |
| tree | 1081fbd6d3c64cf1f583ae3188ab05e0320f03d9 /lib/std/debug/SelfInfo/WindowsModule.zig | |
| parent | b578cca022f4c9ce94439e2ee795639b3a23c8f5 (diff) | |
| download | zig-a18fd41064493e742eacebc88e2afeadd54ff6f0.tar.gz zig-a18fd41064493e742eacebc88e2afeadd54ff6f0.zip | |
std: rework/remove ucontext_t
Our usage of `ucontext_t` in the standard library was kind of
problematic. We unnecessarily mimiced libc-specific structures, and our
`getcontext` implementation was overkill for our use case of stack
tracing.
This commit introduces a new namespace, `std.debug.cpu_context`, which
contains "context" types for various architectures (currently x86,
x86_64, ARM, and AARCH64) containing the general-purpose CPU registers;
the ones needed in practice for stack unwinding. Each implementation has
a function `current` which populates the structure using inline
assembly. The structure is user-overrideable, though that should only be
necessary if the standard library does not have an implementation for
the *architecture*: that is to say, none of this is OS-dependent.
Of course, in POSIX signal handlers, we get a `ucontext_t` from the
kernel. The function `std.debug.cpu_context.fromPosixSignalContext`
converts this to a `std.debug.cpu_context.Native` with a big ol' target
switch.
This functionality is not exposed from `std.c` or `std.posix`, and
neither are `ucontext_t`, `mcontext_t`, or `getcontext`. The rationale
is that these types and functions do not conform to a specific ABI, and
in fact tend to get updated over time based on CPU features and
extensions; in addition, different libcs use different structures which
are "partially compatible" with the kernel structure. Overall, it's a
mess, but all we need is the kernel context, so we can just define a
kernel-compatible structure as long as we don't claim C compatibility by
putting it in `std.c` or `std.posix`.
This change resulted in a few nice `std.debug` simplifications, but
nothing too noteworthy. However, the main benefit of this change is that
DWARF unwinding---sometimes necessary for collecting stack traces
reliably---now requires far less target-specific integration.
Also fix a bug I noticed in `PageAllocator` (I found this due to a bug
in my distro's QEMU distribution; thanks, broken QEMU patch!) and I
think a couple of minor bugs in `std.debug`.
Resolves: #23801
Resolves: #23802
Diffstat (limited to 'lib/std/debug/SelfInfo/WindowsModule.zig')
| -rw-r--r-- | lib/std/debug/SelfInfo/WindowsModule.zig | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/lib/std/debug/SelfInfo/WindowsModule.zig b/lib/std/debug/SelfInfo/WindowsModule.zig index 4bbc220c5b..8c88bd8b2f 100644 --- a/lib/std/debug/SelfInfo/WindowsModule.zig +++ b/lib/std/debug/SelfInfo/WindowsModule.zig @@ -295,11 +295,45 @@ pub const UnwindContext = struct { pc: usize, cur: windows.CONTEXT, history_table: windows.UNWIND_HISTORY_TABLE, - pub fn init(ctx: *const windows.CONTEXT, gpa: Allocator) Allocator.Error!UnwindContext { - _ = gpa; + pub fn init(ctx: *const std.debug.cpu_context.Native) UnwindContext { return .{ .pc = @returnAddress(), - .cur = ctx.*, + .cur = switch (builtin.cpu.arch) { + .x86_64 => std.mem.zeroInit(windows.CONTEXT, .{ + .Rax = ctx.gprs.get(.rax), + .Rcx = ctx.gprs.get(.rcx), + .Rdx = ctx.gprs.get(.rdx), + .Rbx = ctx.gprs.get(.rbx), + .Rsp = ctx.gprs.get(.rsp), + .Rbp = ctx.gprs.get(.rbp), + .Rsi = ctx.gprs.get(.rsi), + .Rdi = ctx.gprs.get(.rdi), + .R8 = ctx.gprs.get(.r8), + .R9 = ctx.gprs.get(.r9), + .R10 = ctx.gprs.get(.r10), + .R11 = ctx.gprs.get(.r11), + .R12 = ctx.gprs.get(.r12), + .R13 = ctx.gprs.get(.r13), + .R14 = ctx.gprs.get(.r14), + .R15 = ctx.gprs.get(.r15), + .Rip = ctx.gprs.get(.rip), + }), + .aarch64, .aarch64_be => .{ + .ContextFlags = 0, + .Cpsr = 0, + .DUMMYUNIONNAME = .{ .X = ctx.x }, + .Sp = ctx.sp, + .Pc = ctx.pc, + .V = @splat(.{ .B = @splat(0) }), + .Fpcr = 0, + .Fpsr = 0, + .Bcr = @splat(0), + .Bvr = @splat(0), + .Wcr = @splat(0), + .Wvr = @splat(0), + }, + else => comptime unreachable, + }, .history_table = std.mem.zeroes(windows.UNWIND_HISTORY_TABLE), }; } |
