diff options
| author | jason <jkercher43@gmail.com> | 2024-06-27 16:29:47 -0400 |
|---|---|---|
| committer | jason <jkercher43@gmail.com> | 2024-06-27 16:29:47 -0400 |
| commit | f22754fc9036cf3c0bb5707e000c5055607ba374 (patch) | |
| tree | 7bcf66dc6cc15b8c777ec4b6185275b9f109aaed /core/sys/linux | |
| parent | aa27cd4b0b7876d028f66fdc92a4636eb9c1dc90 (diff) | |
sys/linux: fix some syscalls and types; add more to Sig_Action and Sig_Info; Pid int->i32
Diffstat (limited to 'core/sys/linux')
| -rw-r--r-- | core/sys/linux/bits.odin | 115 | ||||
| -rw-r--r-- | core/sys/linux/sys.odin | 47 | ||||
| -rw-r--r-- | core/sys/linux/types.odin | 96 |
3 files changed, 182 insertions, 76 deletions
diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index cfae06013..bf7ab4fae 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -150,44 +150,66 @@ Errno :: enum i32 { RDONLY flag is not present, because it has the value of 0, i.e. it is the default, unless WRONLY or RDWR is specified. */ -Open_Flags_Bits :: enum { - WRONLY = 0, - RDWR = 1, - CREAT = 6, - EXCL = 7, - NOCTTY = 8, - TRUNC = 9, - APPEND = 10, - NONBLOCK = 11, - DSYNC = 12, - ASYNC = 13, - DIRECT = 14, - LARGEFILE = 15, - DIRECTORY = 16, - NOFOLLOW = 17, - NOATIME = 18, - 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) +when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 { + Open_Flags_Bits :: enum { + WRONLY = 0, + RDWR = 1, + CREAT = 6, + EXCL = 7, + NOCTTY = 8, + TRUNC = 9, + APPEND = 10, + NONBLOCK = 11, + DSYNC = 12, + ASYNC = 13, + DIRECT = 14, + LARGEFILE = 15, + DIRECTORY = 16, + NOFOLLOW = 17, + NOATIME = 18, + 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) + +} else { + Open_Flags_Bits :: enum { + WRONLY = 0, + RDWR = 1, + CREAT = 6, + EXCL = 7, + NOCTTY = 8, + TRUNC = 9, + APPEND = 10, + NONBLOCK = 11, + DSYNC = 12, + ASYNC = 13, + DIRECTORY = 14, + NOFOLLOW = 15, + DIRECT = 16, + LARGEFILE = 17, + NOATIME = 18, + CLOEXEC = 19, + PATH = 21, + } +} /* Bits for FD_Flags bitset @@ -867,7 +889,7 @@ Wait_Option :: enum { WSTOPPED = 1, WEXITED = 2, WCONTINUED = 3, - WNOWAIT = 24, + WNOWAIT = 24, // // For processes created using clone __WNOTHREAD = 29, __WALL = 30, @@ -946,9 +968,22 @@ Sig_Stack_Flag :: enum i32 { 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 - - For TCP you want to use SOCK_STREAM + - For TCP you want to use SOCK_STREAM - For UDP you want to use SOCK_DGRAM Also see `Protocol` */ diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 171829cde..ed40719bf 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -69,7 +69,7 @@ close :: proc "contextless" (fd: Fd) -> (Errno) { stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { when size_of(int) == 8 { 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) } else { ret := syscall(SYS_stat, cast(rawptr) filename, stat) @@ -201,9 +201,24 @@ brk :: proc "contextless" (addr: uintptr) -> (Errno) { } /* + 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. */ -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)) return Errno(-ret) } @@ -1123,7 +1138,7 @@ ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) { ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length)) return Errno(-ret) } else { - ret := syscall(SYS_truncate, fd, compat64_arg_pair(length)) + ret := syscall(SYS_ftruncate, fd, compat64_arg_pair(length)) return Errno(-ret) } } @@ -1231,7 +1246,7 @@ creat :: proc "contextless" (name: cstring, mode: Mode) -> (Fd, Errno) { */ link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { 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) } else { 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) { 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) } else { 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) { 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) } else { 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. Available since Linux 2.6.10. */ -waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options) -> (Errno) { - ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options) +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, rusage) 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. */ 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) } @@ -2583,8 +2598,8 @@ linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd Create a symbolic link at specified dirfd. Available since Linux 2.6.16. */ -symlinkat :: proc "contextless" (dirfd: Fd, target: cstring, linkpath: cstring) -> (Errno) { - ret := syscall(SYS_symlinkat, dirfd, cast(rawptr) target, cast(rawptr) linkpath) +symlinkat :: proc "contextless" (target: cstring, dirfd: Fd, linkpath: cstring) -> (Errno) { + ret := syscall(SYS_symlinkat, cast(rawptr) target, dirfd, cast(rawptr) linkpath) 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. 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 { ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set)) - return Errno(-ret) + return errno_unwrap(ret, i32) } else { 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. Available since Linux 3.19. */ -execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) { - ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) +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, transmute(i32) flags) return Errno(-ret) } diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index 5053e1e1c..e3fe67a9b 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -18,7 +18,7 @@ Gid :: distinct u32 /* Type for Process IDs, Thread IDs, Thread group ID. */ -Pid :: distinct int +Pid :: distinct i32 /* Type for any of: pid, pidfd, pgid. @@ -89,11 +89,11 @@ FD_Flags :: bit_set[FD_Flags_Bits; i32] Represents file's permission and status bits **Example:** When you're passing a value of this type the recommended usage is: - + ``` linux.Mode{.S_IXOTH, .S_IROTH} | linux.S_IRWXU | linux.S_IRWXG ``` - + This would generate a mode that has full permissions for the file's owner and group, and only "read" and "execute" bits for others. @@ -151,9 +151,9 @@ when ODIN_ARCH == .amd64 { size: i64, blksize: uint, blocks: u64, - atim: Time_Spec, - mtim: Time_Spec, - ctim: Time_Spec, + atime: Time_Spec, + mtime: Time_Spec, + ctime: Time_Spec, 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 // 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. -@private _SIGSET_NWORDS :: (1024 / (8 * size_of(uint))) +@private _SIGSET_NWORDS :: (8 / size_of(uint)) Sig_Set :: [_SIGSET_NWORDS]uint @private SI_MAX_SIZE :: 128 -@private SI_ARCH_PREAMBLE :: 3 * size_of(i32) -@private SI_PAD_SIZE :: (SI_MAX_SIZE - SI_ARCH_PREAMBLE) / size_of(i32) -@private SI_TIMER_PAD_SIZE :: size_of(Uid) - size_of(i32) +@private SI_ARCH_PREAMBLE :: 4 * size_of(i32) +@private SI_PAD_SIZE :: SI_MAX_SIZE - SI_ARCH_PREAMBLE Sig_Handler_Fn :: #type proc "c" (sig: Signal) -Sig_Restore_Fn :: #type proc "c" () +Sig_Restore_Fn :: #type proc "c" () -> ! Sig_Info :: struct #packed { signo: Signal, @@ -518,8 +517,9 @@ Sig_Info :: struct #packed { uid: Uid, /* sender's uid */ }, using _timer: struct { - timerid: i32, /* timer id */ + timerid: i32, /* timer id */ overrun: i32, /* overrun count */ + value: Sig_Val, /* timer value */ }, /* POSIX.1b signals */ using _rt: struct { @@ -528,8 +528,8 @@ Sig_Info :: struct #packed { }, /* SIGCHLD */ using _sigchld: struct { - _pid1: Pid, /* which child */ - _uid1: Uid, /* sender's uid */ + _pid1: Pid, /* which child */ + _uid1: Uid, /* sender's uid */ status: i32, /* exit code */ utime: uint, stime: uint, //clock_t @@ -537,7 +537,24 @@ Sig_Info :: struct #packed { /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ using _sigfault: struct { 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 */ using _sigpoll: struct { @@ -547,12 +564,43 @@ Sig_Info :: struct #packed { /* SIGSYS */ using _sigsys: struct { call_addr: rawptr, /* calling user insn */ - syscall: i32, /* triggering system call number */ - arch: u32, /* AUDIT_ARCH_* of syscall */ + syscall: i32, /* triggering system call number */ + 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_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, } +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) { using _u: struct #raw_union { handler: Sig_Handler_Fn, 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, mask: Sig_Set, } @@ -733,7 +789,7 @@ RLimit :: struct { /* Structure representing how much of each resource got used. -*/ +*/ RUsage :: struct { utime: Time_Val, stime: Time_Val, @@ -813,7 +869,7 @@ when size_of(int) == 8 || ODIN_ARCH == .i386 { cpid: Pid, lpid: Pid, nattach: uint, - _: [2]uint, + _: [2]uint, } } |