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 5package runtime 6 7import "unsafe" 8 9var ( 10 libc_chdir, 11 libc_chroot, 12 libc_close, 13 libc_execve, 14 libc_fcntl, 15 libc_forkx, 16 libc_gethostname, 17 libc_getpid, 18 libc_ioctl, 19 libc_setgid, 20 libc_setgroups, 21 libc_setrlimit, 22 libc_setsid, 23 libc_setuid, 24 libc_setpgid, 25 libc_syscall, 26 libc_issetugid, 27 libc_wait4 libcFunc 28) 29 30// Many of these are exported via linkname to assembly in the syscall 31// package. 32 33//go:nosplit 34//go:linkname syscall_sysvicall6 35//go:cgo_unsafe_args 36func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { 37 call := libcall{ 38 fn: fn, 39 n: nargs, 40 args: uintptr(unsafe.Pointer(&a1)), 41 } 42 entersyscallblock() 43 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 44 exitsyscall() 45 return call.r1, call.r2, call.err 46} 47 48//go:nosplit 49//go:linkname syscall_rawsysvicall6 50//go:cgo_unsafe_args 51func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { 52 call := libcall{ 53 fn: fn, 54 n: nargs, 55 args: uintptr(unsafe.Pointer(&a1)), 56 } 57 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 58 return call.r1, call.r2, call.err 59} 60 61// TODO(aram): Once we remove all instances of C calling sysvicallN, make 62// sysvicallN return errors and replace the body of the following functions 63// with calls to sysvicallN. 64 65//go:nosplit 66//go:linkname syscall_chdir 67func syscall_chdir(path uintptr) (err uintptr) { 68 call := libcall{ 69 fn: uintptr(unsafe.Pointer(&libc_chdir)), 70 n: 1, 71 args: uintptr(unsafe.Pointer(&path)), 72 } 73 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 74 return call.err 75} 76 77//go:nosplit 78//go:linkname syscall_chroot 79func syscall_chroot(path uintptr) (err uintptr) { 80 call := libcall{ 81 fn: uintptr(unsafe.Pointer(&libc_chroot)), 82 n: 1, 83 args: uintptr(unsafe.Pointer(&path)), 84 } 85 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 86 return call.err 87} 88 89// like close, but must not split stack, for forkx. 90// 91//go:nosplit 92//go:linkname syscall_close 93func syscall_close(fd int32) int32 { 94 return int32(sysvicall1(&libc_close, uintptr(fd))) 95} 96 97const _F_DUP2FD = 0x9 98 99//go:nosplit 100//go:linkname syscall_dup2 101func syscall_dup2(oldfd, newfd uintptr) (val, err uintptr) { 102 return syscall_fcntl(oldfd, _F_DUP2FD, newfd) 103} 104 105//go:nosplit 106//go:linkname syscall_execve 107//go:cgo_unsafe_args 108func syscall_execve(path, argv, envp uintptr) (err uintptr) { 109 call := libcall{ 110 fn: uintptr(unsafe.Pointer(&libc_execve)), 111 n: 3, 112 args: uintptr(unsafe.Pointer(&path)), 113 } 114 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 115 return call.err 116} 117 118// like exit, but must not split stack, for forkx. 119// 120//go:nosplit 121//go:linkname syscall_exit 122func syscall_exit(code uintptr) { 123 sysvicall1(&libc_exit, code) 124} 125 126//go:nosplit 127//go:linkname syscall_fcntl 128//go:cgo_unsafe_args 129func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) { 130 call := libcall{ 131 fn: uintptr(unsafe.Pointer(&libc_fcntl)), 132 n: 3, 133 args: uintptr(unsafe.Pointer(&fd)), 134 } 135 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 136 return call.r1, call.err 137} 138 139//go:nosplit 140//go:linkname syscall_forkx 141func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) { 142 call := libcall{ 143 fn: uintptr(unsafe.Pointer(&libc_forkx)), 144 n: 1, 145 args: uintptr(unsafe.Pointer(&flags)), 146 } 147 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 148 if int(call.r1) != -1 { 149 call.err = 0 150 } 151 return call.r1, call.err 152} 153 154//go:linkname syscall_gethostname 155func syscall_gethostname() (name string, err uintptr) { 156 cname := new([_MAXHOSTNAMELEN]byte) 157 var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN} 158 call := libcall{ 159 fn: uintptr(unsafe.Pointer(&libc_gethostname)), 160 n: 2, 161 args: uintptr(unsafe.Pointer(&args[0])), 162 } 163 entersyscallblock() 164 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 165 exitsyscall() 166 if call.r1 != 0 { 167 return "", call.err 168 } 169 cname[_MAXHOSTNAMELEN-1] = 0 170 return gostringnocopy(&cname[0]), 0 171} 172 173//go:nosplit 174//go:linkname syscall_getpid 175func syscall_getpid() (pid, err uintptr) { 176 call := libcall{ 177 fn: uintptr(unsafe.Pointer(&libc_getpid)), 178 n: 0, 179 args: uintptr(unsafe.Pointer(&libc_getpid)), // it's unused but must be non-nil, otherwise crashes 180 } 181 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 182 return call.r1, call.err 183} 184 185//go:nosplit 186//go:linkname syscall_ioctl 187//go:cgo_unsafe_args 188func syscall_ioctl(fd, req, arg uintptr) (err uintptr) { 189 call := libcall{ 190 fn: uintptr(unsafe.Pointer(&libc_ioctl)), 191 n: 3, 192 args: uintptr(unsafe.Pointer(&fd)), 193 } 194 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 195 return call.err 196} 197 198// This is syscall.RawSyscall, it exists to satisfy some build dependency, 199// but it doesn't work. 200// 201//go:linkname syscall_rawsyscall 202func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { 203 panic("RawSyscall not available on Solaris") 204} 205 206// This is syscall.RawSyscall6, it exists to avoid a linker error because 207// syscall.RawSyscall6 is already declared. See golang.org/issue/24357 208// 209//go:linkname syscall_rawsyscall6 210func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { 211 panic("RawSyscall6 not available on Solaris") 212} 213 214//go:nosplit 215//go:linkname syscall_setgid 216func syscall_setgid(gid uintptr) (err uintptr) { 217 call := libcall{ 218 fn: uintptr(unsafe.Pointer(&libc_setgid)), 219 n: 1, 220 args: uintptr(unsafe.Pointer(&gid)), 221 } 222 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 223 return call.err 224} 225 226//go:nosplit 227//go:linkname syscall_setgroups 228//go:cgo_unsafe_args 229func syscall_setgroups(ngid, gid uintptr) (err uintptr) { 230 call := libcall{ 231 fn: uintptr(unsafe.Pointer(&libc_setgroups)), 232 n: 2, 233 args: uintptr(unsafe.Pointer(&ngid)), 234 } 235 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 236 return call.err 237} 238 239//go:nosplit 240//go:linkname syscall_setrlimit 241//go:cgo_unsafe_args 242func syscall_setrlimit(which uintptr, lim unsafe.Pointer) (err uintptr) { 243 call := libcall{ 244 fn: uintptr(unsafe.Pointer(&libc_setrlimit)), 245 n: 2, 246 args: uintptr(unsafe.Pointer(&which)), 247 } 248 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 249 return call.err 250} 251 252//go:nosplit 253//go:linkname syscall_setsid 254func syscall_setsid() (pid, err uintptr) { 255 call := libcall{ 256 fn: uintptr(unsafe.Pointer(&libc_setsid)), 257 n: 0, 258 args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes 259 } 260 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 261 return call.r1, call.err 262} 263 264//go:nosplit 265//go:linkname syscall_setuid 266func syscall_setuid(uid uintptr) (err uintptr) { 267 call := libcall{ 268 fn: uintptr(unsafe.Pointer(&libc_setuid)), 269 n: 1, 270 args: uintptr(unsafe.Pointer(&uid)), 271 } 272 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 273 return call.err 274} 275 276//go:nosplit 277//go:linkname syscall_setpgid 278//go:cgo_unsafe_args 279func syscall_setpgid(pid, pgid uintptr) (err uintptr) { 280 call := libcall{ 281 fn: uintptr(unsafe.Pointer(&libc_setpgid)), 282 n: 2, 283 args: uintptr(unsafe.Pointer(&pid)), 284 } 285 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 286 return call.err 287} 288 289//go:linkname syscall_syscall 290//go:cgo_unsafe_args 291func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { 292 call := libcall{ 293 fn: uintptr(unsafe.Pointer(&libc_syscall)), 294 n: 4, 295 args: uintptr(unsafe.Pointer(&trap)), 296 } 297 entersyscallblock() 298 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 299 exitsyscall() 300 return call.r1, call.r2, call.err 301} 302 303//go:linkname syscall_wait4 304//go:cgo_unsafe_args 305func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) { 306 call := libcall{ 307 fn: uintptr(unsafe.Pointer(&libc_wait4)), 308 n: 4, 309 args: uintptr(unsafe.Pointer(&pid)), 310 } 311 entersyscallblock() 312 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 313 exitsyscall() 314 KeepAlive(wstatus) 315 KeepAlive(rusage) 316 return int(call.r1), call.err 317} 318 319//go:nosplit 320//go:linkname syscall_write 321//go:cgo_unsafe_args 322func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) { 323 call := libcall{ 324 fn: uintptr(unsafe.Pointer(&libc_write)), 325 n: 3, 326 args: uintptr(unsafe.Pointer(&fd)), 327 } 328 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) 329 return call.r1, call.err 330} 331