mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-28 03:17:08 +03:00
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
This commit is contained in:
@@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user