2 * Copyright 1997 Sean Eric Fagan
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Sean Eric Fagan
15 * 4. Neither the name of the author may be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
36 * This file has routines used to print out system calls and their
40 #include <sys/types.h>
41 #include <sys/event.h>
42 #include <sys/ioccom.h>
44 #include <sys/mount.h>
45 #include <sys/procctl.h>
46 #include <sys/ptrace.h>
47 #include <sys/resource.h>
48 #include <sys/socket.h>
53 #include <machine/sysarch.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
68 #include <sysdecode.h>
73 #include <contrib/cloudabi/cloudabi_types_common.h>
79 /* 64-bit alignment on 32-bit platforms. */
80 #if !defined(__LP64__) && defined(__powerpc__)
86 /* Number of slots needed for a 64-bit argument. */
94 * This should probably be in its own file, sorted alphabetically.
96 static struct syscall decoded_syscalls[] = {
98 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
99 .args = { { Name | OUT, 0 }, { Int, 1 } } },
100 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
101 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
103 { .name = "accept", .ret_type = 1, .nargs = 3,
104 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
105 { .name = "access", .ret_type = 1, .nargs = 2,
106 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
107 { .name = "bind", .ret_type = 1, .nargs = 3,
108 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
109 { .name = "bindat", .ret_type = 1, .nargs = 4,
110 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
112 { .name = "break", .ret_type = 1, .nargs = 1,
113 .args = { { Ptr, 0 } } },
114 { .name = "chdir", .ret_type = 1, .nargs = 1,
115 .args = { { Name, 0 } } },
116 { .name = "chflags", .ret_type = 1, .nargs = 2,
117 .args = { { Name | IN, 0 }, { Hex, 1 } } },
118 { .name = "chmod", .ret_type = 1, .nargs = 2,
119 .args = { { Name, 0 }, { Octal, 1 } } },
120 { .name = "chown", .ret_type = 1, .nargs = 3,
121 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
122 { .name = "chroot", .ret_type = 1, .nargs = 1,
123 .args = { { Name, 0 } } },
124 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
125 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
126 { .name = "close", .ret_type = 1, .nargs = 1,
127 .args = { { Int, 0 } } },
128 { .name = "connect", .ret_type = 1, .nargs = 3,
129 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
130 { .name = "connectat", .ret_type = 1, .nargs = 4,
131 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
133 { .name = "eaccess", .ret_type = 1, .nargs = 2,
134 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
135 { .name = "execve", .ret_type = 1, .nargs = 3,
136 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
137 { ExecEnv | IN, 2 } } },
138 { .name = "exit", .ret_type = 0, .nargs = 1,
139 .args = { { Hex, 0 } } },
140 { .name = "faccessat", .ret_type = 1, .nargs = 4,
141 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
143 { .name = "fchmod", .ret_type = 1, .nargs = 2,
144 .args = { { Int, 0 }, { Octal, 1 } } },
145 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
146 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
147 { .name = "fchown", .ret_type = 1, .nargs = 3,
148 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
149 { .name = "fchownat", .ret_type = 1, .nargs = 5,
150 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
152 { .name = "fcntl", .ret_type = 1, .nargs = 3,
153 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
154 { .name = "fstat", .ret_type = 1, .nargs = 2,
155 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
156 { .name = "fstatat", .ret_type = 1, .nargs = 4,
157 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
159 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
160 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
161 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
162 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } },
163 { .name = "futimens", .ret_type = 1, .nargs = 2,
164 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
165 { .name = "futimes", .ret_type = 1, .nargs = 2,
166 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
167 { .name = "futimesat", .ret_type = 1, .nargs = 3,
168 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
169 { .name = "getitimer", .ret_type = 1, .nargs = 2,
170 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
171 { .name = "getpeername", .ret_type = 1, .nargs = 3,
172 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
173 { .name = "getpgid", .ret_type = 1, .nargs = 1,
174 .args = { { Int, 0 } } },
175 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
176 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
177 { .name = "getrusage", .ret_type = 1, .nargs = 2,
178 .args = { { Int, 0 }, { Rusage | OUT, 1 } } },
179 { .name = "getsid", .ret_type = 1, .nargs = 1,
180 .args = { { Int, 0 } } },
181 { .name = "getsockname", .ret_type = 1, .nargs = 3,
182 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
183 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
184 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
185 { .name = "ioctl", .ret_type = 1, .nargs = 3,
186 .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } },
187 { .name = "kevent", .ret_type = 1, .nargs = 6,
188 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
189 { Int, 4 }, { Timespec, 5 } } },
190 { .name = "kill", .ret_type = 1, .nargs = 2,
191 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
192 { .name = "kldfind", .ret_type = 1, .nargs = 1,
193 .args = { { Name | IN, 0 } } },
194 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
195 .args = { { Int, 0 } } },
196 { .name = "kldload", .ret_type = 1, .nargs = 1,
197 .args = { { Name | IN, 0 } } },
198 { .name = "kldnext", .ret_type = 1, .nargs = 1,
199 .args = { { Int, 0 } } },
200 { .name = "kldstat", .ret_type = 1, .nargs = 2,
201 .args = { { Int, 0 }, { Ptr, 1 } } },
202 { .name = "kldunload", .ret_type = 1, .nargs = 1,
203 .args = { { Int, 0 } } },
204 { .name = "kse_release", .ret_type = 0, .nargs = 1,
205 .args = { { Timespec, 0 } } },
206 { .name = "lchflags", .ret_type = 1, .nargs = 2,
207 .args = { { Name | IN, 0 }, { Hex, 1 } } },
208 { .name = "lchmod", .ret_type = 1, .nargs = 2,
209 .args = { { Name, 0 }, { Octal, 1 } } },
210 { .name = "lchown", .ret_type = 1, .nargs = 3,
211 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
212 { .name = "link", .ret_type = 1, .nargs = 2,
213 .args = { { Name, 0 }, { Name, 1 } } },
214 { .name = "linkat", .ret_type = 1, .nargs = 5,
215 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
217 { .name = "lseek", .ret_type = 2, .nargs = 3,
218 .args = { { Int, 0 }, { QuadHex, 1 + QUAD_ALIGN },
219 { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } },
220 { .name = "lstat", .ret_type = 1, .nargs = 2,
221 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
222 { .name = "lutimes", .ret_type = 1, .nargs = 2,
223 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
224 { .name = "mkdir", .ret_type = 1, .nargs = 2,
225 .args = { { Name, 0 }, { Octal, 1 } } },
226 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
227 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
228 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
229 .args = { { Name, 0 }, { Octal, 1 } } },
230 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
231 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
232 { .name = "mknod", .ret_type = 1, .nargs = 3,
233 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
234 { .name = "mknodat", .ret_type = 1, .nargs = 4,
235 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
236 { .name = "mmap", .ret_type = 1, .nargs = 6,
237 .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
238 { Int, 4 }, { QuadHex, 5 + QUAD_ALIGN } } },
239 { .name = "modfind", .ret_type = 1, .nargs = 1,
240 .args = { { Name | IN, 0 } } },
241 { .name = "mount", .ret_type = 1, .nargs = 4,
242 .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
243 { .name = "mprotect", .ret_type = 1, .nargs = 3,
244 .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
245 { .name = "munmap", .ret_type = 1, .nargs = 2,
246 .args = { { Ptr, 0 }, { Int, 1 } } },
247 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
248 .args = { { Timespec, 0 } } },
249 { .name = "open", .ret_type = 1, .nargs = 3,
250 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
251 { .name = "openat", .ret_type = 1, .nargs = 4,
252 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
254 { .name = "pathconf", .ret_type = 1, .nargs = 2,
255 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
256 { .name = "pipe", .ret_type = 1, .nargs = 1,
257 .args = { { PipeFds | OUT, 0 } } },
258 { .name = "pipe2", .ret_type = 1, .nargs = 2,
259 .args = { { Ptr, 0 }, { Open, 1 } } },
260 { .name = "poll", .ret_type = 1, .nargs = 3,
261 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
262 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
263 .args = { { Open, 0 } } },
264 { .name = "procctl", .ret_type = 1, .nargs = 4,
265 .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN },
266 { Procctl, 1 + QUAD_ALIGN + QUAD_SLOTS },
267 { Ptr, 2 + QUAD_ALIGN + QUAD_SLOTS } } },
268 { .name = "read", .ret_type = 1, .nargs = 3,
269 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
270 { .name = "readlink", .ret_type = 1, .nargs = 3,
271 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Int, 2 } } },
272 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
273 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
275 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
276 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 },
277 { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
278 { .name = "rename", .ret_type = 1, .nargs = 2,
279 .args = { { Name, 0 }, { Name, 1 } } },
280 { .name = "renameat", .ret_type = 1, .nargs = 4,
281 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
282 { .name = "rfork", .ret_type = 1, .nargs = 1,
283 .args = { { Rforkflags, 0 } } },
284 { .name = "rmdir", .ret_type = 1, .nargs = 1,
285 .args = { { Name, 0 } } },
286 { .name = "select", .ret_type = 1, .nargs = 5,
287 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
289 { .name = "sendto", .ret_type = 1, .nargs = 6,
290 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 },
291 { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
292 { .name = "setitimer", .ret_type = 1, .nargs = 3,
293 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
294 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
295 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
296 { .name = "shutdown", .ret_type = 1, .nargs = 2,
297 .args = { { Int, 0 }, { Shutdown, 1 } } },
298 { .name = "sigaction", .ret_type = 1, .nargs = 3,
299 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
300 { Sigaction | OUT, 2 } } },
301 { .name = "sigpending", .ret_type = 1, .nargs = 1,
302 .args = { { Sigset | OUT, 0 } } },
303 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
304 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
305 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
306 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
307 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
308 .args = { { Ptr, 0 } } },
309 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
310 .args = { { Sigset | IN, 0 } } },
311 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
312 .args = { { Sigset | IN, 0 }, { Ptr, 1 }, { Timespec | IN, 2 } } },
313 { .name = "sigwait", .ret_type = 1, .nargs = 2,
314 .args = { { Sigset | IN, 0 }, { Ptr, 1 } } },
315 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
316 .args = { { Sigset | IN, 0 }, { Ptr, 1 } } },
317 { .name = "socket", .ret_type = 1, .nargs = 3,
318 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } },
319 { .name = "stat", .ret_type = 1, .nargs = 2,
320 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
321 { .name = "statfs", .ret_type = 1, .nargs = 2,
322 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
323 { .name = "symlink", .ret_type = 1, .nargs = 2,
324 .args = { { Name, 0 }, { Name, 1 } } },
325 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
326 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
327 { .name = "sysarch", .ret_type = 1, .nargs = 2,
328 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
329 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
330 .args = { { Long, 0 }, { Signal, 1 } } },
331 { .name = "thr_self", .ret_type = 1, .nargs = 1,
332 .args = { { Ptr, 0 } } },
333 { .name = "truncate", .ret_type = 1, .nargs = 2,
334 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } },
337 { .name = "umount", .ret_type = 1, .nargs = 2,
338 .args = { { Name, 0 }, { Int, 2 } } },
340 { .name = "unlink", .ret_type = 1, .nargs = 1,
341 .args = { { Name, 0 } } },
342 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
343 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
344 { .name = "unmount", .ret_type = 1, .nargs = 2,
345 .args = { { Name, 0 }, { Int, 1 } } },
346 { .name = "utimensat", .ret_type = 1, .nargs = 4,
347 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
349 { .name = "utimes", .ret_type = 1, .nargs = 2,
350 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
351 { .name = "utrace", .ret_type = 1, .nargs = 1,
352 .args = { { Utrace, 0 } } },
353 { .name = "wait4", .ret_type = 1, .nargs = 4,
354 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
355 { Rusage | OUT, 3 } } },
356 { .name = "wait6", .ret_type = 1, .nargs = 6,
357 .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN },
358 { ExitStatus | OUT, 1 + QUAD_ALIGN + QUAD_SLOTS },
359 { Waitoptions, 2 + QUAD_ALIGN + QUAD_SLOTS },
360 { Rusage | OUT, 3 + QUAD_ALIGN + QUAD_SLOTS },
361 { Ptr, 4 + QUAD_ALIGN + QUAD_SLOTS } } },
362 { .name = "write", .ret_type = 1, .nargs = 3,
363 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } },
366 { .name = "linux_access", .ret_type = 1, .nargs = 2,
367 .args = { { Name, 0 }, { Accessmode, 1 } } },
368 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
369 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
370 { ExecEnv | IN, 2 } } },
371 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
372 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
373 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
374 .args = { { Name | IN, 0 }, { Int, 1 } } },
375 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
376 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
377 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
378 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
379 { .name = "linux_open", .ret_type = 1, .nargs = 3,
380 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
381 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
382 .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } },
383 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
384 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
385 { .name = "linux_stat64", .ret_type = 1, .nargs = 3,
386 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } },
388 /* CloudABI system calls. */
389 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
390 .args = { { CloudABIClockID, 0 } } },
391 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
392 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
393 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
394 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
395 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
396 .args = { { Int, 0 } } },
397 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
398 .args = { { CloudABIFileType, 0 } } },
399 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
400 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
401 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
402 .args = { { Int, 0 } } },
403 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
404 .args = { { Int, 0 } } },
405 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
406 .args = { { Int, 0 }, { Int, 1 } } },
407 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
408 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
409 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
410 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
411 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
412 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
413 { ClouduABIFDSFlags, 2 } } },
414 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
415 .args = { { Int, 0 } } },
416 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
417 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
418 { CloudABIAdvice, 3 } } },
419 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
420 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
421 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
422 .args = { { Int, 0 }, { BinString | IN, 1 },
423 { CloudABIFileType, 3 } } },
424 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
425 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
426 { Int, 3 }, { BinString | IN, 4 } } },
427 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
428 .args = { { Int, 0 }, { BinString | IN, 1 },
429 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
430 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
431 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
433 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
434 .args = { { Int, 0 }, { BinString | IN, 1 },
435 { BinString | OUT, 3 }, { Int, 4 } } },
436 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
437 .args = { { Int, 0 }, { BinString | IN, 1 },
438 { Int, 3 }, { BinString | IN, 4 } } },
439 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
440 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
441 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
442 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
443 { CloudABIFSFlags, 2 } } },
444 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
445 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
446 { CloudABIFileStat | OUT, 3 } } },
447 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
448 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
449 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
450 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
451 .args = { { BinString | IN, 0 },
452 { Int, 2 }, { BinString | IN, 3 } } },
453 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
454 .args = { { Int, 0 }, { BinString | IN, 1 },
455 { CloudABIULFlags, 3 } } },
456 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
457 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
458 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
459 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
460 { .name = "cloudabi_sys_mem_lock", .ret_type = 1, .nargs = 2,
461 .args = { { Ptr, 0 }, { Int, 1 } } },
462 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
463 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
464 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
465 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
466 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
467 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
468 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
469 { .name = "cloudabi_sys_mem_unlock", .ret_type = 1, .nargs = 2,
470 .args = { { Ptr, 0 }, { Int, 1 } } },
471 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
472 .args = { { Ptr, 0 }, { Int, 1 } } },
473 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
474 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
475 { IntArray, 3 }, { Int, 4 } } },
476 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
477 .args = { { Int, 0 } } },
478 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
479 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
480 .args = { { CloudABISignal, 0 } } },
481 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
482 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
483 { .name = "cloudabi_sys_sock_accept", .ret_type = 1, .nargs = 2,
484 .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 } } },
485 { .name = "cloudabi_sys_sock_bind", .ret_type = 1, .nargs = 3,
486 .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } },
487 { .name = "cloudabi_sys_sock_connect", .ret_type = 1, .nargs = 3,
488 .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } },
489 { .name = "cloudabi_sys_sock_listen", .ret_type = 1, .nargs = 2,
490 .args = { { Int, 0 }, { Int, 1 } } },
491 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
492 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
493 { .name = "cloudabi_sys_sock_stat_get", .ret_type = 1, .nargs = 3,
494 .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 },
495 { CloudABISSFlags, 2 } } },
496 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
497 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
498 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
502 static STAILQ_HEAD(, syscall) syscalls;
504 /* Xlat idea taken from strace */
510 #define X(a) { a, #a },
511 #define XEND { 0, NULL }
513 static struct xlat kevent_filters[] = {
514 X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
515 X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
516 X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
517 X(EVFILT_SENDFILE) XEND
520 static struct xlat kevent_flags[] = {
521 X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
522 X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
523 X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
526 static struct xlat kevent_user_ffctrl[] = {
527 X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY)
531 static struct xlat kevent_rdwr_fflags[] = {
532 X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND
535 static struct xlat kevent_vnode_fflags[] = {
536 X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB)
537 X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) XEND
540 static struct xlat kevent_proc_fflags[] = {
541 X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR)
545 static struct xlat kevent_timer_fflags[] = {
546 X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS)
550 static struct xlat poll_flags[] = {
551 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
552 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
553 X(POLLWRBAND) X(POLLINIGNEOF) XEND
556 static struct xlat mmap_flags[] = {
557 X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RESERVED0020)
558 X(MAP_RESERVED0040) X(MAP_RESERVED0080) X(MAP_RESERVED0100)
559 X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON)
560 X(MAP_EXCL) X(MAP_NOCORE) X(MAP_PREFAULT_READ)
567 static struct xlat mprot_flags[] = {
568 X(PROT_NONE) X(PROT_READ) X(PROT_WRITE) X(PROT_EXEC) XEND
571 static struct xlat whence_arg[] = {
572 X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) X(SEEK_DATA) X(SEEK_HOLE) XEND
575 static struct xlat sigaction_flags[] = {
576 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
577 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
580 static struct xlat fcntl_arg[] = {
581 X(F_DUPFD) X(F_GETFD) X(F_SETFD) X(F_GETFL) X(F_SETFL)
582 X(F_GETOWN) X(F_SETOWN) X(F_OGETLK) X(F_OSETLK) X(F_OSETLKW)
583 X(F_DUP2FD) X(F_GETLK) X(F_SETLK) X(F_SETLKW) X(F_SETLK_REMOTE)
584 X(F_READAHEAD) X(F_RDAHEAD) X(F_DUPFD_CLOEXEC) X(F_DUP2FD_CLOEXEC)
588 static struct xlat fcntlfd_arg[] = {
592 static struct xlat fcntlfl_arg[] = {
593 X(O_APPEND) X(O_ASYNC) X(O_FSYNC) X(O_NONBLOCK) X(O_NOFOLLOW)
594 X(FRDAHEAD) X(O_DIRECT) XEND
597 static struct xlat sockdomain_arg[] = {
598 X(PF_UNSPEC) X(PF_LOCAL) X(PF_UNIX) X(PF_INET) X(PF_IMPLINK)
599 X(PF_PUP) X(PF_CHAOS) X(PF_NETBIOS) X(PF_ISO) X(PF_OSI)
600 X(PF_ECMA) X(PF_DATAKIT) X(PF_CCITT) X(PF_SNA) X(PF_DECnet)
601 X(PF_DLI) X(PF_LAT) X(PF_HYLINK) X(PF_APPLETALK) X(PF_ROUTE)
602 X(PF_LINK) X(PF_XTP) X(PF_COIP) X(PF_CNT) X(PF_SIP) X(PF_IPX)
603 X(PF_RTIP) X(PF_PIP) X(PF_ISDN) X(PF_KEY) X(PF_INET6)
604 X(PF_NATM) X(PF_ATM) X(PF_NETGRAPH) X(PF_SLOW) X(PF_SCLUSTER)
605 X(PF_ARP) X(PF_BLUETOOTH) X(PF_IEEE80211) X(PF_INET_SDP)
609 static struct xlat socktype_arg[] = {
610 X(SOCK_STREAM) X(SOCK_DGRAM) X(SOCK_RAW) X(SOCK_RDM)
611 X(SOCK_SEQPACKET) XEND
614 static struct xlat open_flags[] = {
615 X(O_RDONLY) X(O_WRONLY) X(O_RDWR) X(O_ACCMODE) X(O_NONBLOCK)
616 X(O_APPEND) X(O_SHLOCK) X(O_EXLOCK) X(O_ASYNC) X(O_FSYNC)
617 X(O_NOFOLLOW) X(O_CREAT) X(O_TRUNC) X(O_EXCL) X(O_NOCTTY)
618 X(O_DIRECT) X(O_DIRECTORY) X(O_EXEC) X(O_TTY_INIT) X(O_CLOEXEC)
622 static struct xlat shutdown_arg[] = {
623 X(SHUT_RD) X(SHUT_WR) X(SHUT_RDWR) XEND
626 static struct xlat resource_arg[] = {
627 X(RLIMIT_CPU) X(RLIMIT_FSIZE) X(RLIMIT_DATA) X(RLIMIT_STACK)
628 X(RLIMIT_CORE) X(RLIMIT_RSS) X(RLIMIT_MEMLOCK) X(RLIMIT_NPROC)
629 X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) X(RLIMIT_NPTS)
630 X(RLIMIT_SWAP) X(RLIMIT_KQUEUES) XEND
633 static struct xlat pathconf_arg[] = {
634 X(_PC_LINK_MAX) X(_PC_MAX_CANON) X(_PC_MAX_INPUT)
635 X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF)
636 X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE)
637 X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO)
638 X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS)
639 X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE)
640 X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN)
641 X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX)
642 X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT)
643 X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND
646 static struct xlat rfork_flags[] = {
647 X(RFFDG) X(RFPROC) X(RFMEM) X(RFNOWAIT) X(RFCFDG) X(RFTHREAD)
648 X(RFSIGSHARE) X(RFLINUXTHPN) X(RFTSIGZMB) X(RFPPWAIT) XEND
651 static struct xlat wait_options[] = {
652 X(WNOHANG) X(WUNTRACED) X(WCONTINUED) X(WNOWAIT) X(WEXITED)
656 static struct xlat idtype_arg[] = {
657 X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID)
658 X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID)
659 X(P_CTID) X(P_CPUID) X(P_PSETID) XEND
662 static struct xlat procctl_arg[] = {
663 X(PROC_SPROTECT) X(PROC_REAP_ACQUIRE) X(PROC_REAP_RELEASE)
664 X(PROC_REAP_STATUS) X(PROC_REAP_GETPIDS) X(PROC_REAP_KILL)
665 X(PROC_TRACE_CTL) X(PROC_TRACE_STATUS) XEND
668 static struct xlat umtx_ops[] = {
669 X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT)
670 X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK)
671 X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT)
672 X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT)
673 X(UMTX_OP_RW_RDLOCK) X(UMTX_OP_RW_WRLOCK) X(UMTX_OP_RW_UNLOCK)
674 X(UMTX_OP_WAIT_UINT_PRIVATE) X(UMTX_OP_WAKE_PRIVATE)
675 X(UMTX_OP_MUTEX_WAIT) X(UMTX_OP_MUTEX_WAKE) X(UMTX_OP_SEM_WAIT)
676 X(UMTX_OP_SEM_WAKE) X(UMTX_OP_NWAKE_PRIVATE) X(UMTX_OP_MUTEX_WAKE2)
677 X(UMTX_OP_SEM2_WAIT) X(UMTX_OP_SEM2_WAKE)
681 static struct xlat at_flags[] = {
682 X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW)
686 static struct xlat access_modes[] = {
687 X(R_OK) X(W_OK) X(X_OK) XEND
690 static struct xlat sysarch_ops[] = {
691 #if defined(__i386__) || defined(__amd64__)
692 X(I386_GET_LDT) X(I386_SET_LDT) X(I386_GET_IOPERM) X(I386_SET_IOPERM)
693 X(I386_VM86) X(I386_GET_FSBASE) X(I386_SET_FSBASE) X(I386_GET_GSBASE)
694 X(I386_SET_GSBASE) X(I386_GET_XFPUSTATE) X(AMD64_GET_FSBASE)
695 X(AMD64_SET_FSBASE) X(AMD64_GET_GSBASE) X(AMD64_SET_GSBASE)
696 X(AMD64_GET_XFPUSTATE)
701 static struct xlat linux_socketcall_ops[] = {
702 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
703 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
704 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
705 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
706 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
710 static struct xlat sigprocmask_ops[] = {
711 X(SIG_BLOCK) X(SIG_UNBLOCK) X(SIG_SETMASK)
716 #define X(a) { CLOUDABI_##a, #a },
718 static struct xlat cloudabi_advice[] = {
719 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
720 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
724 static struct xlat cloudabi_clockid[] = {
725 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
726 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
730 static struct xlat cloudabi_errno[] = {
731 X(E2BIG) X(EACCES) X(EADDRINUSE) X(EADDRNOTAVAIL)
732 X(EAFNOSUPPORT) X(EAGAIN) X(EALREADY) X(EBADF) X(EBADMSG)
733 X(EBUSY) X(ECANCELED) X(ECHILD) X(ECONNABORTED) X(ECONNREFUSED)
734 X(ECONNRESET) X(EDEADLK) X(EDESTADDRREQ) X(EDOM) X(EDQUOT)
735 X(EEXIST) X(EFAULT) X(EFBIG) X(EHOSTUNREACH) X(EIDRM) X(EILSEQ)
736 X(EINPROGRESS) X(EINTR) X(EINVAL) X(EIO) X(EISCONN) X(EISDIR)
737 X(ELOOP) X(EMFILE) X(EMLINK) X(EMSGSIZE) X(EMULTIHOP)
738 X(ENAMETOOLONG) X(ENETDOWN) X(ENETRESET) X(ENETUNREACH)
739 X(ENFILE) X(ENOBUFS) X(ENODEV) X(ENOENT) X(ENOEXEC) X(ENOLCK)
740 X(ENOLINK) X(ENOMEM) X(ENOMSG) X(ENOPROTOOPT) X(ENOSPC)
741 X(ENOSYS) X(ENOTCONN) X(ENOTDIR) X(ENOTEMPTY) X(ENOTRECOVERABLE)
742 X(ENOTSOCK) X(ENOTSUP) X(ENOTTY) X(ENXIO) X(EOVERFLOW)
743 X(EOWNERDEAD) X(EPERM) X(EPIPE) X(EPROTO) X(EPROTONOSUPPORT)
744 X(EPROTOTYPE) X(ERANGE) X(EROFS) X(ESPIPE) X(ESRCH) X(ESTALE)
745 X(ETIMEDOUT) X(ETXTBSY) X(EXDEV) X(ENOTCAPABLE)
749 static struct xlat cloudabi_fdflags[] = {
750 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
751 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
755 static struct xlat cloudabi_fdsflags[] = {
756 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
760 static struct xlat cloudabi_filetype[] = {
761 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
762 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
763 X(FILETYPE_FIFO) X(FILETYPE_POLL) X(FILETYPE_PROCESS)
764 X(FILETYPE_REGULAR_FILE) X(FILETYPE_SHARED_MEMORY)
765 X(FILETYPE_SOCKET_DGRAM) X(FILETYPE_SOCKET_SEQPACKET)
766 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
770 static struct xlat cloudabi_fsflags[] = {
771 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
772 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
776 static struct xlat cloudabi_mflags[] = {
777 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
781 static struct xlat cloudabi_mprot[] = {
782 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
786 static struct xlat cloudabi_msflags[] = {
787 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
791 static struct xlat cloudabi_oflags[] = {
792 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
796 static struct xlat cloudabi_sa_family[] = {
797 X(AF_UNSPEC) X(AF_INET) X(AF_INET6) X(AF_UNIX)
801 static struct xlat cloudabi_sdflags[] = {
802 X(SHUT_RD) X(SHUT_WR)
806 static struct xlat cloudabi_signal[] = {
807 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
808 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
809 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
810 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
811 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
815 static struct xlat cloudabi_ssflags[] = {
816 X(SOCKSTAT_CLEAR_ERROR)
820 static struct xlat cloudabi_ssstate[] = {
821 X(SOCKSTATE_ACCEPTCONN)
825 static struct xlat cloudabi_ulflags[] = {
830 static struct xlat cloudabi_whence[] = {
831 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
839 * Searches an xlat array for a value, and returns it if found. Otherwise
840 * return a string representation.
843 lookup(struct xlat *xlat, int val, int base)
847 for (; xlat->str != NULL; xlat++)
848 if (xlat->val == val)
852 sprintf(tmp, "0%o", val);
855 sprintf(tmp, "0x%x", val);
858 sprintf(tmp, "%u", val);
861 errx(1,"Unknown lookup base");
868 xlookup(struct xlat *xlat, int val)
871 return (lookup(xlat, val, 16));
875 * Searches an xlat array containing bitfield values. Remaining bits
876 * set after removing the known ones are printed at the end:
880 xlookup_bits(struct xlat *xlat, int val)
883 static char str[512];
887 for (; xlat->str != NULL; xlat++) {
888 if ((xlat->val & rem) == xlat->val) {
890 * Don't print the "all-bits-zero" string unless all
891 * bits are really zero.
893 if (xlat->val == 0 && val != 0)
895 len += sprintf(str + len, "%s|", xlat->str);
901 * If we have leftover bits or didn't match anything, print
905 len += sprintf(str + len, "0x%x", rem);
906 if (len && str[len - 1] == '|')
917 STAILQ_INIT(&syscalls);
918 for (sc = decoded_syscalls; sc->name != NULL; sc++)
919 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
922 * If/when the list gets big, it might be desirable to do it
923 * as a hash table or binary search.
926 get_syscall(const char *name, int nargs)
933 STAILQ_FOREACH(sc, &syscalls, entries)
934 if (strcmp(name, sc->name) == 0)
937 /* It is unknown. Add it into the list. */
939 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
943 sc = calloc(1, sizeof(struct syscall));
944 sc->name = strdup(name);
947 for (i = 0; i < nargs; i++) {
948 sc->args[i].offset = i;
949 /* Treat all unknown arguments as LongHex. */
950 sc->args[i].type = LongHex;
952 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
958 * Copy a fixed amount of bytes from the process.
961 get_struct(pid_t pid, void *offset, void *buf, int len)
963 struct ptrace_io_desc iorequest;
965 iorequest.piod_op = PIOD_READ_D;
966 iorequest.piod_offs = offset;
967 iorequest.piod_addr = buf;
968 iorequest.piod_len = len;
969 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
977 * Copy a string from the process. Note that it is
978 * expected to be a C string, but if max is set, it will
979 * only get that much.
982 get_string(pid_t pid, void *addr, int max)
984 struct ptrace_io_desc iorequest;
986 size_t offset, size, totalsize;
992 /* Read up to the end of the current page. */
993 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
998 buf = malloc(totalsize);
1002 iorequest.piod_op = PIOD_READ_D;
1003 iorequest.piod_offs = (char *)addr + offset;
1004 iorequest.piod_addr = buf + offset;
1005 iorequest.piod_len = size;
1006 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1010 if (memchr(buf + offset, '\0', size) != NULL)
1013 if (totalsize < MAXSIZE && max == 0) {
1014 size = MAXSIZE - totalsize;
1015 if (size > PAGE_SIZE)
1017 nbuf = realloc(buf, totalsize + size);
1019 buf[totalsize - 1] = '\0';
1025 buf[totalsize - 1] = '\0';
1034 static char tmp[sizeof(int) * 3 + 1];
1039 snprintf(tmp, sizeof(tmp), "%d", sig);
1046 print_kevent(FILE *fp, struct kevent *ke, int input)
1049 switch (ke->filter) {
1055 case EVFILT_PROCDESC:
1056 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1059 fputs(strsig2(ke->ident), fp);
1062 fprintf(fp, "%p", (void *)ke->ident);
1064 fprintf(fp, ",%s,%s,", xlookup(kevent_filters, ke->filter),
1065 xlookup_bits(kevent_flags, ke->flags));
1066 switch (ke->filter) {
1069 fputs(xlookup_bits(kevent_rdwr_fflags, ke->fflags), fp);
1072 fputs(xlookup_bits(kevent_vnode_fflags, ke->fflags), fp);
1075 case EVFILT_PROCDESC:
1076 fputs(xlookup_bits(kevent_proc_fflags, ke->fflags), fp);
1079 fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp);
1084 ctrl = ke->fflags & NOTE_FFCTRLMASK;
1085 data = ke->fflags & NOTE_FFLAGSMASK;
1087 fputs(xlookup(kevent_user_ffctrl, ctrl), fp);
1088 if (ke->fflags & NOTE_TRIGGER)
1089 fputs("|NOTE_TRIGGER", fp);
1091 fprintf(fp, "|%#x", data);
1093 fprintf(fp, "%#x", data);
1098 fprintf(fp, "%#x", ke->fflags);
1100 fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
1104 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1106 unsigned char *utrace_buffer;
1109 if (sysdecode_utrace(fp, utrace_addr, len)) {
1114 utrace_buffer = utrace_addr;
1115 fprintf(fp, "%zu:", len);
1117 fprintf(fp, " %02x", *utrace_buffer++);
1122 * Converts a syscall argument into a string. Said string is
1123 * allocated via malloc(), so needs to be free()'d. sc is
1124 * a pointer to the syscall description (see above); args is
1125 * an array of all of the system call arguments.
1128 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1129 struct trussinfo *trussinfo)
1136 fp = open_memstream(&tmp, &tmplen);
1137 pid = trussinfo->curthread->proc->pid;
1138 switch (sc->type & ARG_MASK) {
1140 fprintf(fp, "0x%x", (int)args[sc->offset]);
1143 fprintf(fp, "0%o", (int)args[sc->offset]);
1146 fprintf(fp, "%d", (int)args[sc->offset]);
1149 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1152 fprintf(fp, "0x%lx", args[sc->offset]);
1155 fprintf(fp, "%ld", args[sc->offset]);
1158 /* NULL-terminated string. */
1161 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1162 fprintf(fp, "\"%s\"", tmp2);
1168 * Binary block of data that might have printable characters.
1169 * XXX If type|OUT, assume that the length is the syscall's
1170 * return value. Otherwise, assume that the length of the block
1171 * is in the next syscall argument.
1173 int max_string = trussinfo->strsize;
1174 char tmp2[max_string + 1], *tmp3;
1181 len = args[sc->offset + 1];
1184 * Don't print more than max_string characters, to avoid word
1185 * wrap. If we have to truncate put some ... after the string.
1187 if (len > max_string) {
1191 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1193 tmp3 = malloc(len * 4 + 1);
1195 if (strvisx(tmp3, tmp2, len,
1196 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1201 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1205 fprintf(fp, "0x%lx", args[sc->offset]);
1215 char buf[PAGE_SIZE];
1222 * Only parse argv[] and environment arrays from exec calls
1225 if (((sc->type & ARG_MASK) == ExecArgs &&
1226 (trussinfo->flags & EXECVEARGS) == 0) ||
1227 ((sc->type & ARG_MASK) == ExecEnv &&
1228 (trussinfo->flags & EXECVEENVS) == 0)) {
1229 fprintf(fp, "0x%lx", args[sc->offset]);
1234 * Read a page of pointers at a time. Punt if the top-level
1235 * pointer is not aligned. Note that the first read is of
1238 addr = args[sc->offset];
1239 if (addr % sizeof(char *) != 0) {
1240 fprintf(fp, "0x%lx", args[sc->offset]);
1244 len = PAGE_SIZE - (addr & PAGE_MASK);
1245 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1246 fprintf(fp, "0x%lx", args[sc->offset]);
1253 while (u.strarray[i] != NULL) {
1254 string = get_string(pid, u.strarray[i], 0);
1255 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1260 if (i == len / sizeof(char *)) {
1263 if (get_struct(pid, (void *)addr, u.buf, len) ==
1265 fprintf(fp, ", <inval>");
1276 fprintf(fp, "%ld", args[sc->offset]);
1279 fprintf(fp, "0x%lx", args[sc->offset]);
1284 unsigned long long ll;
1286 #if _BYTE_ORDER == _LITTLE_ENDIAN
1287 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1290 ll = (unsigned long long)args[sc->offset] << 32 |
1291 args[sc->offset + 1];
1293 if ((sc->type & ARG_MASK) == Quad)
1294 fprintf(fp, "%lld", ll);
1296 fprintf(fp, "0x%llx", ll);
1301 fprintf(fp, "0x%lx", args[sc->offset]);
1306 if (retval[0] == -1)
1308 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1309 fprintf(fp, "\"%s\"", tmp2);
1317 cmd = args[sc->offset];
1318 temp = sysdecode_ioctlname(cmd);
1322 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1323 cmd, cmd & IOC_OUT ? "R" : "",
1324 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1325 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1326 cmd & 0xFF, IOCPARM_LEN(cmd));
1333 if (get_struct(pid, (void *)args[sc->offset], &ts,
1335 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1338 fprintf(fp, "0x%lx", args[sc->offset]);
1342 struct timespec ts[2];
1346 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1350 for (i = 0; i < nitems(ts); i++) {
1353 switch (ts[i].tv_nsec) {
1355 fprintf(fp, "UTIME_NOW");
1358 fprintf(fp, "UTIME_OMIT");
1361 fprintf(fp, "%jd.%09ld",
1362 (intmax_t)ts[i].tv_sec,
1369 fprintf(fp, "0x%lx", args[sc->offset]);
1375 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1377 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1380 fprintf(fp, "0x%lx", args[sc->offset]);
1384 struct timeval tv[2];
1386 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1388 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1389 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1390 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1392 fprintf(fp, "0x%lx", args[sc->offset]);
1396 struct itimerval itv;
1398 if (get_struct(pid, (void *)args[sc->offset], &itv,
1400 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1401 (intmax_t)itv.it_interval.tv_sec,
1402 itv.it_interval.tv_usec,
1403 (intmax_t)itv.it_value.tv_sec,
1404 itv.it_value.tv_usec);
1406 fprintf(fp, "0x%lx", args[sc->offset]);
1411 struct linux_socketcall_args largs;
1413 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1414 sizeof(largs)) != -1)
1415 fprintf(fp, "{ %s, 0x%lx }",
1416 lookup(linux_socketcall_ops, largs.what, 10),
1417 (long unsigned int)largs.args);
1419 fprintf(fp, "0x%lx", args[sc->offset]);
1424 * XXX: A Pollfd argument expects the /next/ syscall argument
1425 * to be the number of fds in the array. This matches the poll
1429 int numfds = args[sc->offset + 1];
1430 size_t bytes = sizeof(struct pollfd) * numfds;
1433 if ((pfd = malloc(bytes)) == NULL)
1434 err(1, "Cannot malloc %zu bytes for pollfd array",
1436 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1439 for (i = 0; i < numfds; i++) {
1440 fprintf(fp, " %d/%s", pfd[i].fd,
1441 xlookup_bits(poll_flags, pfd[i].events));
1445 fprintf(fp, "0x%lx", args[sc->offset]);
1452 * XXX: A Fd_set argument expects the /first/ syscall argument
1453 * to be the number of fds in the array. This matches the
1457 int numfds = args[0];
1458 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1461 if ((fds = malloc(bytes)) == NULL)
1462 err(1, "Cannot malloc %zu bytes for fd_set array",
1464 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1467 for (i = 0; i < numfds; i++) {
1468 if (FD_ISSET(i, fds))
1469 fprintf(fp, " %d", i);
1473 fprintf(fp, "0x%lx", args[sc->offset]);
1478 fputs(strsig2(args[sc->offset]), fp);
1485 sig = args[sc->offset];
1486 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1487 sizeof(ss)) == -1) {
1488 fprintf(fp, "0x%lx", args[sc->offset]);
1493 for (i = 1; i < sys_nsig; i++) {
1494 if (sigismember(&ss, i)) {
1495 fprintf(fp, "%s%s", !first ? "|" : "",
1506 fputs(xlookup(sigprocmask_ops, args[sc->offset]), fp);
1510 /* XXX: Output depends on the value of the previous argument. */
1511 switch (args[sc->offset - 1]) {
1513 fputs(xlookup_bits(fcntlfd_arg, args[sc->offset]), fp);
1516 fputs(xlookup_bits(fcntlfl_arg, args[sc->offset]), fp);
1523 fprintf(fp, "0x%lx", args[sc->offset]);
1529 fputs(xlookup_bits(open_flags, args[sc->offset]), fp);
1532 fputs(xlookup(fcntl_arg, args[sc->offset]), fp);
1535 fputs(xlookup_bits(mprot_flags, args[sc->offset]), fp);
1541 * MAP_ALIGNED can't be handled by xlookup_bits(), so
1542 * generate that string manually and prepend it to the
1543 * string from xlookup_bits(). Have to be careful to
1544 * avoid outputting MAP_ALIGNED|0 if MAP_ALIGNED is
1547 flags = args[sc->offset] & ~MAP_ALIGNMENT_MASK;
1548 align = args[sc->offset] & MAP_ALIGNMENT_MASK;
1550 if (align == MAP_ALIGNED_SUPER)
1551 fputs("MAP_ALIGNED_SUPER", fp);
1553 fprintf(fp, "MAP_ALIGNED(%d)",
1554 align >> MAP_ALIGNMENT_SHIFT);
1559 fputs(xlookup_bits(mmap_flags, flags), fp);
1563 fputs(xlookup(whence_arg, args[sc->offset]), fp);
1566 fputs(xlookup(sockdomain_arg, args[sc->offset]), fp);
1571 flags = args[sc->offset] & (SOCK_CLOEXEC | SOCK_NONBLOCK);
1572 type = args[sc->offset] & ~flags;
1573 fputs(xlookup(socktype_arg, type), fp);
1574 if (flags & SOCK_CLOEXEC)
1575 fprintf(fp, "|SOCK_CLOEXEC");
1576 if (flags & SOCK_NONBLOCK)
1577 fprintf(fp, "|SOCK_NONBLOCK");
1581 fputs(xlookup(shutdown_arg, args[sc->offset]), fp);
1584 fputs(xlookup(resource_arg, args[sc->offset]), fp);
1587 fputs(xlookup(pathconf_arg, args[sc->offset]), fp);
1590 fputs(xlookup_bits(rfork_flags, args[sc->offset]), fp);
1594 struct sockaddr_in *lsin;
1595 struct sockaddr_in6 *lsin6;
1596 struct sockaddr_un *sun;
1597 struct sockaddr *sa;
1601 if (args[sc->offset] == 0) {
1607 * Extract the address length from the next argument. If
1608 * this is an output sockaddr (OUT is set), then the
1609 * next argument is a pointer to a socklen_t. Otherwise
1610 * the next argument contains a socklen_t by value.
1612 if (sc->type & OUT) {
1613 if (get_struct(pid, (void *)args[sc->offset + 1],
1614 &len, sizeof(len)) == -1) {
1615 fprintf(fp, "0x%lx", args[sc->offset]);
1619 len = args[sc->offset + 1];
1621 /* If the length is too small, just bail. */
1622 if (len < sizeof(*sa)) {
1623 fprintf(fp, "0x%lx", args[sc->offset]);
1627 sa = calloc(1, len);
1628 if (get_struct(pid, (void *)args[sc->offset], sa, len) == -1) {
1630 fprintf(fp, "0x%lx", args[sc->offset]);
1634 switch (sa->sa_family) {
1636 if (len < sizeof(*lsin))
1637 goto sockaddr_short;
1638 lsin = (struct sockaddr_in *)(void *)sa;
1639 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1640 fprintf(fp, "{ AF_INET %s:%d }", addr,
1641 htons(lsin->sin_port));
1644 if (len < sizeof(*lsin6))
1645 goto sockaddr_short;
1646 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1647 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1649 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1650 htons(lsin6->sin6_port));
1653 sun = (struct sockaddr_un *)sa;
1654 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1655 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1661 "{ sa_len = %d, sa_family = %d, sa_data = {",
1662 (int)sa->sa_len, (int)sa->sa_family);
1663 for (q = (u_char *)sa->sa_data;
1664 q < (u_char *)sa + len; q++)
1665 fprintf(fp, "%s 0x%02x",
1666 q == (u_char *)sa->sa_data ? "" : ",",
1674 struct sigaction sa;
1676 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
1679 if (sa.sa_handler == SIG_DFL)
1680 fputs("SIG_DFL", fp);
1681 else if (sa.sa_handler == SIG_IGN)
1682 fputs("SIG_IGN", fp);
1684 fprintf(fp, "%p", sa.sa_handler);
1685 fprintf(fp, " %s ss_t }",
1686 xlookup_bits(sigaction_flags, sa.sa_flags));
1688 fprintf(fp, "0x%lx", args[sc->offset]);
1693 * XXX XXX: The size of the array is determined by either the
1694 * next syscall argument, or by the syscall return value,
1695 * depending on which argument number we are. This matches the
1696 * kevent syscall, but luckily that's the only syscall that uses
1704 if (sc->offset == 1)
1705 numevents = args[sc->offset+1];
1706 else if (sc->offset == 3 && retval[0] != -1)
1707 numevents = retval[0];
1709 if (numevents >= 0) {
1710 bytes = sizeof(struct kevent) * numevents;
1711 if ((ke = malloc(bytes)) == NULL)
1713 "Cannot malloc %zu bytes for kevent array",
1717 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
1720 for (i = 0; i < numevents; i++) {
1722 print_kevent(fp, &ke[i], sc->offset == 1);
1726 fprintf(fp, "0x%lx", args[sc->offset]);
1734 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
1738 strmode(st.st_mode, mode);
1740 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
1741 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
1742 (long)st.st_blksize);
1744 fprintf(fp, "0x%lx", args[sc->offset]);
1752 if (get_struct(pid, (void *)args[sc->offset], &buf,
1753 sizeof(buf)) != -1) {
1756 bzero(fsid, sizeof(fsid));
1757 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
1758 for (i = 0; i < sizeof(buf.f_fsid); i++)
1759 snprintf(&fsid[i*2],
1760 sizeof(fsid) - (i*2), "%02x",
1761 ((u_char *)&buf.f_fsid)[i]);
1764 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
1765 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
1766 buf.f_mntfromname, fsid);
1768 fprintf(fp, "0x%lx", args[sc->offset]);
1775 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
1778 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
1779 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
1780 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
1781 ru.ru_inblock, ru.ru_oublock);
1783 fprintf(fp, "0x%lx", args[sc->offset]);
1789 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
1791 fprintf(fp, "{ cur=%ju,max=%ju }",
1792 rl.rlim_cur, rl.rlim_max);
1794 fprintf(fp, "0x%lx", args[sc->offset]);
1800 if (get_struct(pid, (void *)args[sc->offset], &status,
1801 sizeof(status)) != -1) {
1803 if (WIFCONTINUED(status))
1804 fputs("CONTINUED", fp);
1805 else if (WIFEXITED(status))
1806 fprintf(fp, "EXITED,val=%d",
1807 WEXITSTATUS(status));
1808 else if (WIFSIGNALED(status))
1809 fprintf(fp, "SIGNALED,sig=%s%s",
1810 strsig2(WTERMSIG(status)),
1811 WCOREDUMP(status) ? ",cored" : "");
1813 fprintf(fp, "STOPPED,sig=%s",
1814 strsig2(WTERMSIG(status)));
1817 fprintf(fp, "0x%lx", args[sc->offset]);
1821 fputs(xlookup_bits(wait_options, args[sc->offset]), fp);
1824 fputs(xlookup(idtype_arg, args[sc->offset]), fp);
1827 fputs(xlookup(procctl_arg, args[sc->offset]), fp);
1830 fputs(xlookup(umtx_ops, args[sc->offset]), fp);
1833 if ((int)args[sc->offset] == AT_FDCWD)
1834 fputs("AT_FDCWD", fp);
1836 fprintf(fp, "%d", (int)args[sc->offset]);
1839 fputs(xlookup_bits(at_flags, args[sc->offset]), fp);
1842 if (args[sc->offset] == F_OK)
1845 fputs(xlookup_bits(access_modes, args[sc->offset]), fp);
1848 fputs(xlookup(sysarch_ops, args[sc->offset]), fp);
1852 * The pipe() system call in the kernel returns its
1853 * two file descriptors via return values. However,
1854 * the interface exposed by libc is that pipe()
1855 * accepts a pointer to an array of descriptors.
1856 * Format the output to match the libc API by printing
1857 * the returned file descriptors as a fake argument.
1859 * Overwrite the first retval to signal a successful
1862 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
1869 len = args[sc->offset + 1];
1870 utrace_addr = calloc(1, len);
1871 if (get_struct(pid, (void *)args[sc->offset],
1872 (void *)utrace_addr, len) != -1)
1873 print_utrace(fp, utrace_addr, len);
1875 fprintf(fp, "0x%lx", args[sc->offset]);
1880 int descriptors[16];
1881 unsigned long i, ndescriptors;
1884 ndescriptors = args[sc->offset + 1];
1886 if (ndescriptors > nitems(descriptors)) {
1887 ndescriptors = nitems(descriptors);
1890 if (get_struct(pid, (void *)args[sc->offset],
1891 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
1893 for (i = 0; i < ndescriptors; i++)
1894 fprintf(fp, i == 0 ? " %d" : ", %d",
1896 fprintf(fp, truncated ? ", ... }" : " }");
1898 fprintf(fp, "0x%lx", args[sc->offset]);
1902 case CloudABIAdvice:
1903 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
1905 case CloudABIClockID:
1906 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
1908 case ClouduABIFDSFlags:
1909 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
1911 case CloudABIFDStat: {
1912 cloudabi_fdstat_t fds;
1913 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
1915 fprintf(fp, "{ %s, ",
1916 xlookup(cloudabi_filetype, fds.fs_filetype));
1917 fprintf(fp, "%s, ... }",
1918 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
1920 fprintf(fp, "0x%lx", args[sc->offset]);
1923 case CloudABIFileStat: {
1924 cloudabi_filestat_t fsb;
1925 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
1927 fprintf(fp, "{ %s, %lu }",
1928 xlookup(cloudabi_filetype, fsb.st_filetype),
1931 fprintf(fp, "0x%lx", args[sc->offset]);
1934 case CloudABIFileType:
1935 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
1937 case CloudABIFSFlags:
1938 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
1940 case CloudABILookup:
1941 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
1942 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
1943 (int)args[sc->offset]);
1945 fprintf(fp, "%d", (int)args[sc->offset]);
1947 case CloudABIMFlags:
1948 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
1951 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
1953 case CloudABIMSFlags:
1954 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
1956 case CloudABIOFlags:
1957 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
1959 case CloudABISDFlags:
1960 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
1962 case CloudABISignal:
1963 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
1965 case CloudABISockStat: {
1966 cloudabi_sockstat_t ss;
1967 if (get_struct(pid, (void *)args[sc->offset], &ss, sizeof(ss))
1969 fprintf(fp, "{ %s, ", xlookup(
1970 cloudabi_sa_family, ss.ss_sockname.sa_family));
1971 fprintf(fp, "%s, ", xlookup(
1972 cloudabi_sa_family, ss.ss_peername.sa_family));
1973 fprintf(fp, "%s, ", xlookup(
1974 cloudabi_errno, ss.ss_error));
1975 fprintf(fp, "%s }", xlookup_bits(
1976 cloudabi_ssstate, ss.ss_state));
1978 fprintf(fp, "0x%lx", args[sc->offset]);
1981 case CloudABISSFlags:
1982 fputs(xlookup_bits(cloudabi_ssflags, args[sc->offset]), fp);
1984 case CloudABITimestamp:
1985 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
1986 args[sc->offset] % 1000000000);
1988 case CloudABIULFlags:
1989 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
1991 case CloudABIWhence:
1992 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
1996 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2003 * Print (to outfile) the system call and its arguments.
2006 print_syscall(struct trussinfo *trussinfo)
2008 struct threadinfo *t;
2013 t = trussinfo->curthread;
2016 nargs = t->cs.nargs;
2017 s_args = t->cs.s_args;
2019 len = print_line_prefix(trussinfo);
2020 len += fprintf(trussinfo->outfile, "%s(", name);
2022 for (i = 0; i < nargs; i++) {
2023 if (s_args[i] != NULL)
2024 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2026 len += fprintf(trussinfo->outfile,
2027 "<missing argument>");
2028 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2031 len += fprintf(trussinfo->outfile, ")");
2032 for (i = 0; i < 6 - (len / 8); i++)
2033 fprintf(trussinfo->outfile, "\t");
2037 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2039 struct timespec timediff;
2040 struct threadinfo *t;
2044 t = trussinfo->curthread;
2046 if (trussinfo->flags & COUNTONLY) {
2047 timespecsubt(&t->after, &t->before, &timediff);
2048 timespecadd(&sc->time, &timediff, &sc->time);
2055 print_syscall(trussinfo);
2056 fflush(trussinfo->outfile);
2058 if (retval == NULL) {
2060 * This system call resulted in the current thread's exit,
2061 * so there is no return value or error to display.
2063 fprintf(trussinfo->outfile, "\n");
2068 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2070 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2071 error == INT_MAX ? "Unknown error" : strerror(error));
2074 else if (sc->ret_type == 2) {
2077 #if _BYTE_ORDER == _LITTLE_ENDIAN
2078 off = (off_t)retval[1] << 32 | retval[0];
2080 off = (off_t)retval[0] << 32 | retval[1];
2082 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2087 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2092 print_summary(struct trussinfo *trussinfo)
2094 struct timespec total = {0, 0};
2098 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2099 "syscall", "seconds", "calls", "errors");
2101 STAILQ_FOREACH(sc, &syscalls, entries)
2103 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2104 sc->name, (intmax_t)sc->time.tv_sec,
2105 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2106 timespecadd(&total, &sc->time, &total);
2107 ncall += sc->ncalls;
2108 nerror += sc->nerror;
2110 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2111 "", "-------------", "-------", "-------");
2112 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2113 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);