Commit 17f2af10b5
Changed files (11)
lib/std/os/bits/linux/arm-eabi.zig
@@ -1,10 +1,11 @@
// arm-eabi-specific declarations that are intended to be imported into the POSIX namespace.
-
-const std = @import("../../std.zig");
+const std = @import("../../../std.zig");
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;
const iovec_const = linux.iovec_const;
+const stack_t = linux.stack_t;
+const sigset_t = linux.sigset_t;
pub const SYS_restart_syscall = 0;
pub const SYS_exit = 1;
@@ -565,4 +566,37 @@ pub const timezone = extern struct {
tz_dsttime: i32,
};
+pub const mcontext_t = extern struct {
+ trap_no: usize,
+ error_code: usize,
+ oldmask: usize,
+ arm_r0: usize,
+ arm_r1: usize,
+ arm_r2: usize,
+ arm_r3: usize,
+ arm_r4: usize,
+ arm_r5: usize,
+ arm_r6: usize,
+ arm_r7: usize,
+ arm_r8: usize,
+ arm_r9: usize,
+ arm_r10: usize,
+ arm_fp: usize,
+ arm_ip: usize,
+ arm_sp: usize,
+ arm_lr: usize,
+ arm_pc: usize,
+ arm_cpsr: usize,
+ fault_address: usize,
+};
+
+pub const ucontext_t = extern struct {
+ flags: usize,
+ link: *ucontext_t,
+ stack: stack_t,
+ mcontext: mcontext_t,
+ sigmask: sigset_t,
+ regspace: [64]u64,
+};
+
pub const Elf_Symndx = u32;
lib/std/os/bits/linux/arm64.zig
@@ -8,6 +8,8 @@ const iovec = linux.iovec;
const iovec_const = linux.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
+const stack_t = linux.stack_t;
+const sigset_t = linux.sigset_t;
pub const SYS_io_setup = 0;
pub const SYS_io_destroy = 1;
@@ -445,4 +447,23 @@ pub const timezone = extern struct {
tz_dsttime: i32,
};
+pub const mcontext_t = extern struct {
+ fault_address: usize,
+ regs: [31]usize,
+ sp: usize,
+ pc: usize,
+ pstate: usize,
+ // Make sure the field is correctly aligned since this area
+ // holds various FP/vector registers
+ reserved1: [256 * 16]u8 align(16),
+};
+
+pub const ucontext_t = extern struct {
+ flags: usize,
+ link: *ucontext_t,
+ stack: stack_t,
+ sigmask: sigset_t,
+ mcontext: mcontext_t,
+};
+
pub const Elf_Symndx = u32;
lib/std/os/bits/linux/x86_64.zig
@@ -536,60 +536,6 @@ pub const timezone = extern struct {
pub const Elf_Symndx = u32;
-pub const sigval = extern union {
- int: i32,
- ptr: *c_void,
-};
-
-pub const siginfo_t = extern struct {
- signo: i32,
- errno: i32,
- code: i32,
- fields: extern union {
- pad: [128 - 2 * @sizeOf(c_int) - @sizeOf(c_long)]u8,
- common: extern struct {
- first: extern union {
- piduid: extern struct {
- pid: pid_t,
- uid: uid_t,
- },
- timer: extern struct {
- timerid: i32,
- overrun: i32,
- },
- },
- second: extern union {
- value: sigval,
- sigchld: extern struct {
- status: i32,
- utime: clock_t,
- stime: clock_t,
- },
- },
- },
- sigfault: extern struct {
- addr: *c_void,
- addr_lsb: i16,
- first: extern union {
- addr_bnd: extern struct {
- lower: *c_void,
- upper: *c_void,
- },
- pkey: u32,
- },
- },
- sigpoll: extern struct {
- band: isize,
- fd: i32,
- },
- sigsys: extern struct {
- call_addr: *c_void,
- syscall: i32,
- arch: u32,
- },
- },
-};
-
pub const greg_t = usize;
pub const gregset_t = [23]greg_t;
pub const fpstate = extern struct {
lib/std/os/bits/linux.zig
@@ -140,9 +140,27 @@ pub const WEXITED = 4;
pub const WCONTINUED = 8;
pub const WNOWAIT = 0x1000000;
-pub const SA_NOCLDSTOP = 1;
-pub const SA_NOCLDWAIT = 2;
-pub const SA_SIGINFO = 4;
+pub usingnamespace if (is_mips)
+ struct {
+ pub const SA_NOCLDSTOP = 1;
+ pub const SA_NOCLDWAIT = 0x10000;
+ pub const SA_SIGINFO = 8;
+
+ pub const SIG_BLOCK = 1;
+ pub const SIG_UNBLOCK = 2;
+ pub const SIG_SETMASK = 3;
+ }
+else
+ struct {
+ pub const SA_NOCLDSTOP = 1;
+ pub const SA_NOCLDWAIT = 2;
+ pub const SA_SIGINFO = 4;
+
+ pub const SIG_BLOCK = 0;
+ pub const SIG_UNBLOCK = 1;
+ pub const SIG_SETMASK = 2;
+ };
+
pub const SA_ONSTACK = 0x08000000;
pub const SA_RESTART = 0x10000000;
pub const SA_NODEFER = 0x40000000;
@@ -209,10 +227,6 @@ pub const SEEK_SET = 0;
pub const SEEK_CUR = 1;
pub const SEEK_END = 2;
-pub const SIG_BLOCK = 0;
-pub const SIG_UNBLOCK = 1;
-pub const SIG_SETMASK = 2;
-
pub const PROTO_ip = 0o000;
pub const PROTO_icmp = 0o001;
pub const PROTO_igmp = 0o002;
@@ -786,17 +800,34 @@ pub const winsize = extern struct {
ws_ypixel: u16,
};
-pub const NSIG = 65;
+pub const NSIG = if (is_mips) 128 else 65;
pub const sigset_t = [128 / @sizeOf(usize)]usize;
-pub const all_mask = [_]u32{ 0xffffffff, 0xffffffff };
-pub const app_mask = [_]u32{ 0xfffffffc, 0x7fffffff };
-pub const k_sigaction = extern struct {
- sigaction: ?extern fn (i32, *siginfo_t, *c_void) void,
- flags: usize,
- restorer: extern fn () void,
- mask: [2]u32,
-};
+pub usingnamespace if (NSIG == 65)
+ struct {
+ pub const all_mask = [2]u32{ 0xffffffff, 0xffffffff };
+ pub const app_mask = [2]u32{ 0xfffffffc, 0x7fffffff };
+ }
+else
+ struct {
+ pub const all_mask = [4]u32{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+ pub const app_mask = [4]u32{ 0xfffffffc, 0x7fffffff, 0xffffffff, 0xffffffff };
+ };
+
+pub const k_sigaction = if (is_mips)
+ extern struct {
+ flags: usize,
+ sigaction: ?extern fn (i32, *siginfo_t, *c_void) void,
+ mask: [4]u32,
+ restorer: extern fn () void,
+ }
+else
+ extern struct {
+ sigaction: ?extern fn (i32, *siginfo_t, *c_void) void,
+ flags: usize,
+ restorer: extern fn () void,
+ mask: [2]u32,
+ };
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
pub const Sigaction = extern struct {
@@ -1030,12 +1061,12 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
pub const MINSIGSTKSZ = switch (builtin.arch) {
- .i386, .x86_64, .arm => 2048,
+ .i386, .x86_64, .arm, .mipsel => 2048,
.aarch64 => 5120,
else => @compileError("MINSIGSTKSZ not defined for this architecture"),
};
pub const SIGSTKSZ = switch (builtin.arch) {
- .i386, .x86_64, .arm => 8192,
+ .i386, .x86_64, .arm, .mipsel => 8192,
.aarch64 => 16384,
else => @compileError("SIGSTKSZ not defined for this architecture"),
};
@@ -1050,6 +1081,70 @@ pub const stack_t = extern struct {
ss_size: isize,
};
+pub const sigval = extern union {
+ int: i32,
+ ptr: *c_void,
+};
+
+const siginfo_fields_union = extern union {
+ pad: [128 - 2 * @sizeOf(c_int) - @sizeOf(c_long)]u8,
+ common: extern struct {
+ first: extern union {
+ piduid: extern struct {
+ pid: pid_t,
+ uid: uid_t,
+ },
+ timer: extern struct {
+ timerid: i32,
+ overrun: i32,
+ },
+ },
+ second: extern union {
+ value: sigval,
+ sigchld: extern struct {
+ status: i32,
+ utime: clock_t,
+ stime: clock_t,
+ },
+ },
+ },
+ sigfault: extern struct {
+ addr: *c_void,
+ addr_lsb: i16,
+ first: extern union {
+ addr_bnd: extern struct {
+ lower: *c_void,
+ upper: *c_void,
+ },
+ pkey: u32,
+ },
+ },
+ sigpoll: extern struct {
+ band: isize,
+ fd: i32,
+ },
+ sigsys: extern struct {
+ call_addr: *c_void,
+ syscall: i32,
+ arch: u32,
+ },
+};
+
+pub const siginfo_t = if (is_mips)
+ extern struct {
+ signo: i32,
+ code: i32,
+ errno: i32,
+ fields: siginfo_fields_union,
+ }
+else
+ extern struct {
+ signo: i32,
+ errno: i32,
+ code: i32,
+ fields: siginfo_fields_union,
+ };
+
pub const io_uring_params = extern struct {
sq_entries: u32,
cq_entries: u32,
lib/std/os/linux/arm-eabi.zig
@@ -1,3 +1,5 @@
+usingnamespace @import("../bits.zig");
+
pub fn syscall0(number: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
@@ -94,3 +96,19 @@ pub extern fn getThreadPointer() usize {
: [ret] "=r" (-> usize)
);
}
+
+pub nakedcc fn restore() void {
+ return asm volatile ("svc #0"
+ :
+ : [number] "{r7}" (usize(SYS_sigreturn))
+ : "memory"
+ );
+}
+
+pub nakedcc fn restore_rt() void {
+ return asm volatile ("svc #0"
+ :
+ : [number] "{r7}" (usize(SYS_rt_sigreturn))
+ : "memory"
+ );
+}
lib/std/os/linux/arm64.zig
@@ -1,3 +1,5 @@
+usingnamespace @import("../bits.zig");
+
pub fn syscall0(number: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
@@ -85,3 +87,13 @@ pub fn syscall6(
/// This matches the libc clone function.
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
+
+pub const restore = restore_rt;
+
+pub nakedcc fn restore_rt() void {
+ return asm volatile ("svc #0"
+ :
+ : [number] "{x8}" (usize(SYS_rt_sigreturn))
+ : "memory", "cc"
+ );
+}
lib/std/os/linux/mipsel.zig
@@ -1,3 +1,5 @@
+usingnamespace @import("../bits.zig");
+
pub fn syscall0(number: usize) usize {
return asm volatile (
\\ syscall
@@ -122,3 +124,19 @@ pub fn syscall6(
/// This matches the libc clone function.
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
+
+pub nakedcc fn restore() void {
+ return asm volatile ("syscall"
+ :
+ : [number] "{$2}" (usize(SYS_sigreturn))
+ : "memory", "cc", "$7"
+ );
+}
+
+pub nakedcc fn restore_rt() void {
+ return asm volatile ("syscall"
+ :
+ : [number] "{$2}" (usize(SYS_rt_sigreturn))
+ : "memory", "cc", "$7"
+ );
+}
lib/std/os/linux/riscv64.zig
@@ -1,3 +1,5 @@
+usingnamespace @import("../bits.zig");
+
pub fn syscall0(number: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
@@ -84,3 +86,13 @@ pub fn syscall6(
}
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
+
+pub const restore = restore_rt;
+
+pub nakedcc fn restore_rt() void {
+ return asm volatile ("ecall"
+ :
+ : [number] "{x17}" (usize(SYS_rt_sigreturn))
+ : "memory"
+ );
+}
lib/std/os/linux/x86_64.zig
@@ -88,10 +88,12 @@ pub fn syscall6(
/// This matches the libc clone function.
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
+pub const restore = restore_rt;
+
pub nakedcc fn restore_rt() void {
return asm volatile ("syscall"
:
: [number] "{rax}" (usize(SYS_rt_sigreturn))
- : "rcx", "r11"
+ : "rcx", "r11", "memory"
);
}
lib/std/os/linux.zig
@@ -673,15 +673,18 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
assert(sig >= 1);
assert(sig != SIGKILL);
assert(sig != SIGSTOP);
+
+ const restorer_fn = if ((act.flags & SA_SIGINFO) != 0) restore_rt else restore;
var ksa = k_sigaction{
.sigaction = act.sigaction,
.flags = act.flags | SA_RESTORER,
.mask = undefined,
- .restorer = @ptrCast(extern fn () void, restore_rt),
+ .restorer = @ptrCast(extern fn () void, restorer_fn),
};
var ksa_old: k_sigaction = undefined;
- @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
- const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
+ const ksa_mask_size = @sizeOf(@typeOf(ksa_old.mask));
+ @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size);
+ const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size);
const err = getErrno(result);
if (err != 0) {
return result;
@@ -689,7 +692,7 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
if (oact) |old| {
old.sigaction = ksa_old.sigaction;
old.flags = @truncate(u32, ksa_old.flags);
- @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
+ @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), ksa_mask_size);
}
return 0;
}
lib/std/debug.zig
@@ -2336,7 +2336,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
}
/// Whether or not the current target can print useful debug information when a segfault occurs.
-pub const have_segfault_handling_support = (builtin.arch == builtin.Arch.x86_64 and builtin.os == .linux) or builtin.os == .windows;
+pub const have_segfault_handling_support = builtin.os == .linux or builtin.os == .windows;
pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
root.enable_segfault_handler
else
@@ -2390,12 +2390,31 @@ extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *con
// and the resulting segfault will crash the process rather than continually dump stack traces.
resetSegfaultHandler();
- const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
- const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]);
- const bp = @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]);
const addr = @ptrToInt(info.fields.sigfault.addr);
std.debug.warn("Segmentation fault at address 0x{x}\n", addr);
- dumpStackTraceFromBase(bp, ip);
+
+ switch (builtin.arch) {
+ .x86_64 => {
+ const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
+ const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]);
+ const bp = @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]);
+ dumpStackTraceFromBase(bp, ip);
+ },
+ .arm => {
+ const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
+ const ip = @intCast(usize, ctx.mcontext.arm_pc);
+ const bp = @intCast(usize, ctx.mcontext.arm_fp);
+ dumpStackTraceFromBase(bp, ip);
+ },
+ .aarch64 => {
+ const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
+ const ip = @intCast(usize, ctx.mcontext.pc);
+ // x29 is the ABI-designated frame pointer
+ const bp = @intCast(usize, ctx.mcontext.regs[29]);
+ dumpStackTraceFromBase(bp, ip);
+ },
+ else => {},
+ }
// We cannot allow the signal handler to return because when it runs the original instruction
// again, the memory may be mapped and undefined behavior would occur rather than repeating