Переглянути джерело

[sys/linux]: Add more syscalls

flysand7 1 рік тому
батько
коміт
1e622979f8
3 змінених файлів з 356 додано та 56 видалено
  1. 51 1
      core/sys/linux/bits.odin
  2. 231 54
      core/sys/linux/sys.odin
  3. 74 1
      core/sys/linux/types.odin

+ 51 - 1
core/sys/linux/bits.odin

@@ -1567,4 +1567,54 @@ PTrace_Get_Syscall_Info_Op :: enum u8 {
 */
 PTrace_Peek_Sig_Info_Flags_Bits :: enum {
 	SHARED = 0,
-}
+}
+
+/*
+	Syslog actions.
+*/
+Syslog_Action :: enum i32 {
+	CLOSE         = 0,
+	OPEN          = 1,
+	READ          = 2,
+	READ_ALL      = 3,
+	READ_CLEAR    = 4,
+	CLEAR         = 5,
+	CONSOLE_OFF   = 6,
+	CONSOLE_ON    = 7,
+	CONSOLE_LEVEL = 8,
+	SIZE_UNREAD   = 9,
+	SIZE_BUFFER   = 10,
+}
+
+/*
+	Bits for splice flags.
+*/
+Splice_Flags_Bits :: enum {
+	MOVE     = 0x01,
+	NONBLOCK = 0x02,
+	MORE     = 0x04,
+	GIFT     = 0x08,
+}
+
+/*
+	Clock IDs for various system clocks.
+*/
+Clock_ID :: enum {
+	REALTIME           = 0,
+	MONOTONIC          = 1,
+	PROCESS_CPUTIME_ID = 2,
+	THREAD_CPUTIME_ID  = 3,
+	MONOTONIC_RAW      = 4,
+	REALTIME_COARSE    = 5,
+	MONOTONIC_COARSE   = 6,
+	BOOTTIME           = 7,
+	REALTIME_ALARM     = 8,
+	BOOTTIME_ALARM     = 9,
+}
+
+/*
+	Bits for POSIX interval timer flags.
+*/
+ITimer_Flags_Bits :: enum {
+	ABSTIME = 1,
+}

+ 231 - 54
core/sys/linux/sys.odin

@@ -1274,83 +1274,148 @@ ptrace_traceme :: proc "contextless" (rq: PTrace_Traceme_Type) -> (Errno) {
 	return Errno(-ret)
 }
 
-ptrace_peek :: proc "contextless" (rq: PTrace_Peek_Type, addr: uintptr) -> (uint, Errno) {
-	ret := syscall(SYS_ptrace, rq, addr)
+ptrace_peek :: proc "contextless" (rq: PTrace_Peek_Type, pid: Pid, addr: uintptr) -> (uint, Errno) {
+	ret := syscall(SYS_ptrace, rq, pid: Pid, addr, pid)
 	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)
+ptrace_poke :: proc "contextless" (rq: PTrace_Poke_Type, pid: Pid, addr: uintptr, data: uint) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid: Pid, addr, data)
 	return Errno(-ret)
 }
 
-ptrace_getregs :: proc "contextless" (rq: PTrace_Getregs_Type, buf: ^User_Regs) -> (Errno) {
-	ret := syscall(SYS_ptrace, rq, 0, buf)
+ptrace_getregs :: proc "contextless" (rq: PTrace_Getregs_Type, pid: Pid, buf: ^User_Regs) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 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)
+ptrace_getfpregs :: proc "contextless" (rq: PTrace_Getfpregs_Type, pid: Pid, buf: ^User_FP_Regs) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 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)
+ptrace_getfpxregs :: proc "contextless" (rq: PTrace_Getfpxregs_Type, pid: Pid, buf: ^User_FPX_Regs) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 0, buf)
 	return Errno(-ret)
 }
 
