432 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			432 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			V
		
	
	
module builtin
 | 
						|
 | 
						|
enum SigIndex {
 | 
						|
	si_signo = 0x00
 | 
						|
	si_code = 0x02
 | 
						|
	si_pid = 0x04
 | 
						|
	si_uid = 0x05
 | 
						|
	si_status = 0x06
 | 
						|
	si_size = 0x80
 | 
						|
}
 | 
						|
 | 
						|
enum Signo {
 | 
						|
	sighup = 1 // Hangup.
 | 
						|
	sigint = 2 // Interactive attention signal.
 | 
						|
	sigquit = 3 // Quit.
 | 
						|
	sigill = 4 // Illegal instruction.
 | 
						|
	sigtrap = 5 // Trace/breakpoint trap.
 | 
						|
	sigabrt = 6 // Abnormal termination.
 | 
						|
	sigbus = 7
 | 
						|
	sigfpe = 8 // Erroneous arithmetic operation.
 | 
						|
	sigkill = 9 // Killed.
 | 
						|
	sigusr1 = 10
 | 
						|
	sigsegv = 11 // Invalid access to memory.
 | 
						|
	sigusr2 = 12
 | 
						|
	sigpipe = 13 // Broken pipe.
 | 
						|
	sigalrm = 14 // Alarm clock.
 | 
						|
	sigterm = 15 // Termination request.
 | 
						|
	sigstkflt = 16
 | 
						|
	sigchld = 17
 | 
						|
	sigcont = 18
 | 
						|
	sigstop = 19
 | 
						|
	sigtstp = 20
 | 
						|
	sigttin = 21 // Background read from control terminal.
 | 
						|
	sigttou = 22 // Background write to control terminal.
 | 
						|
	sigurg = 23
 | 
						|
	sigxcpu = 24 // CPU time limit exceeded.
 | 
						|
	sigxfsz = 25 // File size limit exceeded.
 | 
						|
	sigvtalrm = 26 // Virtual timer expired.
 | 
						|
	sigprof = 27 // Profiling timer expired.
 | 
						|
	sigwinch = 28
 | 
						|
	sigpoll = 29
 | 
						|
	sigsys = 31
 | 
						|
}
 | 
						|
 | 
						|
// List of all the errors returned by syscalls
 | 
						|
enum Errno {
 | 
						|
	enoerror = 0x00000000
 | 
						|
	eperm = 0x00000001
 | 
						|
	enoent = 0x00000002
 | 
						|
	esrch = 0x00000003
 | 
						|
	eintr = 0x00000004
 | 
						|
	eio = 0x00000005
 | 
						|
	enxio = 0x00000006
 | 
						|
	e2big = 0x00000007
 | 
						|
	enoexec = 0x00000008
 | 
						|
	ebadf = 0x00000009
 | 
						|
	echild = 0x0000000a
 | 
						|
	eagain = 0x0000000b
 | 
						|
	enomem = 0x0000000c
 | 
						|
	eacces = 0x0000000d
 | 
						|
	efault = 0x0000000e
 | 
						|
	enotblk = 0x0000000f
 | 
						|
	ebusy = 0x00000010
 | 
						|
	eexist = 0x00000011
 | 
						|
	exdev = 0x00000012
 | 
						|
	enodev = 0x00000013
 | 
						|
	enotdir = 0x00000014
 | 
						|
	eisdir = 0x00000015
 | 
						|
	einval = 0x00000016
 | 
						|
	enfile = 0x00000017
 | 
						|
	emfile = 0x00000018
 | 
						|
	enotty = 0x00000019
 | 
						|
	etxtbsy = 0x0000001a
 | 
						|
	efbig = 0x0000001b
 | 
						|
	enospc = 0x0000001c
 | 
						|
	espipe = 0x0000001d
 | 
						|
	erofs = 0x0000001e
 | 
						|
	emlink = 0x0000001f
 | 
						|
	epipe = 0x00000020
 | 
						|
	edom = 0x00000021
 | 
						|
	erange = 0x00000022
 | 
						|
}
 | 
						|
 | 
						|
enum MemProt {
 | 
						|
	prot_read = 0x1
 | 
						|
	prot_write = 0x2
 | 
						|
	prot_exec = 0x4
 | 
						|
	prot_none = 0x0
 | 
						|
	prot_growsdown = 0x01000000
 | 
						|
	prot_growsup = 0x02000000
 | 
						|
}
 | 
						|
 | 
						|
enum MapFlags {
 | 
						|
	map_shared = 0x01
 | 
						|
	map_private = 0x02
 | 
						|
	map_shared_validate = 0x03
 | 
						|
	map_type = 0x0f
 | 
						|
	map_fixed = 0x10
 | 
						|
	map_file = 0x00
 | 
						|
	map_anonymous = 0x20
 | 
						|
	map_huge_shift = 26
 | 
						|
	map_huge_mask = 0x3f
 | 
						|
}
 | 
						|
 | 
						|
