sys/linux: fix some syscalls and types; add more to Sig_Action and Sig_Info; Pid int->i32

This commit is contained in:
jason
2024-06-27 16:29:47 -04:00
parent aa27cd4b0b
commit f22754fc90
3 changed files with 181 additions and 75 deletions
+73 -38
View File
@@ -150,44 +150,66 @@ Errno :: enum i32 {
RDONLY flag is not present, because it has the value of 0, i.e. it is the RDONLY flag is not present, because it has the value of 0, i.e. it is the
default, unless WRONLY or RDWR is specified. default, unless WRONLY or RDWR is specified.
*/ */
Open_Flags_Bits :: enum { when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 {
WRONLY = 0, Open_Flags_Bits :: enum {
RDWR = 1, WRONLY = 0,
CREAT = 6, RDWR = 1,
EXCL = 7, CREAT = 6,
NOCTTY = 8, EXCL = 7,
TRUNC = 9, NOCTTY = 8,
APPEND = 10, TRUNC = 9,
NONBLOCK = 11, APPEND = 10,
DSYNC = 12, NONBLOCK = 11,
ASYNC = 13, DSYNC = 12,
DIRECT = 14, ASYNC = 13,
LARGEFILE = 15, DIRECT = 14,
DIRECTORY = 16, LARGEFILE = 15,
NOFOLLOW = 17, DIRECTORY = 16,
NOATIME = 18, NOFOLLOW = 17,
CLOEXEC = 19, NOATIME = 18,
PATH = 21, CLOEXEC = 19,
} PATH = 21,
}
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19 } else {
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1) Open_Flags_Bits :: enum {
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2) WRONLY = 0,
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100) RDWR = 1,
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200) CREAT = 6,
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400) EXCL = 7,
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000) NOCTTY = 8,
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000) TRUNC = 9,
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000) APPEND = 10,
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000) NONBLOCK = 11,
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000) DSYNC = 12,
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000) ASYNC = 13,
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000) DIRECTORY = 14,
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000) NOFOLLOW = 15,
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000) DIRECT = 16,
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000) LARGEFILE = 17,
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000) NOATIME = 18,
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000) CLOEXEC = 19,
PATH = 21,
}
}
/* /*
Bits for FD_Flags bitset Bits for FD_Flags bitset
@@ -946,9 +968,22 @@ Sig_Stack_Flag :: enum i32 {
AUTODISARM = 31, AUTODISARM = 31,
} }
Sig_Action_Flag :: enum u32 {
NOCLDSTOP = 0,
NOCLDWAIT = 1,
SIGINFO = 2,
UNSUPPORTED = 10,
EXPOSE_TAGBITS = 11,
RESTORER = 26,
ONSTACK = 27,
RESTART = 28,
NODEFER = 30,
RESETHAND = 31,
}
/* /*
Type of socket to create Type of socket to create
- For TCP you want to use SOCK_STREAM - For TCP you want to use SOCK_STREAM
- For UDP you want to use SOCK_DGRAM - For UDP you want to use SOCK_DGRAM
Also see `Protocol` Also see `Protocol`
*/ */
+31 -16
View File
@@ -69,7 +69,7 @@ close :: proc "contextless" (fd: Fd) -> (Errno) {
stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) {
when size_of(int) == 8 { when size_of(int) == 8 {
when ODIN_ARCH == .arm64 { when ODIN_ARCH == .arm64 {
ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat) ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat, 0)
return Errno(-ret) return Errno(-ret)
} else { } else {
ret := syscall(SYS_stat, cast(rawptr) filename, stat) ret := syscall(SYS_stat, cast(rawptr) filename, stat)
@@ -200,10 +200,25 @@ brk :: proc "contextless" (addr: uintptr) -> (Errno) {
return Errno(-ret) return Errno(-ret)
} }
/*
Returns from signal handlers on some archs.
*/
rt_sigreturn :: proc "c" () -> ! {
intrinsics.syscall(uintptr(SYS_rt_sigreturn))
unreachable()
}
/* /*
Alter an action taken by a process. Alter an action taken by a process.
*/ */
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno { rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action($T), old_sigaction: ^Sig_Action) -> Errno {
// NOTE(jason): It appears that the restorer is required for i386 and amd64
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
sigaction.flags += {.RESTORER}
}
if sigaction != nil && sigaction.restorer == nil && .RESTORER in sigaction.flags {
sigaction.restorer = rt_sigreturn
}
ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set)) ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set))
return Errno(-ret) return Errno(-ret)
} }
@@ -1123,7 +1138,7 @@ ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) {
ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length)) ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length))
return Errno(-ret) return Errno(-ret)
} else { } else {
ret := syscall(SYS_truncate, fd, compat64_arg_pair(length)) ret := syscall(SYS_ftruncate, fd, compat64_arg_pair(length))
return Errno(-ret) return Errno(-ret)
} }
} }
@@ -1231,7 +1246,7 @@ creat :: proc "contextless" (name: cstring, mode: Mode) -> (Fd, Errno) {
*/ */
link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
when ODIN_ARCH == .arm64 { when ODIN_ARCH == .arm64 {
ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath) ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath, 0)
return Errno(-ret) return Errno(-ret)
} else { } else {
ret := syscall(SYS_link, cast(rawptr) target, cast(rawptr) linkpath) ret := syscall(SYS_link, cast(rawptr) target, cast(rawptr) linkpath)
@@ -1261,7 +1276,7 @@ unlink :: proc "contextless" (name: cstring) -> (Errno) {
*/ */
symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
when ODIN_ARCH == .arm64 { when ODIN_ARCH == .arm64 {
ret := syscall(SYS_symlinkat, AT_FDCWD, cast(rawptr) target, cast(rawptr) linkpath) ret := syscall(SYS_symlinkat, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath)
return Errno(-ret) return Errno(-ret)
} else { } else {
ret := syscall(SYS_symlink, cast(rawptr) target, cast(rawptr) linkpath) ret := syscall(SYS_symlink, cast(rawptr) target, cast(rawptr) linkpath)
@@ -1291,7 +1306,7 @@ readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) {
*/ */
chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) {
when ODIN_ARCH == .arm64 { when ODIN_ARCH == .arm64 {
ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, 0) ret := syscall(SYS_fchmodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
return Errno(-ret) return Errno(-ret)
} else { } else {
ret := syscall(SYS_chmod, cast(rawptr) name, transmute(u32) mode) ret := syscall(SYS_chmod, cast(rawptr) name, transmute(u32) mode)
@@ -2476,8 +2491,8 @@ tgkill :: proc "contextless" (tgid, tid: Pid, sig: Signal) -> (Errno) {
Wait on process, process group or pid file descriptor. Wait on process, process group or pid file descriptor.
Available since Linux 2.6.10. Available since Linux 2.6.10.
*/ */
waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options) -> (Errno) { waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options, rusage: ^RUsage) -> (Errno) {
ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options) ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options, rusage)
return Errno(-ret) return Errno(-ret)
} }
@@ -2504,7 +2519,7 @@ waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, opt
Available since Linux 2.6.16. Available since Linux 2.6.16.
*/ */
openat :: proc "contextless" (fd: Fd, name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) { openat :: proc "contextless" (fd: Fd, name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) {
ret := syscall(SYS_openat, fd, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode) ret := syscall(SYS_openat, fd, transmute(uintptr) name, transmute(u32) flags, transmute(u32) mode)
return errno_unwrap(ret, Fd) return errno_unwrap(ret, Fd)
} }
@@ -2583,8 +2598,8 @@ linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd
Create a symbolic link at specified dirfd. Create a symbolic link at specified dirfd.
Available since Linux 2.6.16. Available since Linux 2.6.16.
*/ */
symlinkat :: proc "contextless" (dirfd: Fd, target: cstring, linkpath: cstring) -> (Errno) { symlinkat :: proc "contextless" (target: cstring, dirfd: Fd, linkpath: cstring) -> (Errno) {
ret := syscall(SYS_symlinkat, dirfd, cast(rawptr) target, cast(rawptr) linkpath) ret := syscall(SYS_symlinkat, cast(rawptr) target, dirfd, cast(rawptr) linkpath)
return Errno(-ret) return Errno(-ret)
} }
@@ -2619,13 +2634,13 @@ faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) ->
Wait for events on a file descriptor. Wait for events on a file descriptor.
Available since Linux 2.6.16. Available since Linux 2.6.16.
*/ */
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (Errno) { ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) {
when size_of(int) == 8 { when size_of(int) == 8 {
ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set)) ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
return Errno(-ret) return errno_unwrap(ret, i32)
} else { } else {
ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set)) ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
return Errno(-ret) return errno_unwrap(ret, i32)
} }
} }
@@ -2808,8 +2823,8 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er
Execute program relative to a directory file descriptor. Execute program relative to a directory file descriptor.
Available since Linux 3.19. Available since Linux 3.19.
*/ */
execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) { execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: FD_Flags = {}) -> (Errno) {
ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, transmute(i32) flags)
return Errno(-ret) return Errno(-ret)
} }
+72 -16
View File
@@ -18,7 +18,7 @@ Gid :: distinct u32
/* /*
Type for Process IDs, Thread IDs, Thread group ID. Type for Process IDs, Thread IDs, Thread group ID.
*/ */
Pid :: distinct int Pid :: distinct i32
/* /*
Type for any of: pid, pidfd, pgid. Type for any of: pid, pidfd, pgid.
@@ -151,9 +151,9 @@ when ODIN_ARCH == .amd64 {
size: i64, size: i64,
blksize: uint, blksize: uint,
blocks: u64, blocks: u64,
atim: Time_Spec, atime: Time_Spec,
mtim: Time_Spec, mtime: Time_Spec,
ctim: Time_Spec, ctime: Time_Spec,
ino: Inode, ino: Inode,
} }
} }
@@ -495,16 +495,15 @@ Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
// 1. Odin's bitfields start from 0, whereas signals start from 1 // 1. Odin's bitfields start from 0, whereas signals start from 1
// 2. It's unclear how bitfields act in terms of ABI (are they an array of ints or an array of longs?). // 2. It's unclear how bitfields act in terms of ABI (are they an array of ints or an array of longs?).
// it makes a difference because ARM is big endian. // it makes a difference because ARM is big endian.
@private _SIGSET_NWORDS :: (1024 / (8 * size_of(uint))) @private _SIGSET_NWORDS :: (8 / size_of(uint))
Sig_Set :: [_SIGSET_NWORDS]uint Sig_Set :: [_SIGSET_NWORDS]uint
@private SI_MAX_SIZE :: 128 @private SI_MAX_SIZE :: 128
@private SI_ARCH_PREAMBLE :: 3 * size_of(i32) @private SI_ARCH_PREAMBLE :: 4 * size_of(i32)
@private SI_PAD_SIZE :: (SI_MAX_SIZE - SI_ARCH_PREAMBLE) / size_of(i32) @private SI_PAD_SIZE :: SI_MAX_SIZE - SI_ARCH_PREAMBLE
@private SI_TIMER_PAD_SIZE :: size_of(Uid) - size_of(i32)
Sig_Handler_Fn :: #type proc "c" (sig: Signal) Sig_Handler_Fn :: #type proc "c" (sig: Signal)
Sig_Restore_Fn :: #type proc "c" () Sig_Restore_Fn :: #type proc "c" () -> !
Sig_Info :: struct #packed { Sig_Info :: struct #packed {
signo: Signal, signo: Signal,
@@ -518,8 +517,9 @@ Sig_Info :: struct #packed {
uid: Uid, /* sender's uid */ uid: Uid, /* sender's uid */
}, },
using _timer: struct { using _timer: struct {
timerid: i32, /* timer id */ timerid: i32, /* timer id */
overrun: i32, /* overrun count */ overrun: i32, /* overrun count */
value: Sig_Val, /* timer value */
}, },
/* POSIX.1b signals */ /* POSIX.1b signals */
using _rt: struct { using _rt: struct {
@@ -528,8 +528,8 @@ Sig_Info :: struct #packed {
}, },
/* SIGCHLD */ /* SIGCHLD */
using _sigchld: struct { using _sigchld: struct {
_pid1: Pid, /* which child */ _pid1: Pid, /* which child */
_uid1: Uid, /* sender's uid */ _uid1: Uid, /* sender's uid */
status: i32, /* exit code */ status: i32, /* exit code */
utime: uint, utime: uint,
stime: uint, //clock_t stime: uint, //clock_t
@@ -537,7 +537,24 @@ Sig_Info :: struct #packed {
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
using _sigfault: struct { using _sigfault: struct {
addr: rawptr, /* faulting insn/memory ref. */ addr: rawptr, /* faulting insn/memory ref. */
addr_lsb: i16, /* LSB of the reported address */ using _: struct #raw_union {
trapno: i32, /* Trap number that caused signal */
addr_lsb: i16, /* LSB of the reported address */
using _addr_bnd: struct {
_pad2: u64,
lower: rawptr, /* lower bound during fault */
upper: rawptr, /* upper bound during fault */
},
using _addr_pkey: struct {
_pad3: u64,
pkey: u32, /* protection key on PTE that faulted */
},
using _perf: struct {
perf_data: u64,
perf_type: u32,
perf_flags: u32,
},
},
}, },
/* SIGPOLL */ /* SIGPOLL */
using _sigpoll: struct { using _sigpoll: struct {
@@ -547,12 +564,43 @@ Sig_Info :: struct #packed {
/* SIGSYS */ /* SIGSYS */
using _sigsys: struct { using _sigsys: struct {
call_addr: rawptr, /* calling user insn */ call_addr: rawptr, /* calling user insn */
syscall: i32, /* triggering system call number */ syscall: i32, /* triggering system call number */
arch: u32, /* AUDIT_ARCH_* of syscall */ arch: u32, /* AUDIT_ARCH_* of syscall */
}, },
}, },
} }
#assert(size_of(Sig_Info) == 128)
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
#assert(offset_of(Sig_Info, signo) == 0x00)
#assert(offset_of(Sig_Info, errno) == 0x04)
#assert(offset_of(Sig_Info, code) == 0x08)
#assert(offset_of(Sig_Info, pid) == 0x10)
#assert(offset_of(Sig_Info, uid) == 0x14)
#assert(offset_of(Sig_Info, timerid) == 0x10)
#assert(offset_of(Sig_Info, overrun) == 0x14)
#assert(offset_of(Sig_Info, value) == 0x18)
#assert(offset_of(Sig_Info, status) == 0x18)
#assert(offset_of(Sig_Info, utime) == 0x20)
#assert(offset_of(Sig_Info, stime) == 0x28)
#assert(offset_of(Sig_Info, addr) == 0x10)
#assert(offset_of(Sig_Info, addr_lsb) == 0x18)
#assert(offset_of(Sig_Info, trapno) == 0x18)
#assert(offset_of(Sig_Info, lower) == 0x20)
#assert(offset_of(Sig_Info, upper) == 0x28)
#assert(offset_of(Sig_Info, pkey) == 0x20)
#assert(offset_of(Sig_Info, perf_data) == 0x18)
#assert(offset_of(Sig_Info, perf_type) == 0x20)
#assert(offset_of(Sig_Info, perf_flags) == 0x24)
#assert(offset_of(Sig_Info, band) == 0x10)
#assert(offset_of(Sig_Info, fd) == 0x18)
#assert(offset_of(Sig_Info, call_addr) == 0x10)
#assert(offset_of(Sig_Info, syscall) == 0x18)
#assert(offset_of(Sig_Info, arch) == 0x1C)
} else {
// TODO
}
SIGEV_MAX_SIZE :: 64 SIGEV_MAX_SIZE :: 64
SIGEV_PAD_SIZE :: ((SIGEV_MAX_SIZE-size_of(i32)*2+size_of(Sig_Val))/size_of(i32)) SIGEV_PAD_SIZE :: ((SIGEV_MAX_SIZE-size_of(i32)*2+size_of(Sig_Val))/size_of(i32))
@@ -583,12 +631,20 @@ Sig_Stack :: struct {
size: uintptr, size: uintptr,
} }
Sig_Action_Special :: enum uint {
SIG_DFL = 0,
SIG_IGN = 1,
SIG_ERR = ~uint(0),
}
Sig_Action_Flags :: bit_set[Sig_Action_Flag; uint]
Sig_Action :: struct($T: typeid) { Sig_Action :: struct($T: typeid) {
using _u: struct #raw_union { using _u: struct #raw_union {
handler: Sig_Handler_Fn, handler: Sig_Handler_Fn,
sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: ^T), sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: ^T),
special: Sig_Action_Special,
}, },
flags: uint, flags: Sig_Action_Flags,
restorer: Sig_Restore_Fn, restorer: Sig_Restore_Fn,
mask: Sig_Set, mask: Sig_Set,
} }