Skip to content

Commit a76c4d0

Browse files
committed
unix: take address in assembly for Darwin syscall wrappers
In Go 1.17 we will introduce a register-based ABI on some platforms, as well as ABI wrappers to bridge the ABIs. For Darwin syscall wrappers, it needs to be called directly, instead of through wrappers. Currently, it is written as that the syscall functions are defined in assembly and their addresses are taken from Go using funcPC. In Go 1.17 this will result in the address of the ABI wrapper, which is undesired. In the syscall package in the standard library we changed to use a compiler intrinsic internal/abi.FuncPCABI0 to take the address of the syscall function. But that is not available to this repo and not available in older versions of Go. Here we take a different approach: taking the address directly from assembly. This also ensures we get the address of the defined syscall function, not the ABI wrapper. Updates golang/go#45702. Change-Id: Ia7480d0fb0ca4fb9bf2f36d2deb1e3e5e4eb8284 Reviewed-on: https://go-review.googlesource.com/c/sys/+/317894 Trust: Cherry Mui <[email protected]> Run-TryBot: Cherry Mui <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Than McIntosh <[email protected]>
1 parent 30e306a commit a76c4d0

13 files changed

+2183
-1024
lines changed

unix/darwin_test.go

Lines changed: 137 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616

1717
type darwinTest struct {
1818
name string
19-
f func()
19+
f uintptr
2020
}
2121

