From a9aaa13a09975cceaa29944448553b4f59cb0069 Mon Sep 17 00:00:00 2001 From: bogen85 <52499484+bogen85@users.noreply.github.com> Date: Wed, 4 Dec 2019 02:46:09 -0600 Subject: [PATCH] freestanding: sys_getuid, sys_waitid; minimal fork check; remove bare.S --- vlib/builtin/bare/.checks/linuxsys/linuxsys.v | 34 ++++++--- vlib/builtin/bare/linuxsys_bare.v | 69 ++++++++++++++++++- vlib/builtin/bare/mm_bare.v | 8 ++- vlib/compiler/cc.v | 8 +-- vlib/os/bare/bare.S | 39 ----------- vlib/os/bare/bare_example_linux.v | 21 ++---- 6 files changed, 106 insertions(+), 73 deletions(-) delete mode 100644 vlib/os/bare/bare.S diff --git a/vlib/builtin/bare/.checks/linuxsys/linuxsys.v b/vlib/builtin/bare/.checks/linuxsys/linuxsys.v index 68f67c8ef0..bb7fccaf9a 100644 --- a/vlib/builtin/bare/.checks/linuxsys/linuxsys.v +++ b/vlib/builtin/bare/.checks/linuxsys/linuxsys.v @@ -7,17 +7,34 @@ const ( sample_text_file1 = "" ) -fn fork_test (test_fn fn(), name string) { - //print ("checking") - // a := "$name" - println (name) +fn check_fork_minimal () { child := sys_fork() + ec := 100 if child == 0 { - test_fn() - sys_exit(0) + println("child") + sys_exit(ec) } -// pid := sys_wait(0) -// assert + siginfo := [ + int(0), 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0] + + e := sys_waitid(.p_pid, child, intptr(siginfo.data) , .wexited, 0) + + assert e == .enoerror + //println(i64_tos(buffer,80,siginfo[sig_index.si_code],16)) + assert siginfo[sig_index.si_code] == int(wi_si_code.cld_exited) + assert siginfo[sig_index.si_pid] == child + assert siginfo[sig_index.si_status] == ec + assert siginfo[sig_index.si_signo] == int(signo.sigchld) + assert siginfo[sig_index.si_uid] == sys_getuid() + + println("fork minimal check passed") } fn check_read_write_pipe() { @@ -316,5 +333,6 @@ fn main() { check_int64_array_ro() check_voidptr_array_ro() check_voidptr_array_rw() + check_fork_minimal() sys_exit(0) } diff --git a/vlib/builtin/bare/linuxsys_bare.v b/vlib/builtin/bare/linuxsys_bare.v index c4a6386954..369b74b27a 100644 --- a/vlib/builtin/bare/linuxsys_bare.v +++ b/vlib/builtin/bare/linuxsys_bare.v @@ -64,6 +64,50 @@ pub enum wi_si_code { CLD_CONTINUED (child continued by SIGCONT). */ +pub enum sig_index { + si_signo = 0x00 + si_code = 0x02 + si_pid = 0x04 + si_uid = 0x05 + si_status = 0x06 +} + +pub enum signo { + sigint = 2 // Interactive attention signal. + sigill = 4 // Illegal instruction. + sigabrt = 6 // Abnormal termination. + sigfpe = 8 // Erroneous arithmetic operation. + sigsegv = 11 // Invalid access to storage. + sigterm = 15 // Termination request. + + sighup = 1 // Hangup. + sigquit = 3 // Quit. + sigtrap = 5 // Trace/breakpoint trap. + sigkill = 9 // Killed. + sigpipe = 13 // Broken pipe. + sigalrm = 14 // Alarm clock. + + sigttin = 21 // Background read from control terminal. + sigttou = 22 // Background write to control terminal. + sigpoll = 23 // Pollable event occurred (System V). + sigxcpu = 24 // CPU time limit exceeded. + sigxfsz = 25 // File size limit exceeded. + sigvtalrm = 26 // Virtual timer expired. + sigprof = 27 // Profiling timer expired. + + sigbus = 7 + sigusr1 = 10 + sigusr2 = 12 + sigchld = 17 + sigcont = 18 + sigstop = 19 + sigtstp = 20 + sigurg = 23 + sigpoll = 29 + sigsys = 31 +} + + pub enum fcntl { fd_cloexec = 0x00000001 f_dupfd = 0x00000000 @@ -191,10 +235,23 @@ fn do_not_call_me_asm_keeper0() { "ret\n" "" ".intel_syntax noprefix\n" - ".globl sys_call0\n" + ".globl _start, sys_call0\n" ".globl sys_call1, sys_call2, sys_call3\n" ".globl sys_call4, sys_call5, sys_call6\n" "" + "_start:\n" + "xor rbp,rbp\n" + "pop rdi\n" + "mov rsi,rsp\n" + "and rsp,-16\n" + "call main\n" + "mov rdi,rax\n" /* syscall param 1 = rax (ret value of main) */ + "mov rax,60\n" /* SYS_exit */ + "syscall\n" + "" + // should never be reached, but if the OS somehow fails to kill us, + // it will cause a segmentation fault + "ret\n" "sys_call0:\n" "mov rax,rdi\n" "syscall\n" @@ -352,8 +409,16 @@ pub fn sys_exit (ec int) { sys_call1(60, u64(ec)) } +// 102 sys_getuid +pub fn sys_getuid() int { + return int(sys_call0(102)) +} + // 247 sys_waitid int which pid_t upid struct siginfo *infop int options struct rusage *ru -//pub fn sys_waitid (idtype wi_sys, pid i64, infop voidptr, options +pub fn sys_waitid (which wi_which, pid int, infop intptr, options wp_sys, ru voidptr) errno { + return errno(sys_call5(247, u64(which), u64(pid), u64(infop), u64(options), u64(ru))) +} + /* diff --git a/vlib/builtin/bare/mm_bare.v b/vlib/builtin/bare/mm_bare.v index 29809f777b..d551a1b189 100644 --- a/vlib/builtin/bare/mm_bare.v +++ b/vlib/builtin/bare/mm_bare.v @@ -1,5 +1,10 @@ module builtin +const ( + mem_prot = mm_prot(int(mm_prot.prot_read) | int(mm_prot.prot_write)) + mem_flags = map_flags(int(map_flags.map_private) | int(map_flags.map_anonymous)) +) + pub fn mm_pages(size u64) u32 { pages := (u64(size+u64(4))+u64(linux_mem.page_size))/u64(linux_mem.page_size) return u32(pages) @@ -9,9 +14,6 @@ pub fn mm_alloc(size u64) (byteptr, errno) { pages := mm_pages(size) n_bytes := u64(pages*u32(linux_mem.page_size)) - mem_prot := mm_prot(int(mm_prot.prot_read) | int(mm_prot.prot_write)) - mem_flags := map_flags(int(map_flags.map_private) | int(map_flags.map_anonymous)) - a, e := sys_mmap(0, n_bytes, mem_prot, mem_flags, -1, 0) if e == .enoerror { mut ap := intptr(a) diff --git a/vlib/compiler/cc.v b/vlib/compiler/cc.v index 9bea052c67..6dd822cf43 100644 --- a/vlib/compiler/cc.v +++ b/vlib/compiler/cc.v @@ -126,7 +126,7 @@ fn (v mut V) cc() { v.out_name = v.out_name + '.so' } if v.pref.is_bare { - a << '-fno-stack-protector -static -ffreestanding -nostdlib $vdir/vlib/os/bare/bare.S' + a << '-fno-stack-protector -static -ffreestanding -nostdlib' } if v.pref.build_mode == .build_module { // Create the modules & out directory if it's not there. @@ -146,13 +146,13 @@ fn (v mut V) cc() { debug_mode := v.pref.is_debug mut debug_options := '-g' mut optimization_options := '-O2' - + mut guessed_compiler := v.pref.ccompiler if guessed_compiler == 'cc' && v.pref.is_prod { // deliberately guessing only for -prod builds for performance reasons if ccversion := os.exec('cc --version') { if ccversion.exit_code == 0 { - if ccversion.output.contains('This is free software;') + if ccversion.output.contains('This is free software;') && ccversion.output.contains('Free Software Foundation, Inc.') { guessed_compiler = 'gcc' } @@ -162,7 +162,7 @@ fn (v mut V) cc() { } } } - + if v.pref.ccompiler.contains('clang') || guessed_compiler == 'clang' { if debug_mode { debug_options = '-g -O0 -no-pie' diff --git a/vlib/os/bare/bare.S b/vlib/os/bare/bare.S deleted file mode 100644 index 5bd2424777..0000000000 --- a/vlib/os/bare/bare.S +++ /dev/null @@ -1,39 +0,0 @@ -.intel_syntax noprefix -.text - .globl _start, main__syscall5 - - _start: - xor rbp,rbp - pop rdi - mov rsi,rsp - and rsp,-16 - call main - - mov rdi,rax /* syscall param 1 = rax (ret value of main) */ - mov rax,60 /* SYS_exit */ - syscall - - ret /* should never be reached, but if the OS somehow fails - to kill us, it will cause a segmentation fault */ - - main__syscall5: - mov rax,rdi - mov rdi,rsi - mov rsi,rdx - mov rdx,rcx - mov r10,r8 - mov r8,r9 - syscall - ret - - main__syscall6: - mov rax,rdi - mov rdi,rsi - mov rsi,rdx - mov rdx,rcx - mov r10,r8 - mov r8,r9 - mov r9, [rsp+8] - syscall - ret - diff --git a/vlib/os/bare/bare_example_linux.v b/vlib/os/bare/bare_example_linux.v index 6482576d3c..c3251e9287 100644 --- a/vlib/os/bare/bare_example_linux.v +++ b/vlib/os/bare/bare_example_linux.v @@ -1,20 +1,7 @@ -fn syscall5(number, arg1, arg2, arg3, arg4, arg5 voidptr) voidptr - -fn write(fd int, data voidptr, nbytes int) int { - return syscall5( - 1, // SYS_write - fd, - data, - nbytes, - 0, // ignored - 0 // ignored - ) -} - fn main() { - write(1, c'hello\n', 6) - s := 'test string' - write(1, s.str, s.len) + sys_write(1, 'hello\n'.str, 6) + s := 'test string\n' + sys_write(1, s.str, u64(s.len)) a := s[0] + println("Hello freestanding!") } -