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_tcb_set", .ret_type = 1, .nargs = 1,
499 .args = { { Ptr, 0 } } },
500 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
504 static STAILQ_HEAD(, syscall) syscalls;
506 /* Xlat idea taken from strace */
512 #define X(a) { a, #a },
513 #define XEND { 0, NULL }
515 static struct xlat kevent_filters[] = {
516 X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
517 X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
518 X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
519 X(EVFILT_SENDFILE) XEND
522 static struct xlat kevent_flags[] = {
523 X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
524 X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
525 X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
528 static struct xlat kevent_user_ffctrl[] = {
529 X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY)
533 static struct xlat kevent_rdwr_fflags[] = {
534 X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND
537 static struct xlat kevent_vnode_fflags[] = {
538 X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB)
539 X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) XEND
542 static struct xlat kevent_proc_fflags[] = {
543 X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR)
547 static struct xlat kevent_timer_fflags[] = {
548 X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS)
552 static struct xlat poll_flags[] = {
553 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
554 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
555 X(POLLWRBAND) X(POLLINIGNEOF) XEND
558 static struct xlat mmap_flags[] = {
559 X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RESERVED0020)
560 X(MAP_RESERVED0040) X(MAP_RESERVED0080) X(MAP_RESERVED0100)
561 X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON)
562 X(MAP_EXCL) X(MAP_NOCORE) X(MAP_PREFAULT_READ)
569 static struct xlat mprot_flags[] = {
570 X(PROT_NONE) X(PROT_READ) X(PROT_WRITE) X(PROT_EXEC) XEND
573 static struct xlat whence_arg[] = {
574 X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) X(SEEK_DATA) X(SEEK_HOLE) XEND
577 static struct xlat sigaction_flags[] = {
578 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
579 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
582 static struct xlat fcntl_arg[] = {
583 X(F_DUPFD) X(F_GETFD) X(F_SETFD) X(F_GETFL) X(F_SETFL)
584 X(F_GETOWN) X(F_SETOWN) X(F_OGETLK) X(F_OSETLK) X(F_OSETLKW)
585 X(F_DUP2FD) X(F_GETLK) X(F_SETLK) X(F_SETLKW) X(F_SETLK_REMOTE)
586 X(F_READAHEAD) X(F_RDAHEAD) X(F_DUPFD_CLOEXEC) X(F_DUP2FD_CLOEXEC)
590 static struct xlat fcntlfd_arg[] = {
594 static struct xlat fcntlfl_arg[] = {
595 X(O_APPEND) X(O_ASYNC) X(O_FSYNC) X(O_NONBLOCK) X(O_NOFOLLOW)
596 X(FRDAHEAD) X(O_DIRECT) XEND
599 static struct xlat sockdomain_arg[] = {
600 X(PF_UNSPEC) X(PF_LOCAL) X(PF_UNIX) X(PF_INET) X(PF_IMPLINK)
601 X(PF_PUP) X(PF_CHAOS) X(PF_NETBIOS) X(PF_ISO) X(PF_OSI)
602 X(PF_ECMA) X(PF_DATAKIT) X(PF_CCITT) X(PF_SNA) X(PF_DECnet)
603 X(PF_DLI) X(PF_LAT) X(PF_HYLINK) X(PF_APPLETALK) X(PF_ROUTE)
604 X(PF_LINK) X(PF_XTP) X(PF_COIP) X(PF_CNT) X(PF_SIP) X(PF_IPX)
605 X(PF_RTIP) X(PF_PIP) X(PF_ISDN) X(PF_KEY) X(PF_INET6)
606 X(PF_NATM) X(PF_ATM) X(PF_NETGRAPH) X(PF_SLOW) X(PF_SCLUSTER)
607 X(PF_ARP) X(PF_BLUETOOTH) X(PF_IEEE80211) X(PF_INET_SDP)
611 static struct xlat socktype_arg[] = {
612 X(SOCK_STREAM) X(SOCK_DGRAM) X(SOCK_RAW) X(SOCK_RDM)
613 X(SOCK_SEQPACKET) XEND
616 static struct xlat open_flags[] = {
617 X(O_RDONLY) X(O_WRONLY) X(O_RDWR) X(O_ACCMODE) X(O_NONBLOCK)
618 X(O_APPEND) X(O_SHLOCK) X(O_EXLOCK) X(O_ASYNC) X(O_FSYNC)
619 X(O_NOFOLLOW) X(O_CREAT) X(O_TRUNC) X(O_EXCL) X(O_NOCTTY)
620 X(O_DIRECT) X(O_DIRECTORY) X(O_EXEC) X(O_TTY_INIT) X(O_CLOEXEC)
624 static struct xlat shutdown_arg[] = {
625 X(SHUT_RD) X(SHUT_WR) X(SHUT_RDWR) XEND
628 static struct xlat resource_arg[] = {
629 X(RLIMIT_CPU) X(RLIMIT_FSIZE) X(RLIMIT_DATA) X(RLIMIT_STACK)
630 X(RLIMIT_CORE) X(RLIMIT_RSS) X(RLIMIT_MEMLOCK) X(RLIMIT_NPROC)
631 X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) X(RLIMIT_NPTS)
632 X(RLIMIT_SWAP) X(RLIMIT_KQUEUES) XEND
635 static struct xlat pathconf_arg[] = {
636 X(_PC_LINK_MAX) X(_PC_MAX_CANON) X(_PC_MAX_INPUT)
637 X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF)
638 X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE)
639 X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO)
640 X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS)
641 X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE)
642 X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN)
643 X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX)
644 X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT)
645 X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND
648 static struct xlat rfork_flags[] = {
649 X(RFFDG) X(RFPROC) X(RFMEM) X(RFNOWAIT) X(RFCFDG) X(RFTHREAD)
650 X(RFSIGSHARE) X(RFLINUXTHPN) X(RFTSIGZMB) X(RFPPWAIT) XEND
653 static struct xlat wait_options[] = {
654 X(WNOHANG) X(WUNTRACED) X(WCONTINUED) X(WNOWAIT) X(WEXITED)
658 static struct xlat idtype_arg[] = {
659 X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID)
660 X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID)
661 X(P_CTID) X(P_CPUID) X(P_PSETID) XEND
664 static struct xlat procctl_arg[] = {
665 X(PROC_SPROTECT) X(PROC_REAP_ACQUIRE) X(PROC_REAP_RELEASE)
666 X(PROC_REAP_STATUS) X(PROC_REAP_GETPIDS) X(PROC_REAP_KILL)
667 X(PROC_TRACE_CTL) X(PROC_TRACE_STATUS) XEND
670 static struct xlat umtx_ops[] = {
671 X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT)
672 X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK)
673 X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT)
674 X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT)
675 X(UMTX_OP_RW_RDLOCK) X(UMTX_OP_RW_WRLOCK) X(UMTX_OP_RW_UNLOCK)
676 X(UMTX_OP_WAIT_UINT_PRIVATE) X(UMTX_OP_WAKE_PRIVATE)
677 X(UMTX_OP_MUTEX_WAIT) X(UMTX_OP_MUTEX_WAKE) X(UMTX_OP_SEM_WAIT)
678 X(UMTX_OP_SEM_WAKE) X(UMTX_OP_NWAKE_PRIVATE) X(UMTX_OP_MUTEX_WAKE2)
679 X(UMTX_OP_SEM2_WAIT) X(UMTX_OP_SEM2_WAKE)
683 static struct xlat at_flags[] = {
684 X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW)
688 static struct xlat access_modes[] = {
689 X(R_OK) X(W_OK) X(X_OK) XEND
692 static struct xlat sysarch_ops[] = {
693 #if defined(__i386__) || defined(__amd64__)
694 X(I386_GET_LDT) X(I386_SET_LDT) X(I386_GET_IOPERM) X(I386_SET_IOPERM)
695 X(I386_VM86) X(I386_GET_FSBASE) X(I386_SET_FSBASE) X(I386_GET_GSBASE)
696 X(I386_SET_GSBASE) X(I386_GET_XFPUSTATE) X(AMD64_GET_FSBASE)
697 X(AMD64_SET_FSBASE) X(AMD64_GET_GSBASE) X(AMD64_SET_GSBASE)
698 X(AMD64_GET_XFPUSTATE)
703 static struct xlat linux_socketcall_ops[] = {
704 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
705 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
706 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
707 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
708 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
712 static struct xlat sigprocmask_ops[] = {
713 X(SIG_BLOCK) X(SIG_UNBLOCK) X(SIG_SETMASK)
718 #define X(a) { CLOUDABI_##a, #a },
720 static struct xlat cloudabi_advice[] = {
721 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
722 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
726 static struct xlat cloudabi_clockid[] = {
727 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
728 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
732 static struct xlat cloudabi_errno[] = {
733 X(E2BIG) X(EACCES) X(EADDRINUSE) X(EADDRNOTAVAIL)
734 X(EAFNOSUPPORT) X(EAGAIN) X(EALREADY) X(EBADF) X(EBADMSG)
735 X(EBUSY) X(ECANCELED) X(ECHILD) X(ECONNABORTED) X(ECONNREFUSED)
736 X(ECONNRESET) X(EDEADLK) X(EDESTADDRREQ) X(EDOM) X(EDQUOT)
737 X(EEXIST) X(EFAULT) X(EFBIG) X(EHOSTUNREACH) X(EIDRM) X(EILSEQ)
738 X(EINPROGRESS) X(EINTR) X(EINVAL) X(EIO) X(EISCONN) X(EISDIR)
739 X(ELOOP) X(EMFILE) X(EMLINK) X(EMSGSIZE) X(EMULTIHOP)
740 X(ENAMETOOLONG) X(ENETDOWN) X(ENETRESET) X(ENETUNREACH)
741 X(ENFILE) X(ENOBUFS) X(ENODEV) X(ENOENT) X(ENOEXEC) X(ENOLCK)
742 X(ENOLINK) X(ENOMEM) X(ENOMSG) X(ENOPROTOOPT) X(ENOSPC)
743 X(ENOSYS) X(ENOTCONN) X(ENOTDIR) X(ENOTEMPTY) X(ENOTRECOVERABLE)
744 X(ENOTSOCK) X(ENOTSUP) X(ENOTTY) X(ENXIO) X(EOVERFLOW)
745 X(EOWNERDEAD) X(EPERM) X(EPIPE) X(EPROTO) X(EPROTONOSUPPORT)
746 X(EPROTOTYPE) X(ERANGE) X(EROFS) X(ESPIPE) X(ESRCH) X(ESTALE)
747 X(ETIMEDOUT) X(ETXTBSY) X(EXDEV) X(ENOTCAPABLE)
751 static struct xlat cloudabi_fdflags[] = {
752 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
753 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
757 static struct xlat cloudabi_fdsflags[] = {
758 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
762 static struct xlat cloudabi_filetype[] = {
763 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
764 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
765 X(FILETYPE_FIFO) X(FILETYPE_POLL) X(FILETYPE_PROCESS)
766 X(FILETYPE_REGULAR_FILE) X(FILETYPE_SHARED_MEMORY)
767 X(FILETYPE_SOCKET_DGRAM) X(FILETYPE_SOCKET_SEQPACKET)
768 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
772 static struct xlat cloudabi_fsflags[] = {
773 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
774 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
778 static struct xlat cloudabi_mflags[] = {
779 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
783 static struct xlat cloudabi_mprot[] = {
784 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
788 static struct xlat cloudabi_msflags[] = {
789 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
793 static struct xlat cloudabi_oflags[] = {
794 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
798 static struct xlat cloudabi_sa_family[] = {
799 X(AF_UNSPEC) X(AF_INET) X(AF_INET6) X(AF_UNIX)
803 static struct xlat cloudabi_sdflags[] = {
804 X(SHUT_RD) X(SHUT_WR)
808 static struct xlat cloudabi_signal[] = {
809 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
810 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
811 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
812 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
813 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
817 static struct xlat cloudabi_ssflags[] = {
818 X(SOCKSTAT_CLEAR_ERROR)
822 static struct xlat cloudabi_ssstate[] = {
823 X(SOCKSTATE_ACCEPTCONN)
827 static struct xlat cloudabi_ulflags[] = {
832 static struct xlat cloudabi_whence[] = {
833 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
841 * Searches an xlat array for a value, and returns it if found. Otherwise
842 * return a string representation.
845 lookup(struct xlat *xlat, int val, int base)
849 for (; xlat->str != NULL; xlat++)
850 if (xlat->val == val)
854 sprintf(tmp, "0%o", val);
857 sprintf(tmp, "0x%x", val);
860 sprintf(tmp, "%u", val);
863 errx(1,"Unknown lookup base");
870 xlookup(struct xlat *xlat, int val)
873 return (lookup(xlat, val, 16));
877 * Searches an xlat array containing bitfield values. Remaining bits
878 * set after removing the known ones are printed at the end:
882 xlookup_bits(struct xlat *xlat, int val)
885 static char str[512];
889 for (; xlat->str != NULL; xlat++) {
890 if ((xlat->val & rem) == xlat->val) {
892 * Don't print the "all-bits-zero" string unless all
893 * bits are really zero.
895 if (xlat->val == 0 && val != 0)
897 len += sprintf(str + len, "%s|", xlat->str);
903 * If we have leftover bits or didn't match anything, print
907 len += sprintf(str + len, "0x%x", rem);
908 if (len && str[len - 1] == '|')
919 STAILQ_INIT(&syscalls);
920 for (sc = decoded_syscalls; sc->name != NULL; sc++)
921 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
924 * If/when the list gets big, it might be desirable to do it
925 * as a hash table or binary search.
928 get_syscall(const char *name, int nargs)
935 STAILQ_FOREACH(sc, &syscalls, entries)
936 if (strcmp(name, sc->name) == 0)
939 /* It is unknown. Add it into the list. */
941 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
945 sc = calloc(1, sizeof(struct syscall));
946 sc->name = strdup(name);
949 for (i = 0; i < nargs; i++) {
950 sc->args[i].offset = i;
951 /* Treat all unknown arguments as LongHex. */
952 sc->args[i].type = LongHex;
954 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
960 * Copy a fixed amount of bytes from the process.
963 get_struct(pid_t pid, void *offset, void *buf, int len)
965 struct ptrace_io_desc iorequest;
967 iorequest.piod_op = PIOD_READ_D;
968 iorequest.piod_offs = offset;
969 iorequest.piod_addr = buf;
970 iorequest.piod_len = len;
971 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
979 * Copy a string from the process. Note that it is
980 * expected to be a C string, but if max is set, it will
981 * only get that much.
984 get_string(pid_t pid, void *addr, int max)
986 struct ptrace_io_desc iorequest;
988 size_t offset, size, totalsize;
994 /* Read up to the end of the current page. */
995 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1000 buf = malloc(totalsize);
1004 iorequest.piod_op = PIOD_READ_D;
1005 iorequest.piod_offs = (char *)addr + offset;
1006 iorequest.piod_addr = buf + offset;
1007 iorequest.piod_len = size;
1008 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1012 if (memchr(buf + offset, '\0', size) != NULL)
1015 if (totalsize < MAXSIZE && max == 0) {
1016 size = MAXSIZE - totalsize;
1017 if (size > PAGE_SIZE)
1019 nbuf = realloc(buf, totalsize + size);
1021 buf[totalsize - 1] = '\0';
1027 buf[totalsize - 1] = '\0';
1036 static char tmp[sizeof(int) * 3 + 1];
1041 snprintf(tmp, sizeof(tmp), "%d", sig);
1048 print_kevent(FILE *fp, struct kevent *ke, int input)
1051 switch (ke->filter) {
1057 case EVFILT_PROCDESC:
1058 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1061 fputs(strsig2(ke->ident), fp);
1064 fprintf(fp, "%p", (void *)ke->ident);
1066 fprintf(fp, ",%s,%s,", xlookup(kevent_filters, ke->filter),
1067 xlookup_bits(kevent_flags, ke->flags));
1068 switch (ke->filter) {
1071 fputs(xlookup_bits(kevent_rdwr_fflags, ke->fflags), fp);
1074 fputs(xlookup_bits(kevent_vnode_fflags, ke->fflags), fp);
1077 case EVFILT_PROCDESC:
1078 fputs(xlookup_bits(kevent_proc_fflags, ke->fflags), fp);
1081 fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp);
1086 ctrl = ke->fflags & NOTE_FFCTRLMASK;
1087 data = ke->fflags & NOTE_FFLAGSMASK;
1089 fputs(xlookup(kevent_user_ffctrl, ctrl), fp);
1090 if (ke->fflags & NOTE_TRIGGER)
1091 fputs("|NOTE_TRIGGER", fp);
1093 fprintf(fp, "|%#x", data);
1095 fprintf(fp, "%#x", data);
1100 fprintf(fp, "%#x", ke->fflags);
1102 fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
1106 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1108 unsigned char *utrace_buffer;
1111 if (sysdecode_utrace(fp, utrace_addr, len)) {
1116 utrace_buffer = utrace_addr;
1117 fprintf(fp, "%zu:", len);
1119 fprintf(fp, " %02x", *utrace_buffer++);
1124 * Converts a syscall argument into a string. Said string is
1125 * allocated via malloc(), so needs to be free()'d. sc is
1126 * a pointer to the syscall description (see above); args is
1127 * an array of all of the system call arguments.
1130 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1131 struct trussinfo *trussinfo)
1138 fp = open_memstream(&tmp, &tmplen);
1139 pid = trussinfo->curthread->proc->pid;
1140 switch (sc->type & ARG_MASK) {
1142 fprintf(fp, "0x%x", (int)args[sc->offset]);
1145 fprintf(fp, "0%o", (int)args[sc->offset]);
1148 fprintf(fp, "%d", (int)args[sc->offset]);
1151 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1154 fprintf(fp, "0x%lx", args[sc->offset]);
1157 fprintf(fp, "%ld", args[sc->offset]);
1160 /* NULL-terminated string. */
1163 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1164 fprintf(fp, "\"%s\"", tmp2);
1170 * Binary block of data that might have printable characters.
1171 * XXX If type|OUT, assume that the length is the syscall's
1172 * return value. Otherwise, assume that the length of the block
1173 * is in the next syscall argument.
1175 int max_string = trussinfo->strsize;
1176 char tmp2[max_string + 1], *tmp3;
1183 len = args[sc->offset + 1];
1186 * Don't print more than max_string characters, to avoid word
1187 * wrap. If we have to truncate put some ... after the string.
1189 if (len > max_string) {
1193 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1195 tmp3 = malloc(len * 4 + 1);
1197 if (strvisx(tmp3, tmp2, len,
1198 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1203 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1207 fprintf(fp, "0x%lx", args[sc->offset]);
1217 char buf[PAGE_SIZE];
1224 * Only parse argv[] and environment arrays from exec calls
1227 if (((sc->type & ARG_MASK) == ExecArgs &&
1228 (trussinfo->flags & EXECVEARGS) == 0) ||
1229 ((sc->type & ARG_MASK) == ExecEnv &&
1230 (trussinfo->flags & EXECVEENVS) == 0)) {
1231 fprintf(fp, "0x%lx", args[sc->offset]);
1236 * Read a page of pointers at a time. Punt if the top-level
1237 * pointer is not aligned. Note that the first read is of
1240 addr = args[sc->offset];
1241 if (addr % sizeof(char *) != 0) {
1242 fprintf(fp, "0x%lx", args[sc->offset]);
1246 len = PAGE_SIZE - (addr & PAGE_MASK);
1247 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1248 fprintf(fp, "0x%lx", args[sc->offset]);
1255 while (u.strarray[i] != NULL) {
1256 string = get_string(pid, u.strarray[i], 0);
1257 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1262 if (i == len / sizeof(char *)) {
1265 if (get_struct(pid, (void *)addr, u.buf, len) ==
1267 fprintf(fp, ", <inval>");
1278 fprintf(fp, "%ld", args[sc->offset]);
1281 fprintf(fp, "0x%lx", args[sc->offset]);
1286 unsigned long long ll;
1288 #if _BYTE_ORDER == _LITTLE_ENDIAN
1289 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1292 ll = (unsigned long long)args[sc->offset] << 32 |
1293 args[sc->offset + 1];
1295 if ((sc->type & ARG_MASK) == Quad)
1296 fprintf(fp, "%lld", ll);
1298 fprintf(fp, "0x%llx", ll);
1303 fprintf(fp, "0x%lx", args[sc->offset]);
1308 if (retval[0] == -1)
1310 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1311 fprintf(fp, "\"%s\"", tmp2);
1319 cmd = args[sc->offset];
1320 temp = sysdecode_ioctlname(cmd);
1324 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1325 cmd, cmd & IOC_OUT ? "R" : "",
1326 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1327 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1328 cmd & 0xFF, IOCPARM_LEN(cmd));
1335 if (get_struct(pid, (void *)args[sc->offset], &ts,
1337 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1340 fprintf(fp, "0x%lx", args[sc->offset]);
1344 struct timespec ts[2];
1348 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1352 for (i = 0; i < nitems(ts); i++) {
1355 switch (ts[i].tv_nsec) {
1357 fprintf(fp, "UTIME_NOW");
1360 fprintf(fp, "UTIME_OMIT");
1363 fprintf(fp, "%jd.%09ld",
1364 (intmax_t)ts[i].tv_sec,
1371 fprintf(fp, "0x%lx", args[sc->offset]);
1377 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1379 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1382 fprintf(fp, "0x%lx", args[sc->offset]);
1386 struct timeval tv[2];
1388 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1390 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1391 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1392 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1394 fprintf(fp, "0x%lx", args[sc->offset]);
1398 struct itimerval itv;
1400 if (get_struct(pid, (void *)args[sc->offset], &itv,
1402 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1403 (intmax_t)itv.it_interval.tv_sec,
1404 itv.it_interval.tv_usec,
1405 (intmax_t)itv.it_value.tv_sec,
1406 itv.it_value.tv_usec);
1408 fprintf(fp, "0x%lx", args[sc->offset]);
1413 struct linux_socketcall_args largs;
1415 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1416 sizeof(largs)) != -1)
1417 fprintf(fp, "{ %s, 0x%lx }",
1418 lookup(linux_socketcall_ops, largs.what, 10),
1419 (long unsigned int)largs.args);
1421 fprintf(fp, "0x%lx", args[sc->offset]);
1426 * XXX: A Pollfd argument expects the /next/ syscall argument
1427 * to be the number of fds in the array. This matches the poll
1431 int numfds = args[sc->offset + 1];
1432 size_t bytes = sizeof(struct pollfd) * numfds;
1435 if ((pfd = malloc(bytes)) == NULL)
1436 err(1, "Cannot malloc %zu bytes for pollfd array",
1438 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1441 for (i = 0; i < numfds; i++) {
1442 fprintf(fp, " %d/%s", pfd[i].fd,
1443 xlookup_bits(poll_flags, pfd[i].events));
1447 fprintf(fp, "0x%lx", args[sc->offset]);
1454 * XXX: A Fd_set argument expects the /first/ syscall argument
1455 * to be the number of fds in the array. This matches the
1459 int numfds = args[0];
1460 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1463 if ((fds = malloc(bytes)) == NULL)
1464 err(1, "Cannot malloc %zu bytes for fd_set array",
1466 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1469 for (i = 0; i < numfds; i++) {
1470 if (FD_ISSET(i, fds))
1471 fprintf(fp, " %d", i);
1475 fprintf(fp, "0x%lx", args[sc->offset]);
1480 fputs(strsig2(args[sc->offset]), fp);
1487 sig = args[sc->offset];
1488 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1489 sizeof(ss)) == -1) {
1490 fprintf(fp, "0x%lx", args[sc->offset]);
1495 for (i = 1; i < sys_nsig; i++) {
1496 if (sigismember(&ss, i)) {
1497 fprintf(fp, "%s%s", !first ? "|" : "",
1508 fputs(xlookup(sigprocmask_ops, args[sc->offset]), fp);
1512 /* XXX: Output depends on the value of the previous argument. */
1513 switch (args[sc->offset - 1]) {
1515 fputs(xlookup_bits(fcntlfd_arg, args[sc->offset]), fp);
1518 fputs(xlookup_bits(fcntlfl_arg, args[sc->offset]), fp);
1525 fprintf(fp, "0x%lx", args[sc->offset]);
1531 fputs(xlookup_bits(open_flags, args[sc->offset]), fp);
1534 fputs(xlookup(fcntl_arg, args[sc->offset]), fp);
1537 fputs(xlookup_bits(mprot_flags, args[sc->offset]), fp);
1543 * MAP_ALIGNED can't be handled by xlookup_bits(), so
1544 * generate that string manually and prepend it to the
1545 * string from xlookup_bits(). Have to be careful to
1546 * avoid outputting MAP_ALIGNED|0 if MAP_ALIGNED is
1549 flags = args[sc->offset] & ~MAP_ALIGNMENT_MASK;
1550 align = args[sc->offset] & MAP_ALIGNMENT_MASK;
1552 if (align == MAP_ALIGNED_SUPER)
1553 fputs("MAP_ALIGNED_SUPER", fp);
1555 fprintf(fp, "MAP_ALIGNED(%d)",
1556 align >> MAP_ALIGNMENT_SHIFT);
1561 fputs(xlookup_bits(mmap_flags, flags), fp);
1565 fputs(xlookup(whence_arg, args[sc->offset]), fp);
1568 fputs(xlookup(sockdomain_arg, args[sc->offset]), fp);
1573 flags = args[sc->offset] & (SOCK_CLOEXEC | SOCK_NONBLOCK);
1574 type = args[sc->offset] & ~flags;
1575 fputs(xlookup(socktype_arg, type), fp);
1576 if (flags & SOCK_CLOEXEC)
1577 fprintf(fp, "|SOCK_CLOEXEC");
1578 if (flags & SOCK_NONBLOCK)
1579 fprintf(fp, "|SOCK_NONBLOCK");
1583 fputs(xlookup(shutdown_arg, args[sc->offset]), fp);
1586 fputs(xlookup(resource_arg, args[sc->offset]), fp);
1589 fputs(xlookup(pathconf_arg, args[sc->offset]), fp);
1592 fputs(xlookup_bits(rfork_flags, args[sc->offset]), fp);
1596 struct sockaddr_in *lsin;
1597 struct sockaddr_in6 *lsin6;
1598 struct sockaddr_un *sun;
1599 struct sockaddr *sa;
1603 if (args[sc->offset] == 0) {
1609 * Extract the address length from the next argument. If
1610 * this is an output sockaddr (OUT is set), then the
1611 * next argument is a pointer to a socklen_t. Otherwise
1612 * the next argument contains a socklen_t by value.
1614 if (sc->type & OUT) {
1615 if (get_struct(pid, (void *)args[sc->offset + 1],
1616 &len, sizeof(len)) == -1) {
1617 fprintf(fp, "0x%lx", args[sc->offset]);
1621 len = args[sc->offset + 1];
1623 /* If the length is too small, just bail. */
1624 if (len < sizeof(*sa)) {
1625 fprintf(fp, "0x%lx", args[sc->offset]);
1629 sa = calloc(1, len);
1630 if (get_struct(pid, (void *)args[sc->offset], sa, len) == -1) {
1632 fprintf(fp, "0x%lx", args[sc->offset]);
1636 switch (sa->sa_family) {
1638 if (len < sizeof(*lsin))
1639 goto sockaddr_short;
1640 lsin = (struct sockaddr_in *)(void *)sa;
1641 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1642 fprintf(fp, "{ AF_INET %s:%d }", addr,
1643 htons(lsin->sin_port));
1646 if (len < sizeof(*lsin6))
1647 goto sockaddr_short;
1648 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1649 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1651 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1652 htons(lsin6->sin6_port));
1655 sun = (struct sockaddr_un *)sa;
1656 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1657 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1663 "{ sa_len = %d, sa_family = %d, sa_data = {",
1664 (int)sa->sa_len, (int)sa->sa_family);
1665 for (q = (u_char *)sa->sa_data;
1666 q < (u_char *)sa + len; q++)
1667 fprintf(fp, "%s 0x%02x",
1668 q == (u_char *)sa->sa_data ? "" : ",",
1676 struct sigaction sa;
1678 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
1681 if (sa.sa_handler == SIG_DFL)
1682 fputs("SIG_DFL", fp);
1683 else if (sa.sa_handler == SIG_IGN)
1684 fputs("SIG_IGN", fp);
1686 fprintf(fp, "%p", sa.sa_handler);
1687 fprintf(fp, " %s ss_t }",
1688 xlookup_bits(sigaction_flags, sa.sa_flags));
1690 fprintf(fp, "0x%lx", args[sc->offset]);
1695 * XXX XXX: The size of the array is determined by either the
1696 * next syscall argument, or by the syscall return value,
1697 * depending on which argument number we are. This matches the
1698 * kevent syscall, but luckily that's the only syscall that uses
1706 if (sc->offset == 1)
1707 numevents = args[sc->offset+1];
1708 else if (sc->offset == 3 && retval[0] != -1)
1709 numevents = retval[0];
1711 if (numevents >= 0) {
1712 bytes = sizeof(struct kevent) * numevents;
1713 if ((ke = malloc(bytes)) == NULL)
1715 "Cannot malloc %zu bytes for kevent array",
1719 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
1722 for (i = 0; i < numevents; i++) {
1724 print_kevent(fp, &ke[i], sc->offset == 1);
1728 fprintf(fp, "0x%lx", args[sc->offset]);
1736 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
1740 strmode(st.st_mode, mode);
1742 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
1743 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
1744 (long)st.st_blksize);
1746 fprintf(fp, "0x%lx", args[sc->offset]);
1754 if (get_struct(pid, (void *)args[sc->offset], &buf,
1755 sizeof(buf)) != -1) {
1758 bzero(fsid, sizeof(fsid));
1759 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
1760 for (i = 0; i < sizeof(buf.f_fsid); i++)
1761 snprintf(&fsid[i*2],
1762 sizeof(fsid) - (i*2), "%02x",
1763 ((u_char *)&buf.f_fsid)[i]);
1766 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
1767 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
1768 buf.f_mntfromname, fsid);
1770 fprintf(fp, "0x%lx", args[sc->offset]);
1777 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
1780 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
1781 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
1782 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
1783 ru.ru_inblock, ru.ru_oublock);
1785 fprintf(fp, "0x%lx", args[sc->offset]);
1791 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
1793 fprintf(fp, "{ cur=%ju,max=%ju }",
1794 rl.rlim_cur, rl.rlim_max);
1796 fprintf(fp, "0x%lx", args[sc->offset]);
1802 if (get_struct(pid, (void *)args[sc->offset], &status,
1803 sizeof(status)) != -1) {
1805 if (WIFCONTINUED(status))
1806 fputs("CONTINUED", fp);
1807 else if (WIFEXITED(status))
1808 fprintf(fp, "EXITED,val=%d",
1809 WEXITSTATUS(status));
1810 else if (WIFSIGNALED(status))
1811 fprintf(fp, "SIGNALED,sig=%s%s",
1812 strsig2(WTERMSIG(status)),
1813 WCOREDUMP(status) ? ",cored" : "");
1815 fprintf(fp, "STOPPED,sig=%s",
1816 strsig2(WTERMSIG(status)));
1819 fprintf(fp, "0x%lx", args[sc->offset]);
1823 fputs(xlookup_bits(wait_options, args[sc->offset]), fp);
1826 fputs(xlookup(idtype_arg, args[sc->offset]), fp);
1829 fputs(xlookup(procctl_arg, args[sc->offset]), fp);
1832 fputs(xlookup(umtx_ops, args[sc->offset]), fp);
1835 if ((int)args[sc->offset] == AT_FDCWD)
1836 fputs("AT_FDCWD", fp);
1838 fprintf(fp, "%d", (int)args[sc->offset]);
1841 fputs(xlookup_bits(at_flags, args[sc->offset]), fp);
1844 if (args[sc->offset] == F_OK)
1847 fputs(xlookup_bits(access_modes, args[sc->offset]), fp);
1850 fputs(xlookup(sysarch_ops, args[sc->offset]), fp);
1854 * The pipe() system call in the kernel returns its
1855 * two file descriptors via return values. However,
1856 * the interface exposed by libc is that pipe()
1857 * accepts a pointer to an array of descriptors.
1858 * Format the output to match the libc API by printing
1859 * the returned file descriptors as a fake argument.
1861 * Overwrite the first retval to signal a successful
1864 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
1871 len = args[sc->offset + 1];
1872 utrace_addr = calloc(1, len);
1873 if (get_struct(pid, (void *)args[sc->offset],
1874 (void *)utrace_addr, len) != -1)
1875 print_utrace(fp, utrace_addr, len);
1877 fprintf(fp, "0x%lx", args[sc->offset]);
1882 int descriptors[16];
1883 unsigned long i, ndescriptors;
1886 ndescriptors = args[sc->offset + 1];
1888 if (ndescriptors > nitems(descriptors)) {
1889 ndescriptors = nitems(descriptors);
1892 if (get_struct(pid, (void *)args[sc->offset],
1893 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
1895 for (i = 0; i < ndescriptors; i++)
1896 fprintf(fp, i == 0 ? " %d" : ", %d",
1898 fprintf(fp, truncated ? ", ... }" : " }");
1900 fprintf(fp, "0x%lx", args[sc->offset]);
1904 case CloudABIAdvice:
1905 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
1907 case CloudABIClockID:
1908 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
1910 case ClouduABIFDSFlags:
1911 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
1913 case CloudABIFDStat: {
1914 cloudabi_fdstat_t fds;
1915 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
1917 fprintf(fp, "{ %s, ",
1918 xlookup(cloudabi_filetype, fds.fs_filetype));
1919 fprintf(fp, "%s, ... }",
1920 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
1922 fprintf(fp, "0x%lx", args[sc->offset]);
1925 case CloudABIFileStat: {
1926 cloudabi_filestat_t fsb;
1927 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
1929 fprintf(fp, "{ %s, %lu }",
1930 xlookup(cloudabi_filetype, fsb.st_filetype),
1933 fprintf(fp, "0x%lx", args[sc->offset]);
1936 case CloudABIFileType:
1937 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
1939 case CloudABIFSFlags:
1940 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
1942 case CloudABILookup:
1943 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
1944 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
1945 (int)args[sc->offset]);
1947 fprintf(fp, "%d", (int)args[sc->offset]);
1949 case CloudABIMFlags:
1950 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
1953 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
1955 case CloudABIMSFlags:
1956 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
1958 case CloudABIOFlags:
1959 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
1961 case CloudABISDFlags:
1962 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
1964 case CloudABISignal:
1965 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
1967 case CloudABISockStat: {
1968 cloudabi_sockstat_t ss;
1969 if (get_struct(pid, (void *)args[sc->offset], &ss, sizeof(ss))
1971 fprintf(fp, "{ %s, ", xlookup(
1972 cloudabi_sa_family, ss.ss_sockname.sa_family));
1973 fprintf(fp, "%s, ", xlookup(
1974 cloudabi_sa_family, ss.ss_peername.sa_family));
1975 fprintf(fp, "%s, ", xlookup(
1976 cloudabi_errno, ss.ss_error));
1977 fprintf(fp, "%s }", xlookup_bits(
1978 cloudabi_ssstate, ss.ss_state));
1980 fprintf(fp, "0x%lx", args[sc->offset]);
1983 case CloudABISSFlags:
1984 fputs(xlookup_bits(cloudabi_ssflags, args[sc->offset]), fp);
1986 case CloudABITimestamp:
1987 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
1988 args[sc->offset] % 1000000000);
1990 case CloudABIULFlags:
1991 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
1993 case CloudABIWhence:
1994 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
1998 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2005 * Print (to outfile) the system call and its arguments.
2008 print_syscall(struct trussinfo *trussinfo)
2010 struct threadinfo *t;
2015 t = trussinfo->curthread;
2018 nargs = t->cs.nargs;
2019 s_args = t->cs.s_args;
2021 len = print_line_prefix(trussinfo);
2022 len += fprintf(trussinfo->outfile, "%s(", name);
2024 for (i = 0; i < nargs; i++) {
2025 if (s_args[i] != NULL)
2026 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2028 len += fprintf(trussinfo->outfile,
2029 "<missing argument>");
2030 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2033 len += fprintf(trussinfo->outfile, ")");
2034 for (i = 0; i < 6 - (len / 8); i++)
2035 fprintf(trussinfo->outfile, "\t");
2039 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2041 struct timespec timediff;
2042 struct threadinfo *t;
2046 t = trussinfo->curthread;
2048 if (trussinfo->flags & COUNTONLY) {
2049 timespecsubt(&t->after, &t->before, &timediff);
2050 timespecadd(&sc->time, &timediff, &sc->time);
2057 print_syscall(trussinfo);
2058 fflush(trussinfo->outfile);
2060 if (retval == NULL) {
2062 * This system call resulted in the current thread's exit,
2063 * so there is no return value or error to display.
2065 fprintf(trussinfo->outfile, "\n");
2070 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2072 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2073 error == INT_MAX ? "Unknown error" : strerror(error));
2076 else if (sc->ret_type == 2) {
2079 #if _BYTE_ORDER == _LITTLE_ENDIAN
2080 off = (off_t)retval[1] << 32 | retval[0];
2082 off = (off_t)retval[0] << 32 | retval[1];
2084 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2089 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2094 print_summary(struct trussinfo *trussinfo)
2096 struct timespec total = {0, 0};
2100 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2101 "syscall", "seconds", "calls", "errors");
2103 STAILQ_FOREACH(sc, &syscalls, entries)
2105 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2106 sc->name, (intmax_t)sc->time.tv_sec,
2107 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2108 timespecadd(&total, &sc->time, &total);
2109 ncall += sc->ncalls;
2110 nerror += sc->nerror;
2112 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2113 "", "-------------", "-------", "-------");
2114 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2115 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);