-ptrace_setregs :: proc "contextless" (rq: PTrace_Setregs_Type, buf: ^User_Regs) -> (Errno) {
-	ret := syscall(SYS_ptrace, rq, 0, buf)
+ptrace_setregs :: proc "contextless" (rq: PTrace_Setregs_Type, pid: Pid, buf: ^User_Regs) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 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)
+ptrace_setfpregs :: proc "contextless" (rq: PTrace_Setfpregs_Type, pid: Pid, buf: ^User_FP_Regs) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 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)
+ptrace_setfpxregs :: proc "contextless" (rq: PTrace_Setfpxregs_Type, pid: Pid, buf: ^User_FPX_Regs) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 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_getregset :: proc "contextless" (rq: PTrace_Getgetset_Type, pid: Pid, note: PTrace_Note_Type, buf: ^IO_Vec) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, note, buf)
+	return Errno(-ret)
+}
+
+ptrace_setregset :: proc "contextless" (rq: PTrace_Setgetset_Type, pid: Pid, note: PTrace_Note_Type, buf: ^IO_Vec) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, note, buf)
+	return Errno(-ret)
+}
+
+ptrace_getsiginfo :: proc "contextless" (rq: PTrace_Getsiginfo_Type, pid: Pid, si: ^Sig_Info) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, si)
+	return Errno(-ret)
+}
+
+ptrace_peeksiginfo :: proc "contextless" (rq: PTrace_Peeksiginfo_Type, pid: Pid, si: ^Sig_Info) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, si)
+	return Errno(-ret)
+}
+
+ptrace_getsigmask :: proc "contextless" (rq: PTrace_Getsigmask, pid: Pid, sigmask: ^Sig_Mask) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, size_of(Sig_Mask), sigmask)
+	return Errno(-ret)
+}
+
+ptrace_setsigmask :: proc "contextless" (rq: PTrace_Setsigmask, pid: Pid, sigmask: ^Sig_Mask) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, size_of(Sig_Mask), sigmask)
+	return Errno(-ret)
+}
+
+ptrace_setoptions :: proc "contextless" (rq: PTrace_Setoptions_Type, pid: Pid, options: PTrace_Options) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 0, transmute(u32) options)
+	return Errno(-ret)
+}
+
+ptrace_geteventmsg :: proc "contextless" (rq: PTrace_Geteventmsg_Type, pid: Pid, msg: ^uint) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, msg)
+	return Errno(-ret)
+}
+
+ptrace_cont :: proc "contextless" (rq: PTrace_Cont_Type, pid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, sig)
+	return Errno(-ret)
+}
+
+ptrace_singlestep :: proc "contextless" (rq: PTrace_Singlestep_Type, pid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, sig)
+	return Errno(-ret)
+}
 
-ptrace_setoptions :: proc "contextless" (rq: PTrace_Setoptions_Type, options: PTrace_Options) -> (Errno) {
-	ret := syscall(SYS_ptrace, rq, 0, transmute(u32) options)
+ptrace_syscall :: proc "contextless" (rq: PTrace_Syscall_Type, pid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, sig)
+	return Errno(-ret)
+}
+
+ptrace_sysemu :: proc "contextless" (rq: PTrace_Sysemu_Type, pid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, sig)
+	return Errno(-ret)
+}
+
+ptrace_sysemu_singlestep :: proc "contextless" (rq: PTrace_Sysemu_Singlestep_Type, pid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, sig)
+	return Errno(-ret)
+}
+
+ptrace_listen :: proc "contextless" (rq: PTrace_Listen_Type, pid: Pid) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid)
+	return Errno(-ret)
+}
+
+ptrace_interrupt :: proc "contextless" (rq: PTrace_Interrupt_Type, pid: Pid) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid)
+	return Errno(-ret)
+}
+
+ptrace_attach :: proc "contextless" (rq: PTrace_Attach_Type, pid: Pid) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid)
+	return Errno(-ret)
+}
+
+ptrace_seize :: proc "contextless" (rq: PTrace_Seize_Type, pid: Pid, opt: PTrace_Options) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 0, transmute(u32) opt)
 	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