//   const (
 | 
						|
// 	fcntlf_dupfd         = 0x00000000
 | 
						|
// 	fcntlf_exlck         = 0x00000004
 | 
						|
// 	fcntlf_getfd         = 0x00000001
 | 
						|
// 	fcntlf_getfl         = 0x00000003
 | 
						|
// 	fcntlf_getlk         = 0x00000005
 | 
						|
// 	fcntlf_getlk64       = 0x0000000c
 | 
						|
// 	fcntlf_getown        = 0x00000009
 | 
						|
// 	fcntlf_getowner_uids = 0x00000011
 | 
						|
// 	fcntlf_getown_ex     = 0x00000010
 | 
						|
// 	fcntlf_getsig        = 0x0000000b
 | 
						|
// 	fcntlf_ofd_getlk     = 0x00000024
 | 
						|
// 	fcntlf_ofd_setlk     = 0x00000025
 | 
						|
// 	fcntlf_ofd_setlkw    = 0x00000026
 | 
						|
// 	fcntlf_owner_pgrp    = 0x00000002
 | 
						|
// 	fcntlf_owner_pid     = 0x00000001
 | 
						|
// 	fcntlf_owner_tid     = 0x00000000
 | 
						|
// 	fcntlf_rdlck         = 0x00000000
 | 
						|
// 	fcntlf_setfd         = 0x00000002
 | 
						|
// 	fcntlf_setfl         = 0x00000004
 | 
						|
// 	fcntlf_setlk         = 0x00000006
 | 
						|
// 	fcntlf_setlk64       = 0x0000000d
 | 
						|
// 	fcntlf_setlkw        = 0x00000007
 | 
						|
// 	fcntlf_setlkw64      = 0x0000000e
 | 
						|
// 	fcntlf_setown        = 0x00000008
 | 
						|
// 	fcntlf_setown_ex     = 0x0000000f
 | 
						|
// 	fcntlf_setsig        = 0x0000000a
 | 
						|
// 	fcntlf_shlck         = 0x00000008
 | 
						|
// 	fcntlf_unlck         = 0x00000002
 | 
						|
// 	fcntlf_wrlck         = 0x00000001
 | 
						|
// 	fcntllock_ex         = 0x00000002
 | 
						|
// 	fcntllock_mand       = 0x00000020
 | 
						|
// 	fcntllock_nb         = 0x00000004
 | 
						|
// 	fcntllock_read       = 0x00000040
 | 
						|
// 	fcntllock_rw         = 0x000000c0
 | 
						|
// 	fcntllock_sh         = 0x00000001
 | 
						|
// 	fcntllock_un         = 0x00000008
 | 
						|
// 	fcntllock_write      = 0x00000080
 | 
						|
// 	fcntlo_accmode       = 0x00000003
 | 
						|
// 	fcntlo_append        = 0x00000400
 | 
						|
// 	fcntlo_cloexec       = 0x00080000
 | 
						|
// 	fcntlo_creat         = 0x00000040
 | 
						|
// 	fcntlo_direct        = 0x00004000
 | 
						|
// 	fcntlo_directory     = 0x00010000
 | 
						|
// 	fcntlo_dsync         = 0x00001000
 | 
						|
// 	fcntlo_excl          = 0x00000080
 | 
						|
// 	fcntlo_largefile     = 0x00008000
 | 
						|
// 	fcntlo_ndelay        = 0x00000800
 | 
						|
// 	fcntlo_noatime       = 0x00040000
 | 
						|
// 	fcntlo_noctty        = 0x00000100
 | 
						|
// 	fcntlo_nofollow      = 0x00020000
 | 
						|
// 	fcntlo_nonblock      = 0x00000800
 | 
						|
// 	fcntlo_path          = 0x00200000
 | 
						|
// 	fcntlo_rdonly        = 0x00000000
 | 
						|
// 	fcntlo_rdwr          = 0x00000002
 | 
						|
// 	fcntlo_trunc         = 0x00000200
 | 
						|
// 	fcntlo_wronly        = 0x00000001
 | 
						|
// )
 | 
						|
 | 
						|
