Skip to content

Commit c66a747

Browse files
authored
Merge pull request #2546 from LemonBoy/sigaltstack
Add sigaltstack syscall for Linux
2 parents bfc8677 + b8d1060 commit c66a747

12 files changed

+115
-0
lines changed

std/c/darwin.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,5 @@ pub extern "c" fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t
5454
pub fn sigaddset(set: *sigset_t, signo: u5) void {
5555
set.* |= u32(1) << (signo - 1);
5656
}
57+
58+
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;

std/c/freebsd.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
const std = @import("../std.zig");
2+
use std.c;
3+
14
extern "c" fn __error() *c_int;
25
pub const _errno = __error;
36

47
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
8+
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;

std/c/linux.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ pub extern "c" fn getauxval(__type: c_ulong) c_ulong;
2525

2626
pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
2727
pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
28+
29+
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;

std/c/netbsd.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
const std = @import("../std.zig");
2+
use std.c;
3+
14
extern "c" fn __errno() *c_int;
25
pub const _errno = __errno;
36

47
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
8+
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;

std/os.zig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,6 +2442,29 @@ pub fn unexpectedErrno(err: usize) UnexpectedError {
24422442
return error.Unexpected;
24432443
}
24442444

2445+
pub const SigaltstackError = error{
2446+
/// The supplied stack size was less than MINSIGSTKSZ.
2447+
SizeTooSmall,
2448+
2449+
/// Attempted to change the signal stack while it was active.
2450+
PermissionDenied,
2451+
Unexpected,
2452+
};
2453+
2454+
pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
2455+
if (windows.is_the_target or uefi.is_the_target or wasi.is_the_target)
2456+
@compileError("std.os.sigaltstack not available for this target");
2457+
2458+
switch (errno(system.sigaltstack(ss, old_ss))) {
2459+
0 => return,
2460+
EFAULT => unreachable,
2461+
EINVAL => unreachable,
2462+
ENOMEM => return error.SizeTooSmall,
2463+
EPERM => return error.PermissionDenied,
2464+
else => |err| return unexpectedErrno(err),
2465+
}
2466+
}
2467+
24452468
test "" {
24462469
_ = @import("os/darwin.zig");
24472470
_ = @import("os/freebsd.zig");

std/os/bits/darwin.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,3 +1078,15 @@ pub const EQFULL = 106;
10781078

10791079
/// Must be equal largest errno
10801080
pub const ELAST = 106;
1081+
1082+
pub const SIGSTKSZ = 131072;
1083+
pub const MINSIGSTKSZ = 32768;
1084+
1085+
pub const SS_ONSTACK = 1;
1086+
pub const SS_DISABLE = 4;
1087+
1088+
pub const stack_t = extern struct {
1089+
ss_sp: [*]u8,
1090+
ss_size: isize,
1091+
ss_flags: i32,
1092+
};

std/os/bits/freebsd.zig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,3 +835,19 @@ pub const ENOTRECOVERABLE = 95; // State not recoverable
835835
pub const EOWNERDEAD = 96; // Previous owner died
836836

837837
pub const ELAST = 96; // Must be equal largest errno
838+
839+
pub const MINSIGSTKSZ = switch (builtin.arch) {
840+
.i386, .x86_64 => 2048,
841+
.arm, .aarch64 => 4096,
842+
else => @compileError("MINSIGSTKSZ not defined for this architecture"),
843+
};
844+
pub const SIGSTKSZ = MINSIGSTKSZ + 32768;
845+
846+
pub const SS_ONSTACK = 1;
847+
pub const SS_DISABLE = 4;
848+
849+
pub const stack_t = extern struct {
850+
ss_sp: [*]u8,
851+
ss_size: isize,
852+
ss_flags: i32,
853+
};

std/os/bits/linux.zig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,3 +929,24 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
929929
//#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t),set)
930930
//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)
931931
//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
932+
933+
pub const MINSIGSTKSZ = switch (builtin.arch) {
934+
.i386, .x86_64, .arm => 2048,
935+
.aarch64 => 5120,
936+
else => @compileError("MINSIGSTKSZ not defined for this architecture"),
937+
};
938+
pub const SIGSTKSZ = switch (builtin.arch) {
939+
.i386, .x86_64, .arm => 8192,
940+
.aarch64 => 16384,
941+
else => @compileError("SIGSTKSZ not defined for this architecture"),
942+
};
943+
944+
pub const SS_ONSTACK = 1;
945+
pub const SS_DISABLE = 2;
946+
pub const SS_AUTODISARM = 1 << 31;
947+
948+
pub const stack_t = extern struct {
949+
ss_sp: [*]u8,
950+
ss_flags: i32,
951+
ss_size: isize,
952+
};

std/os/bits/netbsd.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,3 +723,15 @@ pub const ENOLINK = 95; // Link has been severed
723723
pub const EPROTO = 96; // Protocol error
724724

725725
pub const ELAST = 96; // Must equal largest errno
726+
727+
pub const MINSIGSTKSZ = 8192;
728+
pub const SIGSTKSZ = MINSIGSTKSZ + 32768;
729+
730+
pub const SS_ONSTACK = 1;
731+
pub const SS_DISABLE = 4;
732+
733+
pub const stack_t = extern struct {
734+
ss_sp: [*]u8,
735+
ss_size: isize,
736+
ss_flags: i32,
737+
};

std/os/linux.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,10 @@ pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
818818
return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
819819
}
820820

821+
pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) usize {
822+
return syscall2(SYS_sigaltstack, @ptrToInt(ss), @ptrToInt(old_ss));
823+
}
824+
821825
// XXX: This should be weak
822826
extern const __ehdr_start: elf.Ehdr = undefined;
823827

std/os/test.zig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,14 @@ test "realpath" {
149149
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
150150
testing.expectError(error.FileNotFound, fs.realpath("definitely_bogus_does_not_exist1234", &buf));
151151
}
152+
153+
test "sigaltstack" {
154+
if (builtin.os == .windows or builtin.os == .wasi) return error.SkipZigTest;
155+
156+
var st: os.stack_t = undefined;
157+
try os.sigaltstack(null, &st);
158+
// Setting a stack size less than MINSIGSTKSZ returns ENOMEM
159+
st.ss_flags = 0;
160+
st.ss_size = 1;
161+
testing.expectError(error.SizeTooSmall, os.sigaltstack(&st, null));
162+
}

std/os/uefi.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
// TODO this is where the extern declarations go. For example, see
22
// inc/efilib.h in gnu-efi-code
3+
4+
const builtin = @import("builtin");
5+
6+
pub const is_the_target = builtin.os == .uefi;

0 commit comments

Comments
 (0)