+
+ptrace_detach :: proc "contextless" (rq: PTrace_Detach_Type, pid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_ptrace, rq, pid, 0, sig)
+	return Errno(-ret)
+}
+
 // TODO(flysand): ptrace_get_thread_area
 // TODO(flysand): ptrace_set_thread_area
 // TODO(flysand): ptrace_get_syscall_info
-// TODO(flysand): ptrace_setsigmask
 
 /*
-	Trace process
+	Trace process.
 */
 ptrace :: proc {
 	ptrace_traceme,
-	peek,
+	ptrace_peek,
 	ptrace_poke,
 	ptrace_getregs,
 	ptrace_getfpregs,
@@ -1358,7 +1423,24 @@ ptrace :: proc {
 	ptrace_setregs,
 	ptrace_setfpregs,
 	ptrace_setfpxregs,
+	ptrace_getregset,
+	ptrace_setregset,
+	ptrace_getsiginfo,
+	ptrace_peeksiginfo,
+	ptrace_getsigmask,
+	ptrace_setsigmask,
 	ptrace_setoptions,
+	ptrace_geteventmsg,
+	ptrace_cont,
+	ptrace_singlestep,
+	ptrace_syscall,
+	ptrace_sysemu,
+	ptrace_sysemu_singlestep,
+	ptrace_listen,
+	ptrace_interrupt,
+	ptrace_attach,
+	ptrace_seize,
+	ptrace_detach,
 }
 
 /// Get real user ID
@@ -1372,7 +1454,15 @@ getuid :: proc "contextless" () -> Uid {
 	}
 }
 
-// TODO(flysand): syslog
+/*
+	Read or clear kernel message ring buffer.
+	Available since Linux 1.0.
+*/
+syslog :: proc "contextless" (act: Syslog_Action, buf: []u8) -> (int, Errno) {
+	ret := syscall(SYS_syslog, act, raw_data(buf), len(buf))
+	return errno_unwrap(ret, int)
+}
+
 
 /// Get real group ID
 /// Available since Linux 1.0
@@ -1498,9 +1588,35 @@ setregid :: proc "contextless" (real: Gid, effective: Gid) -> (Errno) {
 	}
 }
 
-// TODO(flysand): getgroups
+/*
+	Get supplementary group IDs.
+	Available since Linux 1.0.
+	On 32-bit platforms available since Linux 2.4.
+*/
+getgroups :: proc "contextless" (gids: []Gid) -> (int, Errno) {
+	when size_of(int) == 8 {
+		ret := syscall(SYS_getgroups, len(gids), rawptr(gids))
+		return errno_unwrap(ret, int)
+	} else {
+		ret := syscall(SYS_getgroups32, len(gids), rawptr(gids))
+		return errno_unwrap(ret, int)
+	}
+}
 
-// TODO(flysand): setgroups
+/*
+	Set supplementary group IDs.
+	Available since Linux 1.0.
+	On 32-bit platforms available since Linux 2.4.
+*/
+setgroups :: proc "contextless" (gids: []Gid) -> (Errno) {
+	when size_of(int) == 8 {
+		ret := syscall(SYS_setgroup, len(gids), rawptr(gids))
+		return Errno(-ret)
+	} else {
+		ret := syscall(SYS_setgroup32, len(gids), rawptr(gids))
+		return Errno(-ret)
+	}
+}
 
 /// Set real, effective and/or saved user id
 /// If any of the arguments is -1, the corresponding id is not changed
