aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-05-29 19:38:01 -0400
committerGitHub <noreply@github.com>2019-05-29 19:38:01 -0400
commitc66a747045e660a7e8b8146f9ee28c89f3960940 (patch)
tree6e9ccacd35f42d22f337d21b4e45ce1ffa6106b0 /std
parentbfc86776d501dc317737be09e8ed8d13da18f67c (diff)
parentb8d1060f0a240a3907033490a3e6615f78334a97 (diff)
downloadzig-c66a747045e660a7e8b8146f9ee28c89f3960940.tar.gz
zig-c66a747045e660a7e8b8146f9ee28c89f3960940.zip
Merge pull request #2546 from LemonBoy/sigaltstack
Add sigaltstack syscall for Linux
Diffstat (limited to 'std')
-rw-r--r--std/c/darwin.zig2
-rw-r--r--std/c/freebsd.zig4
-rw-r--r--std/c/linux.zig2
-rw-r--r--std/c/netbsd.zig4
-rw-r--r--std/os.zig23
-rw-r--r--std/os/bits/darwin.zig12
-rw-r--r--std/os/bits/freebsd.zig16
-rw-r--r--std/os/bits/linux.zig21
-rw-r--r--std/os/bits/netbsd.zig12
-rw-r--r--std/os/linux.zig4
-rw-r--r--std/os/test.zig11
-rw-r--r--std/os/uefi.zig4
12 files changed, 115 insertions, 0 deletions
diff --git a/std/c/darwin.zig b/std/c/darwin.zig
index 156429e7b9..14a5baff5c 100644
--- a/std/c/darwin.zig
+++ b/std/c/darwin.zig
@@ -54,3 +54,5 @@ pub extern "c" fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t
pub fn sigaddset(set: *sigset_t, signo: u5) void {
set.* |= u32(1) << (signo - 1);
}
+
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
index 70f3aeb9ca..eaa073677d 100644
--- a/std/c/freebsd.zig
+++ b/std/c/freebsd.zig
@@ -1,4 +1,8 @@
+const std = @import("../std.zig");
+use std.c;
+
extern "c" fn __error() *c_int;
pub const _errno = __error;
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/c/linux.zig b/std/c/linux.zig
index 83c6bdfe5b..50c4b185d8 100644
--- a/std/c/linux.zig
+++ b/std/c/linux.zig
@@ -25,3 +25,5 @@ pub extern "c" fn getauxval(__type: c_ulong) c_ulong;
pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
+
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/c/netbsd.zig b/std/c/netbsd.zig
index c677e1500b..0ee94e8220 100644
--- a/std/c/netbsd.zig
+++ b/std/c/netbsd.zig
@@ -1,4 +1,8 @@
+const std = @import("../std.zig");
+use std.c;
+
extern "c" fn __errno() *c_int;
pub const _errno = __errno;
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/os.zig b/std/os.zig
index 631cc266a8..ee476258ae 100644
--- a/std/os.zig
+++ b/std/os.zig
@@ -2442,6 +2442,29 @@ pub fn unexpectedErrno(err: usize) UnexpectedError {
return error.Unexpected;
}
+pub const SigaltstackError = error{
+ /// The supplied stack size was less than MINSIGSTKSZ.
+ SizeTooSmall,
+
+ /// Attempted to change the signal stack while it was active.
+ PermissionDenied,
+ Unexpected,
+};
+
+pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
+ if (windows.is_the_target or uefi.is_the_target or wasi.is_the_target)
+ @compileError("std.os.sigaltstack not available for this target");
+
+ switch (errno(system.sigaltstack(ss, old_ss))) {
+ 0 => return,
+ EFAULT => unreachable,
+ EINVAL => unreachable,
+ ENOMEM => return error.SizeTooSmall,
+ EPERM => return error.PermissionDenied,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
test "" {
_ = @import("os/darwin.zig");
_ = @import("os/freebsd.zig");
diff --git a/std/os/bits/darwin.zig b/std/os/bits/darwin.zig
index a685735da0..39dae6e7a1 100644
--- a/std/os/bits/darwin.zig
+++ b/std/os/bits/darwin.zig
@@ -1078,3 +1078,15 @@ pub const EQFULL = 106;
/// Must be equal largest errno
pub const ELAST = 106;
+
+pub const SIGSTKSZ = 131072;
+pub const MINSIGSTKSZ = 32768;
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 4;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_size: isize,
+ ss_flags: i32,
+};
diff --git a/std/os/bits/freebsd.zig b/std/os/bits/freebsd.zig
index 1925b75f3f..3fc019f9c1 100644
--- a/std/os/bits/freebsd.zig
+++ b/std/os/bits/freebsd.zig
@@ -835,3 +835,19 @@ pub const ENOTRECOVERABLE = 95; // State not recoverable
pub const EOWNERDEAD = 96; // Previous owner died
pub const ELAST = 96; // Must be equal largest errno
+
+pub const MINSIGSTKSZ = switch (builtin.arch) {
+ .i386, .x86_64 => 2048,
+ .arm, .aarch64 => 4096,
+ else => @compileError("MINSIGSTKSZ not defined for this architecture"),
+};
+pub const SIGSTKSZ = MINSIGSTKSZ + 32768;
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 4;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_size: isize,
+ ss_flags: i32,
+};
diff --git a/std/os/bits/linux.zig b/std/os/bits/linux.zig
index 44e713b15f..4a1734a145 100644
--- a/std/os/bits/linux.zig
+++ b/std/os/bits/linux.zig
@@ -929,3 +929,24 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
//#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t),set)
//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)
//#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,
+ .aarch64 => 5120,
+ else => @compileError("MINSIGSTKSZ not defined for this architecture"),
+};
+pub const SIGSTKSZ = switch (builtin.arch) {
+ .i386, .x86_64, .arm => 8192,
+ .aarch64 => 16384,
+ else => @compileError("SIGSTKSZ not defined for this architecture"),
+};
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 2;
+pub const SS_AUTODISARM = 1 << 31;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_flags: i32,
+ ss_size: isize,
+};
diff --git a/std/os/bits/netbsd.zig b/std/os/bits/netbsd.zig
index fc4c2904e0..e7a0f6ea52 100644
--- a/std/os/bits/netbsd.zig
+++ b/std/os/bits/netbsd.zig
@@ -723,3 +723,15 @@ pub const ENOLINK = 95; // Link has been severed
pub const EPROTO = 96; // Protocol error
pub const ELAST = 96; // Must equal largest errno
+
+pub const MINSIGSTKSZ = 8192;
+pub const SIGSTKSZ = MINSIGSTKSZ + 32768;
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 4;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_size: isize,
+ ss_flags: i32,
+};
diff --git a/std/os/linux.zig b/std/os/linux.zig
index 5d26446682..aee34b10a2 100644
--- a/std/os/linux.zig
+++ b/std/os/linux.zig
@@ -818,6 +818,10 @@ pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
}
+pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) usize {
+ return syscall2(SYS_sigaltstack, @ptrToInt(ss), @ptrToInt(old_ss));
+}
+
// XXX: This should be weak
extern const __ehdr_start: elf.Ehdr = undefined;
diff --git a/std/os/test.zig b/std/os/test.zig
index d4d662e97f..dfcd25c4bb 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -149,3 +149,14 @@ test "realpath" {
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
testing.expectError(error.FileNotFound, fs.realpath("definitely_bogus_does_not_exist1234", &buf));
}
+
+test "sigaltstack" {
+ if (builtin.os == .windows or builtin.os == .wasi) return error.SkipZigTest;
+
+ var st: os.stack_t = undefined;
+ try os.sigaltstack(null, &st);
+ // Setting a stack size less than MINSIGSTKSZ returns ENOMEM
+ st.ss_flags = 0;
+ st.ss_size = 1;
+ testing.expectError(error.SizeTooSmall, os.sigaltstack(&st, null));
+}
diff --git a/std/os/uefi.zig b/std/os/uefi.zig
index 8ed60d9c9b..7102938d70 100644
--- a/std/os/uefi.zig
+++ b/std/os/uefi.zig
@@ -1,2 +1,6 @@
// TODO this is where the extern declarations go. For example, see
// inc/efilib.h in gnu-efi-code
+
+const builtin = @import("builtin");
+
+pub const is_the_target = builtin.os == .uefi;