v2 / vlib / builtin / linux_bare / linux_syscalls.v
445 lines · 399 sloc · 10.31 KB · 2bcab3c78f5edad219ae84837c3e054c4c91c1fb
Raw
1module builtin
2
3enum SigIndex {
4 si_signo = 0x00
5 si_code = 0x02
6 si_pid = 0x04
7 si_uid = 0x05
8 si_status = 0x06
9 si_size = 0x80
10}
11
12enum Signo {
13 sighup = 1 // Hangup.
14 sigint = 2 // Interactive attention signal.
15 sigquit = 3 // Quit.
16 sigill = 4 // Illegal instruction.
17 sigtrap = 5 // Trace/breakpoint trap.
18 sigabrt = 6 // Abnormal termination.
19 sigbus = 7
20 sigfpe = 8 // Erroneous arithmetic operation.
21 sigkill = 9 // Killed.
22 sigusr1 = 10
23 sigsegv = 11 // Invalid access to memory.
24 sigusr2 = 12
25 sigpipe = 13 // Broken pipe.
26 sigalrm = 14 // Alarm clock.
27 sigterm = 15 // Termination request.
28 sigstkflt = 16
29 sigchld = 17
30 sigcont = 18
31 sigstop = 19
32 sigtstp = 20
33 sigttin = 21 // Background read from control terminal.
34 sigttou = 22 // Background write to control terminal.
35 sigurg = 23
36 sigxcpu = 24 // CPU time limit exceeded.
37 sigxfsz = 25 // File size limit exceeded.
38 sigvtalrm = 26 // Virtual timer expired.
39 sigprof = 27 // Profiling timer expired.
40 sigwinch = 28
41 sigpoll = 29
42 sigsys = 31
43}
44
45// List of all the errors returned by syscalls
46enum Errno {
47 enoerror = 0x00000000
48 eperm = 0x00000001
49 enoent = 0x00000002
50 esrch = 0x00000003
51 eintr = 0x00000004
52 eio = 0x00000005
53 enxio = 0x00000006
54 e2big = 0x00000007
55 enoexec = 0x00000008
56 ebadf = 0x00000009
57 echild = 0x0000000a
58 eagain = 0x0000000b
59 enomem = 0x0000000c
60 eacces = 0x0000000d
61 efault = 0x0000000e
62 enotblk = 0x0000000f
63 ebusy = 0x00000010
64 eexist = 0x00000011
65 exdev = 0x00000012
66 enodev = 0x00000013
67 enotdir = 0x00000014
68 eisdir = 0x00000015
69 einval = 0x00000016
70 enfile = 0x00000017
71 emfile = 0x00000018
72 enotty = 0x00000019
73 etxtbsy = 0x0000001a
74 efbig = 0x0000001b
75 enospc = 0x0000001c
76 espipe = 0x0000001d
77 erofs = 0x0000001e
78 emlink = 0x0000001f
79 epipe = 0x00000020
80 edom = 0x00000021
81 erange = 0x00000022
82}
83
84enum MemProt {
85 prot_read = 0x1
86 prot_write = 0x2
87 prot_exec = 0x4
88 prot_none = 0x0
89 prot_growsdown = 0x01000000
90 prot_growsup = 0x02000000
91}
92
93enum MapFlags {
94 map_shared = 0x01
95 map_private = 0x02
96 map_shared_validate = 0x03
97 map_type = 0x0f
98 map_fixed = 0x10
99 map_file = 0x00
100 map_anonymous = 0x20
101 map_huge_shift = 26
102 map_huge_mask = 0x3f
103}
104
105// const (
106// fcntlf_dupfd = 0x00000000
107// fcntlf_exlck = 0x00000004
108// fcntlf_getfd = 0x00000001
109// fcntlf_getfl = 0x00000003
110// fcntlf_getlk = 0x00000005
111// fcntlf_getlk64 = 0x0000000c
112// fcntlf_getown = 0x00000009
113// fcntlf_getowner_uids = 0x00000011
114// fcntlf_getown_ex = 0x00000010
115// fcntlf_getsig = 0x0000000b
116// fcntlf_ofd_getlk = 0x00000024
117// fcntlf_ofd_setlk = 0x00000025
118// fcntlf_ofd_setlkw = 0x00000026
119// fcntlf_owner_pgrp = 0x00000002
120// fcntlf_owner_pid = 0x00000001
121// fcntlf_owner_tid = 0x00000000
122// fcntlf_rdlck = 0x00000000
123// fcntlf_setfd = 0x00000002
124// fcntlf_setfl = 0x00000004
125// fcntlf_setlk = 0x00000006
126// fcntlf_setlk64 = 0x0000000d
127// fcntlf_setlkw = 0x00000007
128// fcntlf_setlkw64 = 0x0000000e
129// fcntlf_setown = 0x00000008
130// fcntlf_setown_ex = 0x0000000f
131// fcntlf_setsig = 0x0000000a
132// fcntlf_shlck = 0x00000008
133// fcntlf_unlck = 0x00000002
134// fcntlf_wrlck = 0x00000001
135// fcntllock_ex = 0x00000002
136// fcntllock_mand = 0x00000020
137// fcntllock_nb = 0x00000004
138// fcntllock_read = 0x00000040
139// fcntllock_rw = 0x000000c0
140// fcntllock_sh = 0x00000001
141// fcntllock_un = 0x00000008
142// fcntllock_write = 0x00000080
143// fcntlo_accmode = 0x00000003
144// fcntlo_append = 0x00000400
145// fcntlo_cloexec = 0x00080000
146// fcntlo_creat = 0x00000040
147// fcntlo_direct = 0x00004000
148// fcntlo_directory = 0x00010000
149// fcntlo_dsync = 0x00001000
150// fcntlo_excl = 0x00000080
151// fcntlo_largefile = 0x00008000
152// fcntlo_ndelay = 0x00000800
153// fcntlo_noatime = 0x00040000
154// fcntlo_noctty = 0x00000100
155// fcntlo_nofollow = 0x00020000
156// fcntlo_nonblock = 0x00000800
157// fcntlo_path = 0x00200000
158// fcntlo_rdonly = 0x00000000
159// fcntlo_rdwr = 0x00000002
160// fcntlo_trunc = 0x00000200
161// fcntlo_wronly = 0x00000001
162// )
163
164/*
165Paraphrased from "man 2 waitid" on Linux
166
167 Upon successful return, waitid() fills in the
168 following fields of the siginfo_t structure
169 pointed to by infop:
170
171 si_pid, offset 0x10, int index 0x04:
172 The process ID of the child.
173
174 si_uid: offset 0x14, int index 0x05
175 The real user ID of the child.
176
177 si_signo: offset 0x00, int index 0x00
178 Always set to SIGCHLD.
179
180 si_status: ofset 0x18, int index 0x06
181 1 the exit status of the child, as given to _exit(2)
182 (or exit(3)) (sc_sys.cld_exited)
183 2 the signal that caused the child to terminate, stop,
184 or continue.
185 3 The si_code field can be used to determine how to
186 interpret this field.
187
188 si_code, set to one of (enum Wi_si_code), offset 0x08, int index 0x02:
189 CLD_EXITED (child called _exit(2));
190 CLD_KILLED (child killed by signal);
191 CLD_DUMPED (child killed by signal, and dumped core);
192 CLD_STOPPED (child stopped by signal);
193 CLD_TRAPPED (traced child has trapped);
194 CLD_CONTINUED (child continued by SIGCONT).
195*/
196
197const wp_sys_wnohang = u64(0x00000001)
198const wp_sys_wuntraced = u64(0x00000002)
199const wp_sys_wstopped = u64(0x00000002)
200const wp_sys_wexited = u64(0x00000004)
201const wp_sys_wcontinued = u64(0x00000008)
202const wp_sys_wnowait = u64(0x01000000) // don't reap, just poll status.
203
204const wp_sys___wnothread = u64(0x20000000) // don't wait on children of other threads in this group
205
206const wp_sys___wall = u64(0x40000000) // wait on all children, regardless of type
207
208const wp_sys___wclone = u64(0x80000000)
209
210// First argument to waitid:
211enum WiWhich {
212 p_all = 0
213 p_pid = 1
214 p_pgid = 2
215}
216
217enum WiSiCode {
218 cld_exited = 1 // child has exited
219 cld_killed = 2 // child was killed
220 cld_dumped = 3 // child terminated abnormally
221 cld_trapped = 4 // traced child has trapped
222 cld_stopped = 5 // child has stopped
223 cld_continued = 6 // stopped child has continued
224}
225
226$if !i386 {
227 fn split_int_errno(rc_in u64) (i64, Errno) {
228 rc := i64(rc_in)
229 if rc < 0 {
230 return i64(-1), unsafe { Errno(-rc) }
231 }
232 return rc, Errno.enoerror
233 }
234
235 // 0 sys_read
236 fn sys_read(fd i64, buf &u8, count u64) (i64, Errno) {
237 return split_int_errno(sys_call3(0, u64(fd), u64(buf), count))
238 }
239
240 // 1 sys_write
241 pub fn sys_write(fd i64, buf &u8, count u64) (i64, Errno) {
242 return split_int_errno(sys_call3(1, u64(fd), u64(buf), count))
243 }
244
245 // 2 sys_open
246 fn sys_open(filename &u8, flags i64, mode int) (i64, Errno) {
247 return split_int_errno(sys_call3(2, u64(filename), u64(flags), u64(mode)))
248 }
249
250 // 3 sys_close
251 fn sys_close(fd i64) Errno {
252 return unsafe { Errno(-i64(sys_call1(3, u64(fd)))) }
253 }
254
255 // 9 sys_mmap
256 fn sys_mmap(addr &u8, len u64, prot MemProt, flags MapFlags, fildes i64, off u64) (&u8, Errno) {
257 rc := sys_call6(9, u64(addr), len, u64(prot), u64(flags), fildes, off)
258 a, e := split_int_errno(rc)
259 return unsafe { &u8(a) }, e
260 }
261
262 // 11 sys_munmap
263 fn sys_munmap(addr voidptr, len u64) Errno {
264 return unsafe { Errno(-sys_call2(11, u64(addr), len)) }
265 }
266
267 // 25 sys_mremap
268 fn sys_mremap(old_addr voidptr, old_len u64, new_len u64, flags u64) (&u8, Errno) {
269 rc := sys_call4(25, u64(old_addr), old_len, new_len, flags)
270 a, e := split_int_errno(rc)
271 return unsafe { &u8(a) }, e
272 }
273
274 // 22 sys_pipe
275 fn sys_pipe(filedes &int) Errno {
276 return unsafe { Errno(sys_call1(22, u64(filedes))) }
277 }
278
279 // 24 sys_sched_yield
280 fn sys_sched_yield() Errno {
281 return unsafe { Errno(sys_call0(24)) }
282 }
283
284 // 28 sys_madvise
285 fn sys_madvise(addr voidptr, len u64, advice int) Errno {
286 return unsafe { Errno(sys_call3(28, u64(addr), len, u64(advice))) }
287 }
288
289 // 39 sys_getpid
290 fn sys_getpid() int {
291 return int(sys_call0(39))
292 }
293
294 // 57 sys_fork
295 fn sys_fork() int {
296 return int(sys_call0(57))
297 }
298
299 // 58 sys_vfork
300 fn sys_vfork() int {
301 return int(sys_call0(58))
302 }
303
304 // 33 sys_dup2
305 fn sys_dup2(oldfd int, newfd int) (i64, Errno) {
306 return split_int_errno(sys_call2(33, u64(oldfd), u64(newfd)))
307 }
308
309 // 59 sys_execve
310 fn sys_execve(filename &u8, argv []&u8, envp []&u8) int {
311 return int(sys_call3(59, u64(filename), u64(argv.data), u64(envp.data)))
312 }
313
314 // 60 sys_exit
315 @[noreturn]
316 fn sys_exit(ec int) {
317 sys_call1(60, u64(ec))
318 for {}
319 }
320
321 // 102 sys_getuid
322 fn sys_getuid() int {
323 return int(sys_call0(102))
324 }
325
326 // 247 sys_waitid
327 fn sys_waitid(which WiWhich, pid int, infop &int, options int, ru voidptr) Errno {
328 return unsafe {
329 Errno(sys_call5(247, u64(which), u64(pid), u64(infop), u64(options), u64(ru)))
330 }
331 }
332
333 fn sys_call0(scn u64) u64 {
334 mut res := u64(0)
335 asm amd64 {
336 syscall
337 ; =a (res)
338 ; 0 (scn)
339 }
340 return res
341 }
342
343 fn sys_call1(scn u64, arg1 u64) u64 {
344 mut res := u64(0)
345 asm amd64 {
346 syscall
347 ; =a (res)
348 ; 0 (scn)
349 D (arg1)
350 }
351 return res
352 }
353
354 fn sys_call2(scn u64, arg1 u64, arg2 u64) u64 {
355 mut res := u64(0)
356 asm amd64 {
357 syscall
358 ; =a (res)
359 ; 0 (scn)
360 D (arg1)
361 S (arg2)
362 }
363 return res
364 }
365
366 fn sys_call3(scn u64, arg1 u64, arg2 u64, arg3 u64) u64 {
367 mut res := u64(0)
368 asm amd64 {
369 syscall
370 ; =a (res)
371 ; 0 (scn)
372 D (arg1)
373 S (arg2)
374 d (arg3)
375 }
376 return res
377 }
378
379 fn sys_call4(scn u64, arg1 u64, arg2 u64, arg3 u64, arg4 u64) u64 {
380 mut res := u64(0)
381 asm amd64 {
382 mov r10, arg4
383 syscall
384 ; =a (res)
385 ; 0 (scn)
386 D (arg1)
387 S (arg2)
388 d (arg3)
389 g (arg4)
390 ; r10
391 }
392 return res
393 }
394
395 fn sys_call5(scn u64, arg1 u64, arg2 u64, arg3 u64, arg4 u64, arg5 u64) u64 {
396 mut res := u64(0)
397 asm amd64 {
398 mov r10, arg4
399 mov r8, arg5
400 syscall
401 ; =a (res)
402 ; 0 (scn)
403 D (arg1)
404 S (arg2)
405 d (arg3)
406 g (arg4)
407 g (arg5)
408 ; r10
409 r8
410 }
411 return res
412 }
413
414 fn sys_call6(scn u64, arg1 u64, arg2 u64, arg3 u64, arg4 u64, arg5 i64, arg6 u64) u64 {
415 mut res := u64(0)
416 asm amd64 {
417 mov r10, arg4
418 mov r8, arg5
419 mov r9, arg6
420 syscall
421 ; =a (res)
422 ; 0 (scn)
423 D (arg1)
424 S (arg2)
425 d (arg3)
426 g (arg4)
427 g (arg5)
428 g (arg6)
429 ; r10
430 r8
431 r9
432 }
433 return res
434 }
435
436 asm amd64 {
437 .globl _start
438 _start:
439 call main
440 mov rax, 60
441 xor rdi, rdi
442 syscall
443 ret
444 }
445}
446