2222
// TODO(khr): decide whether to keep this test enabled permanently or
@@ -62,7 +62,7 @@ func init() {
6262
if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" {
6363
for _, test := range darwinTests {
6464
if test.name == os.Args[2] {
65-
test.f()
65+
syscall_syscall(test.f, ^uintptr(0), ^uintptr(0), ^uintptr(0))
6666
}
6767
}
6868
// Panic with a "success" label, so the parent process can check it.
@@ -72,139 +72,139 @@ func init() {
7272

7373
// All the _trampoline functions in zsyscall_darwin_$ARCH.s
7474
var darwinTests = [...]darwinTest{
75-
{"getgroups", libc_getgroups_trampoline},
76-
{"setgroups", libc_setgroups_trampoline},
77-
{"wait4", libc_wait4_trampoline},
78-
{"accept", libc_accept_trampoline},
79-
{"bind", libc_bind_trampoline},
80-
{"connect", libc_connect_trampoline},
81-
{"socket", libc_socket_trampoline},
82-
{"getsockopt", libc_getsockopt_trampoline},
83-
{"setsockopt", libc_setsockopt_trampoline},
84-
{"getpeername", libc_getpeername_trampoline},
85-
{"getsockname", libc_getsockname_trampoline},
86-
{"shutdown", libc_shutdown_trampoline},
87-
{"socketpair", libc_socketpair_trampoline},
88-
{"recvfrom", libc_recvfrom_trampoline},
89-
{"sendto", libc_sendto_trampoline},
90-
{"recvmsg", libc_recvmsg_trampoline},
91-
{"sendmsg", libc_sendmsg_trampoline},
92-
{"kevent", libc_kevent_trampoline},
93-
{"sysctl", libc_sysctl_trampoline},
94-
{"utimes", libc_utimes_trampoline},
95-
{"futimes", libc_futimes_trampoline},
96-
{"fcntl", libc_fcntl_trampoline},
97-
{"poll", libc_poll_trampoline},
98-
{"madvise", libc_madvise_trampoline},
99-
{"mlock", libc_mlock_trampoline},
100-
{"mlockall", libc_mlockall_trampoline},
101-
{"mprotect", libc_mprotect_trampoline},
102-
{"msync", libc_msync_trampoline},
103-
{"munlock", libc_munlock_trampoline},
104-
{"munlockall", libc_munlockall_trampoline},
105-
{"ptrace", libc_ptrace_trampoline},
106-
{"pipe", libc_pipe_trampoline},
107-
{"getxattr", libc_getxattr_trampoline},
108-
{"fgetxattr", libc_fgetxattr_trampoline},
109-
{"setxattr", libc_setxattr_trampoline},
110-
{"fsetxattr", libc_fsetxattr_trampoline},
111-
{"removexattr", libc_removexattr_trampoline},
112-
{"fremovexattr", libc_fremovexattr_trampoline},
113-
{"listxattr", libc_listxattr_trampoline},
114-
{"flistxattr", libc_flistxattr_trampoline},
115-
{"kill", libc_kill_trampoline},
116-
{"ioctl", libc_ioctl_trampoline},
117-
{"access", libc_access_trampoline},
118-
{"adjtime", libc_adjtime_trampoline},
119-
{"chdir", libc_chdir_trampoline},
120-
{"chflags", libc_chflags_trampoline},
121-
{"chmod", libc_chmod_trampoline},
122-
{"chown", libc_chown_trampoline},
123-
{"chroot", libc_chroot_trampoline},
124-
{"close", libc_close_trampoline},
125-
{"dup", libc_dup_trampoline},
126-
{"dup2", libc_dup2_trampoline},
127-
{"exchangedata", libc_exchangedata_trampoline},
128-
{"exit", libc_exit_trampoline},
129-
{"faccessat", libc_faccessat_trampoline},
130-
{"fchdir", libc_fchdir_trampoline},
131-
{"fchflags", libc_fchflags_trampoline},
132-
{"fchmod", libc_fchmod_trampoline},
133-
{"fchmodat", libc_fchmodat_trampoline},
134-
{"fchown", libc_fchown_trampoline},
135-
{"fchownat", libc_fchownat_trampoline},
136-
{"flock", libc_flock_trampoline},
137-
{"fpathconf", libc_fpathconf_trampoline},
138-
{"fstat64", libc_fstat64_trampoline},
139-
{"fstatat64", libc_fstatat64_trampoline},
140-
{"fstatfs64", libc_fstatfs64_trampoline},
141-
{"fsync", libc_fsync_trampoline},
142-
{"ftruncate", libc_ftruncate_trampoline},
143-
{"getdtablesize", libc_getdtablesize_trampoline},
144-
{"getegid", libc_getegid_trampoline},
145-
{"geteuid", libc_geteuid_trampoline},
146-
{"getgid", libc_getgid_trampoline},
147-
{"getpgid", libc_getpgid_trampoline},
148-
{"getpgrp", libc_getpgrp_trampoline},
149-
{"getpid", libc_getpid_trampoline},
150-
{"getppid", libc_getppid_trampoline},
151-
{"getpriority", libc_getpriority_trampoline},
152-
{"getrlimit", libc_getrlimit_trampoline},
153-
{"getrusage", libc_getrusage_trampoline},
154-
{"getsid", libc_getsid_trampoline},
155-
{"getuid", libc_getuid_trampoline},
156-
{"issetugid", libc_issetugid_trampoline},
157-
{"kqueue", libc_kqueue_trampoline},
158-
{"lchown", libc_lchown_trampoline},
159-
{"link", libc_link_trampoline},
160-
{"linkat", libc_linkat_trampoline},
161-
{"listen", libc_listen_trampoline},
162-
{"lstat64", libc_lstat64_trampoline},
163-
{"mkdir", libc_mkdir_trampoline},
164-
{"mkdirat", libc_mkdirat_trampoline},
165-
{"mkfifo", libc_mkfifo_trampoline},
166-
{"mknod", libc_mknod_trampoline},
167-
{"open", libc_open_trampoline},
168-
{"openat", libc_openat_trampoline},
169-
{"pathconf", libc_pathconf_trampoline},
170-
{"pread", libc_pread_trampoline},
171-
{"pwrite", libc_pwrite_trampoline},
172-
{"read", libc_read_trampoline},
173-
{"readlink", libc_readlink_trampoline},
174-
{"readlinkat", libc_readlinkat_trampoline},
175-
{"rename", libc_rename_trampoline},
176-
{"renameat", libc_renameat_trampoline},
177-
{"revoke", libc_revoke_trampoline},
178-
{"rmdir", libc_rmdir_trampoline},
179-
{"lseek", libc_lseek_trampoline},
180-
{"select", libc_select_trampoline},
181-
{"setegid", libc_setegid_trampoline},
182-
{"seteuid", libc_seteuid_trampoline},
183-
{"setgid", libc_setgid_trampoline},
184-
{"setlogin", libc_setlogin_trampoline},
185-
{"setpgid", libc_setpgid_trampoline},
186-
{"setpriority", libc_setpriority_trampoline},
187-
{"setprivexec", libc_setprivexec_trampoline},
188-
{"setregid", libc_setregid_trampoline},
189-
{"setreuid", libc_setreuid_trampoline},
190-
{"setrlimit", libc_setrlimit_trampoline},
191-
{"setsid", libc_setsid_trampoline},
192-
{"settimeofday", libc_settimeofday_trampoline},
193-
{"setuid", libc_setuid_trampoline},
194-
{"stat64", libc_stat64_trampoline},
195-
{"statfs64", libc_statfs64_trampoline},
196-
{"symlink", libc_symlink_trampoline},
197-
{"symlinkat", libc_symlinkat_trampoline},
198-
{"sync", libc_sync_trampoline},
199-
{"truncate", libc_truncate_trampoline},
200-
{"umask", libc_umask_trampoline},
201-
{"undelete", libc_undelete_trampoline},
202-
{"unlink", libc_unlink_trampoline},
203-
{"unlinkat", libc_unlinkat_trampoline},
204-
{"unmount", libc_unmount_trampoline},
205-
{"write", libc_write_trampoline},
206-
{"mmap", libc_mmap_trampoline},
207-
{"munmap", libc_munmap_trampoline},
208-
{"gettimeofday", libc_gettimeofday_trampoline},
209-
{"getfsstat64", libc_getfsstat64_trampoline},
75+
{"getgroups", libc_getgroups_trampoline_addr},
76+
{"setgroups", libc_setgroups_trampoline_addr},
77+
{"wait4", libc_wait4_trampoline_addr},
78+
{"accept", libc_accept_trampoline_addr},
79+
{"bind", libc_bind_trampoline_addr},
80+
{"connect", libc_connect_trampoline_addr},
81+
{"socket", libc_socket_trampoline_addr},
82+
{"getsockopt", libc_getsockopt_trampoline_addr},
83+
{"setsockopt", libc_setsockopt_trampoline_addr},
84+
{"getpeername", libc_getpeername_trampoline_addr},
85+
{"getsockname", libc_getsockname_trampoline_addr},
86+
{"shutdown", libc_shutdown_trampoline_addr},
87+
{"socketpair", libc_socketpair_trampoline_addr},
88+
{"recvfrom", libc_recvfrom_trampoline_addr},
89+
{"sendto", libc_sendto_trampoline_addr},
90+
{"recvmsg", libc_recvmsg_trampoline_addr},
91+
{"sendmsg", libc_sendmsg_trampoline_addr},
92+
{"kevent", libc_kevent_trampoline_addr},
93+
{"sysctl", libc_sysctl_trampoline_addr},
94+
{"utimes", libc_utimes_trampoline_addr},
95+
{"futimes", libc_futimes_trampoline_addr},
96+
{"fcntl", libc_fcntl_trampoline_addr},
97+
{"poll", libc_poll_trampoline_addr},
98+
{"madvise", libc_madvise_trampoline_addr},
99+
{"mlock", libc_mlock_trampoline_addr},
100+
{"mlockall", libc_mlockall_trampoline_addr},
101+
{"mprotect", libc_mprotect_trampoline_addr},
102+
{"msync", libc_msync_trampoline_addr},
103+
{"munlock", libc_munlock_trampoline_addr},
104+
{"munlockall", libc_munlockall_trampoline_addr},
105+
{"ptrace", libc_ptrace_trampoline_addr},
106+
{"pipe", libc_pipe_trampoline_addr},
107+
{"getxattr", libc_getxattr_trampoline_addr},
108+
{"fgetxattr", libc_fgetxattr_trampoline_addr},
109+
{"setxattr", libc_setxattr_trampoline_addr},
110+
{"fsetxattr", libc_fsetxattr_trampoline_addr},
111+
{"removexattr", libc_removexattr_trampoline_addr},
112+
{"fremovexattr", libc_fremovexattr_trampoline_addr},
113+
{"listxattr", libc_listxattr_trampoline_addr},
114+
{"flistxattr", libc_flistxattr_trampoline_addr},
115+
{"kill", libc_kill_trampoline_addr},
116+
{"ioctl", libc_ioctl_trampoline_addr},
117+
{"access", libc_access_trampoline_addr},
118+
{"adjtime", libc_adjtime_trampoline_addr},
119+
{"chdir", libc_chdir_trampoline_addr},
120+
{"chflags", libc_chflags_trampoline_addr},
121+
{"chmod", libc_chmod_trampoline_addr},
122+
{"chown", libc_chown_trampoline_addr},
123+
{"chroot", libc_chroot_trampoline_addr},
124+
{"close", libc_close_trampoline_addr},
125+
{"dup", libc_dup_trampoline_addr},
126+
{"dup2", libc_dup2_trampoline_addr},
127+
{"exchangedata", libc_exchangedata_trampoline_addr},
128+
{"exit", libc_exit_trampoline_addr},
129+
{"faccessat", libc_faccessat_trampoline_addr},
130+
{"fchdir", libc_fchdir_trampoline_addr},
131+
{"fchflags", libc_fchflags_trampoline_addr},
132+
{"fchmod", libc_fchmod_trampoline_addr},
133+
{"fchmodat", libc_fchmodat_trampoline_addr},
134+
{"fchown", libc_fchown_trampoline_addr},
135+
{"fchownat", libc_fchownat_trampoline_addr},
136+
{"flock", libc_flock_trampoline_addr},
137+
{"fpathconf", libc_fpathconf_trampoline_addr},
138+
{"fstat64", libc_fstat64_trampoline_addr},
139+
{"fstatat64", libc_fstatat64_trampoline_addr},
140+
{"fstatfs64", libc_fstatfs64_trampoline_addr},
141+
{"fsync", libc_fsync_trampoline_addr},
142+
{"ftruncate", libc_ftruncate_trampoline_addr},
143+
{"getdtablesize", libc_getdtablesize_trampoline_addr},
144+
{"getegid", libc_getegid_trampoline_addr},
145+
{"geteuid", libc_geteuid_trampoline_addr},
146+
{"getgid", libc_getgid_trampoline_addr},
147+
{"getpgid", libc_getpgid_trampoline_addr},
148+
{"getpgrp", libc_getpgrp_trampoline_addr},
149+
{"getpid", libc_getpid_trampoline_addr},
150+
{"getppid", libc_getppid_trampoline_addr},
151+
{"getpriority", libc_getpriority_trampoline_addr},
152+
{"getrlimit", libc_getrlimit_trampoline_addr},
153+
{"getrusage", libc_getrusage_trampoline_addr},
154+
{"getsid", libc_getsid_trampoline_addr},
155+
{"getuid", libc_getuid_trampoline_addr},
156+
{"issetugid", libc_issetugid_trampoline_addr},
157+
{"kqueue", libc_kqueue_trampoline_addr},
158+
{"lchown", libc_lchown_trampoline_addr},
159+
{"link", libc_link_trampoline_addr},
160+
{"linkat", libc_linkat_trampoline_addr},
161+
{"listen", libc_listen_trampoline_addr},
162+
{"lstat64", libc_lstat64_trampoline_addr},
163+
{"mkdir", libc_mkdir_trampoline_addr},
164+
{"mkdirat", libc_mkdirat_trampoline_addr},
165+
{"mkfifo", libc_mkfifo_trampoline_addr},
166+
{"mknod", libc_mknod_trampoline_addr},
167+
{"open", libc_open_trampoline_addr},
168+
{"openat", libc_openat_trampoline_addr},
169+
{"pathconf", libc_pathconf_trampoline_addr},
170+
{"pread", libc_pread_trampoline_addr},
171+
{"pwrite", libc_pwrite_trampoline_addr},
172+
{"read", libc_read_trampoline_addr},
173+
{"readlink", libc_readlink_trampoline_addr},
174+
{"readlinkat", libc_readlinkat_trampoline_addr},
175+
{"rename", libc_rename_trampoline_addr},
176+
{"renameat", libc_renameat_trampoline_addr},
177+
{"revoke", libc_revoke_trampoline_addr},
178+
{"rmdir", libc_rmdir_trampoline_addr},
179+
{"lseek", libc_lseek_trampoline_addr},
180+
{"select", libc_select_trampoline_addr},
181+
{"setegid", libc_setegid_trampoline_addr},
182+
{"seteuid", libc_seteuid_trampoline_addr},
183+
{"setgid", libc_setgid_trampoline_addr},
184+
{"setlogin", libc_setlogin_trampoline_addr},
185+
{"setpgid", libc_setpgid_trampoline_addr},
186+
{"setpriority", libc_setpriority_trampoline_addr},
187+
{"setprivexec", libc_setprivexec_trampoline_addr},
188+
{"setregid", libc_setregid_trampoline_addr},
189+
{"setreuid", libc_setreuid_trampoline_addr},
190+
{"setrlimit", libc_setrlimit_trampoline_addr},
191+
{"setsid", libc_setsid_trampoline_addr},
192+
{"settimeofday", libc_settimeofday_trampoline_addr},
193+
{"setuid", libc_setuid_trampoline_addr},
194+
{"stat64", libc_stat64_trampoline_addr},
195+
{"statfs64", libc_statfs64_trampoline_addr},
196+
{"symlink", libc_symlink_trampoline_addr},
197+
{"symlinkat", libc_symlinkat_trampoline_addr},
198+
{"sync", libc_sync_trampoline_addr},
199+
{"truncate", libc_truncate_trampoline_addr},
200+
{"umask", libc_umask_trampoline_addr},
201+
{"undelete", libc_undelete_trampoline_addr},
202+
{"unlink", libc_unlink_trampoline_addr},
203+
{"unlinkat", libc_unlinkat_trampoline_addr},
204+
{"unmount", libc_unmount_trampoline_addr},
205+
{"write", libc_write_trampoline_addr},
206+
{"mmap", libc_mmap_trampoline_addr},
207+
{"munmap", libc_munmap_trampoline_addr},
208+
{"gettimeofday", libc_gettimeofday_trampoline_addr},
209+
{"getfsstat64", libc_getfsstat64_trampoline_addr},
210210
}

unix/mkasm_darwin.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"strings"
1919
)
2020

21+
const ptrsize = 8 // Pointer size. All supported platforms are 64-bit.
22+
2123
func writeASMFile(in string, fileName string, buildTags string) {
2224
trampolines := map[string]bool{}
2325

@@ -31,14 +33,18 @@ func writeASMFile(in string, fileName string, buildTags string) {
3133
fmt.Fprintf(&out, "\n")
3234
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
3335
for _, line := range strings.Split(in, "\n") {
34-
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
36+
const prefix = "var "
37+
const suffix = "_trampoline_addr uintptr"
38+
if !strings.HasPrefix(line, prefix) || !strings.HasSuffix(line, suffix) {
3539
continue
3640
}
37-
fn := line[5 : len(line)-13]
41+
fn := strings.TrimSuffix(strings.TrimPrefix(line, prefix), suffix)
3842
if !trampolines[fn] {
3943
trampolines[fn] = true
40-
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
41-
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
44+
fmt.Fprintf(&out, "\nTEXT %s_trampoline<>(SB),NOSPLIT,$0-0\n", fn)
45+
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n\n", fn)
46+
fmt.Fprintf(&out, "GLOBL\t·%s_trampoline_addr(SB), RODATA, $%d\n", fn, ptrsize)
47+
fmt.Fprintf(&out, "DATA\t·%s_trampoline_addr(SB)/%d, $%s_trampoline<>(SB)\n", fn, ptrsize, fn)
4248
}
4349
}
4450
err := ioutil.WriteFile(fileName, out.Bytes(), 0644)

unix/mksyscall.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ func main() {
290290
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
291291
sysname = strings.ToLower(sysname) // lowercase
292292
libcFn = sysname
293-
sysname = "funcPC(libc_" + sysname + "_trampoline)"
293+
sysname = "libc_" + sysname + "_trampoline_addr"
294294
}
295295

296296
// Actual call.
@@ -363,8 +363,8 @@ func main() {
363363
if libc && !trampolines[libcFn] {
364364
// some system calls share a trampoline, like read and readlen.
365365
trampolines[libcFn] = true
366-
// Declare assembly trampoline.
367-
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
366+
// Declare assembly trampoline address.
367+
text += fmt.Sprintf("var libc_%s_trampoline_addr uintptr\n\n", libcFn)
368368
// Assembly trampoline calls the libc_* function, which this magic
369369
// redirects to use the function from libSystem.
370370
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)

unix/syscall_darwin.1_13.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ import (
1717
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
1818

1919
func fdopendir(fd int) (dir uintptr, err error) {
20-
r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0)
20+
r0, _, e1 := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(fd), 0, 0)
2121
dir = uintptr(r0)
2222
if e1 != 0 {
2323
err = errnoErr(e1)
2424
}
2525
return
2626
}
2727

28-
func libc_fdopendir_trampoline()
28+
var libc_fdopendir_trampoline_addr uintptr
2929

3030
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
3131

unix/syscall_darwin_libSystem.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
package unix
99

10-
import "unsafe"
10+
import _ "unsafe"
1111

1212
// Implemented in the runtime package (runtime/sys_darwin.go)
1313
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
@@ -25,10 +25,3 @@ func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
2525
//go:linkname syscall_rawSyscall syscall.rawSyscall
2626
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
2727
//go:linkname syscall_syscallPtr syscall.syscallPtr
28-
29-
// Find the entry point for f. See comments in runtime/proc.go for the
30-
// function of the same name.
31-
//go:nosplit
32-
func funcPC(f func()) uintptr {
33-
return **(**uintptr)(unsafe.Pointer(&f))
34-
}

0 commit comments

Comments
 (0)