/*
 | 
						|
Paraphrased from "man 2 waitid" on Linux
 | 
						|
 | 
						|
	Upon successful return, waitid() fills in the
 | 
						|
	following fields of the siginfo_t structure
 | 
						|
	pointed to by infop:
 | 
						|
 | 
						|
	si_pid, offset 0x10, int index 0x04:
 | 
						|
		The process ID of the child.
 | 
						|
 | 
						|
	si_uid: offset 0x14, int index 0x05
 | 
						|
		The real user ID of the child.
 | 
						|
 | 
						|
	si_signo: offset 0x00, int index 0x00
 | 
						|
		Always set to SIGCHLD.
 | 
						|
 | 
						|
	si_status: ofset 0x18, int index 0x06
 | 
						|
		1 the exit status of the child, as given to _exit(2)
 | 
						|
			(or exit(3)) (sc_sys.cld_exited)
 | 
						|
		2 the signal that caused the child to terminate, stop,
 | 
						|
			or continue.
 | 
						|
		3 The si_code field can be used to determine how to
 | 
						|
			interpret this field.
 | 
						|
 | 
						|
	si_code, set to one of (enum Wi_si_code), offset 0x08, int index 0x02:
 | 
						|
		CLD_EXITED (child called _exit(2));
 | 
						|
		CLD_KILLED (child killed by signal);
 | 
						|
		CLD_DUMPED (child  killed by signal, and dumped core);
 | 
						|
		CLD_STOPPED (child stopped by signal);
 | 
						|
		CLD_TRAPPED (traced child has trapped);
 | 
						|
		CLD_CONTINUED (child continued by SIGCONT).
 | 
						|
*/
 | 
						|
 | 
						|
const (
 | 
						|
	wp_sys_wnohang     = u64(0x00000001)
 | 
						|
	wp_sys_wuntraced   = u64(0x00000002)
 | 
						|
	wp_sys_wstopped    = u64(0x00000002)
 | 
						|
	wp_sys_wexited     = u64(0x00000004)
 | 
						|
	wp_sys_wcontinued  = u64(0x00000008)
 | 
						|
	wp_sys_wnowait     = u64(0x01000000) // don't reap, just poll status.
 | 
						|
	wp_sys___wnothread = u64(0x20000000) // don't wait on children of other threads in this group
 | 
						|
	wp_sys___wall      = u64(0x40000000) // wait on all children, regardless of type
 | 
						|
	wp_sys___wclone    = u64(0x80000000) // wait only on non-sigchld children
 | 
						|
)
 | 
						|
 | 
						|
// First argument to waitid:
 | 
						|
enum WiWhich {
 | 
						|
	p_all = 0
 | 
						|
	p_pid = 1
 | 
						|
	p_pgid = 2
 | 
						|
}
 | 
						|
 | 
						|
enum WiSiCode {
 | 
						|
	cld_exited = 1 // child has exited
 | 
						|
	cld_killed = 2 // child was killed
 | 
						|
	cld_dumped = 3 // child terminated abnormally
 | 
						|
	cld_trapped = 4 // traced child has trapped
 | 
						|
	cld_stopped = 5 // child has stopped
 | 
						|
	cld_continued = 6 // stopped child has continued
 | 
						|
}
 | 
						|
 | 
						|
fn split_int_errno(rc_in u64) (i64, Errno) {
 | 
						|
	rc := i64(rc_in)
 | 
						|
	if rc < 0 {
 | 
						|
		return i64(-1), Errno(-rc)
 | 
						|
	}
 | 
						|
	return rc, Errno.enoerror
 | 
						|
}
 | 
						|
 | 
						|
// 0 sys_read
 | 
						|
fn sys_read(fd i64, buf &byte, count u64) (i64, Errno) {
 | 
						|
	return split_int_errno(sys_call3(0, u64(fd), u64(buf), count))
 | 
						|
}
 | 
						|
 | 
						|
// 1 sys_write
 | 
						|
pub fn sys_write(fd i64, buf &byte, count u64) (i64, Errno) {
 | 
						|
	return split_int_errno(sys_call3(1, u64(fd), u64(buf), count))
 | 
						|
}
 | 
						|
 | 
						|
// 2 sys_open
 | 
						|
fn sys_open(filename &byte, flags i64, mode int) (i64, Errno) {
 | 
						|
	return split_int_errno(sys_call3(2, u64(filename), u64(flags), u64(mode)))
 | 
						|
}
 | 
						|
 | 
						|
// 3 sys_close
 | 
						|
fn sys_close(fd i64) Errno {
 | 
						|
	return Errno(-i64(sys_call1(3, u64(fd))))
 | 
						|
}
 | 
						|
 | 
						|
// 9 sys_mmap
 | 
						|
fn sys_mmap(addr &byte, len u64, prot MemProt, flags MapFlags, fildes u64, off u64) (&byte, Errno) {
 | 
						|
	rc := sys_call6(9, u64(addr), len, u64(prot), u64(flags), fildes, off)
 | 
						|
	a, e := split_int_errno(rc)
 | 
						|
	return &byte(a), e
 | 
						|
}
 | 
						|
 | 
						|
// 11 sys_munmap
 | 
						|
