internal/fakecgo: implement setgid and friends on Linux (#426)
Implement and linkname the following functions: ``` //go:linkname _cgo_libc_setegid syscall.cgo_libc_setegid //go:linkname _cgo_libc_seteuid syscall.cgo_libc_seteuid //go:linkname _cgo_libc_setgid syscall.cgo_libc_setgid //go:linkname _cgo_libc_setregid syscall.cgo_libc_setregid //go:linkname _cgo_libc_setresgid syscall.cgo_libc_setresgid //go:linkname _cgo_libc_setresuid syscall.cgo_libc_setresuid //go:linkname _cgo_libc_setreuid syscall.cgo_libc_setreuid //go:linkname _cgo_libc_setuid syscall.cgo_libc_setuid //go:linkname _cgo_libc_setgroups syscall.cgo_libc_setgroups ```
- commit
- 6e7b9347ed41b60a744d3193c754f53d419d9574
- author
- Quim Muntal · · 2026-03-04 10:17 UTC
- committer
- GitHub · · 2026-03-04 10:17 UTC
- parent
- 012b8c4
- signature
- GPG Unverified
B5690EEEBB952194The key is unknown
19 files · +1114 -33
M .github/workflows/test.yml +24 -3
| @@ -131,7 +131,15 @@ jobs: | |||
| 131 | 131 | if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }} | |
| 132 | 132 | run: | | |
| 133 | 133 | sudo apt-get update | |
| 134 | - | sudo apt-get install -y qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-armhf-cross | |
| 134 | + | sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-armhf-cross | |
| 135 | + | ||
| 136 | + | # Install QEMU 10.x from Debian trixie. Ubuntu 24.04 ships QEMU 8.2 | |
| 137 | + | # which has a bug where inter-thread signal delivery (tgkill) hangs, | |
| 138 | + | # causing TestSetuidEtc to deadlock. | |
| 139 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user_10.0.7+ds-0+deb13u1+b1_arm64.deb -O /tmp/qemu-user.deb | |
| 140 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-binfmt_10.0.7+ds-0+deb13u1+b1_arm64.deb -O /tmp/qemu-user-binfmt.deb | |
| 141 | + | sudo dpkg --force-depends -i /tmp/qemu-user.deb /tmp/qemu-user-binfmt.deb | |
| 142 | + | ||
| 135 | 143 | # Create symlink for the dynamic linker that QEMU expects | |
| 136 | 144 | sudo ln -sf /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 | |
| 137 | 145 | go env -w CC=arm-linux-gnueabihf-gcc | |
| @@ -180,8 +188,21 @@ jobs: | |||
| 180 | 188 | gcc-14-loongarch64-linux-gnu g++-14-loongarch64-linux-gnu \ | |
| 181 | 189 | gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu \ | |
| 182 | 190 | gcc-riscv64-linux-gnu g++-riscv64-linux-gnu \ | |
| 183 | - | gcc-s390x-linux-gnu g++-s390x-linux-gnu \ | |
| 184 | - | qemu-user | |
| 191 | + | gcc-s390x-linux-gnu g++-s390x-linux-gnu | |
| 192 | + | ||
| 193 | + | # Install QEMU 10.x from Debian trixie. Ubuntu 24.04 ships QEMU 8.2 | |
| 194 | + | # which has a bug where inter-thread signal delivery (tgkill) hangs, | |
| 195 | + | # causing TestSetuidEtc to deadlock. | |
| 196 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user_10.0.7+ds-0+deb13u1+b1_amd64.deb -O /tmp/qemu-user.deb | |
| 197 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-binfmt_10.0.7+ds-0+deb13u1+b1_amd64.deb -O /tmp/qemu-user-binfmt.deb | |
| 198 | + | sudo dpkg --force-depends -i /tmp/qemu-user.deb /tmp/qemu-user-binfmt.deb | |
| 199 | + | sudo apt-get -f install -y | |
| 200 | + | ||
| 201 | + | # Verify that the expected QEMU binaries are installed and usable. | |
| 202 | + | qemu-loongarch64 --version | |
| 203 | + | qemu-ppc64le --version | |
| 204 | + | qemu-riscv64 --version | |
| 205 | + | qemu-s390x --version | |
| 185 | 206 | ||
| 186 | 207 | - name: go test (Linux loong64) | |
| 187 | 208 | run: | | |
| @@ -131,7 +131,15 @@ jobs: | |||||
| 131 | if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }} | 131 | if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }} | ||
| 132 | run: | | 132 | run: | | ||
| 133 | sudo apt-get update | 133 | sudo apt-get update | ||
| 134 | - | sudo apt-get install -y qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-armhf-cross | 134 | + | sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-armhf-cross |
| 135 | + | ||||
| 136 | + | # Install QEMU 10.x from Debian trixie. Ubuntu 24.04 ships QEMU 8.2 | |||
| 137 | + | # which has a bug where inter-thread signal delivery (tgkill) hangs, | |||
| 138 | + | # causing TestSetuidEtc to deadlock. | |||
| 139 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user_10.0.7+ds-0+deb13u1+b1_arm64.deb -O /tmp/qemu-user.deb | |||
| 140 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-binfmt_10.0.7+ds-0+deb13u1+b1_arm64.deb -O /tmp/qemu-user-binfmt.deb | |||
| 141 | + | sudo dpkg --force-depends -i /tmp/qemu-user.deb /tmp/qemu-user-binfmt.deb | |||
| 142 | + | ||||
| 135 | # Create symlink for the dynamic linker that QEMU expects | 143 | # Create symlink for the dynamic linker that QEMU expects | ||
| 136 | sudo ln -sf /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 | 144 | sudo ln -sf /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 | ||
| 137 | go env -w CC=arm-linux-gnueabihf-gcc | 145 | go env -w CC=arm-linux-gnueabihf-gcc | ||
| @@ -180,8 +188,21 @@ jobs: | |||||
| 180 | gcc-14-loongarch64-linux-gnu g++-14-loongarch64-linux-gnu \ | 188 | gcc-14-loongarch64-linux-gnu g++-14-loongarch64-linux-gnu \ | ||
| 181 | gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu \ | 189 | gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu \ | ||
| 182 | gcc-riscv64-linux-gnu g++-riscv64-linux-gnu \ | 190 | gcc-riscv64-linux-gnu g++-riscv64-linux-gnu \ | ||
| 183 | - | gcc-s390x-linux-gnu g++-s390x-linux-gnu \ | 191 | + | gcc-s390x-linux-gnu g++-s390x-linux-gnu |
| 184 | - | qemu-user | 192 | + | |
| 193 | + | # Install QEMU 10.x from Debian trixie. Ubuntu 24.04 ships QEMU 8.2 | |||
| 194 | + | # which has a bug where inter-thread signal delivery (tgkill) hangs, | |||
| 195 | + | # causing TestSetuidEtc to deadlock. | |||
| 196 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user_10.0.7+ds-0+deb13u1+b1_amd64.deb -O /tmp/qemu-user.deb | |||
| 197 | + | wget -q http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-binfmt_10.0.7+ds-0+deb13u1+b1_amd64.deb -O /tmp/qemu-user-binfmt.deb | |||
| 198 | + | sudo dpkg --force-depends -i /tmp/qemu-user.deb /tmp/qemu-user-binfmt.deb | |||
| 199 | + | sudo apt-get -f install -y | |||
| 200 | + | ||||
| 201 | + | # Verify that the expected QEMU binaries are installed and usable. | |||
| 202 | + | qemu-loongarch64 --version | |||
| 203 | + | qemu-ppc64le --version | |||
| 204 | + | qemu-riscv64 --version | |||
| 205 | + | qemu-s390x --version | |||
| 185 | 206 | ||||
| 186 | - name: go test (Linux loong64) | 207 | - name: go test (Linux loong64) | ||
| 187 | run: | | 208 | run: | | ||
M README.md +2 -0
| @@ -112,8 +112,10 @@ This is a list of the copied files: | |||
| 112 | 112 | * `internal/fakecgo/setenv.go` from package `runtime/cgo` | |
| 113 | 113 | * `internal/fakecgo/freebsd.go` from package `runtime/cgo` | |
| 114 | 114 | * `internal/fakecgo/netbsd.go` from package `runtime/cgo` | |
| 115 | + | * `internal/fakecgo/linux.go` from package `runtime/cgo` | |
| 115 | 116 | ||
| 116 | 117 | The `internal/fakecgo/go_GOOS.go` files were modified from `runtime/cgo/gcc_GOOS_GOARCH.go`. | |
| 118 | + | The `internal/fakecgo/linux.go` file is a combination of `runtime/cgo/linux.go` and `runtime/cgo/linux_syscall.c`. | |
| 117 | 119 | ||
| 118 | 120 | The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of | |
| 119 | 121 | `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) | |
| @@ -112,8 +112,10 @@ This is a list of the copied files: | |||||
| 112 | * `internal/fakecgo/setenv.go` from package `runtime/cgo` | 112 | * `internal/fakecgo/setenv.go` from package `runtime/cgo` | ||
| 113 | * `internal/fakecgo/freebsd.go` from package `runtime/cgo` | 113 | * `internal/fakecgo/freebsd.go` from package `runtime/cgo` | ||
| 114 | * `internal/fakecgo/netbsd.go` from package `runtime/cgo` | 114 | * `internal/fakecgo/netbsd.go` from package `runtime/cgo` | ||
| 115 | + | * `internal/fakecgo/linux.go` from package `runtime/cgo` | |||
| 115 | 116 | ||||
| 116 | The `internal/fakecgo/go_GOOS.go` files were modified from `runtime/cgo/gcc_GOOS_GOARCH.go`. | 117 | The `internal/fakecgo/go_GOOS.go` files were modified from `runtime/cgo/gcc_GOOS_GOARCH.go`. | ||
| 118 | + | The `internal/fakecgo/linux.go` file is a combination of `runtime/cgo/linux.go` and `runtime/cgo/linux_syscall.c`. | |||
| 117 | 119 | ||||
| 118 | The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of | 120 | The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of | ||
| 119 | `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) | 121 | `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) | ||
M internal/fakecgo/gen.go +10 -0
| @@ -121,6 +121,16 @@ var ( | |||
| 121 | 121 | {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32", nil}, | |
| 122 | 122 | {"abort", [5]Arg{}, "", nil}, | |
| 123 | 123 | {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32", []string{"netbsd"}}, | |
| 124 | + | {"__errno_location", [5]Arg{}, "uintptr", []string{"linux"}}, | |
| 125 | + | {"setegid", [5]Arg{{"egid", "uint32"}}, "int32", []string{"linux"}}, | |
| 126 | + | {"seteuid", [5]Arg{{"euid", "uint32"}}, "int32", []string{"linux"}}, | |
| 127 | + | {"setgid", [5]Arg{{"gid", "uint32"}}, "int32", []string{"linux"}}, | |
| 128 | + | {"setregid", [5]Arg{{"rgid", "uint32"}, {"egid", "uint32"}}, "int32", []string{"linux"}}, | |
| 129 | + | {"setresgid", [5]Arg{{"rgid", "uint32"}, {"egid", "uint32"}, {"sgid", "uint32"}}, "int32", []string{"linux"}}, | |
| 130 | + | {"setresuid", [5]Arg{{"ruid", "uint32"}, {"euid", "uint32"}, {"suid", "uint32"}}, "int32", []string{"linux"}}, | |
| 131 | + | {"setreuid", [5]Arg{{"ruid", "uint32"}, {"euid", "uint32"}}, "int32", []string{"linux"}}, | |
| 132 | + | {"setuid", [5]Arg{{"uid", "uint32"}}, "int32", []string{"linux"}}, | |
| 133 | + | {"setgroups", [5]Arg{{"ngid", "uint32"}, {"gidset", "*uint32"}}, "int32", []string{"linux"}}, | |
| 124 | 134 | } | |
| 125 | 135 | pthreadSymbols = []Symbol{ | |
| 126 | 136 | {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", nil}, | |
| @@ -121,6 +121,16 @@ var ( | |||||
| 121 | {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32", nil}, | 121 | {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32", nil}, | ||
| 122 | {"abort", [5]Arg{}, "", nil}, | 122 | {"abort", [5]Arg{}, "", nil}, | ||
| 123 | {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32", []string{"netbsd"}}, | 123 | {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32", []string{"netbsd"}}, | ||
| 124 | + | {"__errno_location", [5]Arg{}, "uintptr", []string{"linux"}}, | |||
| 125 | + | {"setegid", [5]Arg{{"egid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 126 | + | {"seteuid", [5]Arg{{"euid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 127 | + | {"setgid", [5]Arg{{"gid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 128 | + | {"setregid", [5]Arg{{"rgid", "uint32"}, {"egid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 129 | + | {"setresgid", [5]Arg{{"rgid", "uint32"}, {"egid", "uint32"}, {"sgid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 130 | + | {"setresuid", [5]Arg{{"ruid", "uint32"}, {"euid", "uint32"}, {"suid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 131 | + | {"setreuid", [5]Arg{{"ruid", "uint32"}, {"euid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 132 | + | {"setuid", [5]Arg{{"uid", "uint32"}}, "int32", []string{"linux"}}, | |||
| 133 | + | {"setgroups", [5]Arg{{"ngid", "uint32"}, {"gidset", "*uint32"}}, "int32", []string{"linux"}}, | |||
| 124 | } | 134 | } | ||
| 125 | pthreadSymbols = []Symbol{ | 135 | pthreadSymbols = []Symbol{ | ||
| 126 | {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", nil}, | 136 | {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", nil}, | ||
A internal/fakecgo/linux.go +184 -0
| @@ -0,0 +1,184 @@ | |||
| 1 | + | // Copyright 2016 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 | + | //go:build !cgo && linux | |
| 6 | + | ||
| 7 | + | package fakecgo | |
| 8 | + | ||
| 9 | + | import "unsafe" | |
| 10 | + | ||
| 11 | + | // argset matches runtime/cgocall.go:argset. | |
| 12 | + | type argset struct { | |
| 13 | + | args *uintptr | |
| 14 | + | retval uintptr | |
| 15 | + | } | |
| 16 | + | ||
| 17 | + | //go:nosplit | |
| 18 | + | //go:norace | |
| 19 | + | func (a *argset) arg(i int) unsafe.Pointer { | |
| 20 | + | return *(*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(a.args), uintptr(i)*unsafe.Sizeof(uintptr(0)))) | |
| 21 | + | } | |
| 22 | + | ||
| 23 | + | //go:linkname _cgo_libc_setegid syscall.cgo_libc_setegid | |
| 24 | + | //go:linkname _cgo_libc_seteuid syscall.cgo_libc_seteuid | |
| 25 | + | //go:linkname _cgo_libc_setgid syscall.cgo_libc_setgid | |
| 26 | + | //go:linkname _cgo_libc_setregid syscall.cgo_libc_setregid | |
| 27 | + | //go:linkname _cgo_libc_setresgid syscall.cgo_libc_setresgid | |
| 28 | + | //go:linkname _cgo_libc_setresuid syscall.cgo_libc_setresuid | |
| 29 | + | //go:linkname _cgo_libc_setreuid syscall.cgo_libc_setreuid | |
| 30 | + | //go:linkname _cgo_libc_setuid syscall.cgo_libc_setuid | |
| 31 | + | //go:linkname _cgo_libc_setgroups syscall.cgo_libc_setgroups | |
| 32 | + | ||
| 33 | + | var _cgo_libc_setegid = &_cgo_purego_setegid_trampoline | |
| 34 | + | var _cgo_libc_seteuid = &_cgo_purego_seteuid_trampoline | |
| 35 | + | var _cgo_libc_setgid = &_cgo_purego_setgid_trampoline | |
| 36 | + | var _cgo_libc_setregid = &_cgo_purego_setregid_trampoline | |
| 37 | + | var _cgo_libc_setresgid = &_cgo_purego_setresgid_trampoline | |
| 38 | + | var _cgo_libc_setresuid = &_cgo_purego_setresuid_trampoline | |
| 39 | + | var _cgo_libc_setreuid = &_cgo_purego_setreuid_trampoline | |
| 40 | + | var _cgo_libc_setuid = &_cgo_purego_setuid_trampoline | |
| 41 | + | var _cgo_libc_setgroups = &_cgo_purego_setgroups_trampoline | |
| 42 | + | ||
| 43 | + | //go:nosplit | |
| 44 | + | //go:norace | |
| 45 | + | func errno() int32 { | |
| 46 | + | // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer | |
| 47 | + | loc := __errno_location() | |
| 48 | + | return **(**int32)(unsafe.Pointer(&loc)) | |
| 49 | + | } | |
| 50 | + | ||
| 51 | + | //go:linkname _cgo_purego_setegid_trampoline _cgo_purego_setegid_trampoline | |
| 52 | + | var _cgo_purego_setegid_trampoline byte | |
| 53 | + | var x_cgo_purego_setegid_call = x_cgo_purego_setegid | |
| 54 | + | ||
| 55 | + | //go:nosplit | |
| 56 | + | //go:norace | |
| 57 | + | func x_cgo_purego_setegid(c *argset) { | |
| 58 | + | ret := setegid(uint32(uintptr(c.arg(0)))) | |
| 59 | + | if ret == -1 { | |
| 60 | + | c.retval = uintptr(errno()) | |
| 61 | + | } else { | |
| 62 | + | c.retval = uintptr(ret) | |
| 63 | + | } | |
| 64 | + | } | |
| 65 | + | ||
| 66 | + | //go:linkname _cgo_purego_seteuid_trampoline _cgo_purego_seteuid_trampoline | |
| 67 | + | var _cgo_purego_seteuid_trampoline byte | |
| 68 | + | var x_cgo_purego_seteuid_call = x_cgo_purego_seteuid | |
| 69 | + | ||
| 70 | + | //go:nosplit | |
| 71 | + | //go:norace | |
| 72 | + | func x_cgo_purego_seteuid(c *argset) { | |
| 73 | + | ret := seteuid(uint32(uintptr(c.arg(0)))) | |
| 74 | + | if ret == -1 { | |
| 75 | + | c.retval = uintptr(errno()) | |
| 76 | + | } else { | |
| 77 | + | c.retval = uintptr(ret) | |
| 78 | + | } | |
| 79 | + | } | |
| 80 | + | ||
| 81 | + | //go:linkname _cgo_purego_setgid_trampoline _cgo_purego_setgid_trampoline | |
| 82 | + | var _cgo_purego_setgid_trampoline byte | |
| 83 | + | var x_cgo_purego_setgid_call = x_cgo_purego_setgid | |
| 84 | + | ||
| 85 | + | //go:nosplit | |
| 86 | + | //go:norace | |
| 87 | + | func x_cgo_purego_setgid(c *argset) { | |
| 88 | + | ret := setgid(uint32(uintptr(c.arg(0)))) | |
| 89 | + | if ret == -1 { | |
| 90 | + | c.retval = uintptr(errno()) | |
| 91 | + | } else { | |
| 92 | + | c.retval = uintptr(ret) | |
| 93 | + | } | |
| 94 | + | } | |
| 95 | + | ||
| 96 | + | //go:linkname _cgo_purego_setregid_trampoline _cgo_purego_setregid_trampoline | |
| 97 | + | var _cgo_purego_setregid_trampoline byte | |
| 98 | + | var x_cgo_purego_setregid_call = x_cgo_purego_setregid | |
| 99 | + | ||
| 100 | + | //go:nosplit | |
| 101 | + | //go:norace | |
| 102 | + | func x_cgo_purego_setregid(c *argset) { | |
| 103 | + | ret := setregid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1)))) | |
| 104 | + | if ret == -1 { | |
| 105 | + | c.retval = uintptr(errno()) | |
| 106 | + | } else { | |
| 107 | + | c.retval = uintptr(ret) | |
| 108 | + | } | |
| 109 | + | } | |
| 110 | + | ||
| 111 | + | //go:linkname _cgo_purego_setresgid_trampoline _cgo_purego_setresgid_trampoline | |
| 112 | + | var _cgo_purego_setresgid_trampoline byte | |
| 113 | + | var x_cgo_purego_setresgid_call = x_cgo_purego_setresgid | |
| 114 | + | ||
| 115 | + | //go:nosplit | |
| 116 | + | //go:norace | |
| 117 | + | func x_cgo_purego_setresgid(c *argset) { | |
| 118 | + | ret := setresgid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1))), uint32(uintptr(c.arg(2)))) | |
| 119 | + | if ret == -1 { | |
| 120 | + | c.retval = uintptr(errno()) | |
| 121 | + | } else { | |
| 122 | + | c.retval = uintptr(ret) | |
| 123 | + | } | |
| 124 | + | } | |
| 125 | + | ||
| 126 | + | //go:linkname _cgo_purego_setresuid_trampoline _cgo_purego_setresuid_trampoline | |
| 127 | + | var _cgo_purego_setresuid_trampoline byte | |
| 128 | + | var x_cgo_purego_setresuid_call = x_cgo_purego_setresuid | |
| 129 | + | ||
| 130 | + | //go:nosplit | |
| 131 | + | //go:norace | |
| 132 | + | func x_cgo_purego_setresuid(c *argset) { | |
| 133 | + | ret := setresuid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1))), uint32(uintptr(c.arg(2)))) | |
| 134 | + | if ret == -1 { | |
| 135 | + | c.retval = uintptr(errno()) | |
| 136 | + | } else { | |
| 137 | + | c.retval = uintptr(ret) | |
| 138 | + | } | |
| 139 | + | } | |
| 140 | + | ||
| 141 | + | //go:linkname _cgo_purego_setreuid_trampoline _cgo_purego_setreuid_trampoline | |
| 142 | + | var _cgo_purego_setreuid_trampoline byte | |
| 143 | + | var x_cgo_purego_setreuid_call = x_cgo_purego_setreuid | |
| 144 | + | ||
| 145 | + | //go:nosplit | |
| 146 | + | //go:norace | |
| 147 | + | func x_cgo_purego_setreuid(c *argset) { | |
| 148 | + | ret := setreuid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1)))) | |
| 149 | + | if ret == -1 { | |
| 150 | + | c.retval = uintptr(errno()) | |
| 151 | + | } else { | |
| 152 | + | c.retval = uintptr(ret) | |
| 153 | + | } | |
| 154 | + | } | |
| 155 | + | ||
| 156 | + | //go:linkname _cgo_purego_setuid_trampoline _cgo_purego_setuid_trampoline | |
| 157 | + | var _cgo_purego_setuid_trampoline byte | |
| 158 | + | var x_cgo_purego_setuid_call = x_cgo_purego_setuid | |
| 159 | + | ||
| 160 | + | //go:nosplit | |
| 161 | + | //go:norace | |
| 162 | + | func x_cgo_purego_setuid(c *argset) { | |
| 163 | + | ret := setuid(uint32(uintptr(c.arg(0)))) | |
| 164 | + | if ret == -1 { | |
| 165 | + | c.retval = uintptr(errno()) | |
| 166 | + | } else { | |
| 167 | + | c.retval = uintptr(ret) | |
| 168 | + | } | |
| 169 | + | } | |
| 170 | + | ||
| 171 | + | //go:linkname _cgo_purego_setgroups_trampoline _cgo_purego_setgroups_trampoline | |
| 172 | + | var _cgo_purego_setgroups_trampoline byte | |
| 173 | + | var x_cgo_purego_setgroups_call = x_cgo_purego_setgroups | |
| 174 | + | ||
| 175 | + | //go:nosplit | |
| 176 | + | //go:norace | |
| 177 | + | func x_cgo_purego_setgroups(c *argset) { | |
| 178 | + | ret := setgroups(uint32(uintptr(c.arg(0))), (*uint32)(c.arg(1))) | |
| 179 | + | if ret == -1 { | |
| 180 | + | c.retval = uintptr(errno()) | |
| 181 | + | } else { | |
| 182 | + | c.retval = uintptr(ret) | |
| 183 | + | } | |
| 184 | + | } | |
| @@ -0,0 +1,184 @@ | |||||
| 1 | + | // Copyright 2016 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 | + | //go:build !cgo && linux | |||
| 6 | + | ||||
| 7 | + | package fakecgo | |||
| 8 | + | ||||
| 9 | + | import "unsafe" | |||
| 10 | + | ||||
| 11 | + | // argset matches runtime/cgocall.go:argset. | |||
| 12 | + | type argset struct { | |||
| 13 | + | args *uintptr | |||
| 14 | + | retval uintptr | |||
| 15 | + | } | |||
| 16 | + | ||||
| 17 | + | //go:nosplit | |||
| 18 | + | //go:norace | |||
| 19 | + | func (a *argset) arg(i int) unsafe.Pointer { | |||
| 20 | + | return *(*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(a.args), uintptr(i)*unsafe.Sizeof(uintptr(0)))) | |||
| 21 | + | } | |||
| 22 | + | ||||
| 23 | + | //go:linkname _cgo_libc_setegid syscall.cgo_libc_setegid | |||
| 24 | + | //go:linkname _cgo_libc_seteuid syscall.cgo_libc_seteuid | |||
| 25 | + | //go:linkname _cgo_libc_setgid syscall.cgo_libc_setgid | |||
| 26 | + | //go:linkname _cgo_libc_setregid syscall.cgo_libc_setregid | |||
| 27 | + | //go:linkname _cgo_libc_setresgid syscall.cgo_libc_setresgid | |||
| 28 | + | //go:linkname _cgo_libc_setresuid syscall.cgo_libc_setresuid | |||
| 29 | + | //go:linkname _cgo_libc_setreuid syscall.cgo_libc_setreuid | |||
| 30 | + | //go:linkname _cgo_libc_setuid syscall.cgo_libc_setuid | |||
| 31 | + | //go:linkname _cgo_libc_setgroups syscall.cgo_libc_setgroups | |||
| 32 | + | ||||
| 33 | + | var _cgo_libc_setegid = &_cgo_purego_setegid_trampoline | |||
| 34 | + | var _cgo_libc_seteuid = &_cgo_purego_seteuid_trampoline | |||
| 35 | + | var _cgo_libc_setgid = &_cgo_purego_setgid_trampoline | |||
| 36 | + | var _cgo_libc_setregid = &_cgo_purego_setregid_trampoline | |||
| 37 | + | var _cgo_libc_setresgid = &_cgo_purego_setresgid_trampoline | |||
| 38 | + | var _cgo_libc_setresuid = &_cgo_purego_setresuid_trampoline | |||
| 39 | + | var _cgo_libc_setreuid = &_cgo_purego_setreuid_trampoline | |||
| 40 | + | var _cgo_libc_setuid = &_cgo_purego_setuid_trampoline | |||
| 41 | + | var _cgo_libc_setgroups = &_cgo_purego_setgroups_trampoline | |||
| 42 | + | ||||
| 43 | + | //go:nosplit | |||
| 44 | + | //go:norace | |||
| 45 | + | func errno() int32 { | |||
| 46 | + | // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer | |||
| 47 | + | loc := __errno_location() | |||
| 48 | + | return **(**int32)(unsafe.Pointer(&loc)) | |||
| 49 | + | } | |||
| 50 | + | ||||
| 51 | + | //go:linkname _cgo_purego_setegid_trampoline _cgo_purego_setegid_trampoline | |||
| 52 | + | var _cgo_purego_setegid_trampoline byte | |||
| 53 | + | var x_cgo_purego_setegid_call = x_cgo_purego_setegid | |||
| 54 | + | ||||
| 55 | + | //go:nosplit | |||
| 56 | + | //go:norace | |||
| 57 | + | func x_cgo_purego_setegid(c *argset) { | |||
| 58 | + | ret := setegid(uint32(uintptr(c.arg(0)))) | |||
| 59 | + | if ret == -1 { | |||
| 60 | + | c.retval = uintptr(errno()) | |||
| 61 | + | } else { | |||
| 62 | + | c.retval = uintptr(ret) | |||
| 63 | + | } | |||
| 64 | + | } | |||
| 65 | + | ||||
| 66 | + | //go:linkname _cgo_purego_seteuid_trampoline _cgo_purego_seteuid_trampoline | |||
| 67 | + | var _cgo_purego_seteuid_trampoline byte | |||
| 68 | + | var x_cgo_purego_seteuid_call = x_cgo_purego_seteuid | |||
| 69 | + | ||||
| 70 | + | //go:nosplit | |||
| 71 | + | //go:norace | |||
| 72 | + | func x_cgo_purego_seteuid(c *argset) { | |||
| 73 | + | ret := seteuid(uint32(uintptr(c.arg(0)))) | |||
| 74 | + | if ret == -1 { | |||
| 75 | + | c.retval = uintptr(errno()) | |||
| 76 | + | } else { | |||
| 77 | + | c.retval = uintptr(ret) | |||
| 78 | + | } | |||
| 79 | + | } | |||
| 80 | + | ||||
| 81 | + | //go:linkname _cgo_purego_setgid_trampoline _cgo_purego_setgid_trampoline | |||
| 82 | + | var _cgo_purego_setgid_trampoline byte | |||
| 83 | + | var x_cgo_purego_setgid_call = x_cgo_purego_setgid | |||
| 84 | + | ||||
| 85 | + | //go:nosplit | |||
| 86 | + | //go:norace | |||
| 87 | + | func x_cgo_purego_setgid(c *argset) { | |||
| 88 | + | ret := setgid(uint32(uintptr(c.arg(0)))) | |||
| 89 | + | if ret == -1 { | |||
| 90 | + | c.retval = uintptr(errno()) | |||
| 91 | + | } else { | |||
| 92 | + | c.retval = uintptr(ret) | |||
| 93 | + | } | |||
| 94 | + | } | |||
| 95 | + | ||||
| 96 | + | //go:linkname _cgo_purego_setregid_trampoline _cgo_purego_setregid_trampoline | |||
| 97 | + | var _cgo_purego_setregid_trampoline byte | |||
| 98 | + | var x_cgo_purego_setregid_call = x_cgo_purego_setregid | |||
| 99 | + | ||||
| 100 | + | //go:nosplit | |||
| 101 | + | //go:norace | |||
| 102 | + | func x_cgo_purego_setregid(c *argset) { | |||
| 103 | + | ret := setregid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1)))) | |||
| 104 | + | if ret == -1 { | |||
| 105 | + | c.retval = uintptr(errno()) | |||
| 106 | + | } else { | |||
| 107 | + | c.retval = uintptr(ret) | |||
| 108 | + | } | |||
| 109 | + | } | |||
| 110 | + | ||||
| 111 | + | //go:linkname _cgo_purego_setresgid_trampoline _cgo_purego_setresgid_trampoline | |||
| 112 | + | var _cgo_purego_setresgid_trampoline byte | |||
| 113 | + | var x_cgo_purego_setresgid_call = x_cgo_purego_setresgid | |||
| 114 | + | ||||
| 115 | + | //go:nosplit | |||
| 116 | + | //go:norace | |||
| 117 | + | func x_cgo_purego_setresgid(c *argset) { | |||
| 118 | + | ret := setresgid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1))), uint32(uintptr(c.arg(2)))) | |||
| 119 | + | if ret == -1 { | |||
| 120 | + | c.retval = uintptr(errno()) | |||
| 121 | + | } else { | |||
| 122 | + | c.retval = uintptr(ret) | |||
| 123 | + | } | |||
| 124 | + | } | |||
| 125 | + | ||||
| 126 | + | //go:linkname _cgo_purego_setresuid_trampoline _cgo_purego_setresuid_trampoline | |||
| 127 | + | var _cgo_purego_setresuid_trampoline byte | |||
| 128 | + | var x_cgo_purego_setresuid_call = x_cgo_purego_setresuid | |||
| 129 | + | ||||
| 130 | + | //go:nosplit | |||
| 131 | + | //go:norace | |||
| 132 | + | func x_cgo_purego_setresuid(c *argset) { | |||
| 133 | + | ret := setresuid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1))), uint32(uintptr(c.arg(2)))) | |||
| 134 | + | if ret == -1 { | |||
| 135 | + | c.retval = uintptr(errno()) | |||
| 136 | + | } else { | |||
| 137 | + | c.retval = uintptr(ret) | |||
| 138 | + | } | |||
| 139 | + | } | |||
| 140 | + | ||||
| 141 | + | //go:linkname _cgo_purego_setreuid_trampoline _cgo_purego_setreuid_trampoline | |||
| 142 | + | var _cgo_purego_setreuid_trampoline byte | |||
| 143 | + | var x_cgo_purego_setreuid_call = x_cgo_purego_setreuid | |||
| 144 | + | ||||
| 145 | + | //go:nosplit | |||
| 146 | + | //go:norace | |||
| 147 | + | func x_cgo_purego_setreuid(c *argset) { | |||
| 148 | + | ret := setreuid(uint32(uintptr(c.arg(0))), uint32(uintptr(c.arg(1)))) | |||
| 149 | + | if ret == -1 { | |||
| 150 | + | c.retval = uintptr(errno()) | |||
| 151 | + | } else { | |||
| 152 | + | c.retval = uintptr(ret) | |||
| 153 | + | } | |||
| 154 | + | } | |||
| 155 | + | ||||
| 156 | + | //go:linkname _cgo_purego_setuid_trampoline _cgo_purego_setuid_trampoline | |||
| 157 | + | var _cgo_purego_setuid_trampoline byte | |||
| 158 | + | var x_cgo_purego_setuid_call = x_cgo_purego_setuid | |||
| 159 | + | ||||
| 160 | + | //go:nosplit | |||
| 161 | + | //go:norace | |||
| 162 | + | func x_cgo_purego_setuid(c *argset) { | |||
| 163 | + | ret := setuid(uint32(uintptr(c.arg(0)))) | |||
| 164 | + | if ret == -1 { | |||
| 165 | + | c.retval = uintptr(errno()) | |||
| 166 | + | } else { | |||
| 167 | + | c.retval = uintptr(ret) | |||
| 168 | + | } | |||
| 169 | + | } | |||
| 170 | + | ||||
| 171 | + | //go:linkname _cgo_purego_setgroups_trampoline _cgo_purego_setgroups_trampoline | |||
| 172 | + | var _cgo_purego_setgroups_trampoline byte | |||
| 173 | + | var x_cgo_purego_setgroups_call = x_cgo_purego_setgroups | |||
| 174 | + | ||||
| 175 | + | //go:nosplit | |||
| 176 | + | //go:norace | |||
| 177 | + | func x_cgo_purego_setgroups(c *argset) { | |||
| 178 | + | ret := setgroups(uint32(uintptr(c.arg(0))), (*uint32)(c.arg(1))) | |||
| 179 | + | if ret == -1 { | |||
| 180 | + | c.retval = uintptr(errno()) | |||
| 181 | + | } else { | |||
| 182 | + | c.retval = uintptr(ret) | |||
| 183 | + | } | |||
| 184 | + | } | |||
M internal/fakecgo/trampolines_386.s +18 -4
| @@ -80,15 +80,29 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $4-8 | |||
| 80 | 80 | CALL BX | |
| 81 | 81 | RET | |
| 82 | 82 | ||
| 83 | - | TEXT threadentry_trampoline(SB), NOSPLIT, $4-0 | |
| 84 | - | MOVL 8(SP), AX // first C arg | |
| 85 | - | MOVL AX, 0(SP) // Go arg 1 | |
| 83 | + | TEXT threadentry_trampoline(SB), NOSPLIT, $24-4 | |
| 84 | + | // Save callee-saved registers | |
| 85 | + | MOVL BP, 20(SP) | |
| 86 | + | MOVL BX, 16(SP) | |
| 87 | + | MOVL SI, 12(SP) | |
| 88 | + | MOVL DI, 8(SP) | |
| 89 | + | ||
| 90 | + | // Move C argument (arg) to stack for Go function | |
| 91 | + | MOVL arg+0(FP), AX | |
| 92 | + | MOVL AX, 0(SP) | |
| 93 | + | ||
| 86 | 94 | MOVL ·threadentry_call(SB), CX | |
| 87 | 95 | MOVL (CX), CX | |
| 88 | 96 | CALL CX | |
| 97 | + | ||
| 98 | + | // Restore callee-saved registers | |
| 99 | + | MOVL 8(SP), DI | |
| 100 | + | MOVL 12(SP), SI | |
| 101 | + | MOVL 16(SP), BX | |
| 102 | + | MOVL 20(SP), BP | |
| 89 | 103 | RET | |
| 90 | 104 | ||
| 91 | - | TEXT ·call5(SB), NOSPLIT, $20-28 | |
| 105 | + | TEXT ·call5(SB), NOSPLIT, $24-28 | |
| 92 | 106 | MOVL fn+0(FP), AX | |
| 93 | 107 | MOVL a1+4(FP), BX | |
| 94 | 108 | MOVL a2+8(FP), CX | |
| @@ -80,15 +80,29 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $4-8 | |||||
| 80 | CALL BX | 80 | CALL BX | ||
| 81 | RET | 81 | RET | ||
| 82 | 82 | ||||
| 83 | - | TEXT threadentry_trampoline(SB), NOSPLIT, $4-0 | 83 | + | TEXT threadentry_trampoline(SB), NOSPLIT, $24-4 |
| 84 | - | MOVL 8(SP), AX // first C arg | 84 | + | // Save callee-saved registers |
| 85 | - | MOVL AX, 0(SP) // Go arg 1 | 85 | + | MOVL BP, 20(SP) |
| 86 | + | MOVL BX, 16(SP) | |||
| 87 | + | MOVL SI, 12(SP) | |||
| 88 | + | MOVL DI, 8(SP) | |||
| 89 | + | ||||
| 90 | + | // Move C argument (arg) to stack for Go function | |||
| 91 | + | MOVL arg+0(FP), AX | |||
| 92 | + | MOVL AX, 0(SP) | |||
| 93 | + | ||||
| 86 | MOVL ·threadentry_call(SB), CX | 94 | MOVL ·threadentry_call(SB), CX | ||
| 87 | MOVL (CX), CX | 95 | MOVL (CX), CX | ||
| 88 | CALL CX | 96 | CALL CX | ||
| 97 | + | ||||
| 98 | + | // Restore callee-saved registers | |||
| 99 | + | MOVL 8(SP), DI | |||
| 100 | + | MOVL 12(SP), SI | |||
| 101 | + | MOVL 16(SP), BX | |||
| 102 | + | MOVL 20(SP), BP | |||
| 89 | RET | 103 | RET | ||
| 90 | 104 | ||||
| 91 | - | TEXT ·call5(SB), NOSPLIT, $20-28 | 105 | + | TEXT ·call5(SB), NOSPLIT, $24-28 |
| 92 | MOVL fn+0(FP), AX | 106 | MOVL fn+0(FP), AX | ||
| 93 | MOVL a1+4(FP), BX | 107 | MOVL a1+4(FP), BX | ||
| 94 | MOVL a2+8(FP), CX | 108 | MOVL a2+8(FP), CX | ||
M internal/fakecgo/trampolines_arm.s +44 -3
| @@ -54,12 +54,53 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0-8 | |||
| 54 | 54 | BL (R12) | |
| 55 | 55 | RET | |
| 56 | 56 | ||
| 57 | - | TEXT threadentry_trampoline(SB), NOSPLIT, $8-0 | |
| 58 | - | // See crosscall2. | |
| 59 | - | MOVW R0, 4(R13) | |
| 57 | + | TEXT threadentry_trampoline(SB), NOSPLIT, $104-0 | |
| 58 | + | // Save C callee-saved registers at C-to-Go boundary. | |
| 59 | + | // See crosscall2 in asm_arm.s. | |
| 60 | + | // ARM AAPCS callee-saved: R4-R11 (includes g=R10), D8-D15. | |
| 61 | + | // LR is saved/restored by the Go-managed frame prologue/epilogue. | |
| 62 | + | MOVW R0, 4(R13) // arg for threadentry_call | |
| 63 | + | ||
| 64 | + | MOVW R4, 8(R13) | |
| 65 | + | MOVW R5, 12(R13) | |
| 66 | + | MOVW R6, 16(R13) | |
| 67 | + | MOVW R7, 20(R13) | |
| 68 | + | MOVW R8, 24(R13) | |
| 69 | + | MOVW R9, 28(R13) | |
| 70 | + | MOVW g, 32(R13) // R10 | |
| 71 | + | MOVW R11, 36(R13) | |
| 72 | + | ||
| 73 | + | MOVD F8, 40(R13) | |
| 74 | + | MOVD F9, 48(R13) | |
| 75 | + | MOVD F10, 56(R13) | |
| 76 | + | MOVD F11, 64(R13) | |
| 77 | + | MOVD F12, 72(R13) | |
| 78 | + | MOVD F13, 80(R13) | |
| 79 | + | MOVD F14, 88(R13) | |
| 80 | + | MOVD F15, 96(R13) | |
| 81 | + | ||
| 60 | 82 | MOVW ·threadentry_call(SB), R12 | |
| 61 | 83 | MOVW (R12), R12 | |
| 62 | 84 | CALL (R12) | |
| 85 | + | ||
| 86 | + | MOVD 40(R13), F8 | |
| 87 | + | MOVD 48(R13), F9 | |
| 88 | + | MOVD 56(R13), F10 | |
| 89 | + | MOVD 64(R13), F11 | |
| 90 | + | MOVD 72(R13), F12 | |
| 91 | + | MOVD 80(R13), F13 | |
| 92 | + | MOVD 88(R13), F14 | |
| 93 | + | MOVD 96(R13), F15 | |
| 94 | + | ||
| 95 | + | MOVW 8(R13), R4 | |
| 96 | + | MOVW 12(R13), R5 | |
| 97 | + | MOVW 16(R13), R6 | |
| 98 | + | MOVW 20(R13), R7 | |
| 99 | + | MOVW 24(R13), R8 | |
| 100 | + | MOVW 28(R13), R9 | |
| 101 | + | MOVW 32(R13), g | |
| 102 | + | MOVW 36(R13), R11 | |
| 103 | + | ||
| 63 | 104 | RET | |
| 64 | 105 | ||
| 65 | 106 | TEXT ·call5(SB), NOSPLIT, $8-28 | |
| @@ -54,12 +54,53 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0-8 | |||||
| 54 | BL (R12) | 54 | BL (R12) | ||
| 55 | RET | 55 | RET | ||
| 56 | 56 | ||||
| 57 | - | TEXT threadentry_trampoline(SB), NOSPLIT, $8-0 | 57 | + | TEXT threadentry_trampoline(SB), NOSPLIT, $104-0 |
| 58 | - | // See crosscall2. | 58 | + | // Save C callee-saved registers at C-to-Go boundary. |
| 59 | - | MOVW R0, 4(R13) | 59 | + | // See crosscall2 in asm_arm.s. |
| 60 | + | // ARM AAPCS callee-saved: R4-R11 (includes g=R10), D8-D15. | |||
| 61 | + | // LR is saved/restored by the Go-managed frame prologue/epilogue. | |||
| 62 | + | MOVW R0, 4(R13) // arg for threadentry_call | |||
| 63 | + | ||||
| 64 | + | MOVW R4, 8(R13) | |||
| 65 | + | MOVW R5, 12(R13) | |||
| 66 | + | MOVW R6, 16(R13) | |||
| 67 | + | MOVW R7, 20(R13) | |||
| 68 | + | MOVW R8, 24(R13) | |||
| 69 | + | MOVW R9, 28(R13) | |||
| 70 | + | MOVW g, 32(R13) // R10 | |||
| 71 | + | MOVW R11, 36(R13) | |||
| 72 | + | ||||
| 73 | + | MOVD F8, 40(R13) | |||
| 74 | + | MOVD F9, 48(R13) | |||
| 75 | + | MOVD F10, 56(R13) | |||
| 76 | + | MOVD F11, 64(R13) | |||
| 77 | + | MOVD F12, 72(R13) | |||
| 78 | + | MOVD F13, 80(R13) | |||
| 79 | + | MOVD F14, 88(R13) | |||
| 80 | + | MOVD F15, 96(R13) | |||
| 81 | + | ||||
| 60 | MOVW ·threadentry_call(SB), R12 | 82 | MOVW ·threadentry_call(SB), R12 | ||
| 61 | MOVW (R12), R12 | 83 | MOVW (R12), R12 | ||
| 62 | CALL (R12) | 84 | CALL (R12) | ||
| 85 | + | ||||
| 86 | + | MOVD 40(R13), F8 | |||
| 87 | + | MOVD 48(R13), F9 | |||
| 88 | + | MOVD 56(R13), F10 | |||
| 89 | + | MOVD 64(R13), F11 | |||
| 90 | + | MOVD 72(R13), F12 | |||
| 91 | + | MOVD 80(R13), F13 | |||
| 92 | + | MOVD 88(R13), F14 | |||
| 93 | + | MOVD 96(R13), F15 | |||
| 94 | + | ||||
| 95 | + | MOVW 8(R13), R4 | |||
| 96 | + | MOVW 12(R13), R5 | |||
| 97 | + | MOVW 16(R13), R6 | |||
| 98 | + | MOVW 20(R13), R7 | |||
| 99 | + | MOVW 24(R13), R8 | |||
| 100 | + | MOVW 28(R13), R9 | |||
| 101 | + | MOVW 32(R13), g | |||
| 102 | + | MOVW 36(R13), R11 | |||
| 103 | + | ||||
| 63 | RET | 104 | RET | ||
| 64 | 105 | ||||
| 65 | TEXT ·call5(SB), NOSPLIT, $8-28 | 106 | TEXT ·call5(SB), NOSPLIT, $8-28 | ||
M internal/fakecgo/trampolines_arm64.s +0 -3
| @@ -58,7 +58,6 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | |||
| 58 | 58 | ||
| 59 | 59 | SAVE_R19_TO_R28(8*4) | |
| 60 | 60 | SAVE_F8_TO_F15(8*14) | |
| 61 | - | STP (R29, R30), (8*22)(RSP) | |
| 62 | 61 | ||
| 63 | 62 | MOVD ·threadentry_call(SB), R9 | |
| 64 | 63 | MOVD (R9), R9 | |
| @@ -67,8 +66,6 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | |||
| 67 | 66 | ||
| 68 | 67 | RESTORE_R19_TO_R28(8*4) | |
| 69 | 68 | RESTORE_F8_TO_F15(8*14) | |
| 70 | - | LDP (8*22)(RSP), (R29, R30) | |
| 71 | - | ||
| 72 | 69 | ADD $(8*24), RSP | |
| 73 | 70 | RET | |
| 74 | 71 | ||
| @@ -58,7 +58,6 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | |||||
| 58 | 58 | ||||
| 59 | SAVE_R19_TO_R28(8*4) | 59 | SAVE_R19_TO_R28(8*4) | ||
| 60 | SAVE_F8_TO_F15(8*14) | 60 | SAVE_F8_TO_F15(8*14) | ||
| 61 | - | STP (R29, R30), (8*22)(RSP) | |||
| 62 | 61 | ||||
| 63 | MOVD ·threadentry_call(SB), R9 | 62 | MOVD ·threadentry_call(SB), R9 | ||
| 64 | MOVD (R9), R9 | 63 | MOVD (R9), R9 | ||
| @@ -67,8 +66,6 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 | |||||
| 67 | 66 | ||||
| 68 | RESTORE_R19_TO_R28(8*4) | 67 | RESTORE_R19_TO_R28(8*4) | ||
| 69 | RESTORE_F8_TO_F15(8*14) | 68 | RESTORE_F8_TO_F15(8*14) | ||
| 70 | - | LDP (8*22)(RSP), (R29, R30) | |||
| 71 | - | ||||
| 72 | ADD $(8*24), RSP | 69 | ADD $(8*24), RSP | ||
| 73 | RET | 70 | RET | ||
| 74 | 71 | ||||
A internal/fakecgo/trampolines_linux_386.s +78 -0
| @@ -0,0 +1,78 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $4-0 | |
| 9 | + | MOVL 8(SP), AX | |
| 10 | + | MOVL AX, 0(SP) | |
| 11 | + | MOVL ·x_cgo_purego_setegid_call(SB), CX | |
| 12 | + | MOVL (CX), CX | |
| 13 | + | CALL CX | |
| 14 | + | RET | |
| 15 | + | ||
| 16 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $4-0 | |
| 17 | + | MOVL 8(SP), AX | |
| 18 | + | MOVL AX, 0(SP) | |
| 19 | + | MOVL ·x_cgo_purego_seteuid_call(SB), CX | |
| 20 | + | MOVL (CX), CX | |
| 21 | + | CALL CX | |
| 22 | + | RET | |
| 23 | + | ||
| 24 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $4-0 | |
| 25 | + | MOVL 8(SP), AX | |
| 26 | + | MOVL AX, 0(SP) | |
| 27 | + | MOVL ·x_cgo_purego_setgid_call(SB), CX | |
| 28 | + | MOVL (CX), CX | |
| 29 | + | CALL CX | |
| 30 | + | RET | |
| 31 | + | ||
| 32 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $4-0 | |
| 33 | + | MOVL 8(SP), AX | |
| 34 | + | MOVL AX, 0(SP) | |
| 35 | + | MOVL ·x_cgo_purego_setregid_call(SB), CX | |
| 36 | + | MOVL (CX), CX | |
| 37 | + | CALL CX | |
| 38 | + | RET | |
| 39 | + | ||
| 40 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $4-0 | |
| 41 | + | MOVL 8(SP), AX | |
| 42 | + | MOVL AX, 0(SP) | |
| 43 | + | MOVL ·x_cgo_purego_setresgid_call(SB), CX | |
| 44 | + | MOVL (CX), CX | |
| 45 | + | CALL CX | |
| 46 | + | RET | |
| 47 | + | ||
| 48 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $4-0 | |
| 49 | + | MOVL 8(SP), AX | |
| 50 | + | MOVL AX, 0(SP) | |
| 51 | + | MOVL ·x_cgo_purego_setresuid_call(SB), CX | |
| 52 | + | MOVL (CX), CX | |
| 53 | + | CALL CX | |
| 54 | + | RET | |
| 55 | + | ||
| 56 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $4-0 | |
| 57 | + | MOVL 8(SP), AX | |
| 58 | + | MOVL AX, 0(SP) | |
| 59 | + | MOVL ·x_cgo_purego_setreuid_call(SB), CX | |
| 60 | + | MOVL (CX), CX | |
| 61 | + | CALL CX | |
| 62 | + | RET | |
| 63 | + | ||
| 64 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $4-0 | |
| 65 | + | MOVL 8(SP), AX | |
| 66 | + | MOVL AX, 0(SP) | |
| 67 | + | MOVL ·x_cgo_purego_setuid_call(SB), CX | |
| 68 | + | MOVL (CX), CX | |
| 69 | + | CALL CX | |
| 70 | + | RET | |
| 71 | + | ||
| 72 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $4-0 | |
| 73 | + | MOVL 8(SP), AX | |
| 74 | + | MOVL AX, 0(SP) | |
| 75 | + | MOVL ·x_cgo_purego_setgroups_call(SB), CX | |
| 76 | + | MOVL (CX), CX | |
| 77 | + | CALL CX | |
| 78 | + | RET | |
| @@ -0,0 +1,78 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $4-0 | |||
| 9 | + | MOVL 8(SP), AX | |||
| 10 | + | MOVL AX, 0(SP) | |||
| 11 | + | MOVL ·x_cgo_purego_setegid_call(SB), CX | |||
| 12 | + | MOVL (CX), CX | |||
| 13 | + | CALL CX | |||
| 14 | + | RET | |||
| 15 | + | ||||
| 16 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $4-0 | |||
| 17 | + | MOVL 8(SP), AX | |||
| 18 | + | MOVL AX, 0(SP) | |||
| 19 | + | MOVL ·x_cgo_purego_seteuid_call(SB), CX | |||
| 20 | + | MOVL (CX), CX | |||
| 21 | + | CALL CX | |||
| 22 | + | RET | |||
| 23 | + | ||||
| 24 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $4-0 | |||
| 25 | + | MOVL 8(SP), AX | |||
| 26 | + | MOVL AX, 0(SP) | |||
| 27 | + | MOVL ·x_cgo_purego_setgid_call(SB), CX | |||
| 28 | + | MOVL (CX), CX | |||
| 29 | + | CALL CX | |||
| 30 | + | RET | |||
| 31 | + | ||||
| 32 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $4-0 | |||
| 33 | + | MOVL 8(SP), AX | |||
| 34 | + | MOVL AX, 0(SP) | |||
| 35 | + | MOVL ·x_cgo_purego_setregid_call(SB), CX | |||
| 36 | + | MOVL (CX), CX | |||
| 37 | + | CALL CX | |||
| 38 | + | RET | |||
| 39 | + | ||||
| 40 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $4-0 | |||
| 41 | + | MOVL 8(SP), AX | |||
| 42 | + | MOVL AX, 0(SP) | |||
| 43 | + | MOVL ·x_cgo_purego_setresgid_call(SB), CX | |||
| 44 | + | MOVL (CX), CX | |||
| 45 | + | CALL CX | |||
| 46 | + | RET | |||
| 47 | + | ||||
| 48 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $4-0 | |||
| 49 | + | MOVL 8(SP), AX | |||
| 50 | + | MOVL AX, 0(SP) | |||
| 51 | + | MOVL ·x_cgo_purego_setresuid_call(SB), CX | |||
| 52 | + | MOVL (CX), CX | |||
| 53 | + | CALL CX | |||
| 54 | + | RET | |||
| 55 | + | ||||
| 56 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $4-0 | |||
| 57 | + | MOVL 8(SP), AX | |||
| 58 | + | MOVL AX, 0(SP) | |||
| 59 | + | MOVL ·x_cgo_purego_setreuid_call(SB), CX | |||
| 60 | + | MOVL (CX), CX | |||
| 61 | + | CALL CX | |||
| 62 | + | RET | |||
| 63 | + | ||||
| 64 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $4-0 | |||
| 65 | + | MOVL 8(SP), AX | |||
| 66 | + | MOVL AX, 0(SP) | |||
| 67 | + | MOVL ·x_cgo_purego_setuid_call(SB), CX | |||
| 68 | + | MOVL (CX), CX | |||
| 69 | + | CALL CX | |||
| 70 | + | RET | |||
| 71 | + | ||||
| 72 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $4-0 | |||
| 73 | + | MOVL 8(SP), AX | |||
| 74 | + | MOVL AX, 0(SP) | |||
| 75 | + | MOVL ·x_cgo_purego_setgroups_call(SB), CX | |||
| 76 | + | MOVL (CX), CX | |||
| 77 | + | CALL CX | |||
| 78 | + | RET | |||
A internal/fakecgo/trampolines_linux_amd64.s +69 -0
| @@ -0,0 +1,69 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8 | |
| 9 | + | MOVQ DI, AX | |
| 10 | + | MOVQ ·x_cgo_purego_setegid_call(SB), R11 | |
| 11 | + | MOVQ (R11), R11 | |
| 12 | + | CALL R11 | |
| 13 | + | RET | |
| 14 | + | ||
| 15 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8 | |
| 16 | + | MOVQ DI, AX | |
| 17 | + | MOVQ ·x_cgo_purego_seteuid_call(SB), R11 | |
| 18 | + | MOVQ (R11), R11 | |
| 19 | + | CALL R11 | |
| 20 | + | RET | |
| 21 | + | ||
| 22 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8 | |
| 23 | + | MOVQ DI, AX | |
| 24 | + | MOVQ ·x_cgo_purego_setgid_call(SB), R11 | |
| 25 | + | MOVQ (R11), R11 | |
| 26 | + | CALL R11 | |
| 27 | + | RET | |
| 28 | + | ||
| 29 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8 | |
| 30 | + | MOVQ DI, AX | |
| 31 | + | MOVQ ·x_cgo_purego_setregid_call(SB), R11 | |
| 32 | + | MOVQ (R11), R11 | |
| 33 | + | CALL R11 | |
| 34 | + | RET | |
| 35 | + | ||
| 36 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8 | |
| 37 | + | MOVQ DI, AX | |
| 38 | + | MOVQ ·x_cgo_purego_setresgid_call(SB), R11 | |
| 39 | + | MOVQ (R11), R11 | |
| 40 | + | CALL R11 | |
| 41 | + | RET | |
| 42 | + | ||
| 43 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8 | |
| 44 | + | MOVQ DI, AX | |
| 45 | + | MOVQ ·x_cgo_purego_setresuid_call(SB), R11 | |
| 46 | + | MOVQ (R11), R11 | |
| 47 | + | CALL R11 | |
| 48 | + | RET | |
| 49 | + | ||
| 50 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8 | |
| 51 | + | MOVQ DI, AX | |
| 52 | + | MOVQ ·x_cgo_purego_setreuid_call(SB), R11 | |
| 53 | + | MOVQ (R11), R11 | |
| 54 | + | CALL R11 | |
| 55 | + | RET | |
| 56 | + | ||
| 57 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8 | |
| 58 | + | MOVQ DI, AX | |
| 59 | + | MOVQ ·x_cgo_purego_setuid_call(SB), R11 | |
| 60 | + | MOVQ (R11), R11 | |
| 61 | + | CALL R11 | |
| 62 | + | RET | |
| 63 | + | ||
| 64 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8 | |
| 65 | + | MOVQ DI, AX | |
| 66 | + | MOVQ ·x_cgo_purego_setgroups_call(SB), R11 | |
| 67 | + | MOVQ (R11), R11 | |
| 68 | + | CALL R11 | |
| 69 | + | RET | |
| @@ -0,0 +1,69 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8 | |||
| 9 | + | MOVQ DI, AX | |||
| 10 | + | MOVQ ·x_cgo_purego_setegid_call(SB), R11 | |||
| 11 | + | MOVQ (R11), R11 | |||
| 12 | + | CALL R11 | |||
| 13 | + | RET | |||
| 14 | + | ||||
| 15 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8 | |||
| 16 | + | MOVQ DI, AX | |||
| 17 | + | MOVQ ·x_cgo_purego_seteuid_call(SB), R11 | |||
| 18 | + | MOVQ (R11), R11 | |||
| 19 | + | CALL R11 | |||
| 20 | + | RET | |||
| 21 | + | ||||
| 22 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8 | |||
| 23 | + | MOVQ DI, AX | |||
| 24 | + | MOVQ ·x_cgo_purego_setgid_call(SB), R11 | |||
| 25 | + | MOVQ (R11), R11 | |||
| 26 | + | CALL R11 | |||
| 27 | + | RET | |||
| 28 | + | ||||
| 29 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8 | |||
| 30 | + | MOVQ DI, AX | |||
| 31 | + | MOVQ ·x_cgo_purego_setregid_call(SB), R11 | |||
| 32 | + | MOVQ (R11), R11 | |||
| 33 | + | CALL R11 | |||
| 34 | + | RET | |||
| 35 | + | ||||
| 36 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8 | |||
| 37 | + | MOVQ DI, AX | |||
| 38 | + | MOVQ ·x_cgo_purego_setresgid_call(SB), R11 | |||
| 39 | + | MOVQ (R11), R11 | |||
| 40 | + | CALL R11 | |||
| 41 | + | RET | |||
| 42 | + | ||||
| 43 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8 | |||
| 44 | + | MOVQ DI, AX | |||
| 45 | + | MOVQ ·x_cgo_purego_setresuid_call(SB), R11 | |||
| 46 | + | MOVQ (R11), R11 | |||
| 47 | + | CALL R11 | |||
| 48 | + | RET | |||
| 49 | + | ||||
| 50 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8 | |||
| 51 | + | MOVQ DI, AX | |||
| 52 | + | MOVQ ·x_cgo_purego_setreuid_call(SB), R11 | |||
| 53 | + | MOVQ (R11), R11 | |||
| 54 | + | CALL R11 | |||
| 55 | + | RET | |||
| 56 | + | ||||
| 57 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8 | |||
| 58 | + | MOVQ DI, AX | |||
| 59 | + | MOVQ ·x_cgo_purego_setuid_call(SB), R11 | |||
| 60 | + | MOVQ (R11), R11 | |||
| 61 | + | CALL R11 | |||
| 62 | + | RET | |||
| 63 | + | ||||
| 64 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8 | |||
| 65 | + | MOVQ DI, AX | |||
| 66 | + | MOVQ ·x_cgo_purego_setgroups_call(SB), R11 | |||
| 67 | + | MOVQ (R11), R11 | |||
| 68 | + | CALL R11 | |||
| 69 | + | RET | |||
A internal/fakecgo/trampolines_linux_arm.s +69 -0
| @@ -0,0 +1,69 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8-0 | |
| 9 | + | MOVW R0, 4(R13) | |
| 10 | + | MOVW ·x_cgo_purego_setegid_call(SB), R12 | |
| 11 | + | MOVW (R12), R12 | |
| 12 | + | CALL (R12) | |
| 13 | + | RET | |
| 14 | + | ||
| 15 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8-0 | |
| 16 | + | MOVW R0, 4(R13) | |
| 17 | + | MOVW ·x_cgo_purego_seteuid_call(SB), R12 | |
| 18 | + | MOVW (R12), R12 | |
| 19 | + | CALL (R12) | |
| 20 | + | RET | |
| 21 | + | ||
| 22 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8-0 | |
| 23 | + | MOVW R0, 4(R13) | |
| 24 | + | MOVW ·x_cgo_purego_setgid_call(SB), R12 | |
| 25 | + | MOVW (R12), R12 | |
| 26 | + | CALL (R12) | |
| 27 | + | RET | |
| 28 | + | ||
| 29 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8-0 | |
| 30 | + | MOVW R0, 4(R13) | |
| 31 | + | MOVW ·x_cgo_purego_setregid_call(SB), R12 | |
| 32 | + | MOVW (R12), R12 | |
| 33 | + | CALL (R12) | |
| 34 | + | RET | |
| 35 | + | ||
| 36 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8-0 | |
| 37 | + | MOVW R0, 4(R13) | |
| 38 | + | MOVW ·x_cgo_purego_setresgid_call(SB), R12 | |
| 39 | + | MOVW (R12), R12 | |
| 40 | + | CALL (R12) | |
| 41 | + | RET | |
| 42 | + | ||
| 43 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8-0 | |
| 44 | + | MOVW R0, 4(R13) | |
| 45 | + | MOVW ·x_cgo_purego_setresuid_call(SB), R12 | |
| 46 | + | MOVW (R12), R12 | |
| 47 | + | CALL (R12) | |
| 48 | + | RET | |
| 49 | + | ||
| 50 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8-0 | |
| 51 | + | MOVW R0, 4(R13) | |
| 52 | + | MOVW ·x_cgo_purego_setreuid_call(SB), R12 | |
| 53 | + | MOVW (R12), R12 | |
| 54 | + | CALL (R12) | |
| 55 | + | RET | |
| 56 | + | ||
| 57 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8-0 | |
| 58 | + | MOVW R0, 4(R13) | |
| 59 | + | MOVW ·x_cgo_purego_setuid_call(SB), R12 | |
| 60 | + | MOVW (R12), R12 | |
| 61 | + | CALL (R12) | |
| 62 | + | RET | |
| 63 | + | ||
| 64 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8-0 | |
| 65 | + | MOVW R0, 4(R13) | |
| 66 | + | MOVW ·x_cgo_purego_setgroups_call(SB), R12 | |
| 67 | + | MOVW (R12), R12 | |
| 68 | + | CALL (R12) | |
| 69 | + | RET | |
| @@ -0,0 +1,69 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8-0 | |||
| 9 | + | MOVW R0, 4(R13) | |||
| 10 | + | MOVW ·x_cgo_purego_setegid_call(SB), R12 | |||
| 11 | + | MOVW (R12), R12 | |||
| 12 | + | CALL (R12) | |||
| 13 | + | RET | |||
| 14 | + | ||||
| 15 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 16 | + | MOVW R0, 4(R13) | |||
| 17 | + | MOVW ·x_cgo_purego_seteuid_call(SB), R12 | |||
| 18 | + | MOVW (R12), R12 | |||
| 19 | + | CALL (R12) | |||
| 20 | + | RET | |||
| 21 | + | ||||
| 22 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8-0 | |||
| 23 | + | MOVW R0, 4(R13) | |||
| 24 | + | MOVW ·x_cgo_purego_setgid_call(SB), R12 | |||
| 25 | + | MOVW (R12), R12 | |||
| 26 | + | CALL (R12) | |||
| 27 | + | RET | |||
| 28 | + | ||||
| 29 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8-0 | |||
| 30 | + | MOVW R0, 4(R13) | |||
| 31 | + | MOVW ·x_cgo_purego_setregid_call(SB), R12 | |||
| 32 | + | MOVW (R12), R12 | |||
| 33 | + | CALL (R12) | |||
| 34 | + | RET | |||
| 35 | + | ||||
| 36 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8-0 | |||
| 37 | + | MOVW R0, 4(R13) | |||
| 38 | + | MOVW ·x_cgo_purego_setresgid_call(SB), R12 | |||
| 39 | + | MOVW (R12), R12 | |||
| 40 | + | CALL (R12) | |||
| 41 | + | RET | |||
| 42 | + | ||||
| 43 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 44 | + | MOVW R0, 4(R13) | |||
| 45 | + | MOVW ·x_cgo_purego_setresuid_call(SB), R12 | |||
| 46 | + | MOVW (R12), R12 | |||
| 47 | + | CALL (R12) | |||
| 48 | + | RET | |||
| 49 | + | ||||
| 50 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 51 | + | MOVW R0, 4(R13) | |||
| 52 | + | MOVW ·x_cgo_purego_setreuid_call(SB), R12 | |||
| 53 | + | MOVW (R12), R12 | |||
| 54 | + | CALL (R12) | |||
| 55 | + | RET | |||
| 56 | + | ||||
| 57 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 58 | + | MOVW R0, 4(R13) | |||
| 59 | + | MOVW ·x_cgo_purego_setuid_call(SB), R12 | |||
| 60 | + | MOVW (R12), R12 | |||
| 61 | + | CALL (R12) | |||
| 62 | + | RET | |||
| 63 | + | ||||
| 64 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8-0 | |||
| 65 | + | MOVW R0, 4(R13) | |||
| 66 | + | MOVW ·x_cgo_purego_setgroups_call(SB), R12 | |||
| 67 | + | MOVW (R12), R12 | |||
| 68 | + | CALL (R12) | |||
| 69 | + | RET | |||
A internal/fakecgo/trampolines_linux_arm64.s +60 -0
| @@ -0,0 +1,60 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $0-0 | |
| 9 | + | MOVD ·x_cgo_purego_setegid_call(SB), R9 | |
| 10 | + | MOVD (R9), R9 | |
| 11 | + | CALL R9 | |
| 12 | + | RET | |
| 13 | + | ||
| 14 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $0-0 | |
| 15 | + | MOVD ·x_cgo_purego_seteuid_call(SB), R9 | |
| 16 | + | MOVD (R9), R9 | |
| 17 | + | CALL R9 | |
| 18 | + | RET | |
| 19 | + | ||
| 20 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $0-0 | |
| 21 | + | MOVD ·x_cgo_purego_setgid_call(SB), R9 | |
| 22 | + | MOVD (R9), R9 | |
| 23 | + | CALL R9 | |
| 24 | + | RET | |
| 25 | + | ||
| 26 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $0-0 | |
| 27 | + | MOVD ·x_cgo_purego_setregid_call(SB), R9 | |
| 28 | + | MOVD (R9), R9 | |
| 29 | + | CALL R9 | |
| 30 | + | RET | |
| 31 | + | ||
| 32 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $0-0 | |
| 33 | + | MOVD ·x_cgo_purego_setresgid_call(SB), R9 | |
| 34 | + | MOVD (R9), R9 | |
| 35 | + | CALL R9 | |
| 36 | + | RET | |
| 37 | + | ||
| 38 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $0-0 | |
| 39 | + | MOVD ·x_cgo_purego_setresuid_call(SB), R9 | |
| 40 | + | MOVD (R9), R9 | |
| 41 | + | CALL R9 | |
| 42 | + | RET | |
| 43 | + | ||
| 44 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $0-0 | |
| 45 | + | MOVD ·x_cgo_purego_setreuid_call(SB), R9 | |
| 46 | + | MOVD (R9), R9 | |
| 47 | + | CALL R9 | |
| 48 | + | RET | |
| 49 | + | ||
| 50 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $0-0 | |
| 51 | + | MOVD ·x_cgo_purego_setuid_call(SB), R9 | |
| 52 | + | MOVD (R9), R9 | |
| 53 | + | CALL R9 | |
| 54 | + | RET | |
| 55 | + | ||
| 56 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $0-0 | |
| 57 | + | MOVD ·x_cgo_purego_setgroups_call(SB), R9 | |
| 58 | + | MOVD (R9), R9 | |
| 59 | + | CALL R9 | |
| 60 | + | RET | |
| @@ -0,0 +1,60 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $0-0 | |||
| 9 | + | MOVD ·x_cgo_purego_setegid_call(SB), R9 | |||
| 10 | + | MOVD (R9), R9 | |||
| 11 | + | CALL R9 | |||
| 12 | + | RET | |||
| 13 | + | ||||
| 14 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $0-0 | |||
| 15 | + | MOVD ·x_cgo_purego_seteuid_call(SB), R9 | |||
| 16 | + | MOVD (R9), R9 | |||
| 17 | + | CALL R9 | |||
| 18 | + | RET | |||
| 19 | + | ||||
| 20 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $0-0 | |||
| 21 | + | MOVD ·x_cgo_purego_setgid_call(SB), R9 | |||
| 22 | + | MOVD (R9), R9 | |||
| 23 | + | CALL R9 | |||
| 24 | + | RET | |||
| 25 | + | ||||
| 26 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $0-0 | |||
| 27 | + | MOVD ·x_cgo_purego_setregid_call(SB), R9 | |||
| 28 | + | MOVD (R9), R9 | |||
| 29 | + | CALL R9 | |||
| 30 | + | RET | |||
| 31 | + | ||||
| 32 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $0-0 | |||
| 33 | + | MOVD ·x_cgo_purego_setresgid_call(SB), R9 | |||
| 34 | + | MOVD (R9), R9 | |||
| 35 | + | CALL R9 | |||
| 36 | + | RET | |||
| 37 | + | ||||
| 38 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $0-0 | |||
| 39 | + | MOVD ·x_cgo_purego_setresuid_call(SB), R9 | |||
| 40 | + | MOVD (R9), R9 | |||
| 41 | + | CALL R9 | |||
| 42 | + | RET | |||
| 43 | + | ||||
| 44 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $0-0 | |||
| 45 | + | MOVD ·x_cgo_purego_setreuid_call(SB), R9 | |||
| 46 | + | MOVD (R9), R9 | |||
| 47 | + | CALL R9 | |||
| 48 | + | RET | |||
| 49 | + | ||||
| 50 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $0-0 | |||
| 51 | + | MOVD ·x_cgo_purego_setuid_call(SB), R9 | |||
| 52 | + | MOVD (R9), R9 | |||
| 53 | + | CALL R9 | |||
| 54 | + | RET | |||
| 55 | + | ||||
| 56 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $0-0 | |||
| 57 | + | MOVD ·x_cgo_purego_setgroups_call(SB), R9 | |||
| 58 | + | MOVD (R9), R9 | |||
| 59 | + | CALL R9 | |||
| 60 | + | RET | |||
A internal/fakecgo/trampolines_linux_loong64.s +60 -0
| @@ -0,0 +1,60 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8 | |
| 9 | + | MOVV ·x_cgo_purego_setegid_call(SB), R23 | |
| 10 | + | MOVV (R23), R23 | |
| 11 | + | CALL (R23) | |
| 12 | + | RET | |
| 13 | + | ||
| 14 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8 | |
| 15 | + | MOVV ·x_cgo_purego_seteuid_call(SB), R23 | |
| 16 | + | MOVV (R23), R23 | |
| 17 | + | CALL (R23) | |
| 18 | + | RET | |
| 19 | + | ||
| 20 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8 | |
| 21 | + | MOVV ·x_cgo_purego_setgid_call(SB), R23 | |
| 22 | + | MOVV (R23), R23 | |
| 23 | + | CALL (R23) | |
| 24 | + | RET | |
| 25 | + | ||
| 26 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8 | |
| 27 | + | MOVV ·x_cgo_purego_setregid_call(SB), R23 | |
| 28 | + | MOVV (R23), R23 | |
| 29 | + | CALL (R23) | |
| 30 | + | RET | |
| 31 | + | ||
| 32 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8 | |
| 33 | + | MOVV ·x_cgo_purego_setresgid_call(SB), R23 | |
| 34 | + | MOVV (R23), R23 | |
| 35 | + | CALL (R23) | |
| 36 | + | RET | |
| 37 | + | ||
| 38 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8 | |
| 39 | + | MOVV ·x_cgo_purego_setresuid_call(SB), R23 | |
| 40 | + | MOVV (R23), R23 | |
| 41 | + | CALL (R23) | |
| 42 | + | RET | |
| 43 | + | ||
| 44 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8 | |
| 45 | + | MOVV ·x_cgo_purego_setreuid_call(SB), R23 | |
| 46 | + | MOVV (R23), R23 | |
| 47 | + | CALL (R23) | |
| 48 | + | RET | |
| 49 | + | ||
| 50 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8 | |
| 51 | + | MOVV ·x_cgo_purego_setuid_call(SB), R23 | |
| 52 | + | MOVV (R23), R23 | |
| 53 | + | CALL (R23) | |
| 54 | + | RET | |
| 55 | + | ||
| 56 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8 | |
| 57 | + | MOVV ·x_cgo_purego_setgroups_call(SB), R23 | |
| 58 | + | MOVV (R23), R23 | |
| 59 | + | CALL (R23) | |
| 60 | + | RET | |
| @@ -0,0 +1,60 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8 | |||
| 9 | + | MOVV ·x_cgo_purego_setegid_call(SB), R23 | |||
| 10 | + | MOVV (R23), R23 | |||
| 11 | + | CALL (R23) | |||
| 12 | + | RET | |||
| 13 | + | ||||
| 14 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8 | |||
| 15 | + | MOVV ·x_cgo_purego_seteuid_call(SB), R23 | |||
| 16 | + | MOVV (R23), R23 | |||
| 17 | + | CALL (R23) | |||
| 18 | + | RET | |||
| 19 | + | ||||
| 20 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8 | |||
| 21 | + | MOVV ·x_cgo_purego_setgid_call(SB), R23 | |||
| 22 | + | MOVV (R23), R23 | |||
| 23 | + | CALL (R23) | |||
| 24 | + | RET | |||
| 25 | + | ||||
| 26 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8 | |||
| 27 | + | MOVV ·x_cgo_purego_setregid_call(SB), R23 | |||
| 28 | + | MOVV (R23), R23 | |||
| 29 | + | CALL (R23) | |||
| 30 | + | RET | |||
| 31 | + | ||||
| 32 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8 | |||
| 33 | + | MOVV ·x_cgo_purego_setresgid_call(SB), R23 | |||
| 34 | + | MOVV (R23), R23 | |||
| 35 | + | CALL (R23) | |||
| 36 | + | RET | |||
| 37 | + | ||||
| 38 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8 | |||
| 39 | + | MOVV ·x_cgo_purego_setresuid_call(SB), R23 | |||
| 40 | + | MOVV (R23), R23 | |||
| 41 | + | CALL (R23) | |||
| 42 | + | RET | |||
| 43 | + | ||||
| 44 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8 | |||
| 45 | + | MOVV ·x_cgo_purego_setreuid_call(SB), R23 | |||
| 46 | + | MOVV (R23), R23 | |||
| 47 | + | CALL (R23) | |||
| 48 | + | RET | |||
| 49 | + | ||||
| 50 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8 | |||
| 51 | + | MOVV ·x_cgo_purego_setuid_call(SB), R23 | |||
| 52 | + | MOVV (R23), R23 | |||
| 53 | + | CALL (R23) | |||
| 54 | + | RET | |||
| 55 | + | ||||
| 56 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8 | |||
| 57 | + | MOVV ·x_cgo_purego_setgroups_call(SB), R23 | |||
| 58 | + | MOVV (R23), R23 | |||
| 59 | + | CALL (R23) | |||
| 60 | + | RET | |||
A internal/fakecgo/trampolines_linux_ppc64le.s +69 -0
| @@ -0,0 +1,69 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8-0 | |
| 9 | + | MOVD ·x_cgo_purego_setegid_call(SB), R12 | |
| 10 | + | MOVD (R12), R12 | |
| 11 | + | MOVD R12, CTR | |
| 12 | + | CALL CTR | |
| 13 | + | RET | |
| 14 | + | ||
| 15 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8-0 | |
| 16 | + | MOVD ·x_cgo_purego_seteuid_call(SB), R12 | |
| 17 | + | MOVD (R12), R12 | |
| 18 | + | MOVD R12, CTR | |
| 19 | + | CALL CTR | |
| 20 | + | RET | |
| 21 | + | ||
| 22 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8-0 | |
| 23 | + | MOVD ·x_cgo_purego_setgid_call(SB), R12 | |
| 24 | + | MOVD (R12), R12 | |
| 25 | + | MOVD R12, CTR | |
| 26 | + | CALL CTR | |
| 27 | + | RET | |
| 28 | + | ||
| 29 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8-0 | |
| 30 | + | MOVD ·x_cgo_purego_setregid_call(SB), R12 | |
| 31 | + | MOVD (R12), R12 | |
| 32 | + | MOVD R12, CTR | |
| 33 | + | CALL CTR | |
| 34 | + | RET | |
| 35 | + | ||
| 36 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8-0 | |
| 37 | + | MOVD ·x_cgo_purego_setresgid_call(SB), R12 | |
| 38 | + | MOVD (R12), R12 | |
| 39 | + | MOVD R12, CTR | |
| 40 | + | CALL CTR | |
| 41 | + | RET | |
| 42 | + | ||
| 43 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8-0 | |
| 44 | + | MOVD ·x_cgo_purego_setresuid_call(SB), R12 | |
| 45 | + | MOVD (R12), R12 | |
| 46 | + | MOVD R12, CTR | |
| 47 | + | CALL CTR | |
| 48 | + | RET | |
| 49 | + | ||
| 50 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8-0 | |
| 51 | + | MOVD ·x_cgo_purego_setreuid_call(SB), R12 | |
| 52 | + | MOVD (R12), R12 | |
| 53 | + | MOVD R12, CTR | |
| 54 | + | CALL CTR | |
| 55 | + | RET | |
| 56 | + | ||
| 57 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8-0 | |
| 58 | + | MOVD ·x_cgo_purego_setuid_call(SB), R12 | |
| 59 | + | MOVD (R12), R12 | |
| 60 | + | MOVD R12, CTR | |
| 61 | + | CALL CTR | |
| 62 | + | RET | |
| 63 | + | ||
| 64 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8-0 | |
| 65 | + | MOVD ·x_cgo_purego_setgroups_call(SB), R12 | |
| 66 | + | MOVD (R12), R12 | |
| 67 | + | MOVD R12, CTR | |
| 68 | + | CALL CTR | |
| 69 | + | RET | |
| @@ -0,0 +1,69 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8-0 | |||
| 9 | + | MOVD ·x_cgo_purego_setegid_call(SB), R12 | |||
| 10 | + | MOVD (R12), R12 | |||
| 11 | + | MOVD R12, CTR | |||
| 12 | + | CALL CTR | |||
| 13 | + | RET | |||
| 14 | + | ||||
| 15 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 16 | + | MOVD ·x_cgo_purego_seteuid_call(SB), R12 | |||
| 17 | + | MOVD (R12), R12 | |||
| 18 | + | MOVD R12, CTR | |||
| 19 | + | CALL CTR | |||
| 20 | + | RET | |||
| 21 | + | ||||
| 22 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8-0 | |||
| 23 | + | MOVD ·x_cgo_purego_setgid_call(SB), R12 | |||
| 24 | + | MOVD (R12), R12 | |||
| 25 | + | MOVD R12, CTR | |||
| 26 | + | CALL CTR | |||
| 27 | + | RET | |||
| 28 | + | ||||
| 29 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8-0 | |||
| 30 | + | MOVD ·x_cgo_purego_setregid_call(SB), R12 | |||
| 31 | + | MOVD (R12), R12 | |||
| 32 | + | MOVD R12, CTR | |||
| 33 | + | CALL CTR | |||
| 34 | + | RET | |||
| 35 | + | ||||
| 36 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8-0 | |||
| 37 | + | MOVD ·x_cgo_purego_setresgid_call(SB), R12 | |||
| 38 | + | MOVD (R12), R12 | |||
| 39 | + | MOVD R12, CTR | |||
| 40 | + | CALL CTR | |||
| 41 | + | RET | |||
| 42 | + | ||||
| 43 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 44 | + | MOVD ·x_cgo_purego_setresuid_call(SB), R12 | |||
| 45 | + | MOVD (R12), R12 | |||
| 46 | + | MOVD R12, CTR | |||
| 47 | + | CALL CTR | |||
| 48 | + | RET | |||
| 49 | + | ||||
| 50 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 51 | + | MOVD ·x_cgo_purego_setreuid_call(SB), R12 | |||
| 52 | + | MOVD (R12), R12 | |||
| 53 | + | MOVD R12, CTR | |||
| 54 | + | CALL CTR | |||
| 55 | + | RET | |||
| 56 | + | ||||
| 57 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8-0 | |||
| 58 | + | MOVD ·x_cgo_purego_setuid_call(SB), R12 | |||
| 59 | + | MOVD (R12), R12 | |||
| 60 | + | MOVD R12, CTR | |||
| 61 | + | CALL CTR | |||
| 62 | + | RET | |||
| 63 | + | ||||
| 64 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8-0 | |||
| 65 | + | MOVD ·x_cgo_purego_setgroups_call(SB), R12 | |||
| 66 | + | MOVD (R12), R12 | |||
| 67 | + | MOVD R12, CTR | |||
| 68 | + | CALL CTR | |||
| 69 | + | RET | |||
A internal/fakecgo/trampolines_linux_riscv64.s +60 -0
| @@ -0,0 +1,60 @@ | |||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |
| 3 | + | ||
| 4 | + | //go:build !cgo && linux | |
| 5 | + | ||
| 6 | + | #include "textflag.h" | |
| 7 | + | ||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8 | |
| 9 | + | MOV ·x_cgo_purego_setegid_call(SB), X5 | |
| 10 | + | MOV (X5), X5 | |
| 11 | + | CALL X5 | |
| 12 | + | RET | |
| 13 | + | ||
| 14 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8 | |
| 15 | + | MOV ·x_cgo_purego_seteuid_call(SB), X5 | |
| 16 | + | MOV (X5), X5 | |
| 17 | + | CALL X5 | |
| 18 | + | RET | |
| 19 | + | ||
| 20 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8 | |
| 21 | + | MOV ·x_cgo_purego_setgid_call(SB), X5 | |
| 22 | + | MOV (X5), X5 | |
| 23 | + | CALL X5 | |
| 24 | + | RET | |
| 25 | + | ||
| 26 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8 | |
| 27 | + | MOV ·x_cgo_purego_setregid_call(SB), X5 | |
| 28 | + | MOV (X5), X5 | |
| 29 | + | CALL X5 | |
| 30 | + | RET | |
| 31 | + | ||
| 32 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8 | |
| 33 | + | MOV ·x_cgo_purego_setresgid_call(SB), X5 | |
| 34 | + | MOV (X5), X5 | |
| 35 | + | CALL X5 | |
| 36 | + | RET | |
| 37 | + | ||
| 38 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8 | |
| 39 | + | MOV ·x_cgo_purego_setresuid_call(SB), X5 | |
| 40 | + | MOV (X5), X5 | |
| 41 | + | CALL X5 | |
| 42 | + | RET | |
| 43 | + | ||
| 44 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8 | |
| 45 | + | MOV ·x_cgo_purego_setreuid_call(SB), X5 | |
| 46 | + | MOV (X5), X5 | |
| 47 | + | CALL X5 | |
| 48 | + | RET | |
| 49 | + | ||
| 50 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8 | |
| 51 | + | MOV ·x_cgo_purego_setuid_call(SB), X5 | |
| 52 | + | MOV (X5), X5 | |
| 53 | + | CALL X5 | |
| 54 | + | RET | |
| 55 | + | ||
| 56 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8 | |
| 57 | + | MOV ·x_cgo_purego_setgroups_call(SB), X5 | |
| 58 | + | MOV (X5), X5 | |
| 59 | + | CALL X5 | |
| 60 | + | RET | |
| @@ -0,0 +1,60 @@ | |||||
| 1 | + | // SPDX-License-Identifier: Apache-2.0 | |||
| 2 | + | // SPDX-FileCopyrightText: 2026 The Ebitengine Authors | |||
| 3 | + | ||||
| 4 | + | //go:build !cgo && linux | |||
| 5 | + | ||||
| 6 | + | #include "textflag.h" | |||
| 7 | + | ||||
| 8 | + | TEXT _cgo_purego_setegid_trampoline(SB), NOSPLIT, $8 | |||
| 9 | + | MOV ·x_cgo_purego_setegid_call(SB), X5 | |||
| 10 | + | MOV (X5), X5 | |||
| 11 | + | CALL X5 | |||
| 12 | + | RET | |||
| 13 | + | ||||
| 14 | + | TEXT _cgo_purego_seteuid_trampoline(SB), NOSPLIT, $8 | |||
| 15 | + | MOV ·x_cgo_purego_seteuid_call(SB), X5 | |||
| 16 | + | MOV (X5), X5 | |||
| 17 | + | CALL X5 | |||
| 18 | + | RET | |||
| 19 | + | ||||
| 20 | + | TEXT _cgo_purego_setgid_trampoline(SB), NOSPLIT, $8 | |||
| 21 | + | MOV ·x_cgo_purego_setgid_call(SB), X5 | |||
| 22 | + | MOV (X5), X5 | |||
| 23 | + | CALL X5 | |||
| 24 | + | RET | |||
| 25 | + | ||||
| 26 | + | TEXT _cgo_purego_setregid_trampoline(SB), NOSPLIT, $8 | |||
| 27 | + | MOV ·x_cgo_purego_setregid_call(SB), X5 | |||
| 28 | + | MOV (X5), X5 | |||
| 29 | + | CALL X5 | |||
| 30 | + | RET | |||
| 31 | + | ||||
| 32 | + | TEXT _cgo_purego_setresgid_trampoline(SB), NOSPLIT, $8 | |||
| 33 | + | MOV ·x_cgo_purego_setresgid_call(SB), X5 | |||
| 34 | + | MOV (X5), X5 | |||
| 35 | + | CALL X5 | |||
| 36 | + | RET | |||
| 37 | + | ||||
| 38 | + | TEXT _cgo_purego_setresuid_trampoline(SB), NOSPLIT, $8 | |||
| 39 | + | MOV ·x_cgo_purego_setresuid_call(SB), X5 | |||
| 40 | + | MOV (X5), X5 | |||
| 41 | + | CALL X5 | |||
| 42 | + | RET | |||
| 43 | + | ||||
| 44 | + | TEXT _cgo_purego_setreuid_trampoline(SB), NOSPLIT, $8 | |||
| 45 | + | MOV ·x_cgo_purego_setreuid_call(SB), X5 | |||
| 46 | + | MOV (X5), X5 | |||
| 47 | + | CALL X5 | |||
| 48 | + | RET | |||
| 49 | + | ||||
| 50 | + | TEXT _cgo_purego_setuid_trampoline(SB), NOSPLIT, $8 | |||
| 51 | + | MOV ·x_cgo_purego_setuid_call(SB), X5 | |||
| 52 | + | MOV (X5), X5 | |||
| 53 | + | CALL X5 | |||
| 54 | + | RET | |||
| 55 | + | ||||
| 56 | + | TEXT _cgo_purego_setgroups_trampoline(SB), NOSPLIT, $8 | |||
| 57 | + | MOV ·x_cgo_purego_setgroups_call(SB), X5 | |||
| 58 | + | MOV (X5), X5 | |||
| 59 | + | CALL X5 | |||
| 60 | + | RET | |||
M internal/fakecgo/trampolines_loong64.s +1 -6
| @@ -49,16 +49,14 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0 | |||
| 49 | 49 | CALL (R23) | |
| 50 | 50 | RET | |
| 51 | 51 | ||
| 52 | - | TEXT threadentry_trampoline(SB), NOSPLIT, $0 | |
| 52 | + | TEXT threadentry_trampoline(SB), NOSPLIT, $176 | |
| 53 | 53 | // See crosscall2. | |
| 54 | - | ADDV $(-23*8), R3 | |
| 55 | 54 | MOVV R4, (1*8)(R3) // fn unsafe.Pointer | |
| 56 | 55 | MOVV R5, (2*8)(R3) // a unsafe.Pointer | |
| 57 | 56 | MOVV R7, (3*8)(R3) // ctxt uintptr | |
| 58 | 57 | ||
| 59 | 58 | SAVE_R22_TO_R31((4*8)) | |
| 60 | 59 | SAVE_F24_TO_F31((14*8)) | |
| 61 | - | MOVV R1, (22*8)(R3) | |
| 62 | 60 | ||
| 63 | 61 | MOVV ·threadentry_call(SB), R23 | |
| 64 | 62 | MOVV (R23), R23 | |
| @@ -66,9 +64,6 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0 | |||
| 66 | 64 | ||
| 67 | 65 | RESTORE_R22_TO_R31((4*8)) | |
| 68 | 66 | RESTORE_F24_TO_F31((14*8)) | |
| 69 | - | MOVV (22*8)(R3), R1 | |
| 70 | - | ||
| 71 | - | ADDV $(23*8), R3 | |
| 72 | 67 | RET | |
| 73 | 68 | ||
| 74 | 69 | TEXT ·call5(SB), NOSPLIT, $0-0 | |
| @@ -49,16 +49,14 @@ TEXT ·setg_trampoline(SB), NOSPLIT, $0 | |||||
| 49 | CALL (R23) | 49 | CALL (R23) | ||
| 50 | RET | 50 | RET | ||
| 51 | 51 | ||||
| 52 | - | TEXT threadentry_trampoline(SB), NOSPLIT, $0 | 52 | + | TEXT threadentry_trampoline(SB), NOSPLIT, $176 |
| 53 | // See crosscall2. | 53 | // See crosscall2. | ||
| 54 | - | ADDV $(-23*8), R3 | |||
| 55 | MOVV R4, (1*8)(R3) // fn unsafe.Pointer | 54 | MOVV R4, (1*8)(R3) // fn unsafe.Pointer | ||
| 56 | MOVV R5, (2*8)(R3) // a unsafe.Pointer | 55 | MOVV R5, (2*8)(R3) // a unsafe.Pointer | ||
| 57 | MOVV R7, (3*8)(R3) // ctxt uintptr | 56 | MOVV R7, (3*8)(R3) // ctxt uintptr | ||
| 58 | 57 | ||||
| 59 | SAVE_R22_TO_R31((4*8)) | 58 | SAVE_R22_TO_R31((4*8)) | ||
| 60 | SAVE_F24_TO_F31((14*8)) | 59 | SAVE_F24_TO_F31((14*8)) | ||
| 61 | - | MOVV R1, (22*8)(R3) | |||
| 62 | 60 | ||||
| 63 | MOVV ·threadentry_call(SB), R23 | 61 | MOVV ·threadentry_call(SB), R23 | ||
| 64 | MOVV (R23), R23 | 62 | MOVV (R23), R23 | ||
| @@ -66,9 +64,6 @@ TEXT threadentry_trampoline(SB), NOSPLIT, $0 | |||||
| 66 | 64 | ||||
| 67 | RESTORE_R22_TO_R31((4*8)) | 65 | RESTORE_R22_TO_R31((4*8)) | ||
| 68 | RESTORE_F24_TO_F31((14*8)) | 66 | RESTORE_F24_TO_F31((14*8)) | ||
| 69 | - | MOVV (22*8)(R3), R1 | |||
| 70 | - | ||||
| 71 | - | ADDV $(23*8), R3 | |||
| 72 | RET | 67 | RET | ||
| 73 | 68 | ||||
| 74 | TEXT ·call5(SB), NOSPLIT, $0-0 | 69 | TEXT ·call5(SB), NOSPLIT, $0-0 | ||
M internal/fakecgo/zsymbols_linux.go +110 -0
| @@ -16,6 +16,16 @@ import "unsafe" | |||
| 16 | 16 | //go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6" | |
| 17 | 17 | //go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6" | |
| 18 | 18 | //go:cgo_import_dynamic purego_abort abort "libc.so.6" | |
| 19 | + | //go:cgo_import_dynamic purego___errno_location __errno_location "libc.so.6" | |
| 20 | + | //go:cgo_import_dynamic purego_setegid setegid "libc.so.6" | |
| 21 | + | //go:cgo_import_dynamic purego_seteuid seteuid "libc.so.6" | |
| 22 | + | //go:cgo_import_dynamic purego_setgid setgid "libc.so.6" | |
| 23 | + | //go:cgo_import_dynamic purego_setregid setregid "libc.so.6" | |
| 24 | + | //go:cgo_import_dynamic purego_setresgid setresgid "libc.so.6" | |
| 25 | + | //go:cgo_import_dynamic purego_setresuid setresuid "libc.so.6" | |
| 26 | + | //go:cgo_import_dynamic purego_setreuid setreuid "libc.so.6" | |
| 27 | + | //go:cgo_import_dynamic purego_setuid setuid "libc.so.6" | |
| 28 | + | //go:cgo_import_dynamic purego_setgroups setgroups "libc.so.6" | |
| 19 | 29 | //go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0" | |
| 20 | 30 | //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0" | |
| 21 | 31 | //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0" | |
| @@ -27,6 +37,66 @@ import "unsafe" | |||
| 27 | 37 | //go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0" | |
| 28 | 38 | //go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0" | |
| 29 | 39 | ||
| 40 | + | //go:nosplit | |
| 41 | + | //go:norace | |
| 42 | + | func __errno_location() uintptr { | |
| 43 | + | return uintptr(call5(__errno_locationABI0, 0, 0, 0, 0, 0)) | |
| 44 | + | } | |
| 45 | + | ||
| 46 | + | //go:nosplit | |
| 47 | + | //go:norace | |
| 48 | + | func setegid(egid uint32) int32 { | |
| 49 | + | return int32(call5(setegidABI0, uintptr(egid), 0, 0, 0, 0)) | |
| 50 | + | } | |
| 51 | + | ||
| 52 | + | //go:nosplit | |
| 53 | + | //go:norace | |
| 54 | + | func seteuid(euid uint32) int32 { | |
| 55 | + | return int32(call5(seteuidABI0, uintptr(euid), 0, 0, 0, 0)) | |
| 56 | + | } | |
| 57 | + | ||
| 58 | + | //go:nosplit | |
| 59 | + | //go:norace | |
| 60 | + | func setgid(gid uint32) int32 { | |
| 61 | + | return int32(call5(setgidABI0, uintptr(gid), 0, 0, 0, 0)) | |
| 62 | + | } | |
| 63 | + | ||
| 64 | + | //go:nosplit | |
| 65 | + | //go:norace | |
| 66 | + | func setregid(rgid uint32, egid uint32) int32 { | |
| 67 | + | return int32(call5(setregidABI0, uintptr(rgid), uintptr(egid), 0, 0, 0)) | |
| 68 | + | } | |
| 69 | + | ||
| 70 | + | //go:nosplit | |
| 71 | + | //go:norace | |
| 72 | + | func setresgid(rgid uint32, egid uint32, sgid uint32) int32 { | |
| 73 | + | return int32(call5(setresgidABI0, uintptr(rgid), uintptr(egid), uintptr(sgid), 0, 0)) | |
| 74 | + | } | |
| 75 | + | ||
| 76 | + | //go:nosplit | |
| 77 | + | //go:norace | |
| 78 | + | func setresuid(ruid uint32, euid uint32, suid uint32) int32 { | |
| 79 | + | return int32(call5(setresuidABI0, uintptr(ruid), uintptr(euid), uintptr(suid), 0, 0)) | |
| 80 | + | } | |
| 81 | + | ||
| 82 | + | //go:nosplit | |
| 83 | + | //go:norace | |
| 84 | + | func setreuid(ruid uint32, euid uint32) int32 { | |
| 85 | + | return int32(call5(setreuidABI0, uintptr(ruid), uintptr(euid), 0, 0, 0)) | |
| 86 | + | } | |
| 87 | + | ||
| 88 | + | //go:nosplit | |
| 89 | + | //go:norace | |
| 90 | + | func setuid(uid uint32) int32 { | |
| 91 | + | return int32(call5(setuidABI0, uintptr(uid), 0, 0, 0, 0)) | |
| 92 | + | } | |
| 93 | + | ||
| 94 | + | //go:nosplit | |
| 95 | + | //go:norace | |
| 96 | + | func setgroups(ngid uint32, gidset *uint32) int32 { | |
| 97 | + | return int32(call5(setgroupsABI0, uintptr(ngid), uintptr(unsafe.Pointer(gidset)), 0, 0, 0)) | |
| 98 | + | } | |
| 99 | + | ||
| 30 | 100 | //go:nosplit | |
| 31 | 101 | //go:norace | |
| 32 | 102 | func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { | |
| @@ -39,6 +109,46 @@ func pthread_attr_destroy(attr *pthread_attr_t) int32 { | |||
| 39 | 109 | return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | |
| 40 | 110 | } | |
| 41 | 111 | ||
| 112 | + | //go:linkname ___errno_location ___errno_location | |
| 113 | + | var ___errno_location uint8 | |
| 114 | + | var __errno_locationABI0 = uintptr(unsafe.Pointer(&___errno_location)) | |
| 115 | + | ||
| 116 | + | //go:linkname _setegid _setegid | |
| 117 | + | var _setegid uint8 | |
| 118 | + | var setegidABI0 = uintptr(unsafe.Pointer(&_setegid)) | |
| 119 | + | ||
| 120 | + | //go:linkname _seteuid _seteuid | |
| 121 | + | var _seteuid uint8 | |
| 122 | + | var seteuidABI0 = uintptr(unsafe.Pointer(&_seteuid)) | |
| 123 | + | ||
| 124 | + | //go:linkname _setgid _setgid | |
| 125 | + | var _setgid uint8 | |
| 126 | + | var setgidABI0 = uintptr(unsafe.Pointer(&_setgid)) | |
| 127 | + | ||
| 128 | + | //go:linkname _setregid _setregid | |
| 129 | + | var _setregid uint8 | |
| 130 | + | var setregidABI0 = uintptr(unsafe.Pointer(&_setregid)) | |
| 131 | + | ||
| 132 | + | //go:linkname _setresgid _setresgid | |
| 133 | + | var _setresgid uint8 | |
| 134 | + | var setresgidABI0 = uintptr(unsafe.Pointer(&_setresgid)) | |
| 135 | + | ||
| 136 | + | //go:linkname _setresuid _setresuid | |
| 137 | + | var _setresuid uint8 | |
| 138 | + | var setresuidABI0 = uintptr(unsafe.Pointer(&_setresuid)) | |
| 139 | + | ||
| 140 | + | //go:linkname _setreuid _setreuid | |
| 141 | + | var _setreuid uint8 | |
| 142 | + | var setreuidABI0 = uintptr(unsafe.Pointer(&_setreuid)) | |
| 143 | + | ||
| 144 | + | //go:linkname _setuid _setuid | |
| 145 | + | var _setuid uint8 | |
| 146 | + | var setuidABI0 = uintptr(unsafe.Pointer(&_setuid)) | |
| 147 | + | ||
| 148 | + | //go:linkname _setgroups _setgroups | |
| 149 | + | var _setgroups uint8 | |
| 150 | + | var setgroupsABI0 = uintptr(unsafe.Pointer(&_setgroups)) | |
| 151 | + | ||
| 42 | 152 | //go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize | |
| 43 | 153 | var _pthread_attr_getstacksize uint8 | |
| 44 | 154 | var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize)) | |
| @@ -16,6 +16,16 @@ import "unsafe" | |||||
| 16 | //go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6" | 16 | //go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6" | ||
| 17 | //go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6" | 17 | //go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6" | ||
| 18 | //go:cgo_import_dynamic purego_abort abort "libc.so.6" | 18 | //go:cgo_import_dynamic purego_abort abort "libc.so.6" | ||
| 19 | + | //go:cgo_import_dynamic purego___errno_location __errno_location "libc.so.6" | |||
| 20 | + | //go:cgo_import_dynamic purego_setegid setegid "libc.so.6" | |||
| 21 | + | //go:cgo_import_dynamic purego_seteuid seteuid "libc.so.6" | |||
| 22 | + | //go:cgo_import_dynamic purego_setgid setgid "libc.so.6" | |||
| 23 | + | //go:cgo_import_dynamic purego_setregid setregid "libc.so.6" | |||
| 24 | + | //go:cgo_import_dynamic purego_setresgid setresgid "libc.so.6" | |||
| 25 | + | //go:cgo_import_dynamic purego_setresuid setresuid "libc.so.6" | |||
| 26 | + | //go:cgo_import_dynamic purego_setreuid setreuid "libc.so.6" | |||
| 27 | + | //go:cgo_import_dynamic purego_setuid setuid "libc.so.6" | |||
| 28 | + | //go:cgo_import_dynamic purego_setgroups setgroups "libc.so.6" | |||
| 19 | //go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0" | 29 | //go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0" | ||
| 20 | //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0" | 30 | //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0" | ||
| 21 | //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0" | 31 | //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0" | ||
| @@ -27,6 +37,66 @@ import "unsafe" | |||||
| 27 | //go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0" | 37 | //go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0" | ||
| 28 | //go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0" | 38 | //go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0" | ||
| 29 | 39 | ||||
| 40 | + | //go:nosplit | |||
| 41 | + | //go:norace | |||
| 42 | + | func __errno_location() uintptr { | |||
| 43 | + | return uintptr(call5(__errno_locationABI0, 0, 0, 0, 0, 0)) | |||
| 44 | + | } | |||
| 45 | + | ||||
| 46 | + | //go:nosplit | |||
| 47 | + | //go:norace | |||
| 48 | + | func setegid(egid uint32) int32 { | |||
| 49 | + | return int32(call5(setegidABI0, uintptr(egid), 0, 0, 0, 0)) | |||
| 50 | + | } | |||
| 51 | + | ||||
| 52 | + | //go:nosplit | |||
| 53 | + | //go:norace | |||
| 54 | + | func seteuid(euid uint32) int32 { | |||
| 55 | + | return int32(call5(seteuidABI0, uintptr(euid), 0, 0, 0, 0)) | |||
| 56 | + | } | |||
| 57 | + | ||||
| 58 | + | //go:nosplit | |||
| 59 | + | //go:norace | |||
| 60 | + | func setgid(gid uint32) int32 { | |||
| 61 | + | return int32(call5(setgidABI0, uintptr(gid), 0, 0, 0, 0)) | |||
| 62 | + | } | |||
| 63 | + | ||||
| 64 | + | //go:nosplit | |||
| 65 | + | //go:norace | |||
| 66 | + | func setregid(rgid uint32, egid uint32) int32 { | |||
| 67 | + | return int32(call5(setregidABI0, uintptr(rgid), uintptr(egid), 0, 0, 0)) | |||
| 68 | + | } | |||
| 69 | + | ||||
| 70 | + | //go:nosplit | |||
| 71 | + | //go:norace | |||
| 72 | + | func setresgid(rgid uint32, egid uint32, sgid uint32) int32 { | |||
| 73 | + | return int32(call5(setresgidABI0, uintptr(rgid), uintptr(egid), uintptr(sgid), 0, 0)) | |||
| 74 | + | } | |||
| 75 | + | ||||
| 76 | + | //go:nosplit | |||
| 77 | + | //go:norace | |||
| 78 | + | func setresuid(ruid uint32, euid uint32, suid uint32) int32 { | |||
| 79 | + | return int32(call5(setresuidABI0, uintptr(ruid), uintptr(euid), uintptr(suid), 0, 0)) | |||
| 80 | + | } | |||
| 81 | + | ||||
| 82 | + | //go:nosplit | |||
| 83 | + | //go:norace | |||
| 84 | + | func setreuid(ruid uint32, euid uint32) int32 { | |||
| 85 | + | return int32(call5(setreuidABI0, uintptr(ruid), uintptr(euid), 0, 0, 0)) | |||
| 86 | + | } | |||
| 87 | + | ||||
| 88 | + | //go:nosplit | |||
| 89 | + | //go:norace | |||
| 90 | + | func setuid(uid uint32) int32 { | |||
| 91 | + | return int32(call5(setuidABI0, uintptr(uid), 0, 0, 0, 0)) | |||
| 92 | + | } | |||
| 93 | + | ||||
| 94 | + | //go:nosplit | |||
| 95 | + | //go:norace | |||
| 96 | + | func setgroups(ngid uint32, gidset *uint32) int32 { | |||
| 97 | + | return int32(call5(setgroupsABI0, uintptr(ngid), uintptr(unsafe.Pointer(gidset)), 0, 0, 0)) | |||
| 98 | + | } | |||
| 99 | + | ||||
| 30 | //go:nosplit | 100 | //go:nosplit | ||
| 31 | //go:norace | 101 | //go:norace | ||
| 32 | func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { | 102 | func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { | ||
| @@ -39,6 +109,46 @@ func pthread_attr_destroy(attr *pthread_attr_t) int32 { | |||||
| 39 | return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | 109 | return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | ||
| 40 | } | 110 | } | ||
| 41 | 111 | ||||
| 112 | + | //go:linkname ___errno_location ___errno_location | |||
| 113 | + | var ___errno_location uint8 | |||
| 114 | + | var __errno_locationABI0 = uintptr(unsafe.Pointer(&___errno_location)) | |||
| 115 | + | ||||
| 116 | + | //go:linkname _setegid _setegid | |||
| 117 | + | var _setegid uint8 | |||
| 118 | + | var setegidABI0 = uintptr(unsafe.Pointer(&_setegid)) | |||
| 119 | + | ||||
| 120 | + | //go:linkname _seteuid _seteuid | |||
| 121 | + | var _seteuid uint8 | |||
| 122 | + | var seteuidABI0 = uintptr(unsafe.Pointer(&_seteuid)) | |||
| 123 | + | ||||
| 124 | + | //go:linkname _setgid _setgid | |||
| 125 | + | var _setgid uint8 | |||
| 126 | + | var setgidABI0 = uintptr(unsafe.Pointer(&_setgid)) | |||
| 127 | + | ||||
| 128 | + | //go:linkname _setregid _setregid | |||
| 129 | + | var _setregid uint8 | |||
| 130 | + | var setregidABI0 = uintptr(unsafe.Pointer(&_setregid)) | |||
| 131 | + | ||||
| 132 | + | //go:linkname _setresgid _setresgid | |||
| 133 | + | var _setresgid uint8 | |||
| 134 | + | var setresgidABI0 = uintptr(unsafe.Pointer(&_setresgid)) | |||
| 135 | + | ||||
| 136 | + | //go:linkname _setresuid _setresuid | |||
| 137 | + | var _setresuid uint8 | |||
| 138 | + | var setresuidABI0 = uintptr(unsafe.Pointer(&_setresuid)) | |||
| 139 | + | ||||
| 140 | + | //go:linkname _setreuid _setreuid | |||
| 141 | + | var _setreuid uint8 | |||
| 142 | + | var setreuidABI0 = uintptr(unsafe.Pointer(&_setreuid)) | |||
| 143 | + | ||||
| 144 | + | //go:linkname _setuid _setuid | |||
| 145 | + | var _setuid uint8 | |||
| 146 | + | var setuidABI0 = uintptr(unsafe.Pointer(&_setuid)) | |||
| 147 | + | ||||
| 148 | + | //go:linkname _setgroups _setgroups | |||
| 149 | + | var _setgroups uint8 | |||
| 150 | + | var setgroupsABI0 = uintptr(unsafe.Pointer(&_setgroups)) | |||
| 151 | + | ||||
| 42 | //go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize | 152 | //go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize | ||
| 43 | var _pthread_attr_getstacksize uint8 | 153 | var _pthread_attr_getstacksize uint8 | ||
| 44 | var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize)) | 154 | var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize)) | ||
M internal/fakecgo/ztrampolines_linux.s +30 -0
| @@ -9,6 +9,36 @@ | |||
| 9 | 9 | ||
| 10 | 10 | // these stubs are here because it is not possible to go:linkname directly the C functions | |
| 11 | 11 | ||
| 12 | + | TEXT ___errno_location(SB), NOSPLIT|NOFRAME, $0-0 | |
| 13 | + | JMP purego___errno_location(SB) | |
| 14 | + | ||
| 15 | + | TEXT _setegid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 16 | + | JMP purego_setegid(SB) | |
| 17 | + | ||
| 18 | + | TEXT _seteuid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 19 | + | JMP purego_seteuid(SB) | |
| 20 | + | ||
| 21 | + | TEXT _setgid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 22 | + | JMP purego_setgid(SB) | |
| 23 | + | ||
| 24 | + | TEXT _setregid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 25 | + | JMP purego_setregid(SB) | |
| 26 | + | ||
| 27 | + | TEXT _setresgid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 28 | + | JMP purego_setresgid(SB) | |
| 29 | + | ||
| 30 | + | TEXT _setresuid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 31 | + | JMP purego_setresuid(SB) | |
| 32 | + | ||
| 33 | + | TEXT _setreuid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 34 | + | JMP purego_setreuid(SB) | |
| 35 | + | ||
| 36 | + | TEXT _setuid(SB), NOSPLIT|NOFRAME, $0-0 | |
| 37 | + | JMP purego_setuid(SB) | |
| 38 | + | ||
| 39 | + | TEXT _setgroups(SB), NOSPLIT|NOFRAME, $0-0 | |
| 40 | + | JMP purego_setgroups(SB) | |
| 41 | + | ||
| 12 | 42 | TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0 | |
| 13 | 43 | JMP purego_pthread_attr_getstacksize(SB) | |
| 14 | 44 | ||
| @@ -9,6 +9,36 @@ | |||||
| 9 | 9 | ||||
| 10 | // these stubs are here because it is not possible to go:linkname directly the C functions | 10 | // these stubs are here because it is not possible to go:linkname directly the C functions | ||
| 11 | 11 | ||||
| 12 | + | TEXT ___errno_location(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 13 | + | JMP purego___errno_location(SB) | |||
| 14 | + | ||||
| 15 | + | TEXT _setegid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 16 | + | JMP purego_setegid(SB) | |||
| 17 | + | ||||
| 18 | + | TEXT _seteuid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 19 | + | JMP purego_seteuid(SB) | |||
| 20 | + | ||||
| 21 | + | TEXT _setgid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 22 | + | JMP purego_setgid(SB) | |||
| 23 | + | ||||
| 24 | + | TEXT _setregid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 25 | + | JMP purego_setregid(SB) | |||
| 26 | + | ||||
| 27 | + | TEXT _setresgid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 28 | + | JMP purego_setresgid(SB) | |||
| 29 | + | ||||
| 30 | + | TEXT _setresuid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 31 | + | JMP purego_setresuid(SB) | |||
| 32 | + | ||||
| 33 | + | TEXT _setreuid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 34 | + | JMP purego_setreuid(SB) | |||
| 35 | + | ||||
| 36 | + | TEXT _setuid(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 37 | + | JMP purego_setuid(SB) | |||
| 38 | + | ||||
| 39 | + | TEXT _setgroups(SB), NOSPLIT|NOFRAME, $0-0 | |||
| 40 | + | JMP purego_setgroups(SB) | |||
| 41 | + | ||||
| 12 | TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0 | 42 | TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0 | ||
| 13 | JMP purego_pthread_attr_getstacksize(SB) | 43 | JMP purego_pthread_attr_getstacksize(SB) | ||
| 14 | 44 | ||||
M sys_amd64.s +8 -14
| @@ -38,11 +38,8 @@ | |||
| 38 | 38 | // C calling convention (use libcCall). | |
| 39 | 39 | GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8 | |
| 40 | 40 | DATA ·syscall15XABI0(SB)/8, $syscall15X(SB) | |
| 41 | - | TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 | |
| 42 | - | PUSHQ BP | |
| 43 | - | MOVQ SP, BP | |
| 44 | - | SUBQ $STACK_SIZE, SP | |
| 45 | - | MOVQ DI, PTR_ADDRESS(BP) // save the pointer | |
| 41 | + | TEXT syscall15X(SB), NOSPLIT, $STACK_SIZE | |
| 42 | + | MOVQ DI, PTR_ADDRESS(SP) // save the pointer | |
| 46 | 43 | MOVQ DI, R11 | |
| 47 | 44 | ||
| 48 | 45 | MOVQ syscall15Args_f1(R11), X0 // f1 | |
| @@ -61,7 +58,7 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 | |||
| 61 | 58 | MOVQ syscall15Args_a5(R11), R8 // a5 | |
| 62 | 59 | MOVQ syscall15Args_a6(R11), R9 // a6 | |
| 63 | 60 | ||
| 64 | - | // push the remaining paramters onto the stack | |
| 61 | + | // push the remaining parameters onto the stack | |
| 65 | 62 | MOVQ syscall15Args_a7(R11), R12 | |
| 66 | 63 | MOVQ R12, 0(SP) // push a7 | |
| 67 | 64 | MOVQ syscall15Args_a8(R11), R12 | |
| @@ -85,23 +82,20 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 | |||
| 85 | 82 | MOVQ syscall15Args_fn(R11), R10 // fn | |
| 86 | 83 | CALL R10 | |
| 87 | 84 | ||
| 88 | - | MOVQ PTR_ADDRESS(BP), DI // get the pointer back | |
| 85 | + | MOVQ PTR_ADDRESS(SP), DI // get the pointer back | |
| 89 | 86 | MOVQ AX, syscall15Args_a1(DI) // r1 | |
| 90 | - | MOVQ DX, syscall15Args_a2(DI) // r3 | |
| 87 | + | MOVQ DX, syscall15Args_a2(DI) // r2 | |
| 91 | 88 | MOVQ X0, syscall15Args_f1(DI) // f1 | |
| 92 | 89 | MOVQ X1, syscall15Args_f2(DI) // f2 | |
| 93 | 90 | ||
| 94 | 91 | #ifdef GOOS_darwin | |
| 95 | 92 | CALL purego_error(SB) | |
| 96 | - | MOVD (AX), AX | |
| 97 | - | MOVD AX, syscall15Args_a3(DI) // save errno | |
| 98 | - | ||
| 93 | + | MOVQ PTR_ADDRESS(SP), DI // reload (DI clobbered by call) | |
| 94 | + | MOVQ (AX), AX | |
| 95 | + | MOVQ AX, syscall15Args_a3(DI) // save errno | |
| 99 | 96 | #endif | |
| 100 | 97 | ||
| 101 | 98 | XORL AX, AX // no error (it's ignored anyway) | |
| 102 | - | ADDQ $STACK_SIZE, SP | |
| 103 | - | MOVQ BP, SP | |
| 104 | - | POPQ BP | |
| 105 | 99 | RET | |
| 106 | 100 | ||
| 107 | 101 | TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 | |
| @@ -38,11 +38,8 @@ | |||||
| 38 | // C calling convention (use libcCall). | 38 | // C calling convention (use libcCall). | ||
| 39 | GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8 | 39 | GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8 | ||
| 40 | DATA ·syscall15XABI0(SB)/8, $syscall15X(SB) | 40 | DATA ·syscall15XABI0(SB)/8, $syscall15X(SB) | ||
| 41 | - | TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 | 41 | + | TEXT syscall15X(SB), NOSPLIT, $STACK_SIZE |
| 42 | - | PUSHQ BP | 42 | + | MOVQ DI, PTR_ADDRESS(SP) // save the pointer |
| 43 | - | MOVQ SP, BP | |||
| 44 | - | SUBQ $STACK_SIZE, SP | |||
| 45 | - | MOVQ DI, PTR_ADDRESS(BP) // save the pointer | |||
| 46 | MOVQ DI, R11 | 43 | MOVQ DI, R11 | ||
| 47 | 44 | ||||
| 48 | MOVQ syscall15Args_f1(R11), X0 // f1 | 45 | MOVQ syscall15Args_f1(R11), X0 // f1 | ||
| @@ -61,7 +58,7 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 | |||||
| 61 | MOVQ syscall15Args_a5(R11), R8 // a5 | 58 | MOVQ syscall15Args_a5(R11), R8 // a5 | ||
| 62 | MOVQ syscall15Args_a6(R11), R9 // a6 | 59 | MOVQ syscall15Args_a6(R11), R9 // a6 | ||
| 63 | 60 | ||||
| 64 | - | // push the remaining paramters onto the stack | 61 | + | // push the remaining parameters onto the stack |
| 65 | MOVQ syscall15Args_a7(R11), R12 | 62 | MOVQ syscall15Args_a7(R11), R12 | ||
| 66 | MOVQ R12, 0(SP) // push a7 | 63 | MOVQ R12, 0(SP) // push a7 | ||
| 67 | MOVQ syscall15Args_a8(R11), R12 | 64 | MOVQ syscall15Args_a8(R11), R12 | ||
| @@ -85,23 +82,20 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 | |||||
| 85 | MOVQ syscall15Args_fn(R11), R10 // fn | 82 | MOVQ syscall15Args_fn(R11), R10 // fn | ||
| 86 | CALL R10 | 83 | CALL R10 | ||
| 87 | 84 | ||||
| 88 | - | MOVQ PTR_ADDRESS(BP), DI // get the pointer back | 85 | + | MOVQ PTR_ADDRESS(SP), DI // get the pointer back |
| 89 | MOVQ AX, syscall15Args_a1(DI) // r1 | 86 | MOVQ AX, syscall15Args_a1(DI) // r1 | ||
| 90 | - | MOVQ DX, syscall15Args_a2(DI) // r3 | 87 | + | MOVQ DX, syscall15Args_a2(DI) // r2 |
| 91 | MOVQ X0, syscall15Args_f1(DI) // f1 | 88 | MOVQ X0, syscall15Args_f1(DI) // f1 | ||
| 92 | MOVQ X1, syscall15Args_f2(DI) // f2 | 89 | MOVQ X1, syscall15Args_f2(DI) // f2 | ||
| 93 | 90 | ||||
| 94 | #ifdef GOOS_darwin | 91 | #ifdef GOOS_darwin | ||
| 95 | CALL purego_error(SB) | 92 | CALL purego_error(SB) | ||
| 96 | - | MOVD (AX), AX | 93 | + | MOVQ PTR_ADDRESS(SP), DI // reload (DI clobbered by call) |
| 97 | - | MOVD AX, syscall15Args_a3(DI) // save errno | 94 | + | MOVQ (AX), AX |
| 98 | - | 95 | + | MOVQ AX, syscall15Args_a3(DI) // save errno | |
| 99 | #endif | 96 | #endif | ||
| 100 | 97 | ||||
| 101 | XORL AX, AX // no error (it's ignored anyway) | 98 | XORL AX, AX // no error (it's ignored anyway) | ||
| 102 | - | ADDQ $STACK_SIZE, SP | |||
| 103 | - | MOVQ BP, SP | |||
| 104 | - | POPQ BP | |||
| 105 | RET | 99 | RET | ||
| 106 | 100 | ||||
| 107 | TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 | 101 | TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 | ||
A syscall_linux_test.go +218 -0
| @@ -0,0 +1,218 @@ | |||
| 1 | + | // Copyright 2015 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 purego_test | |
| 6 | + | ||
| 7 | + | import ( | |
| 8 | + | "errors" | |
| 9 | + | "fmt" | |
| 10 | + | "os" | |
| 11 | + | "path/filepath" | |
| 12 | + | "runtime" | |
| 13 | + | "sort" | |
| 14 | + | "strings" | |
| 15 | + | "syscall" | |
| 16 | + | "testing" | |
| 17 | + | "unsafe" | |
| 18 | + | ||
| 19 | + | "github.com/ebitengine/purego" | |
| 20 | + | ) | |
| 21 | + | ||
| 22 | + | func TestAllThreadsSyscall(t *testing.T) { | |
| 23 | + | _, _, err := syscall.AllThreadsSyscall(syscall.SYS_FCNTL, 0, 0, 0) | |
| 24 | + | if err != syscall.ENOTSUP { | |
| 25 | + | t.Errorf("AllThreadsSyscall should return ENOTSUP, got: %v", err) | |
| 26 | + | } | |
| 27 | + | } | |
| 28 | + | ||
| 29 | + | // TestSetuidEtc performs tests on all of the wrapped system calls | |
| 30 | + | // that mirror to the 9 glibc syscalls with POSIX semantics. The test | |
| 31 | + | // here is considered authoritative and should compile and run | |
| 32 | + | // CGO_ENABLED=0 or 1. | |
| 33 | + | func TestSetuidEtc(t *testing.T) { | |
| 34 | + | vs := []struct { | |
| 35 | + | call string | |
| 36 | + | fn func() error | |
| 37 | + | filter, expect string | |
| 38 | + | }{ | |
| 39 | + | {call: "Setegid(1)", fn: func() error { return syscall.Setegid(1) }, filter: "Gid:", expect: "\t0\t1\t0\t1"}, | |
| 40 | + | {call: "Setegid(0)", fn: func() error { return syscall.Setegid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |
| 41 | + | ||
| 42 | + | {call: "Seteuid(1)", fn: func() error { return syscall.Seteuid(1) }, filter: "Uid:", expect: "\t0\t1\t0\t1"}, | |
| 43 | + | {call: "Setuid(0)", fn: func() error { return syscall.Setuid(0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"}, | |
| 44 | + | ||
| 45 | + | {call: "Setgid(1)", fn: func() error { return syscall.Setgid(1) }, filter: "Gid:", expect: "\t1\t1\t1\t1"}, | |
| 46 | + | {call: "Setgid(0)", fn: func() error { return syscall.Setgid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |
| 47 | + | ||
| 48 | + | {call: "Setgroups([]int{0,1,2,3})", fn: func() error { return syscall.Setgroups([]int{0, 1, 2, 3}) }, filter: "Groups:", expect: "\t0 1 2 3"}, | |
| 49 | + | {call: "Setgroups(nil)", fn: func() error { return syscall.Setgroups(nil) }, filter: "Groups:", expect: ""}, | |
| 50 | + | {call: "Setgroups([]int{0})", fn: func() error { return syscall.Setgroups([]int{0}) }, filter: "Groups:", expect: "\t0"}, | |
| 51 | + | ||
| 52 | + | {call: "Setregid(101,0)", fn: func() error { return syscall.Setregid(101, 0) }, filter: "Gid:", expect: "\t101\t0\t0\t0"}, | |
| 53 | + | {call: "Setregid(0,102)", fn: func() error { return syscall.Setregid(0, 102) }, filter: "Gid:", expect: "\t0\t102\t102\t102"}, | |
| 54 | + | {call: "Setregid(0,0)", fn: func() error { return syscall.Setregid(0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |
| 55 | + | ||
| 56 | + | {call: "Setreuid(1,0)", fn: func() error { return syscall.Setreuid(1, 0) }, filter: "Uid:", expect: "\t1\t0\t0\t0"}, | |
| 57 | + | {call: "Setreuid(0,2)", fn: func() error { return syscall.Setreuid(0, 2) }, filter: "Uid:", expect: "\t0\t2\t2\t2"}, | |
| 58 | + | {call: "Setreuid(0,0)", fn: func() error { return syscall.Setreuid(0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"}, | |
| 59 | + | ||
| 60 | + | {call: "Setresgid(101,0,102)", fn: func() error { return syscall.Setresgid(101, 0, 102) }, filter: "Gid:", expect: "\t101\t0\t102\t0"}, | |
| 61 | + | {call: "Setresgid(0,102,101)", fn: func() error { return syscall.Setresgid(0, 102, 101) }, filter: "Gid:", expect: "\t0\t102\t101\t102"}, | |
| 62 | + | {call: "Setresgid(0,0,0)", fn: func() error { return syscall.Setresgid(0, 0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |
| 63 | + | ||
| 64 | + | {call: "Setresuid(1,0,2)", fn: func() error { return syscall.Setresuid(1, 0, 2) }, filter: "Uid:", expect: "\t1\t0\t2\t0"}, | |
| 65 | + | {call: "Setresuid(0,2,1)", fn: func() error { return syscall.Setresuid(0, 2, 1) }, filter: "Uid:", expect: "\t0\t2\t1\t2"}, | |
| 66 | + | {call: "Setresuid(0,0,0)", fn: func() error { return syscall.Setresuid(0, 0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"}, | |
| 67 | + | } | |
| 68 | + | ||
| 69 | + | for i, v := range vs { | |
| 70 | + | // Generate some thread churn. | |
| 71 | + | c := make(chan struct{}) | |
| 72 | + | go killAThread(c) | |
| 73 | + | close(c) | |
| 74 | + | ||
| 75 | + | if err := v.fn(); err != nil { | |
| 76 | + | if syscall.Getuid() == 0 && syscall.Getgid() == 0 { | |
| 77 | + | // If root, then the syscall should have succeeded. | |
| 78 | + | t.Errorf("[%d] %q setup failed: %v", i, v.call, err) | |
| 79 | + | } else if !errors.Is(err, syscall.EPERM) { | |
| 80 | + | // If not root, then EPERM is the only acceptable error. | |
| 81 | + | t.Errorf("[%d] %q unexpected error: %v", i, v.call, err) | |
| 82 | + | } | |
| 83 | + | continue | |
| 84 | + | } | |
| 85 | + | if err := compareStatus(v.filter, v.expect); err != nil { | |
| 86 | + | t.Errorf("[%d] %q comparison: %v", i, v.call, err) | |
| 87 | + | } | |
| 88 | + | } | |
| 89 | + | } | |
| 90 | + | ||
| 91 | + | // killAThread locks the goroutine to an OS thread and exits; this | |
| 92 | + | // causes an OS thread to terminate. | |
| 93 | + | func killAThread(c <-chan struct{}) { | |
| 94 | + | runtime.LockOSThread() | |
| 95 | + | <-c | |
| 96 | + | } | |
| 97 | + | ||
| 98 | + | // compareStatus is used to confirm the contents of the thread | |
| 99 | + | // specific status files match expectations. | |
| 100 | + | func compareStatus(filter, expect string) error { | |
| 101 | + | expected := filter + expect | |
| 102 | + | pid := syscall.Getpid() | |
| 103 | + | fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) | |
| 104 | + | if err != nil { | |
| 105 | + | return fmt.Errorf("unable to find %d tasks: %v", pid, err) | |
| 106 | + | } | |
| 107 | + | expectedProc := fmt.Sprintf("Pid:\t%d", pid) | |
| 108 | + | foundAThread := false | |
| 109 | + | for _, f := range fs { | |
| 110 | + | tf := fmt.Sprintf("/proc/%s/status", f.Name()) | |
| 111 | + | d, err := os.ReadFile(tf) | |
| 112 | + | if err != nil { | |
| 113 | + | // There are a surprising number of ways this | |
| 114 | + | // can error out on linux. We've seen all of | |
| 115 | + | // the following, so treat any error here as | |
| 116 | + | // equivalent to the "process is gone": | |
| 117 | + | // os.IsNotExist(err), | |
| 118 | + | // "... : no such process", | |
| 119 | + | // "... : bad file descriptor. | |
| 120 | + | continue | |
| 121 | + | } | |
| 122 | + | lines := strings.Split(string(d), "\n") | |
| 123 | + | for _, line := range lines { | |
| 124 | + | // Different kernel vintages pad differently. | |
| 125 | + | line = strings.TrimSpace(line) | |
| 126 | + | if strings.HasPrefix(line, "Pid:\t") { | |
| 127 | + | // On loaded systems, it is possible | |
| 128 | + | // for a TID to be reused really | |
| 129 | + | // quickly. As such, we need to | |
| 130 | + | // validate that the thread status | |
| 131 | + | // info we just read is a task of the | |
| 132 | + | // same process PID as we are | |
| 133 | + | // currently running, and not a | |
| 134 | + | // recently terminated thread | |
| 135 | + | // resurfaced in a different process. | |
| 136 | + | if line != expectedProc { | |
| 137 | + | break | |
| 138 | + | } | |
| 139 | + | // Fall through in the unlikely case | |
| 140 | + | // that filter at some point is | |
| 141 | + | // "Pid:\t". | |
| 142 | + | } | |
| 143 | + | if strings.HasPrefix(line, filter) { | |
| 144 | + | if line == expected { | |
| 145 | + | foundAThread = true | |
| 146 | + | break | |
| 147 | + | } | |
| 148 | + | if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") { | |
| 149 | + | // https://github.com/golang/go/issues/46145 | |
| 150 | + | // Containers don't reliably output this line in sorted order so manually sort and compare that. | |
| 151 | + | a := strings.Split(line[8:], " ") | |
| 152 | + | sort.Slice(a, func(i, j int) bool { return a[i] < a[j] }) | |
| 153 | + | got := strings.Join(a, " ") | |
| 154 | + | if got == expected[8:] { | |
| 155 | + | foundAThread = true | |
| 156 | + | break | |
| 157 | + | } | |
| 158 | + | ||
| 159 | + | } | |
| 160 | + | return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) | |
| 161 | + | } | |
| 162 | + | } | |
| 163 | + | } | |
| 164 | + | if !foundAThread { | |
| 165 | + | return fmt.Errorf("found no thread /proc/<TID>/status files for process %q", expectedProc) | |
| 166 | + | } | |
| 167 | + | return nil | |
| 168 | + | } | |
| 169 | + | ||
| 170 | + | // TestDlopenThenAllThreadsSyscall reproduces a crash where loading a shared | |
| 171 | + | // library and calling a C function that invokes a Go callback, followed by | |
| 172 | + | // AllThreadsSyscall (used by Setuid etc.), causes a SIGSEGV on amd64. | |
| 173 | + | func TestDlopenThenAllThreadsSyscall(t *testing.T) { | |
| 174 | + | // Step 1: Build and load a shared C library that calls back into Go. | |
| 175 | + | libFileName := filepath.Join(t.TempDir(), "libcbtest.so") | |
| 176 | + | if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "libcbtest", "callback_test.c")); err != nil { | |
| 177 | + | t.Fatal(err) | |
| 178 | + | } | |
| 179 | + | defer os.Remove(libFileName) | |
| 180 | + | ||
| 181 | + | lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL) | |
| 182 | + | if err != nil { | |
| 183 | + | t.Fatalf("Dlopen(%q) failed: %v", libFileName, err) | |
| 184 | + | } | |
| 185 | + | ||
| 186 | + | var callCallback func(p uintptr, s string) int | |
| 187 | + | purego.RegisterLibFunc(&callCallback, lib, "callCallback") | |
| 188 | + | ||
| 189 | + | goFunc := func(cstr *byte, n int) int { | |
| 190 | + | _ = string(unsafe.Slice(cstr, n)) | |
| 191 | + | return 1 | |
| 192 | + | } | |
| 193 | + | ||
| 194 | + | cb := purego.NewCallback(goFunc) | |
| 195 | + | for i := 0; i < 10; i++ { | |
| 196 | + | callCallback(cb, "hello") | |
| 197 | + | } | |
| 198 | + | ||
| 199 | + | // Step 2: Generate thread churn + AllThreadsSyscall (via Setuid). | |
| 200 | + | for i := 0; i < 20; i++ { | |
| 201 | + | c := make(chan struct{}) | |
| 202 | + | go func() { | |
| 203 | + | runtime.LockOSThread() | |
| 204 | + | <-c | |
| 205 | + | }() | |
| 206 | + | close(c) | |
| 207 | + | ||
| 208 | + | if err := syscall.Setuid(0); err != nil { | |
| 209 | + | if syscall.Getuid() == 0 && syscall.Getgid() == 0 { | |
| 210 | + | // If root, then the syscall should have succeeded. | |
| 211 | + | t.Errorf("setup failed: %v", err) | |
| 212 | + | } else if !errors.Is(err, syscall.EPERM) { | |
| 213 | + | // If not root, then EPERM is the only acceptable error. | |
| 214 | + | t.Errorf("unexpected error: %v", err) | |
| 215 | + | } | |
| 216 | + | } | |
| 217 | + | } | |
| 218 | + | } | |
| @@ -0,0 +1,218 @@ | |||||
| 1 | + | // Copyright 2015 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 purego_test | |||
| 6 | + | ||||
| 7 | + | import ( | |||
| 8 | + | "errors" | |||
| 9 | + | "fmt" | |||
| 10 | + | "os" | |||
| 11 | + | "path/filepath" | |||
| 12 | + | "runtime" | |||
| 13 | + | "sort" | |||
| 14 | + | "strings" | |||
| 15 | + | "syscall" | |||
| 16 | + | "testing" | |||
| 17 | + | "unsafe" | |||
| 18 | + | ||||
| 19 | + | "github.com/ebitengine/purego" | |||
| 20 | + | ) | |||
| 21 | + | ||||
| 22 | + | func TestAllThreadsSyscall(t *testing.T) { | |||
| 23 | + | _, _, err := syscall.AllThreadsSyscall(syscall.SYS_FCNTL, 0, 0, 0) | |||
| 24 | + | if err != syscall.ENOTSUP { | |||
| 25 | + | t.Errorf("AllThreadsSyscall should return ENOTSUP, got: %v", err) | |||
| 26 | + | } | |||
| 27 | + | } | |||
| 28 | + | ||||
| 29 | + | // TestSetuidEtc performs tests on all of the wrapped system calls | |||
| 30 | + | // that mirror to the 9 glibc syscalls with POSIX semantics. The test | |||
| 31 | + | // here is considered authoritative and should compile and run | |||
| 32 | + | // CGO_ENABLED=0 or 1. | |||
| 33 | + | func TestSetuidEtc(t *testing.T) { | |||
| 34 | + | vs := []struct { | |||
| 35 | + | call string | |||
| 36 | + | fn func() error | |||
| 37 | + | filter, expect string | |||
| 38 | + | }{ | |||
| 39 | + | {call: "Setegid(1)", fn: func() error { return syscall.Setegid(1) }, filter: "Gid:", expect: "\t0\t1\t0\t1"}, | |||
| 40 | + | {call: "Setegid(0)", fn: func() error { return syscall.Setegid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |||
| 41 | + | ||||
| 42 | + | {call: "Seteuid(1)", fn: func() error { return syscall.Seteuid(1) }, filter: "Uid:", expect: "\t0\t1\t0\t1"}, | |||
| 43 | + | {call: "Setuid(0)", fn: func() error { return syscall.Setuid(0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"}, | |||
| 44 | + | ||||
| 45 | + | {call: "Setgid(1)", fn: func() error { return syscall.Setgid(1) }, filter: "Gid:", expect: "\t1\t1\t1\t1"}, | |||
| 46 | + | {call: "Setgid(0)", fn: func() error { return syscall.Setgid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |||
| 47 | + | ||||
| 48 | + | {call: "Setgroups([]int{0,1,2,3})", fn: func() error { return syscall.Setgroups([]int{0, 1, 2, 3}) }, filter: "Groups:", expect: "\t0 1 2 3"}, | |||
| 49 | + | {call: "Setgroups(nil)", fn: func() error { return syscall.Setgroups(nil) }, filter: "Groups:", expect: ""}, | |||
| 50 | + | {call: "Setgroups([]int{0})", fn: func() error { return syscall.Setgroups([]int{0}) }, filter: "Groups:", expect: "\t0"}, | |||
| 51 | + | ||||
| 52 | + | {call: "Setregid(101,0)", fn: func() error { return syscall.Setregid(101, 0) }, filter: "Gid:", expect: "\t101\t0\t0\t0"}, | |||
| 53 | + | {call: "Setregid(0,102)", fn: func() error { return syscall.Setregid(0, 102) }, filter: "Gid:", expect: "\t0\t102\t102\t102"}, | |||
| 54 | + | {call: "Setregid(0,0)", fn: func() error { return syscall.Setregid(0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |||
| 55 | + | ||||
| 56 | + | {call: "Setreuid(1,0)", fn: func() error { return syscall.Setreuid(1, 0) }, filter: "Uid:", expect: "\t1\t0\t0\t0"}, | |||
| 57 | + | {call: "Setreuid(0,2)", fn: func() error { return syscall.Setreuid(0, 2) }, filter: "Uid:", expect: "\t0\t2\t2\t2"}, | |||
| 58 | + | {call: "Setreuid(0,0)", fn: func() error { return syscall.Setreuid(0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"}, | |||
| 59 | + | ||||
| 60 | + | {call: "Setresgid(101,0,102)", fn: func() error { return syscall.Setresgid(101, 0, 102) }, filter: "Gid:", expect: "\t101\t0\t102\t0"}, | |||
| 61 | + | {call: "Setresgid(0,102,101)", fn: func() error { return syscall.Setresgid(0, 102, 101) }, filter: "Gid:", expect: "\t0\t102\t101\t102"}, | |||
| 62 | + | {call: "Setresgid(0,0,0)", fn: func() error { return syscall.Setresgid(0, 0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"}, | |||
| 63 | + | ||||
| 64 | + | {call: "Setresuid(1,0,2)", fn: func() error { return syscall.Setresuid(1, 0, 2) }, filter: "Uid:", expect: "\t1\t0\t2\t0"}, | |||
| 65 | + | {call: "Setresuid(0,2,1)", fn: func() error { return syscall.Setresuid(0, 2, 1) }, filter: "Uid:", expect: "\t0\t2\t1\t2"}, | |||
| 66 | + | {call: "Setresuid(0,0,0)", fn: func() error { return syscall.Setresuid(0, 0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"}, | |||
| 67 | + | } | |||
| 68 | + | ||||
| 69 | + | for i, v := range vs { | |||
| 70 | + | // Generate some thread churn. | |||
| 71 | + | c := make(chan struct{}) | |||
| 72 | + | go killAThread(c) | |||
| 73 | + | close(c) | |||
| 74 | + | ||||
| 75 | + | if err := v.fn(); err != nil { | |||
| 76 | + | if syscall.Getuid() == 0 && syscall.Getgid() == 0 { | |||
| 77 | + | // If root, then the syscall should have succeeded. | |||
| 78 | + | t.Errorf("[%d] %q setup failed: %v", i, v.call, err) | |||
| 79 | + | } else if !errors.Is(err, syscall.EPERM) { | |||
| 80 | + | // If not root, then EPERM is the only acceptable error. | |||
| 81 | + | t.Errorf("[%d] %q unexpected error: %v", i, v.call, err) | |||
| 82 | + | } | |||
| 83 | + | continue | |||
| 84 | + | } | |||
| 85 | + | if err := compareStatus(v.filter, v.expect); err != nil { | |||
| 86 | + | t.Errorf("[%d] %q comparison: %v", i, v.call, err) | |||
| 87 | + | } | |||
| 88 | + | } | |||
| 89 | + | } | |||
| 90 | + | ||||
| 91 | + | // killAThread locks the goroutine to an OS thread and exits; this | |||
| 92 | + | // causes an OS thread to terminate. | |||
| 93 | + | func killAThread(c <-chan struct{}) { | |||
| 94 | + | runtime.LockOSThread() | |||
| 95 | + | <-c | |||
| 96 | + | } | |||
| 97 | + | ||||
| 98 | + | // compareStatus is used to confirm the contents of the thread | |||
| 99 | + | // specific status files match expectations. | |||
| 100 | + | func compareStatus(filter, expect string) error { | |||
| 101 | + | expected := filter + expect | |||
| 102 | + | pid := syscall.Getpid() | |||
| 103 | + | fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) | |||
| 104 | + | if err != nil { | |||
| 105 | + | return fmt.Errorf("unable to find %d tasks: %v", pid, err) | |||
| 106 | + | } | |||
| 107 | + | expectedProc := fmt.Sprintf("Pid:\t%d", pid) | |||
| 108 | + | foundAThread := false | |||
| 109 | + | for _, f := range fs { | |||
| 110 | + | tf := fmt.Sprintf("/proc/%s/status", f.Name()) | |||
| 111 | + | d, err := os.ReadFile(tf) | |||
| 112 | + | if err != nil { | |||
| 113 | + | // There are a surprising number of ways this | |||
| 114 | + | // can error out on linux. We've seen all of | |||
| 115 | + | // the following, so treat any error here as | |||
| 116 | + | // equivalent to the "process is gone": | |||
| 117 | + | // os.IsNotExist(err), | |||
| 118 | + | // "... : no such process", | |||
| 119 | + | // "... : bad file descriptor. | |||
| 120 | + | continue | |||
| 121 | + | } | |||
| 122 | + | lines := strings.Split(string(d), "\n") | |||
| 123 | + | for _, line := range lines { | |||
| 124 | + | // Different kernel vintages pad differently. | |||
| 125 | + | line = strings.TrimSpace(line) | |||
| 126 | + | if strings.HasPrefix(line, "Pid:\t") { | |||
| 127 | + | // On loaded systems, it is possible | |||
| 128 | + | // for a TID to be reused really | |||
| 129 | + | // quickly. As such, we need to | |||
| 130 | + | // validate that the thread status | |||
| 131 | + | // info we just read is a task of the | |||
| 132 | + | // same process PID as we are | |||
| 133 | + | // currently running, and not a | |||
| 134 | + | // recently terminated thread | |||
| 135 | + | // resurfaced in a different process. | |||
| 136 | + | if line != expectedProc { | |||
| 137 | + | break | |||
| 138 | + | } | |||
| 139 | + | // Fall through in the unlikely case | |||
| 140 | + | // that filter at some point is | |||
| 141 | + | // "Pid:\t". | |||
| 142 | + | } | |||
| 143 | + | if strings.HasPrefix(line, filter) { | |||
| 144 | + | if line == expected { | |||
| 145 | + | foundAThread = true | |||
| 146 | + | break | |||
| 147 | + | } | |||
| 148 | + | if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") { | |||
| 149 | + | // https://github.com/golang/go/issues/46145 | |||
| 150 | + | // Containers don't reliably output this line in sorted order so manually sort and compare that. | |||
| 151 | + | a := strings.Split(line[8:], " ") | |||
| 152 | + | sort.Slice(a, func(i, j int) bool { return a[i] < a[j] }) | |||
| 153 | + | got := strings.Join(a, " ") | |||
| 154 | + | if got == expected[8:] { | |||
| 155 | + | foundAThread = true | |||
| 156 | + | break | |||
| 157 | + | } | |||
| 158 | + | ||||
| 159 | + | } | |||
| 160 | + | return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) | |||
| 161 | + | } | |||
| 162 | + | } | |||
| 163 | + | } | |||
| 164 | + | if !foundAThread { | |||
| 165 | + | return fmt.Errorf("found no thread /proc/<TID>/status files for process %q", expectedProc) | |||
| 166 | + | } | |||
| 167 | + | return nil | |||
| 168 | + | } | |||
| 169 | + | ||||
| 170 | + | // TestDlopenThenAllThreadsSyscall reproduces a crash where loading a shared | |||
| 171 | + | // library and calling a C function that invokes a Go callback, followed by | |||
| 172 | + | // AllThreadsSyscall (used by Setuid etc.), causes a SIGSEGV on amd64. | |||
| 173 | + | func TestDlopenThenAllThreadsSyscall(t *testing.T) { | |||
| 174 | + | // Step 1: Build and load a shared C library that calls back into Go. | |||
| 175 | + | libFileName := filepath.Join(t.TempDir(), "libcbtest.so") | |||
| 176 | + | if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "libcbtest", "callback_test.c")); err != nil { | |||
| 177 | + | t.Fatal(err) | |||
| 178 | + | } | |||
| 179 | + | defer os.Remove(libFileName) | |||
| 180 | + | ||||
| 181 | + | lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL) | |||
| 182 | + | if err != nil { | |||
| 183 | + | t.Fatalf("Dlopen(%q) failed: %v", libFileName, err) | |||
| 184 | + | } | |||
| 185 | + | ||||
| 186 | + | var callCallback func(p uintptr, s string) int | |||
| 187 | + | purego.RegisterLibFunc(&callCallback, lib, "callCallback") | |||
| 188 | + | ||||
| 189 | + | goFunc := func(cstr *byte, n int) int { | |||
| 190 | + | _ = string(unsafe.Slice(cstr, n)) | |||
| 191 | + | return 1 | |||
| 192 | + | } | |||
| 193 | + | ||||
| 194 | + | cb := purego.NewCallback(goFunc) | |||
| 195 | + | for i := 0; i < 10; i++ { | |||
| 196 | + | callCallback(cb, "hello") | |||
| 197 | + | } | |||
| 198 | + | ||||
| 199 | + | // Step 2: Generate thread churn + AllThreadsSyscall (via Setuid). | |||
| 200 | + | for i := 0; i < 20; i++ { | |||
| 201 | + | c := make(chan struct{}) | |||
| 202 | + | go func() { | |||
| 203 | + | runtime.LockOSThread() | |||
| 204 | + | <-c | |||
| 205 | + | }() | |||
| 206 | + | close(c) | |||
| 207 | + | ||||
| 208 | + | if err := syscall.Setuid(0); err != nil { | |||
| 209 | + | if syscall.Getuid() == 0 && syscall.Getgid() == 0 { | |||
| 210 | + | // If root, then the syscall should have succeeded. | |||
| 211 | + | t.Errorf("setup failed: %v", err) | |||
| 212 | + | } else if !errors.Is(err, syscall.EPERM) { | |||
| 213 | + | // If not root, then EPERM is the only acceptable error. | |||
| 214 | + | t.Errorf("unexpected error: %v", err) | |||
| 215 | + | } | |||
| 216 | + | } | |||
| 217 | + | } | |||
| 218 | + | } | |||