Home | History | Annotate | Download | only in runtime
      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package runtime
      6 
      7 import "unsafe"
      8 
      9 var (
     10 	libc_chdir,
     11 	libc_chroot,
     12 	libc_execve,
     13 	libc_fcntl,
     14 	libc_forkx,
     15 	libc_gethostname,
     16 	libc_getpid,
     17 	libc_ioctl,
     18 	libc_pipe,
     19 	libc_setgid,
     20 	libc_setgroups,
     21 	libc_setsid,
     22 	libc_setuid,
     23 	libc_setpgid,
     24 	libc_syscall,
     25 	libc_wait4,
     26 	pipe1 libcFunc
     27 )
     28 
     29 //go:nosplit
     30 func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
     31 	call := libcall{
     32 		fn:   fn,
     33 		n:    nargs,
     34 		args: uintptr(unsafe.Pointer(&a1)),
     35 	}
     36 	entersyscallblock(0)
     37 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     38 	exitsyscall(0)
     39 	return call.r1, call.r2, call.err
     40 }
     41 
     42 //go:nosplit
     43 func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
     44 	call := libcall{
     45 		fn:   fn,
     46 		n:    nargs,
     47 		args: uintptr(unsafe.Pointer(&a1)),
     48 	}
     49 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     50 	return call.r1, call.r2, call.err
     51 }
     52 
     53 // TODO(aram): Once we remove all instances of C calling sysvicallN, make
     54 // sysvicallN return errors and replace the body of the following functions
     55 // with calls to sysvicallN.
     56 
     57 //go:nosplit
     58 func syscall_chdir(path uintptr) (err uintptr) {
     59 	call := libcall{
     60 		fn:   uintptr(unsafe.Pointer(&libc_chdir)),
     61 		n:    1,
     62 		args: uintptr(unsafe.Pointer(&path)),
     63 	}
     64 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     65 	return call.err
     66 }
     67 
     68 //go:nosplit
     69 func syscall_chroot(path uintptr) (err uintptr) {
     70 	call := libcall{
     71 		fn:   uintptr(unsafe.Pointer(&libc_chroot)),
     72 		n:    1,
     73 		args: uintptr(unsafe.Pointer(&path)),
     74 	}
     75 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     76 	return call.err
     77 }
     78 
     79 // like close, but must not split stack, for forkx.
     80 //go:nosplit
     81 func syscall_close(fd int32) int32 {
     82 	return int32(sysvicall1(&libc_close, uintptr(fd)))
     83 }
     84 
     85 //go:nosplit
     86 func syscall_execve(path, argv, envp uintptr) (err uintptr) {
     87 	call := libcall{
     88 		fn:   uintptr(unsafe.Pointer(&libc_execve)),
     89 		n:    3,
     90 		args: uintptr(unsafe.Pointer(&path)),
     91 	}
     92 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     93 	return call.err
     94 }
     95 
     96 // like exit, but must not split stack, for forkx.
     97 //go:nosplit
     98 func syscall_exit(code uintptr) {
     99 	sysvicall1(&libc_exit, code)
    100 }
    101 
    102 //go:nosplit
    103 func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
    104 	call := libcall{
    105 		fn:   uintptr(unsafe.Pointer(&libc_fcntl)),
    106 		n:    3,
    107 		args: uintptr(unsafe.Pointer(&fd)),
    108 	}
    109 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    110 	return call.r1, call.err
    111 }
    112 
    113 //go:nosplit
    114 func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
    115 	call := libcall{
    116 		fn:   uintptr(unsafe.Pointer(&libc_forkx)),
    117 		n:    1,
    118 		args: uintptr(unsafe.Pointer(&flags)),
    119 	}
    120 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    121 	return call.r1, call.err
    122 }
    123 
    124 func syscall_gethostname() (name string, err uintptr) {
    125 	cname := new([_MAXHOSTNAMELEN]byte)
    126 	var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
    127 	call := libcall{
    128 		fn:   uintptr(unsafe.Pointer(&libc_gethostname)),
    129 		n:    2,
    130 		args: uintptr(unsafe.Pointer(&args[0])),
    131 	}
    132 	entersyscallblock(0)
    133 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    134 	exitsyscall(0)
    135 	if call.r1 != 0 {
    136 		return "", call.err
    137 	}
    138 	cname[_MAXHOSTNAMELEN-1] = 0
    139 	return gostringnocopy(&cname[0]), 0
    140 }
    141 
    142 //go:nosplit
    143 func syscall_getpid() (pid, err uintptr) {
    144 	call := libcall{
    145 		fn:   uintptr(unsafe.Pointer(&libc_getpid)),
    146 		n:    0,
    147 		args: uintptr(unsafe.Pointer(&libc_getpid)), // it's unused but must be non-nil, otherwise crashes
    148 	}
    149 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    150 	return call.r1, call.err
    151 }
    152 
    153 //go:nosplit
    154 func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
    155 	call := libcall{
    156 		fn:   uintptr(unsafe.Pointer(&libc_ioctl)),
    157 		n:    3,
    158 		args: uintptr(unsafe.Pointer(&fd)),
    159 	}
    160 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    161 	return call.err
    162 }
    163 
    164 func syscall_pipe() (r, w, err uintptr) {
    165 	call := libcall{
    166 		fn:   uintptr(unsafe.Pointer(&pipe1)),
    167 		n:    0,
    168 		args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes
    169 	}
    170 	entersyscallblock(0)
    171 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    172 	exitsyscall(0)
    173 	return call.r1, call.r2, call.err
    174 }
    175 
    176 // This is syscall.RawSyscall, it exists to satisfy some build dependency,
    177 // but it doesn't work.
    178 func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
    179 	panic("RawSyscall not available on Solaris")
    180 }
    181 
    182 //go:nosplit
    183 func syscall_setgid(gid uintptr) (err uintptr) {
    184 	call := libcall{
    185 		fn:   uintptr(unsafe.Pointer(&libc_setgid)),
    186 		n:    1,
    187 		args: uintptr(unsafe.Pointer(&gid)),
    188 	}
    189 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    190 	return call.err
    191 }
    192 
    193 //go:nosplit
    194 func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
    195 	call := libcall{
    196 		fn:   uintptr(unsafe.Pointer(&libc_setgroups)),
    197 		n:    2,
    198 		args: uintptr(unsafe.Pointer(&ngid)),
    199 	}
    200 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    201 	return call.err
    202 }
    203 
    204 //go:nosplit
    205 func syscall_setsid() (pid, err uintptr) {
    206 	call := libcall{
    207 		fn:   uintptr(unsafe.Pointer(&libc_setsid)),
    208 		n:    0,
    209 		args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes
    210 	}
    211 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    212 	return call.r1, call.err
    213 }
    214 
    215 //go:nosplit
    216 func syscall_setuid(uid uintptr) (err uintptr) {
    217 	call := libcall{
    218 		fn:   uintptr(unsafe.Pointer(&libc_setuid)),
    219 		n:    1,
    220 		args: uintptr(unsafe.Pointer(&uid)),
    221 	}
    222 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    223 	return call.err
    224 }
    225 
    226 //go:nosplit
    227 func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
    228 	call := libcall{
    229 		fn:   uintptr(unsafe.Pointer(&libc_setpgid)),
    230 		n:    2,
    231 		args: uintptr(unsafe.Pointer(&pid)),
    232 	}
    233 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    234 	return call.err
    235 }
    236 
    237 // This is syscall.Syscall, it exists to satisfy some build dependency,
    238 // but it doesn't work correctly.
    239 //
    240 // DO NOT USE!
    241 //
    242 // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
    243 func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
    244 	call := libcall{
    245 		fn:   uintptr(unsafe.Pointer(&libc_syscall)),
    246 		n:    4,
    247 		args: uintptr(unsafe.Pointer(&trap)),
    248 	}
    249 	entersyscallblock(0)
    250 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    251 	exitsyscall(0)
    252 	return call.r1, call.r2, call.err
    253 }
    254 
    255 func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
    256 	call := libcall{
    257 		fn:   uintptr(unsafe.Pointer(&libc_wait4)),
    258 		n:    4,
    259 		args: uintptr(unsafe.Pointer(&pid)),
    260 	}
    261 	entersyscallblock(0)
    262 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    263 	exitsyscall(0)
    264 	return int(call.r1), call.err
    265 }
    266 
    267 //go:nosplit
    268 func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
    269 	call := libcall{
    270 		fn:   uintptr(unsafe.Pointer(&libc_write)),
    271 		n:    3,
    272 		args: uintptr(unsafe.Pointer(&fd)),
    273 	}
    274 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    275 	return call.r1, call.err
    276 }
    277