1// Copyright 2018 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// +build darwin,go1.12,amd64 darwin,go1.12,386
6
7package unix
8
9import (
10	"os"
11	"os/exec"
12	"strings"
13	"testing"
14)
15
16type darwinTest struct {
17	name string
18	f    func()
19}
20
21// TODO(khr): decide whether to keep this test enabled permanently or
22// only temporarily.
23func TestDarwinLoader(t *testing.T) {
24	// Make sure the Darwin dynamic loader can actually resolve
25	// all the system calls into libSystem.dylib. Unfortunately
26	// there is no easy way to test this at compile time. So we
27	// implement a crazy hack here, calling into the syscall
28	// function with all its arguments set to junk, and see what
29	// error we get. We are happy with any error (or none) except
30	// an error from the dynamic loader.
31	//
32	// We have to run each test in a separate subprocess for fault isolation.
33	//
34	// Hopefully the junk args won't accidentally ask the system to do "rm -fr /".
35	//
36	// In an ideal world each syscall would have its own test, so this test
37	// would be unnecessary. Unfortunately, we do not live in that world.
38	for _, test := range darwinTests {
39		// Call the test binary recursively, giving it a magic argument
40		// (see init below) and the name of the test to run.
41		cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name)
42
43		// Run subprocess, collect results. Note that we expect the subprocess
44		// to fail somehow, so the error is irrelevant.
45		out, _ := cmd.CombinedOutput()
46
47		if strings.Contains(string(out), "dyld: Symbol not found:") {
48			t.Errorf("can't resolve %s in libSystem.dylib", test.name)
49		}
50		if !strings.Contains(string(out), "success") {
51			// Not really an error. Might be a syscall that never returns,
52			// like exit, or one that segfaults, like gettimeofday.
53			t.Logf("test never finished: %s: %s", test.name, string(out))
54		}
55	}
56}
57
58func init() {
59	// The test binary execs itself with the "testDarwinLoader" argument.
60	// Run the test specified by os.Args[2], then panic.
61	if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" {
62		for _, test := range darwinTests {
63			if test.name == os.Args[2] {
64				test.f()
65			}
66		}
67		// Panic with a "success" label, so the parent process can check it.
68		panic("success")
69	}
70}
71
72// All the _trampoline functions in zsyscall_darwin_$ARCH.s
73var darwinTests = [...]darwinTest{
74	{"getgroups", libc_getgroups_trampoline},
75	{"setgroups", libc_setgroups_trampoline},
76	{"wait4", libc_wait4_trampoline},
77	{"accept", libc_accept_trampoline},
78	{"bind", libc_bind_trampoline},
79	{"connect", libc_connect_trampoline},
80	{"socket", libc_socket_trampoline},
81	{"getsockopt", libc_getsockopt_trampoline},
82	{"setsockopt", libc_setsockopt_trampoline},
83	{"getpeername", libc_getpeername_trampoline},
84	{"getsockname", libc_getsockname_trampoline},
85	{"shutdown", libc_shutdown_trampoline},
86	{"socketpair", libc_socketpair_trampoline},
87	{"recvfrom", libc_recvfrom_trampoline},
88	{"sendto", libc_sendto_trampoline},
89	{"recvmsg", libc_recvmsg_trampoline},
90	{"sendmsg", libc_sendmsg_trampoline},
91	{"kevent", libc_kevent_trampoline},
92	{"sysctl", libc_sysctl_trampoline},
93	{"utimes", libc_utimes_trampoline},
94	{"futimes", libc_futimes_trampoline},
95	{"fcntl", libc_fcntl_trampoline},
96	{"poll", libc_poll_trampoline},
97	{"madvise", libc_madvise_trampoline},
98	{"mlock", libc_mlock_trampoline},
99	{"mlockall", libc_mlockall_trampoline},
100	{"mprotect", libc_mprotect_trampoline},
101	{"msync", libc_msync_trampoline},
102	{"munlock", libc_munlock_trampoline},
103	{"munlockall", libc_munlockall_trampoline},
104	{"ptrace", libc_ptrace_trampoline},
105	{"pipe", libc_pipe_trampoline},
106	{"getxattr", libc_getxattr_trampoline},
107	{"fgetxattr", libc_fgetxattr_trampoline},
108	{"setxattr", libc_setxattr_trampoline},
109	{"fsetxattr", libc_fsetxattr_trampoline},
110	{"removexattr", libc_removexattr_trampoline},
111	{"fremovexattr", libc_fremovexattr_trampoline},
112	{"listxattr", libc_listxattr_trampoline},
113	{"flistxattr", libc_flistxattr_trampoline},
114	{"kill", libc_kill_trampoline},
115	{"ioctl", libc_ioctl_trampoline},
116	{"access", libc_access_trampoline},
117	{"adjtime", libc_adjtime_trampoline},
118	{"chdir", libc_chdir_trampoline},
119	{"chflags", libc_chflags_trampoline},
120	{"chmod", libc_chmod_trampoline},
121	{"chown", libc_chown_trampoline},
122	{"chroot", libc_chroot_trampoline},
123	{"close", libc_close_trampoline},
124	{"dup", libc_dup_trampoline},
125	{"dup2", libc_dup2_trampoline},
126	{"exchangedata", libc_exchangedata_trampoline},
127	{"exit", libc_exit_trampoline},
128	{"faccessat", libc_faccessat_trampoline},
129	{"fchdir", libc_fchdir_trampoline},
130	{"fchflags", libc_fchflags_trampoline},
131	{"fchmod", libc_fchmod_trampoline},
132	{"fchmodat", libc_fchmodat_trampoline},
133	{"fchown", libc_fchown_trampoline},
134	{"fchownat", libc_fchownat_trampoline},
135	{"flock", libc_flock_trampoline},
136	{"fpathconf", libc_fpathconf_trampoline},
137	{"fstat64", libc_fstat64_trampoline},
138	{"fstatat64", libc_fstatat64_trampoline},
139	{"fstatfs64", libc_fstatfs64_trampoline},
140	{"fsync", libc_fsync_trampoline},
141	{"ftruncate", libc_ftruncate_trampoline},
142	{"getdtablesize", libc_getdtablesize_trampoline},
143	{"getegid", libc_getegid_trampoline},
144	{"geteuid", libc_geteuid_trampoline},
145	{"getgid", libc_getgid_trampoline},
146	{"getpgid", libc_getpgid_trampoline},
147	{"getpgrp", libc_getpgrp_trampoline},
148	{"getpid", libc_getpid_trampoline},
149	{"getppid", libc_getppid_trampoline},
150	{"getpriority", libc_getpriority_trampoline},
151	{"getrlimit", libc_getrlimit_trampoline},
152	{"getrusage", libc_getrusage_trampoline},
153	{"getsid", libc_getsid_trampoline},
154	{"getuid", libc_getuid_trampoline},
155	{"issetugid", libc_issetugid_trampoline},
156	{"kqueue", libc_kqueue_trampoline},
157	{"lchown", libc_lchown_trampoline},
158	{"link", libc_link_trampoline},
159	{"linkat", libc_linkat_trampoline},
160	{"listen", libc_listen_trampoline},
161	{"lstat64", libc_lstat64_trampoline},
162	{"mkdir", libc_mkdir_trampoline},
163	{"mkdirat", libc_mkdirat_trampoline},
164	{"mkfifo", libc_mkfifo_trampoline},
165	{"mknod", libc_mknod_trampoline},
166	{"open", libc_open_trampoline},
167	{"openat", libc_openat_trampoline},
168	{"pathconf", libc_pathconf_trampoline},
169	{"pread", libc_pread_trampoline},
170	{"pwrite", libc_pwrite_trampoline},
171	{"read", libc_read_trampoline},
172	{"readlink", libc_readlink_trampoline},
173	{"readlinkat", libc_readlinkat_trampoline},
174	{"rename", libc_rename_trampoline},
175	{"renameat", libc_renameat_trampoline},
176	{"revoke", libc_revoke_trampoline},
177	{"rmdir", libc_rmdir_trampoline},
178	{"lseek", libc_lseek_trampoline},
179	{"select", libc_select_trampoline},
180	{"setegid", libc_setegid_trampoline},
181	{"seteuid", libc_seteuid_trampoline},
182	{"setgid", libc_setgid_trampoline},
183	{"setlogin", libc_setlogin_trampoline},
184	{"setpgid", libc_setpgid_trampoline},
185	{"setpriority", libc_setpriority_trampoline},
186	{"setprivexec", libc_setprivexec_trampoline},
187	{"setregid", libc_setregid_trampoline},
188	{"setreuid", libc_setreuid_trampoline},
189	{"setrlimit", libc_setrlimit_trampoline},
190	{"setsid", libc_setsid_trampoline},
191	{"settimeofday", libc_settimeofday_trampoline},
192	{"setuid", libc_setuid_trampoline},
193	{"stat64", libc_stat64_trampoline},
194	{"statfs64", libc_statfs64_trampoline},
195	{"symlink", libc_symlink_trampoline},
196	{"symlinkat", libc_symlinkat_trampoline},
197	{"sync", libc_sync_trampoline},
198	{"truncate", libc_truncate_trampoline},
199	{"umask", libc_umask_trampoline},
200	{"undelete", libc_undelete_trampoline},
201	{"unlink", libc_unlink_trampoline},
202	{"unlinkat", libc_unlinkat_trampoline},
203	{"unmount", libc_unmount_trampoline},
204	{"write", libc_write_trampoline},
205	{"mmap", libc_mmap_trampoline},
206	{"munmap", libc_munmap_trampoline},
207	{"gettimeofday", libc_gettimeofday_trampoline},
208	{"getfsstat64", libc_getfsstat64_trampoline},
209}
210