@@ -1969,15 +2085,50 @@ set_tid_address :: proc "contextless" (tidptr: ^u32) {
 
 // TODO(flysand): fadvise64
 
-// TODO(flysand): timer_create
+/*
+	Create POSIX per-process timer.
+	Available since Linux 2.6.
+*/
+timer_create :: proc "contextless" (clock_id: Clock_Id, sigevent: ^Sig_Event, timer: ^Timer) -> (Errno) {
+	ret := syscall(SYS_timer_create, clock_id, sigevent, timer)
+	return Errno(-ret)
+}
 
-// TODO(flysand): timer_settime
+/*
+	Get the state of the POSIX per-process timer.
+	Available since Linux 2.6.
+*/
+timer_gettime :: proc "contextless" (timer: Timer, curr_value: ^ITimer_Spec) -> (Errno) {
+	ret := syscall(SYS_timer_gettime, timer, curr_value)
+	return Errno(-ret)
+}
 
-// TODO(flysand): timer_gettime
+/*
+	Arm/disarm the state of the POSIX per-process timer.
+	Available since Linux 2.6.
+*/
+timer_settime :: proc "contextless" (timer: Timer, flags: ITimer_Flags, #no_alias new_value, old_value: ^ITimer_Spec) -> (Errno) {
+	ret := syscall(SYS_timer_settime, timer, transmute(u32) flags, new_value, old_value)
+	return Errno(-ret)
+}
 
-// TODO(flysand): timer_getoverrun
+/*
+	Get overrun count of the POSIX per-process timer.
+	Available since Linux 2.6.
+*/
+timer_getoverrun :: proc "contextless" (timer: Timer) -> (int, Errno) {
+	ret := syscall(SYS_timer_getoverrun, timer)
+	return errno_unwrap(ret, int)
+}
 
-// TODO(flysand): timer_delete
+/*
+	Delete a POSIX per-process timer.
+	Available since Linux 2.6.
+*/
+timer_delete :: proc "contextless" (timer: Timer) -> (Errno) {
+	ret := syscall(SYS_timer_delete, timer)
+	return Errno(-ret)
+}
 
 // TODO(flysand): clock_settime
 
@@ -1998,7 +2149,14 @@ exit_group :: proc "contextless" (code: i32) -> ! {
 
 // TODO(flysand): epoll_ctl
 
-// TODO(flysand): tgkill
+/*
+	Send a signal to a specific thread in a thread group.
+	Available since Linux 2.6.
+*/
+tgkill :: proc "contextless" (tgid, tid: Pid, sig: Signal) -> (Errno) {
+	ret := syscall(SYS_tgkill, tgid, tid, sig)
+	return Errno(-ret)
+}
 
 // TODO(flysand): utimes
 
@@ -2078,8 +2236,6 @@ fchownat :: proc "contextless" (dirfd: Fd, name: cstring, uid: Uid, gid: Gid) ->
 	return Errno(-ret)
 }
 
-// TODO(flysand): futimesat
-
 /// Get information about a file at a specific directory
 /// Available since Linux 2.6.16
 fstatat :: proc "contextless" (dirfd: Fd, name: cstring, stat: ^Stat, flags: FD_Flags) -> (Errno) {
@@ -2164,9 +2320,23 @@ ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_
 
 // TODO(flysand): get_robust_list
 
-// TODO(flysand): splice
+/*
+	Transfer the data between file descriptors.
+	Available since Linux 2.6.17.
+*/
+splice :: proc "contextless" (fd_in: Fd, off_in: ^i64, fd_out: Fd, off_out: ^i64, len: uint, flags: Splice_Flags) -> (int, Errno) {
+	ret := syscall(SYS_splice, fd_in, off_in, fd_out, off_out, len, transmute(u32) flags)
+	return errno_unwrap(ret, int)
+}
 
-// TODO(flysand): tee
+/*
+	Transfer the data between file descriptors.
+	Available since Linux 2.6.16.
+*/
+tee :: proc "contextless" (fd_in: Fd, fd_out: Fd, len: uint, flags: Splice_Flags) -> (int, Errno) {
+	ret := syscall(SYS_tee, fd_in, fd_out, len, transmute(u32) flags)
+	return errno_unwrap(ret, int)
+}
 
 // TODO(flysand): sync_file_range
 
@@ -2299,7 +2469,14 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er
 
 // TODO(flysand): bpf
 
-// TODO(flysand): execveat
+/*
+	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)
+	return Errno(-ret)
+}
 
 // TODO(flysand): userfaultfd
 

+ 74 - 1
core/sys/linux/types.odin

@@ -29,6 +29,11 @@ Inode :: distinct u64
 /// Shared memory identifiers used by `shm*` calls
 Key :: distinct i32
 
+/*
+	Represents timer IDs
+*/
+Timer :: distinct i32
+
 /// Represents time with nanosecond precision
 Time_Spec :: struct {
 	time_sec:  uint,
@@ -458,6 +463,28 @@ Sig_Info :: struct #packed {
 	},
 }
 
+SIGEV_MAX_SIZE :: 64
+SIGEV_PAD_SIZE :: ((SIGEV_MAX_SIZE-size_of(i32)*2+size_of(Sig_Val))/size_of(i32))
+
+Sig_Val :: struct #raw_union {
+	sival_int: i32,
+	sival_ptr: rawptr,
+}
+
+Sig_Event :: struct {
+	value:  Sig_Val,
+	signo:  i32,
+	notify: i32,
+	using: struct #raw_union {
+		_: [SIGEV_PAD_SIZE]u32,
+		thread_id: Pid,
+		using _: struct {
+			notify_function:  #type proc "c" (val: Sig_Val),
+			notify_attribute: rawptr,
+		},
+	},
+}
+
 Sig_Stack_Flags :: bit_set[Sig_Stack_Flag; i32]
 
 Sig_Stack :: struct {
@@ -805,6 +832,16 @@ ITimer_Val :: struct {
 	value:    Time_Val,
 }
 
+ITimer_Spec {
+	interval: Time_Spec,
+	value:    Time_Spec,
+}
+
+/*
+	Flags for POSIX interval timers.
+*/
+ITimer_Flags :: bit_set[ITimer_Flags_Bits, u32]
+
 when ODIN_ARCH == .arm32 {
 	_Arch_User_Regs :: struct {
 		cpsr:             uint,
@@ -1015,4 +1052,40 @@ PTrace_RSeq_Configuration {
 	signature:        u32,
 	flags:            u32,
 	_:                u32,
-};
+};
+
+/*
+	Note types for PTRACE_GETREGSET. Mirrors constants in `elf` definition,
+	files though this enum only contains the constants defined for architectures
+	Odin can compile to.
+*/
+PTrace_Note_Type :: enum {
+	NT_PRSTATUS             = 1,
+	NT_PRFPREG              = 2,
+	NT_PRPSINFO             = 3,
+	NT_TASKSTRUCT           = 4,
+	NT_AUXV                 = 6,
+	NT_SIGINFO              = 0x53494749,
+	NT_FILE                 = 0x46494c45,
+	NT_PRXFPREG             = 0x46e62b7f,
+	NT_386_TLS              = 0x200,
+	NT_386_IOPERM           = 0x201,
+	NT_X86_XSTATE           = 0x202,
+	NT_X86_SHSTK            = 0x204,
+	NT_ARM_VFP              = 0x400,
+	NT_ARM_TLS              = 0x401,
+	NT_ARM_HW_BREAK         = 0x402,
+	NT_ARM_HW_WATCH         = 0x403,
+	NT_ARM_SYSTEM_CALL      = 0x404,
+	NT_ARM_SVE              = 0x405,
+	NT_ARM_PAC_MASK         = 0x406,
+	NT_ARM_PACA_KEYS        = 0x407,
+	NT_ARM_PACG_KEYS        = 0x408,
+	NT_ARM_TAGGED_ADDR_CTRL = 0x409,
+	NT_ARM_PAC_ENABLED_KEYS = 0x40a,
+	NT_ARM_SSVE             = 0x40b,
+	NT_ARM_ZA               = 0x40c,
+	NT_ARM_ZT               = 0x40d,
+}
+
+Splice_Flags :: bit_set[Splice_Flags_Bits; u32]