Parcourir la source

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

jason il y a 1 an
Parent
commit
f22754fc90
3 fichiers modifiés avec 182 ajouts et 76 suppressions
  1. 75 40
      core/sys/linux/bits.odin
  2. 31 16
      core/sys/linux/sys.odin
  3. 76 20
      core/sys/linux/types.odin

+ 75 - 40
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`
 */

+ 31 - 16
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)
@@ -200,10 +200,25 @@ brk :: proc "contextless" (addr: uintptr) -> (Errno) {
 	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.
 */
-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)
 }
 

+ 76 - 20
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,
 	}
 }