diff options
| author | flysand7 <yyakut.ac@gmail.com> | 2023-11-02 08:51:33 +1100 |
|---|---|---|
| committer | flysand7 <yyakut.ac@gmail.com> | 2023-11-03 00:56:20 +1100 |
| commit | 7faa1460049a3f9500239a10f8377fc508d6f19e (patch) | |
| tree | 05a48950f6ff1762e303f9ae0d482b27ada909b6 /core/sys/linux | |
| parent | 62d0b0ae72bc858ed77876d097663eac4f157ab9 (diff) | |
WIP
Diffstat (limited to 'core/sys/linux')
| -rw-r--r-- | core/sys/linux/bits.odin | 170 | ||||
| -rw-r--r-- | core/sys/linux/constants.odin | 83 | ||||
| -rw-r--r-- | core/sys/linux/sys.odin | 505 | ||||
| -rw-r--r-- | core/sys/linux/types.odin | 452 |
4 files changed, 1149 insertions, 61 deletions
diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index 0cf90ed3b..fd86b798f 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -1398,3 +1398,173 @@ PER_OSF4 :: 0x000f PER_HPUX :: 0x0010 PER_MASK :: 0x00ff +/* + Bits for access modes for shared memory +*/ +IPC_Mode_Bits :: enum { + WROTH = 1, + RDOTH = 2, + WRGRP = 4, + RDGRP = 5, + WRUSR = 7, + RDUSR = 8, + DEST = 9, + LOCKED = 10, +} + +/* + Shared memory flags bits +*/ +IPC_Flags_Bits :: enum { + IPC_CREAT = 9, + IPC_EXCL = 10, + IPC_NOWAIT = 11, + // Semaphore + SEM_UNDO = 9, + // Shared memory + SHM_HUGETLB = 11, + SHM_NORESERVE = 12, + SHM_RDONLY = 12, + SHM_RND = 13, + SHM_REMAP = 14, + SHM_EXEC = 15, + // Message queue + MSG_NOERROR = 12, + MSG_EXCEPT = 13, + MSG_COPY = 14, +} + +/* + IPC memory commands +*/ +IPC_Cmd :: enum i16 { + // IPC common + IPC_RMID = 0, + IPC_SET = 1, + IPC_STAT = 2, + // Shared memory + SHM_LOCK = 11, + SHM_UNLOCK = 12, + SHM_STAT = 13, + SHM_INFO = 14, + SHM_STAT_ANY = 15, + // Semaphore + GETPID = 11, + GETVAL = 12, + GETALL = 13, + GETNCNT = 14, + GETZCNT = 15, + SETVAL = 16, + SETALL = 17, + SEM_STAT = 18, + SEM_INFO = 19, + SEM_STAT_ANY = 20, + // Message queue + MSG_STAT = 11, + MSG_INFO = 12, + MSG_STAT_ANY = 13, +} + +/* + File locking operation bits +*/ +FLock_Op_Bits :: enum { + SH = 1, + EX = 2, + NB = 4, + UN = 8, +} + +/* + ptrace requests +*/ +PTrace_Request :: enum { + TRACEME = 0, + PEEKTEXT = 1, + PEEKDATA = 2, + PEEKUSER = 3, + POKETEXT = 4, + POKEDATA = 5, + POKEUSER = 6, + CONT = 7, + KILL = 8, + SINGLESTEP = 9, + GETREGS = 12, + SETREGS = 13, + GETFPREGS = 14, + SETFPREGS = 15, + ATTACH = 16, + DETACH = 17, + GETFPXREGS = 18, + SETFPXREGS = 19, + SYSCALL = 24, + GET_THREAD_AREA = 25, + SET_THREAD_AREA = 26, + ARCH_PRCTL = 30, + SYSEMU = 31, + SYSEMU_SINGLESTEP = 32, + SINGLEBLOCK = 33, + SETOPTIONS = 0x4200, + GETEVENTMSG = 0x4201, + GETSIGINFO = 0x4202, + SETSIGINFO = 0x4203, + GETREGSET = 0x4204, + SETREGSET = 0x4205, + SEIZE = 0x4206, + INTERRUPT = 0x4207, + LISTEN = 0x4208, + PEEKSIGINFO = 0x4209, + GETSIGMASK = 0x420a, + SETSIGMASK = 0x420b, + SECCOMP_GET_FILTER = 0x420c, + SECCOMP_GET_METADATA = 0x420d, + GET_SYSCALL_INFO = 0x420e, + GET_RSEQ_CONFIGURATION = 0x420f, +}; + +/* + ptrace options +*/ +PTrace_Options_Bits :: enum { + TRACESYSGOOD = 0, + TRACEFORK = 1, + TRACEVFORK = 2, + TRACECLONE = 3, + TRACEEXEC = 4, + TRACEVFORKDONE = 5, + TRACEEXIT = 6, + TRACESECCOMP = 7, + EXITKILL = 20, + SUSPEND_SECCOMP = 21, +} + +/* + ptrace event codes. +*/ +PTrace_Event_Code :: enum { + EVENT_FORK = 1, + EVENT_VFORK = 2, + EVENT_CLONE = 3, + EVENT_EXEC = 4, + EVENT_VFORK_DONE = 5, + EVENT_EXIT = 6, + EVENT_SECCOMP = 7, + EVENT_STOP = 128, +} + +/* + ptrace's get syscall info operation. +*/ +PTrace_Get_Syscall_Info_Op :: enum u8 { + NONE = 0, + ENTRY = 1, + EXIT = 2, + SECCOMP = 3, +}; + +/* + ptrace's PEEKSIGINFO flags bits +*/ +PTrace_Peek_Sig_Info_Flags_Bits :: enum { + SHARED = 0, +}
\ No newline at end of file diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index e725ed2fd..a1bcd09ab 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -83,6 +83,10 @@ STATX_BASIC_STATS :: Statx_Mask { .BLOCKS, } +/* + Tell `shmget` to create a new key +*/ +IPC_PRIVATE :: Key(0) FCntl_Command_DUPFD :: distinct FCntl_Command FCntl_Command_GETFD :: distinct FCntl_Command @@ -197,3 +201,82 @@ FUTEX_WAIT_REQUEUE_PI :: Futex_Wait_requeue_Pi_Type(.WAIT_REQUEUE_PI) FUTEX_CMP_REQUEUE_PI :: Futex_Cmp_requeue_Pi_Type(.CMP_REQUEUE_PI) FUTEX_LOCK_PI2 :: Futex_Lock_Pi2_Type(.LOCK_PI2) +PTrace_Traceme_Type :: distinct PTrace_Request +PTrace_Peek_Type :: distinct PTrace_Request +PTrace_Poke_Type :: distinct PTrace_Request +PTrace_Cont_Type :: distinct PTrace_Request +PTrace_Kill_Type :: distinct PTrace_Request +PTrace_Singlestep_Type :: distinct PTrace_Request +PTrace_Getregs_Type :: distinct PTrace_Request +PTrace_Setregs_Type :: distinct PTrace_Request +PTrace_Getfpregs_Type :: distinct PTrace_Request +PTrace_Setfpregs_Type :: distinct PTrace_Request +PTrace_Attach_Type :: distinct PTrace_Request +PTrace_Detach_Type :: distinct PTrace_Request +PTrace_Getfpxregs_Type :: distinct PTrace_Request +PTrace_Setfpxregs_Type :: distinct PTrace_Request +PTrace_Syscall_Type :: distinct PTrace_Request +PTrace_Get_Thread_Area_Type :: distinct PTrace_Request +PTrace_Set_Thread_Area_Type :: distinct PTrace_Request +PTrace_Arch_Prctl_Type :: distinct PTrace_Request +PTrace_Sysemu_Type :: distinct PTrace_Request +PTrace_Sysemu_Singlestep_Type :: distinct PTrace_Request +PTrace_Singleblock_Type :: distinct PTrace_Request +PTrace_Setoptions_Type :: distinct PTrace_Request +PTrace_Geteventmsg_Type :: distinct PTrace_Request +PTrace_Getsiginfo_Type :: distinct PTrace_Request +PTrace_Setsiginfo_Type :: distinct PTrace_Request +PTrace_Getregset_Type :: distinct PTrace_Request +PTrace_Setregset_Type :: distinct PTrace_Request +PTrace_Seize_Type :: distinct PTrace_Request +PTrace_Interrupt_Type :: distinct PTrace_Request +PTrace_Listen_Type :: distinct PTrace_Request +PTrace_Peeksiginfo_Type :: distinct PTrace_Request +PTrace_Getsigmask_Type :: distinct PTrace_Request +PTrace_Setsigmask_Type :: distinct PTrace_Request +PTrace_Seccomp_Get_Filter_Type :: distinct PTrace_Request +PTrace_Seccomp_Get_Metadata_Type :: distinct PTrace_Request +PTrace_Get_Syscall_Info_Type :: distinct PTrace_Request +PTrace_Get_RSeq_Configuration_Type :: distinct PTrace_Request + +PTRACE_TRACEME :: PTrace_Traceme_Type(.TRACEME) +PTRACE_PEEKTEXT :: PTrace_Peek_Type(.PEEKTEXT) +PTRACE_PEEKDATA :: PTrace_Peek_Type(.PEEKDATA) +PTRACE_PEEKUSER :: PTrace_Peek_Type(.PEEKUSER) +PTRACE_POKETEXT :: PTrace_Poke_Type(.POKETEXT) +PTRACE_POKEDATA :: PTrace_Poke_Type(.POKEDATA) +PTRACE_POKEUSER :: PTrace_Poke_Type(.POKEUSER) +PTRACE_CONT :: PTrace_Cont_Type(.CONT) +PTRACE_KILL :: PTrace_Kill_Type(.KILL) +PTRACE_SINGLESTEP :: PTrace_Singlestep_Type(.SINGLESTEP) +PTRACE_GETREGS :: PTrace_Getregs_Type(.GETREGS) +PTRACE_SETREGS :: PTrace_Setregs_Type(.SETREGS) +PTRACE_GETFPREGS :: PTrace_Getfpregs_Type(.GETFPREGS) +PTRACE_SETFPREGS :: PTrace_Setfpregs_Type(.SETFPREGS) +PTRACE_ATTACH :: PTrace_Attach_Type(.ATTACH) +PTRACE_DETACH :: PTrace_Detach_Type(.DETACH) +PTRACE_GETFPXREGS :: PTrace_Getfpxregs_Type(.GETFPXREGS) +PTRACE_SETFPXREGS :: PTrace_Setfpxregs_Type(.SETFPXREGS) +PTRACE_SYSCALL :: PTrace_Syscall_Type(.SYSCALL) +PTRACE_GET_THREAD_AREA :: PTrace_Get_Thread_Area_Type(.GET_THREAD_AREA) +PTRACE_SET_THREAD_AREA :: PTrace_Set_Thread_Area_Type(.SET_THREAD_AREA) +PTRACE_ARCH_PRCTL :: PTrace_Arch_Prctl_Type(.ARCH_PRCTL) +PTRACE_SYSEMU :: PTrace_Sysemu_Type(.SYSEMU) +PTRACE_SYSEMU_SINGLESTEP :: PTrace_Sysemu_Singlestep_Type(.SYSEMU_SINGLESTEP) +PTRACE_SINGLEBLOCK :: PTrace_Singleblock_Type(.SINGLEBLOCK) +PTRACE_SETOPTIONS :: PTrace_Setoptions_Type(.SETOPTIONS) +PTRACE_GETEVENTMSG :: PTrace_Geteventmsg_Type(.GETEVENTMSG) +PTRACE_GETSIGINFO :: PTrace_Getsiginfo_Type(.GETSIGINFO) +PTRACE_SETSIGINFO :: PTrace_Setsiginfo_Type(.SETSIGINFO) +PTRACE_GETREGSET :: PTrace_Getregset_Type(.GETREGSET) +PTRACE_SETREGSET :: PTrace_Setregset_Type(.SETREGSET) +PTRACE_SEIZE :: PTrace_Seize_Type(.SEIZE) +PTRACE_INTERRUPT :: PTrace_Interrupt_Type(.INTERRUPT) +PTRACE_LISTEN :: PTrace_Listen_Type(.LISTEN) +PTRACE_PEEKSIGINFO :: PTrace_Peeksiginfo_Type(.PEEKSIGINFO) +PTRACE_GETSIGMASK :: PTrace_Getsigmask_Type(.GETSIGMASK) +PTRACE_SETSIGMASK :: PTrace_Setsigmask_Type(.SETSIGMASK) +PTRACE_SECCOMP_GET_FILTER :: PTrace_Seccomp_Get_Filter_Type(.SECCOMP_GET_FILTER) +PTRACE_SECCOMP_GET_METADATA :: PTrace_Seccomp_Get_Metadata_Type(.SECCOMP_GET_METADATA) +PTRACE_GET_SYSCALL_INFO :: PTrace_Get_Syscall_Info_Type(.GET_SYSCALL_INFO) +PTRACE_GET_RSEQ_CONFIGURATION :: PTrace_Get_RSeq_Configuration_Type(.GET_RSEQ_CONFIGURATION) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index dfb25e5dd..d04a6c857 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -165,7 +165,16 @@ munmap :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) { return Errno(-ret) } -// TODO(flysand): brk +/* + Extend the data segment size until the address `addr`. Note: you may be + familiar with sbrk(), which is not actually a syscall, so is not + implemented here. + Available since Linux 1.0. +*/ +brk :: proc "contextless" (addr: uintptr) -> (Errno) { + ret := syscall(SYS_brk, addr) + return Errno(-ret) +} /// Alter an action taken by a process rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno { @@ -180,8 +189,6 @@ rt_sigprocmask :: proc "contextless" (mask_kind: Sig_Mask_Kind, new_set: ^Sig_Se return Errno(-ret) } -// TODO(flysand): rt_sigreturn - // TODO(flysand): ioctl /// Read the file at a specified offset @@ -200,9 +207,23 @@ pwrite :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) { return errno_unwrap(ret, int) } -// TODO(flysand): readv +/* + Read the data from file into multiple buffers. + Available since Linux 2.0. +*/ +readv :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) { + ret := syscall(SYS_readv, fd, raw_data(iov), len(iov)) + return errno_unwrap(ret, int) +} -// TODO(flysand): writev +/* + Write the data from multiple buffers into a file. + Available since Linux 2.0. +*/ +writev :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) { + ret := syscall(SYS_writev, fd, raw_data(iov), len(iov)) + return errno_unwrap(ret, int) +} /// Check user permissions for a file /// If Mode is F_OK, checks whether the file exists @@ -226,11 +247,18 @@ pipe2 :: proc "contextless" (pipes: ^[2]Fd, flags: Open_Flags) -> (Errno) { return Errno(-ret) } -// TODO(flysand): select - -// TODO(flysand): sched_yield +/* + Yield the processor. + Available since Linux 2.0. +*/ +sched_yield :: proc "contextless" () { + syscall(SYS_sched_yield) +} -// TODO(flysand): add docs here +/* + Remap a virtual memory address. + Available since Linux 2.0. +*/ mremap :: proc "contextless" (old_addr: rawptr, old_size: uint, new_size: uint, flags: MRemap_Flags, new_addr: uintptr = 0) -> (rawptr, Errno) { if .FIXED in flags { ret := syscall(SYS_mremap, old_addr, old_size, new_size, transmute(i32) flags, new_addr) @@ -248,7 +276,14 @@ msync :: proc "contextless" (addr: rawptr, size: uint, flags: MSync_Flags) -> (E return Errno(-ret) } -// TODO(flysand): mincore +/* + Determine if pages are resident in memory. + Available since Linux 2.4. +*/ +mincore :: proc "contextless" (addr: rawptr, size: uint, vec: []b8) -> (Errno) { + ret := syscall(SYS_mincore, addr, size, raw_data(vec)) + return Errno(-ret) +} /// Give advice about use of memory /// Available since Linux 2.4 @@ -257,11 +292,44 @@ madvise :: proc "contextless" (addr: rawptr, size: uint, advice: MAdvice) -> (Er return Errno(-ret) } -// TODO(flysand): shmget +/* + Allocate a SystemV shared memory segment. + Available since Linux 2.0. +*/ +shmget :: proc "contextless" (key: Key, size: uint, flags: IPC_Flags) -> (Key, Errno) { + ret := syscall(SYS_shmget, key, size, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): shmat +/* + SystemV shared memory segment operations. + Available since Linux 2.0. +*/ +shmat :: proc "contextless" (key: Key, addr: rawptr, flags: IPC_Flags) -> (rawptr, Errno) { + ret := syscall(SYS_shmat, key, addr, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): shmctl +shmctl_ds :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Shmid_DS) -> (Errno) { + ret := syscall(SYS_shmctl, key, cmd, buf) + return Errno(-ret) +} + +shmctl_info :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Shmid_Info) -> (int, Errno) { + ret := syscall(SYS_shmctl, key, cmd, buf) + return errno_unwrap(ret, int) +} + +shmctl_stat :: proc "contextless" (index: int, cmd: IPC_Cmd, buf: ^Shmid_DS) -> (Key, Errno) { + ret := syscall(SYS_shmctl, key, cmd, buf) + return errno_unwrap(ret, Key) +} + +/* + SystemV shared memory control. + Available since Linux 2.0. +*/ +shmctl :: proc {shmctl_ds, shmctl_info, shmctl_stat} /// Allocate a new file descriptor that refers to the same file as the one provided /// Available since Linux 1.0 @@ -283,15 +351,48 @@ dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) { } } -// TODO(flysand): pause +/* + Wait until the next signal is delivered. + Available since Linux 1.0. +*/ +pause :: proc "contextless" () { + syscall(SYS_pause) +} -// TODO(flysand): nanosleep +/* + High-resolution sleep. + Available since Linux 2.0. +*/ +nanosleep :: proc "contextless" (req: ^Time_Spec, rem: ^Time_Spec) -> (Errno) { + ret := syscall(SYS_nanosleep, req, rem) + return Errno(-ret) +} -// TODO(flysand): getitimer +/* + Get the value of an internal timer. + Available since Linux 1.0. +*/ +getitimer :: proc "contextless" (which: ITimer_Which, cur: ^ITimer_Val) -> (Errno) { + ret := syscall(SYS_getitimer, cur) + return Errno(-ret) +} -// TODO(flysand): alarm +/* + Set an alarm clock for delivery of a signal. + Available since Linux 1.0. +*/ +alarm :: proc "contextless" (seconds: u32) -> u32 { + return cast(u32) syscall(SYS_alarm, seconds) +} -// TODO(flysand): setitimer +/* + Set the value of an internal timer. + Available since Linux 1.0. +*/ +getitimer :: proc "contextless" (which: ITimer_Which, new: ^ITimer_Val, old: ^ITimer_Val) -> (Errno) { + ret := syscall(SYS_getitimer, new, old) + return Errno(-ret) +} /// Returns the thread group ID of the current process /// Note that it doesn't return the pid, despite it's name. @@ -300,7 +401,20 @@ getpid :: proc "contextless" () -> Pid { return cast(Pid) syscall(SYS_getpid) } -// TODO(flysand): sendfile +/* + Transfer the data between file descriptors. + Available since Linux 2.2. + On 32-bit platforms available since Linux 2.6. +*/ +sendfile :: proc "contextless" (out: Fd, in: Fd, offset: ^i64, count: uint) -> (int, Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_sendfile, out, in, offset, count) + return errno_unwrap(ret, Errno) + } else { + ret := syscall(SYS_sendfile64, out, in, offset, count) + return errno_unwrap(ret, Errno) + } +} /// Create a socket file descriptor /// Available since Linux 2.0 @@ -377,10 +491,28 @@ recv :: proc {recvfrom, recv_noaddr} /// Available since Linux 2.0 send :: proc {sendto, send_noaddr} -// TODO(flysand): sendmsg +/* + Send a message on a socket. + Available since Linux 2.0. +*/ +sendmsg :: proc "contextless" (sock: Fd, msghdr: ^Msg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_sendmsg, sock, msghdr, transmute(i32) flags) + return errno_unwrap(ret, int) +} -// TODO(flysand): recvmsg +/* + Receive a message on a socket. + Available since Linux 2.0. +*/ +recvmsg :: proc "contextless" (sock: Fd, msghdr: ^Msg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_recvmsg, sock, msghdr, transmute(i32) flags) + return errno_unwrap(ret, int) +} +/* + Shutdown a socket. + Available since Linux 2.0. +*/ shutdown :: proc "contextless" (sock: Fd, how: Shutdown_How) -> (Errno) { ret := syscall(SYS_shutdown, sock, how) return Errno(-ret) @@ -405,11 +537,34 @@ listen :: proc "contextless" (sock: Fd, queue_len: i32) -> (Errno) { return Errno(-ret) } -// TODO(flysand): getsockname +/* + Get socket name (aka it's bound address). + Available since Linux 2.0. +*/ +getsockname :: proc "contextless" (sock: Fd, addr: ^Sock_Addr_Any) -> (Errno) { + addr_len := size_of(Sock_Addr_Any) + ret := syscall(SYS_getsockname, sock, addr, &addr_len) + return Errno(-ret) +} -// TODO(flysand): getpeername +/* + Get the name of the connected peer socket. + Available since Linux 2.0. +*/ +getpeername :: proc "contextless" (sock: Fd, addr: ^Sock_Addr_Any) -> (Errno) { + addr_len := size_of(Sock_Addr_Any) + ret := syscall(SYS_getpeername, sock, addr, &addr_len) + return Errno(-ret) +} -// TODO(flysand): socketpair +/* + Create a pair of connected sockets. + Available since Linux 2.0. +*/ +socketpair :: proc "contextless" (domain: Protocol_Family, type: Socket_Type, proto: Protocol, pair: ^[2]Fd) -> (Errno) { + ret := syscall(SYS_socketpair, domain, type, proto, pair) + return Errno(-ret) +} // TODO(flysand): the parameters are the same, maybe there's a way to make it into a single proc, sacrificing type // safety slightly @@ -518,9 +673,32 @@ fork :: proc "contextless" () -> (Pid, Errno) { } } -// TODO(flysand): vfork +/* + Create a child process and block parent. + Available since Linux 2.2. +*/ +vfork :: proc "contextless" () -> Pid { + when ODIN_ARCH != .arm64 { + return Pid(syscall(SYS_vfork)) + } else { + return Pid(syscall(SYS_fork)) + } +} -// TODO(flysand): execve +/* + Replace the current process with another program. + Available since Linux 1.0. + On ARM64 available since Linux 3.19. +*/ +execve :: proc "contextless" (name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) { + when ODIN_ARCH != .arm64 { + ret := syscall(SYS_execve, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) + return Errno(-ret) + } else { + ret := syscall(SYS_execveat, AT_FDCWD, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) + return Errno(-ret) + } +} /// Exit the thread with a given exit code /// Available since Linux 1.0 @@ -539,7 +717,14 @@ wait4 :: proc "contextless" (pid: Pid, status: ^u32, options: Wait_Options) -> ( /// See wait4 waitpid :: wait4 -// TODO(flysand): kill +/* + Send signal to a process. + Available since Linux 1.0. +*/ +kill :: proc "contextless" (pid: Pid, signal: Signal) -> (Errno) { + ret := syscall(SYS_kill, pid, signal) + return Errno(-ret) +} /// Get system information /// Available since Linux 1.0 @@ -548,21 +733,84 @@ uname :: proc "contextless" (uts_name: ^UTS_Name) -> (Errno) { return Errno(-ret) } -// TODO(flysand): semget +/* + Get a SystemV semaphore set identifier. + Available since Linux 2.0. +*/ +semget :: proc "contextless" (key: Key, n: i32, flags: IPC_Flags) -> (Key, Errno) { + ret := syscall(SYS_semget, key, n, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): semop +/* + SystemV semaphore operations. + Available since Linux 2.0. +*/ +semop :: proc "contextless" (key: Key, ops: []Sem_Buf) -> (Errno) { + ret := syscall(SYS_semop, key, raw_data(ops), len(ops)) + return Errno(-ret) +} -// TODO(flysand): semctl +semctl3 :: proc "contextless" (key: Key, semnum: i32, cmd: IPC_Cmd) -> (int, Errno) { + ret := syscall(SYS_semctl, key, semnum, cmd) + return errno_unwrap(ret, int) +} -// TODO(flysand): shmdt +semctl4 :: proc "contextless" (key: Key, semnum: i32, cmd: IPC_Cmd, semun: Sem_Un) -> (int, Errno) { + ret := syscall(SYS_semctl, key, semnum, cmd, semun) + return errno_unwrap(ret, int) +} -// TODO(flysand): msgget +/* + SystemV semaphore control operations. + Available since Linux 2.0. +*/ +semctl :: proc {semctl3, semctl4} -// TODO(flysand): msgsnd +/* + SystemV shared memory operations. + Available since Linux 2.0. +*/ +shmdt :: proc "contextless" (shmaddr: rawptr) -> (Errno) { + ret := syscall(SYS_shmdt, shmaddr) + return Errno(-ret) +} -// TODO(flysand): msgrcv +/* + Get SystemV message queue identifier. + Available since Linux 2.0. +*/ +msgget :: proc "contextless" (key: Key, flags: IPC_Flags) -> (Key, Errno) { + ret := syscall(SYS_msgget, key, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): msgctl +/* + Send message to a SystemV message queue. + Available since Linux 2.0. +*/ +msgsnd :: proc "contextless" (key: Key, buf: rawptr, size: int, flags: IPC_Flags) -> (Errno) { + ret := syscall(SYS_msgsnd, key, buf, size, transmute(i16) flags) + return Errno(-ret) +} + +/* + Receive a message from a SystemV message queue. + Available since Linux 2.0. +*/ +msgrcv :: proc "contextless" (key: Key, buf: rawptr, size: int, type: uint, flags: IPC_Flags) -> (int, Errno) { + ret := syscall(SYS_msgrcv, key, buf, size, type, transmute(i16) flags) + return errno_unwrap(ret, int) +} + +/* + SystemV message control operations. + Available since Linux 2.0. +*/ +msgctl :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Msqid_DS) -> (int, Errno) { + ret := syscall(SYS_msgctl, key, cmd, buf) + return errno_unwrap(ret, int) +} fcntl_dupfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD, newfd: Fd) -> (Fd, Errno) { ret := syscall(SYS_fcntl, fd, cmd, newfd) @@ -726,7 +974,14 @@ fcntl :: proc { fcntl_set_file_rw_hint, } -// TODO(flysand): flock +/* + Apply or remove advisory lock on an open file. + Available since Linux 2.0. +*/ +flock :: proc "contextless" (fd: Fd, operation: FLock_Op) -> (Errno) { + ret := syscall(SYS_flock, fd, transmute(i32) operation) + return Errno(-ret) +} /// Sync state of the file with the storage device fsync :: proc "contextless" (fd: Fd) -> (Errno) { @@ -734,7 +989,15 @@ fsync :: proc "contextless" (fd: Fd) -> (Errno) { return Errno(-ret) } -// TODO(flysand): fdatasync +/* + Synchronize the state of the file with the storage device. Similar to `fsync`, + except does not flush the metadata. + Available since Linux 2.0. +*/ +fdatasync :: proc "contextless" (fd: Fd) -> (Errno) { + ret := syscall(SYS_fdatasync, fd) + return Errno(-ret) +} /// Truncate a file to specified length /// On 32-bit architectures available since Linux 2.4 @@ -828,7 +1091,19 @@ rmdir :: proc "contextless" (name: cstring) -> (Errno) { } } -// TODO(flysand): creat +/* + Create a file. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ +creat :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { + when ODIN_ARCH == .arm64 { + return openat(AT_FDCWD, name, {.CREAT, .WRONLY,.TRUNC}, mode) + } else { + ret := syscall(SYS_creat, cast(rawptr) name, transmute(u32) mode) + return Errno(-ret) + } +} /// Create a hard link on a file /// Available since Linux 1.0 @@ -949,9 +1224,23 @@ lchown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { } } -// TODO(flysand): umask +/* + Set file mode creation mask. + Available since Linux 1.0. +*/ +umask :: proc "contextless" (mask: Mask) -> Mask { + ret := syscall(SYS_umask, transmute(u32) mask) + return transmute(u32) cast(u32) ret +} -// TODO(flysand): gettimeofday +/* + Get current time. + Available since Linux 1.0. +*/ +gettimeofday :: proc "contextless" (tv: ^Time_Val) -> (Errno) { + ret := syscall(SYS_gettimeofday, tv) + return Errno(-ret) +} /// Get limits on resources /// Available since Linux 1.0 @@ -980,7 +1269,97 @@ times :: proc "contextless" (tms: ^Tms) -> (Errno) { return Errno(-ret) } -// TODO(flysand): ptrace +ptrace_traceme :: proc "contextless" (rq: PTrace_Traceme_Type) -> (Errno) { + ret := syscall(SYS_ptrace, rq) + return Errno(-ret) +} + +ptrace_peek :: proc "contextless" (rq: PTrace_Peek_Type, addr: uintptr) -> (uint, Errno) { + ret := syscall(SYS_ptrace, rq, addr) + return errno_unwrap(rq, uint) +} + +ptrace_poke :: proc "contextless" (rq: PTrace_Poke_Type, addr: uintptr, data: uint) -> (Errno) { + ret := syscall(SYS_ptrace, rq, addr, data) + return Errno(-ret) +} + +ptrace_getregs :: proc "contextless" (rq: PTrace_Getregs_Type, buf: ^User_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, buf) + return Errno(-ret) +} + +ptrace_getfpregs :: proc "contextless" (rq: PTrace_Getfpregs_Type, buf: ^User_FP_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, buf) + return Errno(-ret) +} + +ptrace_getfpxregs :: proc "contextless" (rq: PTrace_Getfpxregs_Type, buf: ^User_FPX_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, buf) + return Errno(-ret) +} + +ptrace_setregs :: proc "contextless" (rq: PTrace_Setregs_Type, buf: ^User_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, buf) + return Errno(-ret) +} + +ptrace_setfpregs :: proc "contextless" (rq: PTrace_Setfpregs_Type, buf: ^User_FP_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, buf) + return Errno(-ret) +} + +ptrace_setfpxregs :: proc "contextless" (rq: PTrace_Setfpxregs_Type, buf: ^User_FPX_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, buf) + return Errno(-ret) +} + +// TODO(flysand): ptrace_getregset +// TODO(flysand): ptrace_setregset +// TODO(flysand): ptrace_setsiginfo +// TODO(flysand): ptrace_peeksiginfo +// TODO(flysand): ptrace_getsigmask +// TODO(flysand): ptrace_setsigmask + +ptrace_setoptions :: proc "contextless" (rq: PTrace_Setoptions_Type, options: PTrace_Options) -> (Errno) { + ret := syscall(SYS_ptrace, rq, 0, transmute(u32) options) + return Errno(-ret) +} + +// TODO(flysand): ptrace_geteventmsg +// TODO(flysand): ptrace_cont +// TODO(flysand): ptrace_syscall +// TODO(flysand): ptrace_singlestep +// TODO(flysand): ptrace_set_syscall +// TODO(flysand): ptrace_sysemu +// TODO(flysand): ptrace_sysemu_singlestep +// TODO(flysand): ptrace_listen +// TODO(flysand): ptrace_kill +// TODO(flysand): ptrace_interrupt +// TODO(flysand): ptrace_attach +// TODO(flysand): ptrace_seize +// TODO(flysand): ptrace_seccomp_get_filter +// TODO(flysand): ptrace_detach +// TODO(flysand): ptrace_get_thread_area +// TODO(flysand): ptrace_set_thread_area +// TODO(flysand): ptrace_get_syscall_info +// TODO(flysand): ptrace_setsigmask + +/* + Trace process +*/ +ptrace :: proc { + ptrace_traceme, + peek, + ptrace_poke, + ptrace_getregs, + ptrace_getfpregs, + ptrace_getfpxregs, + ptrace_setregs, + ptrace_setfpregs, + ptrace_setfpxregs, + ptrace_setoptions, +} /// Get real user ID /// Available since Linux 1.0 @@ -1186,8 +1565,6 @@ getpgid :: proc "contextless" (pid: Pid) -> (Pid, Errno) { return errno_unwrap(ret, Pid) } -// NOTE(flysand): setfsuid and setfsgid are deprecated - /// Get session ID of the calling process /// Available since Linux 2.0 getsid :: proc "contextless" (pid: Pid) -> (Pid, Errno) { @@ -1234,8 +1611,6 @@ sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) -> return Errno(-ret) } -// TODO(flysand): utime - /// Create a special or ordinary file /// `mode` parameter contains both the the file mode and the type of the node to create /// -> Add one of S_IFSOCK, S_IFBLK, S_IFFIFO, S_IFCHR to mode @@ -1251,8 +1626,6 @@ mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) { } } -// TODO(flysand): uselib - /// Set the process execution domain /// Available since Linux 1.2 personality :: proc "contextless" (personality: uint) -> (uint, Errno) { @@ -1414,16 +1787,10 @@ setdomainname :: proc "contextless" (name: string) -> (Errno) { // TODO(flysand): ioperm -// TODO(flysand): create_module - // TODO(flysand): init_module // TODO(flysand): delete_module -// TODO(flysand): get_kernel_syms - -// TODO(flysand): query_module - // TODO(flysand): quotactl // TODO(flysand): nfsservctl @@ -1474,9 +1841,14 @@ gettid :: proc "contextless" () -> Pid { // TODO(flysand): fremovexattr -// TODO(flysand): tkill - -// TODO(flysand): time +/* + Get current time in seconds. + Available since Linux 1.0. +*/ +time :: proc "contextless" (tloc: ^uint) -> (Errno) { + ret := syscall(SYS_time, tloc) + return Errno(-ret) +} /// Wait on a futex until it's signaled futex_wait :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Type, flags: Futex_Flags, val: u32, timeout: ^Time_Spec = nil) -> (Errno) { @@ -1593,8 +1965,6 @@ set_tid_address :: proc "contextless" (tidptr: ^u32) { syscall(SYS_set_tid_address, tidptr) } -// TODO(flysand): restart_syscall - // TODO(flysand): semtimedop // TODO(flysand): fadvise64 @@ -1847,7 +2217,6 @@ dup3 :: proc "contextless" (old: Fd, new: Fd, flags: Open_Flags) -> (Fd, Errno) // TODO(flysand): pwritev - /// Send signal information to a thread /// Available since Linux 2.2 rt_tgsigqueueinfo :: proc "contextless" (tgid: Pid, pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) { @@ -1862,7 +2231,14 @@ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: in return errno_unwrap(ret, Fd) } -// TODO(flysand): recvmmsg +/* + Receive multiple messages from a socket. + Available since Linux 2.6.33. +*/ +recvmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_recvmmsg, sock, raw_data(msg_vec), len(msg_vec), transmute(i32) flags) + return errno_unwrap(ret, int) +} // TODO(flysand): fanotify_init @@ -1878,7 +2254,14 @@ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: in // TODO(flysand): syncfs -// TODO(flysand): sendmmsg +/* + Send multiple messages on a socket. + Available since Linux 3.0. +*/ +sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_sendmmsg, sock, raw_data(msg_vec), len(msg_vec), transmute(i32) flags) + return errno_unwrap(ret, int) +} // TODO(flysand): setns diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index 8789ca2d1..cc3c24075 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -26,6 +26,9 @@ Pid_FD :: distinct i32 /// Used pretty much only in struct Stat64 for 32-bit platforms Inode :: distinct u64 +/// Shared memory identifiers used by `shm*` calls +Key :: distinct i32 + /// Represents time with nanosecond precision Time_Spec :: struct { time_sec: uint, @@ -38,6 +41,15 @@ Time_Val :: struct { microseconds: int, } +/* + Access and modification times for files +*/ +UTim_Buf :: struct { + actime: uint, + modtime: uint, +}; + + /// open.2 flags Open_Flags :: bit_set[Open_Flags_Bits; u32] @@ -235,6 +247,13 @@ FLock :: struct { pid: Pid, } +/* + File locking operations. + Use one of `EX`, `RW` or `UN` to specify the operation, and add `UN` if + you need a non-blocking operation. +*/ +FLock_Op :: bit_set[FLock_Op_Bits; i32] + /// Flags for fcntl_notify FD_Notifications :: bit_set[FD_Notifications_Bits; i32] @@ -496,6 +515,25 @@ Sock_Addr_Any :: struct #raw_union { using ipv6: Sock_Addr_In6, } +/* + Message header for sendmsg/recvmsg +*/ +Msg_Hdr :: struct { + name: rawptr, + namelen: i32, + iov: []IO_Vec, // ptr followed by length, abi matches + control: []u8, + flags: Socket_Msg, +}; + +/* + Multiple message header for sendmmsg/recvmmsg +*/ +MMsg_Hdr :: struct { + hdr: Msg_Hdr, + len: u32, +} + /// Just an alias to make futex-values more visible Futex :: u32 @@ -564,3 +602,417 @@ RUsage :: struct { nvcsw_word: int, nivcsw_word: int, } + +/* + Struct used for IO operations +*/ +IO_Vec :: struct { + base: rawptr, + len: uint, +} + +/* + Access mode for shared memory +*/ +IPC_Mode :: bit_set[IPC_Mode; u32] + +/* + Flags used by IPC objects +*/ +IPC_Flags :: bit_set[IPC_Flags_Bits; i16] + +/* + Permissions for IPC objects +*/ +IPC_Perm :: struct { + key: Key, + uid: u32, + gid: u32, + cuid: u32, + cgid: u32, + mode: IPC_Mode, + seq: u16, + _: [2 + 2*size_of(int)], +} + +when size_of(int) == 8 || ODIN_ARCH == .i386 { + // 32-bit and 64-bit x86, 64-bit arm + _Arch_Shmid_DS :: struct { + perm: IPC_Perm, + segsz: uint, + atime: int, + dtime: int, + ctime: int, + cpid: Pid, + lpid: Pid, + nattch: uint, + _: [2]uint, + } +} else { + // Other 32-bit platforms + // NOTE(flysand): I'm not risking assuming it's little endian... + _Arch_Shmid_DS :: struct { + perm: IPC_Perm, + segsz: uint, + atime: uint, + atime_high: uint, + dtime: uint, + dtime_high: uint, + ctime: uint, + ctime_high: uint, + cpid: Pid, + lpid: Pid, + nattach: uint, + _: [2]uint, + } +} + +/* + SystemV shared memory data. +*/ +Shmid_DS :: _Arch_Shmid_DS + +/* + SystemV shared memory info. +*/ +Shm_Info :: struct { + used_ids: i32 + shm_tot: uint, + shm_rss: uint, + shm_swp: uint, + swap_attempts: uint, + swap_successes: uint, +} + +/* + SystemV semaphore operation. +*/ +Sem_Buf :: struct { + num: u16, + op: IPC_Cmd, + flg: IPC_Flags, +} + +when ODIN_ARCH == .i386 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: uint, + otime_high: uint, + ctime: uint, + ctime_high: uint, + nsems: uint, + _: [2]uint, + } +else when ODIN_ARCH == .amd64 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: int, + ctime: int, + nsems: uint, + _: [2]uint, + } +} else when ODIN_ARCH == .amd32 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: uint, + otime_high: uint, + ctime: uint, + ctime_high: uint, + nsems: uint, + _: [2]uint, + } +} else when ODIN_ARCH == .amd64 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: int, + ctime: int, + sem_nsems: uint, + __unused3: uint, + __unused4: uint, + } +} + +/* + Architecture-specific semaphore data. +*/ +Semid_DS :: _Arch_Semid_DS + +/* + Argument for semctl functions +*/ +Sem_Un :: struct #raw_union { + val: i32, + buf: rawptr, + array: u16, + __buf: Sem_Info, + _: uintptr, +} + +/* + SystenV semaphore info. +*/ +Sem_Info { + map: i32, + mni: i32, + mns: i32, + mnu: i32, + msl: i32, + opm: i32, + ume: i32, + usz: i32, + vmx: i32, + aem: i32, +} + +/* + Template for the struct used for sending and receiving messages +*/ +Msg_Buf :: struct { + type: int, + text: [0]u8, +} + +/* + SystemV message queue data. +*/ +struct Msqid_DS { + perm: IPC_Perm, + stime: uint, + rtime: uint, + ctime: uint, + cbytes: uint, + qnum: uint, + qbytes: uint, + lspid: Pid, + lrpid: Pid, + _: [2]uint +}; + +/* + Interval timer types +*/ +ITimer_Which :: enum { + REAL = 0, + VIRTUAL = 1, + PROF = 2, +} + +/* + Interval timer value +*/ +ITimer_Val :: struct { + interval: Time_Val, + value: Time_Val, +} + +when ODIN_ARCH == .arm32 { + _Arch_User_Regs :: struct { + cpsr: uint, + pc: uint, + lr: uint, + sp: uint, + ip: uint, + fp: uint, + r10: uint, + r9: uint, + r8: uint, + r7: uint, + r6: uint, + r5: uint, + r4: uint, + r3: uint, + r2: uint, + r1: uint, + r0: uint, + ORIG_r0: uint, + } + // TODO(flysand): Idk what to do about these, couldn't find their + // definitions + _Arch_User_FP_Regs :: struct {} + _Arch_User_FPX_Regs :: struct {} +} else when ODIN_ARCH == .arm64 { + _Arch_User_Regs :: struct { + regs: [31]uint, + sp: uint, + pc: uint, + pstate: uint, + } + _Arch_User_FP_Regs :: struct { + vregs: [32]u128, + fpsr: u32, + fpcr: u32, + _: [2]u32 + } + _Arch_User_FPX_Regs :: struct {} +} else when ODIN_ARCH == .i386 { + _Arch_User_Regs :: struct { + ebx: uint, + ecx: uint, + edx: uint, + esi: uint, + edi: uint, + ebp: uint, + eax: uint, + xds: uint, + xes: uint, + xfs: uint, + xgs: uint, + orig_eax: uint, + eip: uint, + xcs: uint, + eflags: uint, + esp: uint, + xss: uint, + } + // x87 FPU state + _Arch_User_FP_Regs :: struct { + cwd: uint, + swd: uint, + twd: uint, + fip: uint, + fcs: uint, + foo: uint, + fos: uint, + st_space: [20]uint, + } + // FXSR instruction set state + _Arch_User_FPX_Regs :: struct { + cwd: u16, + swd: u16, + twd: u16, + fop: u16, + fip: uint, + fcs: uint, + foo: uint, + fos: uint, + mxcsr: uint, + _: uint, + st_space: [32]uint, + xmm_space: [32]uint, + padding: [56]uint, + } +} else when ODIN_ARCH == .amd64 { + _Arch_User_Regs { + // Callee-preserved, may not be correct if the syscall doesn't need + // these registers + r15: uint, + r14: uint, + r13: uint, + r12: uint, + rbp: uint, + rbx: uint, + // Always saved + r11: uint, + r10: uint, + r9: uint, + r8: uint, + rax: uint, + rcx: uint, + rdx: uint, + rsi: uint, + rdi: uint, + // On syscall entry this is the syscall number, on CPU exception this + // is the error code, on hardware interrupt this is its IRQ number + orig_rax: uint, + // Return frame for iretq + rip: uint, + cs: uint, + eflags: uint, + rsp: uint, + ss: uint, + } + // All floating point state + _Arch_User_FP_Regs :: struct { + cwd: u16, + swd: u16, + twd: u16, + fop: u16, + rip: uint, + rdp: uint, + mxcsr: u32, + mxcsr_mask: u32, + st_space: [32]u32, + xmm_space: [64]u32, + _: [24]u32; + } +} + +/* + Architecture-specific registers struct. +*/ +User_Regs :: _Arch_User_Regs + +/* + Architecture-specific floating-point registers +*/ +User_FP_Regs :: _Arch_User_FP_Regs + +/* + Architecture-specific extended floating-point registers. + Currently only used for x86 CPU's. +*/ +User_FPX_Regs :: _Arch_User_FPX_Regs + +/* + ptrace options. +*/ +PTrace_Options :: bit_set[PTrace_Options_Bits; u32] + +/* + ptrace's PEEKSIGINFO argument. +*/ +PTrace_Peek_Sig_Info_Args :: struct { + off: u64, + flags: PTrace_Peek_Sig_Info_Flags, + nr: i32, +} + +/* + ptrace's PEEKSIGINFO flags. +*/ +PTrace_Peek_Sig_Info_Flags :: bit_set[PTrace_Peek_Sig_Info_Flags_Bits, u32] + +/* + ptrace's SECCOMP metadata. +*/ +PTrace_Seccomp_Metadata +{ + filter_off: u64, + flags: u64, +} + +/* + ptrace's results of GET_SYSCALL_INFO. +*/ +PTrace_Syscall_Info :: struct { + op: PTrace_Get_Syscall_Info_Op, + arch: u32, // TODO: AUDIT_ARCH* + instruction_pointer: u64, + stack_pointer: u64, + using _: struct #raw_union { + entry: struct { + nr: u64, + args: [6]u64, + }, + exit: struct { + rval: i64, + is_error: b8, + }, + seccomp: struct { + nr: u64, + args: [6]u64, + ret_data: u32, + }, + }; +}; + +/* + ptrace's results of GET_RSEQ_CONFIGURATION. +*/ +PTrace_RSeq_Configuration { + rseq_abi_pointer: u64, + rseq_abi_size: u32, + signature: u32, + flags: u32, + _: u32, +};
\ No newline at end of file |