2 * SPDX-License-Identifier: BSD-4-Clause
4 * Copyright 1997 Sean Eric Fagan
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Sean Eric Fagan
17 * 4. Neither the name of the author may be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * This file has routines used to print out system calls and their
42 #include <sys/capsicum.h>
43 #include <sys/types.h>
44 #define _WANT_FREEBSD11_KEVENT
45 #include <sys/event.h>
46 #include <sys/ioccom.h>
48 #include <sys/mount.h>
49 #include <sys/ptrace.h>
50 #include <sys/resource.h>
51 #include <sys/socket.h>
52 #define _WANT_FREEBSD11_STAT
54 #include <sys/sysctl.h>
58 #include <netinet/in.h>
59 #include <netinet/sctp.h>
60 #include <arpa/inet.h>
65 #define _WANT_KERNEL_ERRNO
75 #include <sysdecode.h>
79 #include <contrib/cloudabi/cloudabi_types_common.h>
86 * This should probably be in its own file, sorted alphabetically.
88 static struct syscall decoded_syscalls[] = {
90 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
91 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
92 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
93 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
94 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
95 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
96 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
97 .args = { { Int, 0 }, { Acltype, 1 } } },
98 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
99 .args = { { Name, 0 }, { Acltype, 1 } } },
100 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
101 .args = { { Name, 0 }, { Acltype, 1 } } },
102 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
103 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
104 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
105 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
106 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
107 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
108 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
109 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
110 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
111 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
112 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
113 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
114 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
115 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
116 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
117 .args = { { Name | OUT, 0 }, { Int, 1 } } },
118 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
119 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
121 { .name = "accept", .ret_type = 1, .nargs = 3,
122 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
123 { .name = "access", .ret_type = 1, .nargs = 2,
124 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
125 { .name = "bind", .ret_type = 1, .nargs = 3,
126 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
127 { .name = "bindat", .ret_type = 1, .nargs = 4,
128 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
130 { .name = "break", .ret_type = 1, .nargs = 1,
131 .args = { { Ptr, 0 } } },
132 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
133 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
134 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
135 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
136 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
137 .args = { { PUInt | OUT, 0 } } },
138 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
139 .args = { { Int, 0 }, { CapRights, 1 } } },
140 { .name = "chdir", .ret_type = 1, .nargs = 1,
141 .args = { { Name, 0 } } },
142 { .name = "chflags", .ret_type = 1, .nargs = 2,
143 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
144 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
145 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
147 { .name = "chmod", .ret_type = 1, .nargs = 2,
148 .args = { { Name, 0 }, { Octal, 1 } } },
149 { .name = "chown", .ret_type = 1, .nargs = 3,
150 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
151 { .name = "chroot", .ret_type = 1, .nargs = 1,
152 .args = { { Name, 0 } } },
153 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
154 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
155 { .name = "close", .ret_type = 1, .nargs = 1,
156 .args = { { Int, 0 } } },
157 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
158 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
159 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
160 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
162 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
163 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
164 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
165 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
166 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
167 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
168 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
169 { .name = "connect", .ret_type = 1, .nargs = 3,
170 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
171 { .name = "connectat", .ret_type = 1, .nargs = 4,
172 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
174 { .name = "dup", .ret_type = 1, .nargs = 1,
175 .args = { { Int, 0 } } },
176 { .name = "dup2", .ret_type = 1, .nargs = 2,
177 .args = { { Int, 0 }, { Int, 1 } } },
178 { .name = "eaccess", .ret_type = 1, .nargs = 2,
179 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
180 { .name = "execve", .ret_type = 1, .nargs = 3,
181 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
182 { ExecEnv | IN, 2 } } },
183 { .name = "exit", .ret_type = 0, .nargs = 1,
184 .args = { { Hex, 0 } } },
185 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
186 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
187 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
188 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
189 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
190 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
191 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
192 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
193 { BinString | OUT, 3 }, { Sizet, 4 } } },
194 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
195 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
196 { BinString | OUT, 3 }, { Sizet, 4 } } },
197 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
198 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
199 { BinString | OUT, 3 }, { Sizet, 4 } } },
200 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
201 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
203 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
204 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
206 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
207 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
209 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
210 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
211 { BinString | IN, 3 }, { Sizet, 4 } } },
212 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
213 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
214 { BinString | IN, 3 }, { Sizet, 4 } } },
215 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
216 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
217 { BinString | IN, 3 }, { Sizet, 4 } } },
218 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
219 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
220 { Extattrnamespace, 3 }, { Name, 4 } } },
221 { .name = "faccessat", .ret_type = 1, .nargs = 4,
222 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
224 { .name = "fchflags", .ret_type = 1, .nargs = 2,
225 .args = { { Int, 0 }, { FileFlags, 1 } } },
226 { .name = "fchmod", .ret_type = 1, .nargs = 2,
227 .args = { { Int, 0 }, { Octal, 1 } } },
228 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
229 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
230 { .name = "fchown", .ret_type = 1, .nargs = 3,
231 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
232 { .name = "fchownat", .ret_type = 1, .nargs = 5,
233 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
235 { .name = "fcntl", .ret_type = 1, .nargs = 3,
236 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
237 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
238 .args = { { Int, 0 } } },
239 { .name = "flock", .ret_type = 1, .nargs = 2,
240 .args = { { Int, 0 }, { Flockop, 1 } } },
241 { .name = "fstat", .ret_type = 1, .nargs = 2,
242 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
243 { .name = "fstatat", .ret_type = 1, .nargs = 4,
244 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
246 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
247 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
248 { .name = "fsync", .ret_type = 1, .nargs = 1,
249 .args = { { Int, 0 } } },
250 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
251 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
252 { .name = "futimens", .ret_type = 1, .nargs = 2,
253 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
254 { .name = "futimes", .ret_type = 1, .nargs = 2,
255 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
256 { .name = "futimesat", .ret_type = 1, .nargs = 3,
257 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
258 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
259 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
260 { PQuadHex | OUT, 3 } } },
261 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
262 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
263 { .name = "getitimer", .ret_type = 1, .nargs = 2,
264 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
265 { .name = "getpeername", .ret_type = 1, .nargs = 3,
266 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
267 { .name = "getpgid", .ret_type = 1, .nargs = 1,
268 .args = { { Int, 0 } } },
269 { .name = "getpriority", .ret_type = 1, .nargs = 2,
270 .args = { { Priowhich, 0 }, { Int, 1 } } },
271 { .name = "getrandom", .ret_type = 1, .nargs = 3,
272 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
273 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
274 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
275 { .name = "getrusage", .ret_type = 1, .nargs = 2,
276 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
277 { .name = "getsid", .ret_type = 1, .nargs = 1,
278 .args = { { Int, 0 } } },
279 { .name = "getsockname", .ret_type = 1, .nargs = 3,
280 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
281 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
282 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
283 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
284 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
285 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
286 { .name = "ioctl", .ret_type = 1, .nargs = 3,
287 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
288 { .name = "kevent", .ret_type = 1, .nargs = 6,
289 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
290 { Int, 4 }, { Timespec, 5 } } },
291 { .name = "kill", .ret_type = 1, .nargs = 2,
292 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
293 { .name = "kldfind", .ret_type = 1, .nargs = 1,
294 .args = { { Name | IN, 0 } } },
295 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
296 .args = { { Int, 0 } } },
297 { .name = "kldload", .ret_type = 1, .nargs = 1,
298 .args = { { Name | IN, 0 } } },
299 { .name = "kldnext", .ret_type = 1, .nargs = 1,
300 .args = { { Int, 0 } } },
301 { .name = "kldstat", .ret_type = 1, .nargs = 2,
302 .args = { { Int, 0 }, { Ptr, 1 } } },
303 { .name = "kldsym", .ret_type = 1, .nargs = 3,
304 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
305 { .name = "kldunload", .ret_type = 1, .nargs = 1,
306 .args = { { Int, 0 } } },
307 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
308 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
309 { .name = "kse_release", .ret_type = 0, .nargs = 1,
310 .args = { { Timespec, 0 } } },
311 { .name = "lchflags", .ret_type = 1, .nargs = 2,
312 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
313 { .name = "lchmod", .ret_type = 1, .nargs = 2,
314 .args = { { Name, 0 }, { Octal, 1 } } },
315 { .name = "lchown", .ret_type = 1, .nargs = 3,
316 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
317 { .name = "link", .ret_type = 1, .nargs = 2,
318 .args = { { Name, 0 }, { Name, 1 } } },
319 { .name = "linkat", .ret_type = 1, .nargs = 5,
320 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
322 { .name = "listen", .ret_type = 1, .nargs = 2,
323 .args = { { Int, 0 }, { Int, 1 } } },
324 { .name = "lseek", .ret_type = 2, .nargs = 3,
325 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
326 { .name = "lstat", .ret_type = 1, .nargs = 2,
327 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
328 { .name = "lutimes", .ret_type = 1, .nargs = 2,
329 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
330 { .name = "madvise", .ret_type = 1, .nargs = 3,
331 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
332 { .name = "minherit", .ret_type = 1, .nargs = 3,
333 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
334 { .name = "mkdir", .ret_type = 1, .nargs = 2,
335 .args = { { Name, 0 }, { Octal, 1 } } },
336 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
337 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
338 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
339 .args = { { Name, 0 }, { Octal, 1 } } },
340 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
341 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
342 { .name = "mknod", .ret_type = 1, .nargs = 3,
343 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
344 { .name = "mknodat", .ret_type = 1, .nargs = 4,
345 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
346 { .name = "mlock", .ret_type = 1, .nargs = 2,
347 .args = { { Ptr, 0 }, { Sizet, 1 } } },
348 { .name = "mlockall", .ret_type = 1, .nargs = 1,
349 .args = { { Mlockall, 0 } } },
350 { .name = "mmap", .ret_type = 1, .nargs = 6,
351 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
352 { Int, 4 }, { QuadHex, 5 } } },
353 { .name = "modfind", .ret_type = 1, .nargs = 1,
354 .args = { { Name | IN, 0 } } },
355 { .name = "mount", .ret_type = 1, .nargs = 4,
356 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
357 { .name = "mprotect", .ret_type = 1, .nargs = 3,
358 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
359 { .name = "msync", .ret_type = 1, .nargs = 3,
360 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
361 { .name = "munlock", .ret_type = 1, .nargs = 2,
362 .args = { { Ptr, 0 }, { Sizet, 1 } } },
363 { .name = "munmap", .ret_type = 1, .nargs = 2,
364 .args = { { Ptr, 0 }, { Sizet, 1 } } },
365 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
366 .args = { { Timespec, 0 } } },
367 { .name = "nmount", .ret_type = 1, .nargs = 3,
368 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
369 { .name = "open", .ret_type = 1, .nargs = 3,
370 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
371 { .name = "openat", .ret_type = 1, .nargs = 4,
372 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
374 { .name = "pathconf", .ret_type = 1, .nargs = 2,
375 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
376 { .name = "pipe", .ret_type = 1, .nargs = 1,
377 .args = { { PipeFds | OUT, 0 } } },
378 { .name = "pipe2", .ret_type = 1, .nargs = 2,
379 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
380 { .name = "poll", .ret_type = 1, .nargs = 3,
381 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
382 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
383 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
385 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
386 .args = { { Open, 0 } } },
387 { .name = "pread", .ret_type = 1, .nargs = 4,
388 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
390 { .name = "procctl", .ret_type = 1, .nargs = 4,
391 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
392 { .name = "ptrace", .ret_type = 1, .nargs = 4,
393 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
394 { .name = "pwrite", .ret_type = 1, .nargs = 4,
395 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
397 { .name = "quotactl", .ret_type = 1, .nargs = 4,
398 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
399 { .name = "read", .ret_type = 1, .nargs = 3,
400 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
401 { .name = "readlink", .ret_type = 1, .nargs = 3,
402 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
403 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
404 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
406 { .name = "readv", .ret_type = 1, .nargs = 3,
407 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
408 { .name = "reboot", .ret_type = 1, .nargs = 1,
409 .args = { { Reboothowto, 0 } } },
410 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
411 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
412 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
413 { Ptr | OUT, 5 } } },
414 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
415 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
416 { .name = "rename", .ret_type = 1, .nargs = 2,
417 .args = { { Name, 0 }, { Name, 1 } } },
418 { .name = "renameat", .ret_type = 1, .nargs = 4,
419 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
420 { .name = "rfork", .ret_type = 1, .nargs = 1,
421 .args = { { Rforkflags, 0 } } },
422 { .name = "rmdir", .ret_type = 1, .nargs = 1,
423 .args = { { Name, 0 } } },
424 { .name = "rtprio", .ret_type = 1, .nargs = 3,
425 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
426 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
427 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
428 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
429 .args = { { Schedpolicy, 0 } } },
430 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
431 .args = { { Schedpolicy, 0 } } },
432 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
433 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
434 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
435 .args = { { Int, 0 } } },
436 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
437 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
438 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
439 .args = { { Int, 0 }, { Schedparam, 1 } } },
440 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
441 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
442 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
443 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
444 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
445 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
446 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
447 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
448 { Sockaddr | IN, 3 }, { Socklent, 4 },
449 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
450 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
451 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
452 { Sockaddr | IN, 3 }, { Socklent, 4 },
453 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
454 { .name = "select", .ret_type = 1, .nargs = 5,
455 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
457 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
458 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
459 { .name = "sendto", .ret_type = 1, .nargs = 6,
460 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
461 { Msgflags, 3 }, { Sockaddr | IN, 4 },
462 { Socklent | IN, 5 } } },
463 { .name = "setitimer", .ret_type = 1, .nargs = 3,
464 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
465 { .name = "setpriority", .ret_type = 1, .nargs = 3,
466 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
467 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
468 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
469 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
470 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
471 { Ptr | IN, 3 }, { Socklent, 4 } } },
472 { .name = "shm_open", .ret_type = 1, .nargs = 3,
473 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
474 { .name = "shm_rename", .ret_type = 1, .nargs = 3,
475 .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } },
476 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
477 .args = { { Name | IN, 0 } } },
478 { .name = "shutdown", .ret_type = 1, .nargs = 2,
479 .args = { { Int, 0 }, { Shutdown, 1 } } },
480 { .name = "sigaction", .ret_type = 1, .nargs = 3,
481 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
482 { Sigaction | OUT, 2 } } },
483 { .name = "sigpending", .ret_type = 1, .nargs = 1,
484 .args = { { Sigset | OUT, 0 } } },
485 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
486 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
487 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
488 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
489 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
490 .args = { { Ptr, 0 } } },
491 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
492 .args = { { Sigset | IN, 0 } } },
493 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
494 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
495 { Timespec | IN, 2 } } },
496 { .name = "sigwait", .ret_type = 1, .nargs = 2,
497 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
498 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
499 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
500 { .name = "socket", .ret_type = 1, .nargs = 3,
501 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
502 { .name = "stat", .ret_type = 1, .nargs = 2,
503 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
504 { .name = "statfs", .ret_type = 1, .nargs = 2,
505 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
506 { .name = "symlink", .ret_type = 1, .nargs = 2,
507 .args = { { Name, 0 }, { Name, 1 } } },
508 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
509 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
510 { .name = "sysarch", .ret_type = 1, .nargs = 2,
511 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
512 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
513 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
514 { Ptr, 4 }, { Sizet, 5 } } },
515 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
516 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
517 { Ptr, 4}, { Sizet, 5 } } },
518 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
519 .args = { { Long, 0 }, { Signal, 1 } } },
520 { .name = "thr_self", .ret_type = 1, .nargs = 1,
521 .args = { { Ptr, 0 } } },
522 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
523 .args = { { Long, 0 }, { Name, 1 } } },
524 { .name = "truncate", .ret_type = 1, .nargs = 2,
525 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
528 { .name = "umount", .ret_type = 1, .nargs = 2,
529 .args = { { Name, 0 }, { Int, 2 } } },
531 { .name = "unlink", .ret_type = 1, .nargs = 1,
532 .args = { { Name, 0 } } },
533 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
534 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
535 { .name = "unmount", .ret_type = 1, .nargs = 2,
536 .args = { { Name, 0 }, { Mountflags, 1 } } },
537 { .name = "utimensat", .ret_type = 1, .nargs = 4,
538 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
540 { .name = "utimes", .ret_type = 1, .nargs = 2,
541 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
542 { .name = "utrace", .ret_type = 1, .nargs = 1,
543 .args = { { Utrace, 0 } } },
544 { .name = "wait4", .ret_type = 1, .nargs = 4,
545 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
546 { Rusage | OUT, 3 } } },
547 { .name = "wait6", .ret_type = 1, .nargs = 6,
548 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
549 { Waitoptions, 3 }, { Rusage | OUT, 4 },
550 { Siginfo | OUT, 5 } } },
551 { .name = "write", .ret_type = 1, .nargs = 3,
552 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
553 { .name = "writev", .ret_type = 1, .nargs = 3,
554 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
557 { .name = "linux_access", .ret_type = 1, .nargs = 2,
558 .args = { { Name, 0 }, { Accessmode, 1 } } },
559 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
560 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
561 { ExecEnv | IN, 2 } } },
562 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
563 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
564 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
565 .args = { { Name | IN, 0 }, { Int, 1 } } },
566 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
567 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
568 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
569 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
570 { .name = "linux_open", .ret_type = 1, .nargs = 3,
571 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
572 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
573 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
574 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
575 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
576 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
577 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
579 /* CloudABI system calls. */
580 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
581 .args = { { CloudABIClockID, 0 } } },
582 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
583 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
584 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
585 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
586 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
587 .args = { { Int, 0 } } },
588 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
589 .args = { { CloudABIFileType, 0 } } },
590 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
591 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
592 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
593 .args = { { Int, 0 } } },
594 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
595 .args = { { Int, 0 } } },
596 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
597 .args = { { Int, 0 }, { Int, 1 } } },
598 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
599 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
600 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
601 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
602 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
603 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
604 { CloudABIFDSFlags, 2 } } },
605 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
606 .args = { { Int, 0 } } },
607 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
608 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
609 { CloudABIAdvice, 3 } } },
610 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
611 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
612 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
613 .args = { { Int, 0 }, { BinString | IN, 1 },
614 { CloudABIFileType, 3 } } },
615 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
616 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
617 { Int, 3 }, { BinString | IN, 4 } } },
618 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
619 .args = { { Int, 0 }, { BinString | IN, 1 },
620 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
621 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
622 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
624 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
625 .args = { { Int, 0 }, { BinString | IN, 1 },
626 { BinString | OUT, 3 }, { Int, 4 } } },
627 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
628 .args = { { Int, 0 }, { BinString | IN, 1 },
629 { Int, 3 }, { BinString | IN, 4 } } },
630 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
631 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
632 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
633 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
634 { CloudABIFSFlags, 2 } } },
635 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
636 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
637 { CloudABIFileStat | OUT, 3 } } },
638 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
639 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
640 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
641 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
642 .args = { { BinString | IN, 0 },
643 { Int, 2 }, { BinString | IN, 3 } } },
644 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
645 .args = { { Int, 0 }, { BinString | IN, 1 },
646 { CloudABIULFlags, 3 } } },
647 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
648 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
649 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
650 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
651 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
652 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
653 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
654 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
655 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
656 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
657 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
658 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
659 .args = { { Ptr, 0 }, { Int, 1 } } },
660 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
661 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
662 { IntArray, 3 }, { Int, 4 } } },
663 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
664 .args = { { Int, 0 } } },
665 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
666 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
667 .args = { { CloudABISignal, 0 } } },
668 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
669 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
670 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
671 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
672 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
673 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
674 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
678 static STAILQ_HEAD(, syscall) syscalls;
680 /* Xlat idea taken from strace */
686 #define X(a) { a, #a },
687 #define XEND { 0, NULL }
689 static struct xlat poll_flags[] = {
690 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
691 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
692 X(POLLWRBAND) X(POLLINIGNEOF) XEND
695 static struct xlat sigaction_flags[] = {
696 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
697 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
700 static struct xlat linux_socketcall_ops[] = {
701 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
702 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
703 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
704 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
705 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
710 #define X(a) { CLOUDABI_##a, #a },
712 static struct xlat cloudabi_advice[] = {
713 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
714 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
718 static struct xlat cloudabi_clockid[] = {
719 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
720 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
724 static struct xlat cloudabi_fdflags[] = {
725 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
726 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
730 static struct xlat cloudabi_fdsflags[] = {
731 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
735 static struct xlat cloudabi_filetype[] = {
736 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
737 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
738 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
739 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
740 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
744 static struct xlat cloudabi_fsflags[] = {
745 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
746 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
750 static struct xlat cloudabi_mflags[] = {
751 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
755 static struct xlat cloudabi_mprot[] = {
756 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
760 static struct xlat cloudabi_msflags[] = {
761 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
765 static struct xlat cloudabi_oflags[] = {
766 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
770 static struct xlat cloudabi_sdflags[] = {
771 X(SHUT_RD) X(SHUT_WR)
775 static struct xlat cloudabi_signal[] = {
776 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
777 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
778 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
779 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
780 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
784 static struct xlat cloudabi_ulflags[] = {
789 static struct xlat cloudabi_whence[] = {
790 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
798 * Searches an xlat array for a value, and returns it if found. Otherwise
799 * return a string representation.
802 lookup(struct xlat *xlat, int val, int base)
806 for (; xlat->str != NULL; xlat++)
807 if (xlat->val == val)
811 sprintf(tmp, "0%o", val);
814 sprintf(tmp, "0x%x", val);
817 sprintf(tmp, "%u", val);
820 errx(1,"Unknown lookup base");
827 xlookup(struct xlat *xlat, int val)
830 return (lookup(xlat, val, 16));
834 * Searches an xlat array containing bitfield values. Remaining bits
835 * set after removing the known ones are printed at the end:
839 xlookup_bits(struct xlat *xlat, int val)
842 static char str[512];
846 for (; xlat->str != NULL; xlat++) {
847 if ((xlat->val & rem) == xlat->val) {
849 * Don't print the "all-bits-zero" string unless all
850 * bits are really zero.
852 if (xlat->val == 0 && val != 0)
854 len += sprintf(str + len, "%s|", xlat->str);
860 * If we have leftover bits or didn't match anything, print
864 len += sprintf(str + len, "0x%x", rem);
865 if (len && str[len - 1] == '|')
872 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
876 str = decoder(value);
880 fprintf(fp, "%d", value);
884 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
888 if (!decoder(fp, value, &rem))
889 fprintf(fp, "0x%x", rem);
891 fprintf(fp, "|0x%x", rem);
895 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
900 if (!decoder(fp, value, &rem))
901 fprintf(fp, "0x%x", rem);
903 fprintf(fp, "|0x%x", rem);
908 * Add argument padding to subsequent system calls after Quad
909 * syscall arguments as needed. This used to be done by hand in the
910 * decoded_syscalls table which was ugly and error prone. It is
911 * simpler to do the fixup of offsets at initialization time than when
912 * decoding arguments.
915 quad_fixup(struct syscall *sc)
922 for (i = 0; i < sc->nargs; i++) {
923 /* This arg type is a dummy that doesn't use offset. */
924 if ((sc->args[i].type & ARG_MASK) == PipeFds)
927 assert(prev < sc->args[i].offset);
928 prev = sc->args[i].offset;
929 sc->args[i].offset += offset;
930 switch (sc->args[i].type & ARG_MASK) {
935 * 64-bit arguments on 32-bit powerpc must be
936 * 64-bit aligned. If the current offset is
937 * not aligned, the calling convention inserts
938 * a 32-bit pad argument that should be skipped.
940 if (sc->args[i].offset % 2 == 1) {
941 sc->args[i].offset++;
958 STAILQ_INIT(&syscalls);
959 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
963 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
967 static struct syscall *
968 find_syscall(struct procabi *abi, u_int number)
970 struct extra_syscall *es;
972 if (number < nitems(abi->syscalls))
973 return (abi->syscalls[number]);
974 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
975 if (es->number == number)
982 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
984 struct extra_syscall *es;
986 if (number < nitems(abi->syscalls)) {
987 assert(abi->syscalls[number] == NULL);
988 abi->syscalls[number] = sc;
990 es = malloc(sizeof(*es));
993 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
998 * If/when the list gets big, it might be desirable to do it
999 * as a hash table or binary search.
1002 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1009 sc = find_syscall(t->proc->abi, number);
1013 name = sysdecode_syscallname(t->proc->abi->abi, number);
1015 asprintf(&new_name, "#%d", number);
1019 STAILQ_FOREACH(sc, &syscalls, entries) {
1020 if (strcmp(name, sc->name) == 0) {
1021 add_syscall(t->proc->abi, number, sc);
1027 /* It is unknown. Add it into the list. */
1029 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1033 sc = calloc(1, sizeof(struct syscall));
1035 if (new_name != NULL)
1039 for (i = 0; i < nargs; i++) {
1040 sc->args[i].offset = i;
1041 /* Treat all unknown arguments as LongHex. */
1042 sc->args[i].type = LongHex;
1044 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1045 add_syscall(t->proc->abi, number, sc);
1051 * Copy a fixed amount of bytes from the process.
1054 get_struct(pid_t pid, uintptr_t offset, void *buf, int len)
1056 struct ptrace_io_desc iorequest;
1058 iorequest.piod_op = PIOD_READ_D;
1059 iorequest.piod_offs = (void *)offset;
1060 iorequest.piod_addr = buf;
1061 iorequest.piod_len = len;
1062 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1067 #define MAXSIZE 4096
1070 * Copy a string from the process. Note that it is
1071 * expected to be a C string, but if max is set, it will
1072 * only get that much.
1075 get_string(pid_t pid, uintptr_t addr, int max)
1077 struct ptrace_io_desc iorequest;
1079 size_t offset, size, totalsize;
1085 /* Read up to the end of the current page. */
1086 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1091 buf = malloc(totalsize);
1095 iorequest.piod_op = PIOD_READ_D;
1096 iorequest.piod_offs = (void *)(addr + offset);
1097 iorequest.piod_addr = buf + offset;
1098 iorequest.piod_len = size;
1099 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1103 if (memchr(buf + offset, '\0', size) != NULL)
1106 if (totalsize < MAXSIZE && max == 0) {
1107 size = MAXSIZE - totalsize;
1108 if (size > PAGE_SIZE)
1110 nbuf = realloc(buf, totalsize + size);
1112 buf[totalsize - 1] = '\0';
1118 buf[totalsize - 1] = '\0';
1127 static char tmp[32];
1128 const char *signame;
1130 signame = sysdecode_signal(sig);
1131 if (signame == NULL) {
1132 snprintf(tmp, sizeof(tmp), "%d", sig);
1139 print_kevent(FILE *fp, struct kevent *ke)
1142 switch (ke->filter) {
1148 case EVFILT_PROCDESC:
1150 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1153 fputs(strsig2(ke->ident), fp);
1156 fprintf(fp, "%p", (void *)ke->ident);
1159 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1161 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1163 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1164 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1168 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1170 unsigned char *utrace_buffer;
1173 if (sysdecode_utrace(fp, utrace_addr, len)) {
1178 utrace_buffer = utrace_addr;
1179 fprintf(fp, "%zu:", len);
1181 fprintf(fp, " %02x", *utrace_buffer++);
1186 print_pointer(FILE *fp, uintptr_t arg)
1189 fprintf(fp, "%p", (void *)arg);
1193 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg,
1197 struct sockaddr_in *lsin;
1198 struct sockaddr_in6 *lsin6;
1199 struct sockaddr_un *sun;
1200 struct sockaddr *sa;
1202 pid_t pid = trussinfo->curthread->proc->pid;
1208 /* If the length is too small, just bail. */
1209 if (len < sizeof(*sa)) {
1210 print_pointer(fp, arg);
1214 sa = calloc(1, len);
1215 if (get_struct(pid, arg, sa, len) == -1) {
1217 print_pointer(fp, arg);
1221 switch (sa->sa_family) {
1223 if (len < sizeof(*lsin))
1224 goto sockaddr_short;
1225 lsin = (struct sockaddr_in *)(void *)sa;
1226 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1227 fprintf(fp, "{ AF_INET %s:%d }", addr,
1228 htons(lsin->sin_port));
1231 if (len < sizeof(*lsin6))
1232 goto sockaddr_short;
1233 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1234 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1236 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1237 htons(lsin6->sin6_port));
1240 sun = (struct sockaddr_un *)sa;
1241 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1242 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1248 "{ sa_len = %d, sa_family = %d, sa_data = {",
1249 (int)sa->sa_len, (int)sa->sa_family);
1250 for (q = (u_char *)sa->sa_data;
1251 q < (u_char *)sa + len; q++)
1252 fprintf(fp, "%s 0x%02x",
1253 q == (u_char *)sa->sa_data ? "" : ",",
1260 #define IOV_LIMIT 16
1263 print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
1265 struct iovec iov[IOV_LIMIT];
1266 size_t max_string = trussinfo->strsize;
1267 char tmp2[max_string + 1], *tmp3;
1269 pid_t pid = trussinfo->curthread->proc->pid;
1271 bool buf_truncated, iov_truncated;
1274 print_pointer(fp, arg);
1277 if (iovcnt > IOV_LIMIT) {
1279 iov_truncated = true;
1281 iov_truncated = false;
1283 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1284 print_pointer(fp, arg);
1289 for (i = 0; i < iovcnt; i++) {
1290 len = iov[i].iov_len;
1291 if (len > max_string) {
1293 buf_truncated = true;
1295 buf_truncated = false;
1297 fprintf(fp, "%s{", (i > 0) ? "," : "");
1298 if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
1299 tmp3 = malloc(len * 4 + 1);
1301 if (strvisx(tmp3, tmp2, len,
1302 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1306 buf_truncated = true;
1308 fprintf(fp, "\"%s\"%s", tmp3,
1309 buf_truncated ? "..." : "");
1312 print_pointer(fp, (uintptr_t)iov[i].iov_base);
1314 fprintf(fp, ",%zu}", iov[i].iov_len);
1316 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1320 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1325 for (q = CMSG_DATA(cmsghdr);
1326 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1327 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1333 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1335 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1336 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1337 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1338 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1342 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1344 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1346 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1349 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1350 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1352 fprintf(fp, "ctx=%u,", info->sinfo_context);
1353 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1356 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1357 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1359 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1363 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1365 fprintf(fp, "{sid=%u,", info->snd_sid);
1367 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1368 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1369 fprintf(fp, "ctx=%u,", info->snd_context);
1370 fprintf(fp, "id=%u}", info->snd_assoc_id);
1374 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1376 fprintf(fp, "{sid=%u,", info->rcv_sid);
1377 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1379 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1380 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1381 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1382 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1383 fprintf(fp, "ctx=%u,", info->rcv_context);
1384 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1388 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1390 fprintf(fp, "{sid=%u,", info->nxt_sid);
1392 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1393 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1394 fprintf(fp, "len=%u,", info->nxt_length);
1395 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1399 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1402 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1403 fprintf(fp, ",val=%u}", info->pr_value);
1407 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1409 fprintf(fp, "{num=%u}", info->auth_keynumber);
1413 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1415 char buf[INET_ADDRSTRLEN];
1418 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1420 fprintf(fp, "{addr=%s}", s);
1422 fputs("{addr=???}", fp);
1426 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1428 char buf[INET6_ADDRSTRLEN];
1431 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1433 fprintf(fp, "{addr=%s}", s);
1435 fputs("{addr=???}", fp);
1439 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1444 len = cmsghdr->cmsg_len;
1445 data = CMSG_DATA(cmsghdr);
1446 switch (cmsghdr->cmsg_type) {
1448 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1449 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1451 print_gen_cmsg(fp, cmsghdr);
1454 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1455 print_sctp_sndrcvinfo(fp, receive,
1456 (struct sctp_sndrcvinfo *)data);
1458 print_gen_cmsg(fp, cmsghdr);
1462 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1463 print_sctp_extrcvinfo(fp,
1464 (struct sctp_extrcvinfo *)data);
1466 print_gen_cmsg(fp, cmsghdr);
1470 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1471 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1473 print_gen_cmsg(fp, cmsghdr);
1476 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1477 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1479 print_gen_cmsg(fp, cmsghdr);
1482 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1483 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1485 print_gen_cmsg(fp, cmsghdr);
1488 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1489 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1491 print_gen_cmsg(fp, cmsghdr);
1494 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1495 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1497 print_gen_cmsg(fp, cmsghdr);
1499 case SCTP_DSTADDRV4:
1500 if (len == CMSG_LEN(sizeof(struct in_addr)))
1501 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1503 print_gen_cmsg(fp, cmsghdr);
1505 case SCTP_DSTADDRV6:
1506 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1507 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1509 print_gen_cmsg(fp, cmsghdr);
1512 print_gen_cmsg(fp, cmsghdr);
1517 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1519 struct cmsghdr *cmsghdr;
1526 len = msghdr->msg_controllen;
1531 cmsgbuf = calloc(1, len);
1532 if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
1533 print_pointer(fp, (uintptr_t)msghdr->msg_control);
1537 msghdr->msg_control = cmsgbuf;
1540 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1542 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1543 level = cmsghdr->cmsg_level;
1544 type = cmsghdr->cmsg_type;
1545 len = cmsghdr->cmsg_len;
1546 fprintf(fp, "%s{level=", first ? "" : ",");
1547 print_integer_arg(sysdecode_sockopt_level, fp, level);
1548 fputs(",type=", fp);
1549 temp = sysdecode_cmsg_type(level, type);
1553 fprintf(fp, "%d", type);
1555 fputs(",data=", fp);
1558 print_sctp_cmsg(fp, receive, cmsghdr);
1561 print_gen_cmsg(fp, cmsghdr);
1572 print_sysctl_oid(FILE *fp, int *oid, int len)
1576 for (i = 0; i < len; i++)
1577 fprintf(fp, ".%d", oid[i]);
1581 * Converts a syscall argument into a string. Said string is
1582 * allocated via malloc(), so needs to be free()'d. sc is
1583 * a pointer to the syscall description (see above); args is
1584 * an array of all of the system call arguments.
1587 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1588 struct trussinfo *trussinfo)
1595 fp = open_memstream(&tmp, &tmplen);
1596 pid = trussinfo->curthread->proc->pid;
1597 switch (sc->type & ARG_MASK) {
1599 fprintf(fp, "0x%x", (int)args[sc->offset]);
1602 fprintf(fp, "0%o", (int)args[sc->offset]);
1605 fprintf(fp, "%d", (int)args[sc->offset]);
1608 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1613 if (get_struct(pid, args[sc->offset], &val,
1615 fprintf(fp, "{ %u }", val);
1617 print_pointer(fp, args[sc->offset]);
1621 fprintf(fp, "0x%lx", args[sc->offset]);
1624 fprintf(fp, "%ld", args[sc->offset]);
1627 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1630 /* Handle special SHM_ANON value. */
1631 if ((char *)args[sc->offset] == SHM_ANON) {
1632 fprintf(fp, "SHM_ANON");
1637 /* NULL-terminated string. */
1640 tmp2 = get_string(pid, args[sc->offset], 0);
1641 fprintf(fp, "\"%s\"", tmp2);
1647 * Binary block of data that might have printable characters.
1648 * XXX If type|OUT, assume that the length is the syscall's
1649 * return value. Otherwise, assume that the length of the block
1650 * is in the next syscall argument.
1652 int max_string = trussinfo->strsize;
1653 char tmp2[max_string + 1], *tmp3;
1660 len = args[sc->offset + 1];
1663 * Don't print more than max_string characters, to avoid word
1664 * wrap. If we have to truncate put some ... after the string.
1666 if (len > max_string) {
1670 if (len && get_struct(pid, args[sc->offset], &tmp2, len)
1672 tmp3 = malloc(len * 4 + 1);
1674 if (strvisx(tmp3, tmp2, len,
1675 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1680 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1684 print_pointer(fp, args[sc->offset]);
1694 char buf[PAGE_SIZE];
1701 * Only parse argv[] and environment arrays from exec calls
1704 if (((sc->type & ARG_MASK) == ExecArgs &&
1705 (trussinfo->flags & EXECVEARGS) == 0) ||
1706 ((sc->type & ARG_MASK) == ExecEnv &&
1707 (trussinfo->flags & EXECVEENVS) == 0)) {
1708 print_pointer(fp, args[sc->offset]);
1713 * Read a page of pointers at a time. Punt if the top-level
1714 * pointer is not aligned. Note that the first read is of
1717 addr = args[sc->offset];
1718 if (addr % sizeof(char *) != 0) {
1719 print_pointer(fp, args[sc->offset]);
1723 len = PAGE_SIZE - (addr & PAGE_MASK);
1724 if (get_struct(pid, addr, u.buf, len) == -1) {
1725 print_pointer(fp, args[sc->offset]);
1732 while (u.strarray[i] != NULL) {
1733 string = get_string(pid, (uintptr_t)u.strarray[i], 0);
1734 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1739 if (i == len / sizeof(char *)) {
1742 if (get_struct(pid, addr, u.buf, len) ==
1744 fprintf(fp, ", <inval>");
1755 fprintf(fp, "%ld", args[sc->offset]);
1758 fprintf(fp, "0x%lx", args[sc->offset]);
1763 unsigned long long ll;
1765 #if _BYTE_ORDER == _LITTLE_ENDIAN
1766 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1769 ll = (unsigned long long)args[sc->offset] << 32 |
1770 args[sc->offset + 1];
1772 if ((sc->type & ARG_MASK) == Quad)
1773 fprintf(fp, "%lld", ll);
1775 fprintf(fp, "0x%llx", ll);
1782 if (get_struct(pid, args[sc->offset], &val,
1784 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1786 print_pointer(fp, args[sc->offset]);
1790 print_pointer(fp, args[sc->offset]);
1795 if (retval[0] == -1)
1797 tmp2 = get_string(pid, args[sc->offset], retval[0]);
1798 fprintf(fp, "\"%s\"", tmp2);
1806 cmd = args[sc->offset];
1807 temp = sysdecode_ioctlname(cmd);
1811 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1812 cmd, cmd & IOC_OUT ? "R" : "",
1813 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1814 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1815 cmd & 0xFF, IOCPARM_LEN(cmd));
1822 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
1823 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1826 print_pointer(fp, args[sc->offset]);
1830 struct timespec ts[2];
1834 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
1837 for (i = 0; i < nitems(ts); i++) {
1840 switch (ts[i].tv_nsec) {
1842 fprintf(fp, "UTIME_NOW");
1845 fprintf(fp, "UTIME_OMIT");
1848 fprintf(fp, "%jd.%09ld",
1849 (intmax_t)ts[i].tv_sec,
1856 print_pointer(fp, args[sc->offset]);
1862 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1863 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1866 print_pointer(fp, args[sc->offset]);
1870 struct timeval tv[2];
1872 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1873 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1874 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1875 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1877 print_pointer(fp, args[sc->offset]);
1881 struct itimerval itv;
1883 if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
1884 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1885 (intmax_t)itv.it_interval.tv_sec,
1886 itv.it_interval.tv_usec,
1887 (intmax_t)itv.it_value.tv_sec,
1888 itv.it_value.tv_usec);
1890 print_pointer(fp, args[sc->offset]);
1895 struct linux_socketcall_args largs;
1897 if (get_struct(pid, args[sc->offset], (void *)&largs,
1898 sizeof(largs)) != -1)
1899 fprintf(fp, "{ %s, 0x%lx }",
1900 lookup(linux_socketcall_ops, largs.what, 10),
1901 (long unsigned int)largs.args);
1903 print_pointer(fp, args[sc->offset]);
1908 * XXX: A Pollfd argument expects the /next/ syscall argument
1909 * to be the number of fds in the array. This matches the poll
1913 int numfds = args[sc->offset + 1];
1914 size_t bytes = sizeof(struct pollfd) * numfds;
1917 if ((pfd = malloc(bytes)) == NULL)
1918 err(1, "Cannot malloc %zu bytes for pollfd array",
1920 if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
1922 for (i = 0; i < numfds; i++) {
1923 fprintf(fp, " %d/%s", pfd[i].fd,
1924 xlookup_bits(poll_flags, pfd[i].events));
1928 print_pointer(fp, args[sc->offset]);
1935 * XXX: A Fd_set argument expects the /first/ syscall argument
1936 * to be the number of fds in the array. This matches the
1940 int numfds = args[0];
1941 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1944 if ((fds = malloc(bytes)) == NULL)
1945 err(1, "Cannot malloc %zu bytes for fd_set array",
1947 if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
1949 for (i = 0; i < numfds; i++) {
1950 if (FD_ISSET(i, fds))
1951 fprintf(fp, " %d", i);
1955 print_pointer(fp, args[sc->offset]);
1960 fputs(strsig2(args[sc->offset]), fp);
1967 sig = args[sc->offset];
1968 if (get_struct(pid, args[sc->offset], (void *)&ss,
1969 sizeof(ss)) == -1) {
1970 print_pointer(fp, args[sc->offset]);
1975 for (i = 1; i < sys_nsig; i++) {
1976 if (sigismember(&ss, i)) {
1977 fprintf(fp, "%s%s", !first ? "|" : "",
1988 print_integer_arg(sysdecode_sigprocmask_how, fp,
1992 /* XXX: Output depends on the value of the previous argument. */
1993 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1994 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1995 args[sc->offset], 16);
1998 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2001 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2004 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2007 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2010 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2013 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2016 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2019 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2022 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2025 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2028 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2031 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2036 if (args[sc->offset] == 0) {
2042 * Extract the address length from the next argument. If
2043 * this is an output sockaddr (OUT is set), then the
2044 * next argument is a pointer to a socklen_t. Otherwise
2045 * the next argument contains a socklen_t by value.
2047 if (sc->type & OUT) {
2048 if (get_struct(pid, args[sc->offset + 1], &len,
2049 sizeof(len)) == -1) {
2050 print_pointer(fp, args[sc->offset]);
2054 len = args[sc->offset + 1];
2056 print_sockaddr(fp, trussinfo, args[sc->offset], len);
2060 struct sigaction sa;
2062 if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
2064 if (sa.sa_handler == SIG_DFL)
2065 fputs("SIG_DFL", fp);
2066 else if (sa.sa_handler == SIG_IGN)
2067 fputs("SIG_IGN", fp);
2069 fprintf(fp, "%p", sa.sa_handler);
2070 fprintf(fp, " %s ss_t }",
2071 xlookup_bits(sigaction_flags, sa.sa_flags));
2073 print_pointer(fp, args[sc->offset]);
2078 * XXX XXX: The size of the array is determined by either the
2079 * next syscall argument, or by the syscall return value,
2080 * depending on which argument number we are. This matches the
2081 * kevent syscall, but luckily that's the only syscall that uses
2089 if (sc->offset == 1)
2090 numevents = args[sc->offset+1];
2091 else if (sc->offset == 3 && retval[0] != -1)
2092 numevents = retval[0];
2094 if (numevents >= 0) {
2095 bytes = sizeof(struct kevent) * numevents;
2096 if ((ke = malloc(bytes)) == NULL)
2098 "Cannot malloc %zu bytes for kevent array",
2102 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2105 for (i = 0; i < numevents; i++) {
2107 print_kevent(fp, &ke[i]);
2111 print_pointer(fp, args[sc->offset]);
2117 struct kevent_freebsd11 *ke11;
2123 if (sc->offset == 1)
2124 numevents = args[sc->offset+1];
2125 else if (sc->offset == 3 && retval[0] != -1)
2126 numevents = retval[0];
2128 if (numevents >= 0) {
2129 bytes = sizeof(struct kevent_freebsd11) * numevents;
2130 if ((ke11 = malloc(bytes)) == NULL)
2132 "Cannot malloc %zu bytes for kevent array",
2136 memset(&ke, 0, sizeof(ke));
2137 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2138 ke11, bytes) != -1) {
2140 for (i = 0; i < numevents; i++) {
2142 ke.ident = ke11[i].ident;
2143 ke.filter = ke11[i].filter;
2144 ke.flags = ke11[i].flags;
2145 ke.fflags = ke11[i].fflags;
2146 ke.data = ke11[i].data;
2147 ke.udata = ke11[i].udata;
2148 print_kevent(fp, &ke);
2152 print_pointer(fp, args[sc->offset]);
2160 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2164 strmode(st.st_mode, mode);
2166 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2167 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2168 (long)st.st_blksize);
2170 print_pointer(fp, args[sc->offset]);
2175 struct freebsd11_stat st;
2177 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2181 strmode(st.st_mode, mode);
2183 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2184 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2185 (long)st.st_blksize);
2187 print_pointer(fp, args[sc->offset]);
2195 if (get_struct(pid, args[sc->offset], &buf,
2196 sizeof(buf)) != -1) {
2199 bzero(fsid, sizeof(fsid));
2200 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2201 for (i = 0; i < sizeof(buf.f_fsid); i++)
2202 snprintf(&fsid[i*2],
2203 sizeof(fsid) - (i*2), "%02x",
2204 ((u_char *)&buf.f_fsid)[i]);
2207 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2208 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2209 buf.f_mntfromname, fsid);
2211 print_pointer(fp, args[sc->offset]);
2218 if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
2221 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2222 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2223 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2224 ru.ru_inblock, ru.ru_oublock);
2226 print_pointer(fp, args[sc->offset]);
2232 if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
2234 fprintf(fp, "{ cur=%ju,max=%ju }",
2235 rl.rlim_cur, rl.rlim_max);
2237 print_pointer(fp, args[sc->offset]);
2243 if (get_struct(pid, args[sc->offset], &status,
2244 sizeof(status)) != -1) {
2246 if (WIFCONTINUED(status))
2247 fputs("CONTINUED", fp);
2248 else if (WIFEXITED(status))
2249 fprintf(fp, "EXITED,val=%d",
2250 WEXITSTATUS(status));
2251 else if (WIFSIGNALED(status))
2252 fprintf(fp, "SIGNALED,sig=%s%s",
2253 strsig2(WTERMSIG(status)),
2254 WCOREDUMP(status) ? ",cored" : "");
2256 fprintf(fp, "STOPPED,sig=%s",
2257 strsig2(WTERMSIG(status)));
2260 print_pointer(fp, args[sc->offset]);
2264 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2267 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2270 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2273 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2276 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2279 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2282 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2285 print_integer_arg(sysdecode_sysarch_number, fp,
2290 int oid[CTL_MAXNAME + 2], qoid[CTL_MAXNAME + 2];
2294 memset(name, 0, sizeof(name));
2295 len = args[sc->offset + 1];
2296 if (get_struct(pid, args[sc->offset], oid,
2297 len * sizeof(oid[0])) != -1) {
2299 if (oid[0] == CTL_SYSCTL) {
2300 fprintf(fp, "sysctl.");
2302 case CTL_SYSCTL_DEBUG:
2303 fprintf(fp, "debug");
2305 case CTL_SYSCTL_NAME:
2306 fprintf(fp, "name");
2307 print_sysctl_oid(fp, oid + 2, len - 2);
2309 case CTL_SYSCTL_NEXT:
2310 fprintf(fp, "next");
2312 case CTL_SYSCTL_NAME2OID:
2313 fprintf(fp, "name2oid");
2315 case CTL_SYSCTL_OIDFMT:
2316 fprintf(fp, "oidfmt");
2317 print_sysctl_oid(fp, oid + 2, len - 2);
2319 case CTL_SYSCTL_OIDDESCR:
2320 fprintf(fp, "oiddescr");
2321 print_sysctl_oid(fp, oid + 2, len - 2);
2323 case CTL_SYSCTL_OIDLABEL:
2324 fprintf(fp, "oidlabel");
2325 print_sysctl_oid(fp, oid + 2, len - 2);
2328 print_sysctl_oid(fp, oid + 1, len - 1);
2331 qoid[0] = CTL_SYSCTL;
2332 qoid[1] = CTL_SYSCTL_NAME;
2333 memcpy(qoid + 2, oid, len * sizeof(int));
2335 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
2336 print_sysctl_oid(fp, qoid + 2, len);
2338 fprintf(fp, "%s", name);
2346 * The pipe() system call in the kernel returns its
2347 * two file descriptors via return values. However,
2348 * the interface exposed by libc is that pipe()
2349 * accepts a pointer to an array of descriptors.
2350 * Format the output to match the libc API by printing
2351 * the returned file descriptors as a fake argument.
2353 * Overwrite the first retval to signal a successful
2356 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2363 len = args[sc->offset + 1];
2364 utrace_addr = calloc(1, len);
2365 if (get_struct(pid, args[sc->offset],
2366 (void *)utrace_addr, len) != -1)
2367 print_utrace(fp, utrace_addr, len);
2369 print_pointer(fp, args[sc->offset]);
2374 int descriptors[16];
2375 unsigned long i, ndescriptors;
2378 ndescriptors = args[sc->offset + 1];
2380 if (ndescriptors > nitems(descriptors)) {
2381 ndescriptors = nitems(descriptors);
2384 if (get_struct(pid, args[sc->offset],
2385 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2387 for (i = 0; i < ndescriptors; i++)
2388 fprintf(fp, i == 0 ? " %d" : ", %d",
2390 fprintf(fp, truncated ? ", ... }" : " }");
2392 print_pointer(fp, args[sc->offset]);
2396 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2398 case CapFcntlRights: {
2401 if (sc->type & OUT) {
2402 if (get_struct(pid, args[sc->offset], &rights,
2403 sizeof(rights)) == -1) {
2404 print_pointer(fp, args[sc->offset]);
2408 rights = args[sc->offset];
2409 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2413 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2418 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2419 fprintf(fp, "0x%x", rem);
2421 fprintf(fp, "|0x%x", rem);
2425 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2428 print_integer_arg(sysdecode_getfsstat_mode, fp,
2432 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2434 case Kldunloadflags:
2435 print_integer_arg(sysdecode_kldunload_flags, fp,
2439 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2442 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2444 case Sockprotocol: {
2446 int domain, protocol;
2448 domain = args[sc->offset - 2];
2449 protocol = args[sc->offset];
2450 if (protocol == 0) {
2453 temp = sysdecode_socket_protocol(domain, protocol);
2457 fprintf(fp, "%d", protocol);
2463 print_integer_arg(sysdecode_sockopt_level, fp,
2470 level = args[sc->offset - 1];
2471 name = args[sc->offset];
2472 temp = sysdecode_sockopt_name(level, name);
2476 fprintf(fp, "%d", name);
2481 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2484 cap_rights_t rights;
2486 if (get_struct(pid, args[sc->offset], &rights,
2487 sizeof(rights)) != -1) {
2489 sysdecode_cap_rights(fp, &rights);
2492 print_pointer(fp, args[sc->offset]);
2496 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2498 case Extattrnamespace:
2499 print_integer_arg(sysdecode_extattrnamespace, fp,
2503 print_integer_arg(sysdecode_minherit_inherit, fp,
2507 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2510 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2513 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2516 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2519 print_integer_arg(sysdecode_ptrace_request, fp,
2523 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2524 fprintf(fp, "%#x", (int)args[sc->offset]);
2527 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2530 print_integer_arg(sysdecode_rtprio_function, fp,
2534 print_integer_arg(sysdecode_scheduler_policy, fp,
2538 struct sched_param sp;
2540 if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
2541 fprintf(fp, "{ %d }", sp.sched_priority);
2543 print_pointer(fp, args[sc->offset]);
2549 if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
2550 fprintf(fp, "{ %s }", strsig2(sig));
2552 print_pointer(fp, args[sc->offset]);
2558 if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
2559 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2560 decode_siginfo(fp, &si);
2563 print_pointer(fp, args[sc->offset]);
2568 * Print argument as an array of struct iovec, where the next
2569 * syscall argument is the number of elements of the array.
2572 print_iovec(fp, trussinfo, args[sc->offset],
2573 (int)args[sc->offset + 1]);
2575 case Sctpsndrcvinfo: {
2576 struct sctp_sndrcvinfo info;
2578 if (get_struct(pid, args[sc->offset],
2579 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2580 print_pointer(fp, args[sc->offset]);
2583 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2587 struct msghdr msghdr;
2589 if (get_struct(pid, args[sc->offset],
2590 &msghdr, sizeof(struct msghdr)) == -1) {
2591 print_pointer(fp, args[sc->offset]);
2595 print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
2596 fprintf(fp, ",%d,", msghdr.msg_namelen);
2597 print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
2598 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2599 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2600 fprintf(fp, ",%u,", msghdr.msg_controllen);
2601 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2606 case CloudABIAdvice:
2607 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2609 case CloudABIClockID:
2610 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2612 case CloudABIFDSFlags:
2613 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2615 case CloudABIFDStat: {
2616 cloudabi_fdstat_t fds;
2617 if (get_struct(pid, args[sc->offset], &fds, sizeof(fds))
2619 fprintf(fp, "{ %s, ",
2620 xlookup(cloudabi_filetype, fds.fs_filetype));
2621 fprintf(fp, "%s, ... }",
2622 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2624 print_pointer(fp, args[sc->offset]);
2627 case CloudABIFileStat: {
2628 cloudabi_filestat_t fsb;
2629 if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb))
2631 fprintf(fp, "{ %s, %ju }",
2632 xlookup(cloudabi_filetype, fsb.st_filetype),
2633 (uintmax_t)fsb.st_size);
2635 print_pointer(fp, args[sc->offset]);
2638 case CloudABIFileType:
2639 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2641 case CloudABIFSFlags:
2642 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2644 case CloudABILookup:
2645 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2646 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2647 (int)args[sc->offset]);
2649 fprintf(fp, "%d", (int)args[sc->offset]);
2651 case CloudABIMFlags:
2652 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2655 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2657 case CloudABIMSFlags:
2658 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2660 case CloudABIOFlags:
2661 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2663 case CloudABISDFlags:
2664 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2666 case CloudABISignal:
2667 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2669 case CloudABITimestamp:
2670 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2671 args[sc->offset] % 1000000000);
2673 case CloudABIULFlags:
2674 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2676 case CloudABIWhence:
2677 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2681 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2688 * Print (to outfile) the system call and its arguments.
2691 print_syscall(struct trussinfo *trussinfo)
2693 struct threadinfo *t;
2698 t = trussinfo->curthread;
2700 name = t->cs.sc->name;
2701 nargs = t->cs.nargs;
2702 s_args = t->cs.s_args;
2704 len = print_line_prefix(trussinfo);
2705 len += fprintf(trussinfo->outfile, "%s(", name);
2707 for (i = 0; i < nargs; i++) {
2708 if (s_args[i] != NULL)
2709 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2711 len += fprintf(trussinfo->outfile,
2712 "<missing argument>");
2713 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2716 len += fprintf(trussinfo->outfile, ")");
2717 for (i = 0; i < 6 - (len / 8); i++)
2718 fprintf(trussinfo->outfile, "\t");
2722 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2724 struct timespec timediff;
2725 struct threadinfo *t;
2728 t = trussinfo->curthread;
2730 if (trussinfo->flags & COUNTONLY) {
2731 timespecsub(&t->after, &t->before, &timediff);
2732 timespecadd(&sc->time, &timediff, &sc->time);
2739 print_syscall(trussinfo);
2740 fflush(trussinfo->outfile);
2742 if (retval == NULL) {
2744 * This system call resulted in the current thread's exit,
2745 * so there is no return value or error to display.
2747 fprintf(trussinfo->outfile, "\n");
2751 if (error == ERESTART)
2752 fprintf(trussinfo->outfile, " ERESTART\n");
2753 else if (error == EJUSTRETURN)
2754 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2755 else if (error != 0) {
2756 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2757 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2761 else if (sc->ret_type == 2) {
2764 #if _BYTE_ORDER == _LITTLE_ENDIAN
2765 off = (off_t)retval[1] << 32 | retval[0];
2767 off = (off_t)retval[0] << 32 | retval[1];
2769 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2774 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2775 (intmax_t)retval[0], (intmax_t)retval[0]);
2779 print_summary(struct trussinfo *trussinfo)
2781 struct timespec total = {0, 0};
2785 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2786 "syscall", "seconds", "calls", "errors");
2788 STAILQ_FOREACH(sc, &syscalls, entries)
2790 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2791 sc->name, (intmax_t)sc->time.tv_sec,
2792 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2793 timespecadd(&total, &sc->time, &total);
2794 ncall += sc->ncalls;
2795 nerror += sc->nerror;
2797 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2798 "", "-------------", "-------", "-------");
2799 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2800 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);