fn sys_munmap(addr voidptr, len u64) Errno {
 | 
						|
	return Errno(-sys_call2(11, u64(addr), len))
 | 
						|
}
 | 
						|
 | 
						|
// 22  sys_pipe
 | 
						|
fn sys_pipe(filedes &int) Errno {
 | 
						|
	return Errno(sys_call1(22, u64(filedes)))
 | 
						|
}
 | 
						|
 | 
						|
// 24 sys_sched_yield
 | 
						|
fn sys_sched_yield() Errno {
 | 
						|
	return Errno(sys_call0(24))
 | 
						|
}
 | 
						|
 | 
						|
// 28 sys_madvise
 | 
						|
fn sys_madvise(addr voidptr, len u64, advice int) Errno {
 | 
						|
	return Errno(sys_call3(28, u64(addr), len, u64(advice)))
 | 
						|
}
 | 
						|
 | 
						|
// 39 sys_getpid
 | 
						|
fn sys_getpid() int {
 | 
						|
	return int(sys_call0(39))
 | 
						|
}
 | 
						|
 | 
						|
// 57 sys_fork
 | 
						|
fn sys_fork() int {
 | 
						|
	return int(sys_call0(57))
 | 
						|
}
 | 
						|
 | 
						|
// 58 sys_vfork
 | 
						|
fn sys_vfork() int {
 | 
						|
	return int(sys_call0(58))
 | 
						|
}
 | 
						|
 | 
						|
// 33  sys_dup2
 | 
						|
fn sys_dup2(oldfd int, newfd int) (i64, Errno) {
 | 
						|
	return split_int_errno(sys_call2(33, u64(oldfd), u64(newfd)))
 | 
						|
}
 | 
						|
 | 
						|
// 59  sys_execve
 | 
						|
fn sys_execve(filename &byte, argv []&byte, envp []&byte) int {
 | 
						|
	return int(sys_call3(59, u64(filename), argv.data, envp.data))
 | 
						|
}
 | 
						|
 | 
						|
// 60 sys_exit
 | 
						|
fn sys_exit(ec int) {
 | 
						|
	sys_call1(60, u64(ec))
 | 
						|
}
 | 
						|
 | 
						|
// 102 sys_getuid
 | 
						|
fn sys_getuid() int {
 | 
						|
	return int(sys_call0(102))
 | 
						|
}
 | 
						|
 | 
						|
// 247 sys_waitid
 | 
						|
fn sys_waitid(which WiWhich, pid int, infop &int, options int, ru voidptr) Errno {
 | 
						|
	return Errno(sys_call5(247, u64(which), u64(pid), u64(infop), u64(options), u64(ru)))
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call0(scn u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call1(scn u64, arg1 u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
		  D (arg1)
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call2(scn u64, arg1 u64, arg2 u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
		  D (arg1)
 | 
						|
		  S (arg2)
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call3(scn u64, arg1 u64, arg2 u64, arg3 u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
		  D (arg1)
 | 
						|
		  S (arg2)
 | 
						|
		  d (arg3)
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call4(scn u64, arg1 u64, arg2 u64, arg3 u64, arg4 u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		mov r10, arg4
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
		  D (arg1)
 | 
						|
		  S (arg2)
 | 
						|
		  d (arg3)
 | 
						|
		  r (arg4)
 | 
						|
		; r10
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call5(scn u64, arg1 u64, arg2 u64, arg3 u64, arg4 u64, arg5 u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		mov r10, arg4
 | 
						|
		mov r8, arg5
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
		  D (arg1)
 | 
						|
		  S (arg2)
 | 
						|
		  d (arg3)
 | 
						|
		  r (arg4)
 | 
						|
		  r (arg5)
 | 
						|
		; r10
 | 
						|
		  r8
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
fn sys_call6(scn u64, arg1 u64, arg2 u64, arg3 u64, arg4 u64, arg5 u64, arg6 u64) u64 {
 | 
						|
	mut res := u64(0)
 | 
						|
	asm amd64 {
 | 
						|
		mov r10, arg4
 | 
						|
		mov r8, arg5
 | 
						|
		mov r9, arg6
 | 
						|
		syscall
 | 
						|
		; =a (res)
 | 
						|
		; a (scn)
 | 
						|
		  D (arg1)
 | 
						|
		  S (arg2)
 | 
						|
		  d (arg3)
 | 
						|
		  r (arg4)
 | 
						|
		  r (arg5)
 | 
						|
		  r (arg6)
 | 
						|
		; r10
 | 
						|
		  r8
 | 
						|
		  r9
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
asm amd64 {
 | 
						|
	.globl _start
 | 
						|
	_start:
 | 
						|
	call main
 | 
						|
	mov rax, 60
 | 
						|
	xor rdi, rdi
 | 
						|
	syscall
 | 
						|
	ret
 | 
						|
}
 |