authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-02-07 18:20:33+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-11 12:12:38-07:00
logfbde43524f0534b911bb749ad302ff3ed063ca97
treeb325f11d1e81ea68c695f2f7a4453e954001935e
parent8e10c80c5fc8ffcd3ebffd00848e4b2daac9d555

debug: implement segfault handler for macOS aarch64

Tested on a M1 MacBook Pro, macOS Monterey 12.2.

4 files changed, 83 insertions(+), 50 deletions(-)

lib/std/c/darwin.zig+20-45
......@@ -6,6 +6,26 @@ const native_arch = builtin.target.cpu.arch;
66const maxInt = std.math.maxInt;
77const iovec_const = std.os.iovec_const;
88
9const arch_bits = switch (native_arch) {
10 .aarch64 => @import("darwin/aarch64.zig"),
11 .x86_64 => @import("darwin/x86_64.zig"),
12 else => struct {},
13};
14
15pub const ucontext_t = extern struct {
16 onstack: c_int,
17 sigmask: sigset_t,
18 stack: stack_t,
19 link: ?*ucontext_t,
20 mcsize: u64,
21 mcontext: *mcontext_t,
22};
23
24pub const mcontext_t = extern struct {
25 es: arch_bits.exception_state,
26 ss: arch_bits.thread_state,
27};
28
929extern "c" fn __error() *c_int;
1030pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
1131pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
......@@ -478,51 +498,6 @@ pub const SIG = struct {
478498 pub const USR2 = 31;
479499};
480500
481pub const ucontext_t = extern struct {
482 onstack: c_int,
483 sigmask: sigset_t,
484 stack: stack_t,
485 link: ?*ucontext_t,
486 mcsize: u64,
487 mcontext: *mcontext_t,
488};
489
490pub const exception_state = extern struct {
491 trapno: u16,
492 cpu: u16,
493 err: u32,
494 faultvaddr: u64,
495};
496
497pub const thread_state = extern struct {
498 rax: u64,
499 rbx: u64,
500 rcx: u64,
501 rdx: u64,
502 rdi: u64,
503 rsi: u64,
504 rbp: u64,
505 rsp: u64,
506 r8: u64,
507 r9: u64,
508 r10: u64,
509 r11: u64,
510 r12: u64,
511 r13: u64,
512 r14: u64,
513 r15: u64,
514 rip: u64,
515 rflags: u64,
516 cs: u64,
517 fs: u64,
518 gs: u64,
519};
520
521pub const mcontext_t = extern struct {
522 es: exception_state,
523 ss: thread_state,
524};
525
526501pub const siginfo_t = extern struct {
527502 signo: c_int,
528503 errno: c_int,
lib/std/c/darwin/aarch64.zig created+18
......@@ -0,0 +1,18 @@
1// See C headers in
2// lib/libc/include/aarch64-macos.12-gnu/mach/arm/_structs.h
3
4pub const exception_state = extern struct {
5 far: u64, // Virtual Fault Address
6 esr: u32, // Exception syndrome
7 exception: u32, // Number of arm exception taken
8};
9
10pub const thread_state = extern struct {
11 regs: [29]u64, // General purpose registers
12 fp: u64, // Frame pointer x29
13 lr: u64, // Link register x30
14 sp: u64, // Stack pointer x31
15 pc: u64, // Program counter
16 cpsr: u32, // Current program status register
17 __pad: u32,
18};
lib/std/c/darwin/x86_64.zig created+30
......@@ -0,0 +1,30 @@
1pub const exception_state = extern struct {
2 trapno: u16,
3 cpu: u16,
4 err: u32,
5 faultvaddr: u64,
6};
7
8pub const thread_state = extern struct {
9 rax: u64,
10 rbx: u64,
11 rcx: u64,
12 rdx: u64,
13 rdi: u64,
14 rsi: u64,
15 rbp: u64,
16 rsp: u64,
17 r8: u64,
18 r9: u64,
19 r10: u64,
20 r11: u64,
21 r12: u64,
22 r13: u64,
23 r14: u64,
24 r15: u64,
25 rip: u64,
26 rflags: u64,
27 cs: u64,
28 fs: u64,
29 gs: u64,
30};
lib/std/debug.zig+15-5
......@@ -1601,9 +1601,13 @@ fn getDebugInfoAllocator() mem.Allocator {
16011601
16021602/// Whether or not the current target can print useful debug information when a segfault occurs.
16031603pub const have_segfault_handling_support = switch (native_os) {
1604 .linux, .netbsd, .solaris => true,
1605 .macos => native_arch == .x86_64,
1606 .windows => true,
1604 .linux,
1605 .macos,
1606 .netbsd,
1607 .solaris,
1608 .windows,
1609 => true,
1610
16071611 .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
16081612 else => false,
16091613};
......@@ -1717,9 +1721,15 @@ fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
17171721 },
17181722 .aarch64 => {
17191723 const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
1720 const ip = @intCast(usize, ctx.mcontext.pc);
1724 const ip = switch (native_os) {
1725 .macos => @intCast(usize, ctx.mcontext.ss.pc),
1726 else => @intCast(usize, ctx.mcontext.pc),
1727 };
17211728 // x29 is the ABI-designated frame pointer
1722 const bp = @intCast(usize, ctx.mcontext.regs[29]);
1729 const bp = switch (native_os) {
1730 .macos => @intCast(usize, ctx.mcontext.ss.fp),
1731 else => @intCast(usize, ctx.mcontext.regs[29]),
1732 };
17231733 dumpStackTraceFromBase(bp, ip);
17241734 },
17251735 else => {},