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 = "__realpathat", .ret_type = 1, .nargs = 5,
119 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Name | OUT, 2 },
120 { Sizet, 3 }, { Int, 4} } },
121 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
122 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
124 { .name = "accept", .ret_type = 1, .nargs = 3,
125 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
126 { .name = "access", .ret_type = 1, .nargs = 2,
127 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
128 { .name = "bind", .ret_type = 1, .nargs = 3,
129 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
130 { .name = "bindat", .ret_type = 1, .nargs = 4,
131 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
133 { .name = "break", .ret_type = 1, .nargs = 1,
134 .args = { { Ptr, 0 } } },
135 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
136 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
137 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
138 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
139 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
140 .args = { { PUInt | OUT, 0 } } },
141 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
142 .args = { { Int, 0 }, { CapRights, 1 } } },
143 { .name = "chdir", .ret_type = 1, .nargs = 1,
144 .args = { { Name, 0 } } },
145 { .name = "chflags", .ret_type = 1, .nargs = 2,
146 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
147 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
148 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
150 { .name = "chmod", .ret_type = 1, .nargs = 2,
151 .args = { { Name, 0 }, { Octal, 1 } } },
152 { .name = "chown", .ret_type = 1, .nargs = 3,
153 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
154 { .name = "chroot", .ret_type = 1, .nargs = 1,
155 .args = { { Name, 0 } } },
156 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
157 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
158 { .name = "close", .ret_type = 1, .nargs = 1,
159 .args = { { Int, 0 } } },
160 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
161 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
162 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
163 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
165 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
166 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
167 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
168 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
169 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
170 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
171 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
172 { .name = "connect", .ret_type = 1, .nargs = 3,
173 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
174 { .name = "connectat", .ret_type = 1, .nargs = 4,
175 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
177 { .name = "dup", .ret_type = 1, .nargs = 1,
178 .args = { { Int, 0 } } },
179 { .name = "dup2", .ret_type = 1, .nargs = 2,
180 .args = { { Int, 0 }, { Int, 1 } } },
181 { .name = "eaccess", .ret_type = 1, .nargs = 2,
182 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
183 { .name = "execve", .ret_type = 1, .nargs = 3,
184 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
185 { ExecEnv | IN, 2 } } },
186 { .name = "exit", .ret_type = 0, .nargs = 1,
187 .args = { { Hex, 0 } } },
188 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
189 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
190 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
191 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
192 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
193 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
194 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
195 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
196 { BinString | OUT, 3 }, { Sizet, 4 } } },
197 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
198 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
199 { BinString | OUT, 3 }, { Sizet, 4 } } },
200 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
201 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
202 { BinString | OUT, 3 }, { Sizet, 4 } } },
203 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
204 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
206 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
207 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
209 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
210 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
212 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
213 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
214 { BinString | IN, 3 }, { Sizet, 4 } } },
215 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
216 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
217 { BinString | IN, 3 }, { Sizet, 4 } } },
218 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
219 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
220 { BinString | IN, 3 }, { Sizet, 4 } } },
221 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
222 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
223 { Extattrnamespace, 3 }, { Name, 4 } } },
224 { .name = "faccessat", .ret_type = 1, .nargs = 4,
225 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
227 { .name = "fchflags", .ret_type = 1, .nargs = 2,
228 .args = { { Int, 0 }, { FileFlags, 1 } } },
229 { .name = "fchmod", .ret_type = 1, .nargs = 2,
230 .args = { { Int, 0 }, { Octal, 1 } } },
231 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
232 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
233 { .name = "fchown", .ret_type = 1, .nargs = 3,
234 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
235 { .name = "fchownat", .ret_type = 1, .nargs = 5,
236 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
238 { .name = "fcntl", .ret_type = 1, .nargs = 3,
239 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
240 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
241 .args = { { Int, 0 } } },
242 { .name = "flock", .ret_type = 1, .nargs = 2,
243 .args = { { Int, 0 }, { Flockop, 1 } } },
244 { .name = "fstat", .ret_type = 1, .nargs = 2,
245 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
246 { .name = "fstatat", .ret_type = 1, .nargs = 4,
247 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
249 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
250 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
251 { .name = "fsync", .ret_type = 1, .nargs = 1,
252 .args = { { Int, 0 } } },
253 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
254 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
255 { .name = "futimens", .ret_type = 1, .nargs = 2,
256 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
257 { .name = "futimes", .ret_type = 1, .nargs = 2,
258 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
259 { .name = "futimesat", .ret_type = 1, .nargs = 3,
260 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
261 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
262 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
263 { PQuadHex | OUT, 3 } } },
264 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
265 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
266 { .name = "getitimer", .ret_type = 1, .nargs = 2,
267 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
268 { .name = "getpeername", .ret_type = 1, .nargs = 3,
269 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
270 { .name = "getpgid", .ret_type = 1, .nargs = 1,
271 .args = { { Int, 0 } } },
272 { .name = "getpriority", .ret_type = 1, .nargs = 2,
273 .args = { { Priowhich, 0 }, { Int, 1 } } },
274 { .name = "getrandom", .ret_type = 1, .nargs = 3,
275 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
276 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
277 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
278 { .name = "getrusage", .ret_type = 1, .nargs = 2,
279 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
280 { .name = "getsid", .ret_type = 1, .nargs = 1,
281 .args = { { Int, 0 } } },
282 { .name = "getsockname", .ret_type = 1, .nargs = 3,
283 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
284 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
285 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
286 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
287 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
288 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
289 { .name = "ioctl", .ret_type = 1, .nargs = 3,
290 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
291 { .name = "kevent", .ret_type = 1, .nargs = 6,
292 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
293 { Int, 4 }, { Timespec, 5 } } },
294 { .name = "kill", .ret_type = 1, .nargs = 2,
295 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
296 { .name = "kldfind", .ret_type = 1, .nargs = 1,
297 .args = { { Name | IN, 0 } } },
298 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
299 .args = { { Int, 0 } } },
300 { .name = "kldload", .ret_type = 1, .nargs = 1,
301 .args = { { Name | IN, 0 } } },
302 { .name = "kldnext", .ret_type = 1, .nargs = 1,
303 .args = { { Int, 0 } } },
304 { .name = "kldstat", .ret_type = 1, .nargs = 2,
305 .args = { { Int, 0 }, { Ptr, 1 } } },
306 { .name = "kldsym", .ret_type = 1, .nargs = 3,
307 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
308 { .name = "kldunload", .ret_type = 1, .nargs = 1,
309 .args = { { Int, 0 } } },
310 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
311 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
312 { .name = "kse_release", .ret_type = 0, .nargs = 1,
313 .args = { { Timespec, 0 } } },
314 { .name = "lchflags", .ret_type = 1, .nargs = 2,
315 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
316 { .name = "lchmod", .ret_type = 1, .nargs = 2,
317 .args = { { Name, 0 }, { Octal, 1 } } },
318 { .name = "lchown", .ret_type = 1, .nargs = 3,
319 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
320 { .name = "link", .ret_type = 1, .nargs = 2,
321 .args = { { Name, 0 }, { Name, 1 } } },
322 { .name = "linkat", .ret_type = 1, .nargs = 5,
323 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
325 { .name = "listen", .ret_type = 1, .nargs = 2,
326 .args = { { Int, 0 }, { Int, 1 } } },
327 { .name = "lseek", .ret_type = 2, .nargs = 3,
328 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
329 { .name = "lstat", .ret_type = 1, .nargs = 2,
330 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
331 { .name = "lutimes", .ret_type = 1, .nargs = 2,
332 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
333 { .name = "madvise", .ret_type = 1, .nargs = 3,
334 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
335 { .name = "minherit", .ret_type = 1, .nargs = 3,
336 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
337 { .name = "mkdir", .ret_type = 1, .nargs = 2,
338 .args = { { Name, 0 }, { Octal, 1 } } },
339 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
340 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
341 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
342 .args = { { Name, 0 }, { Octal, 1 } } },
343 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
344 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
345 { .name = "mknod", .ret_type = 1, .nargs = 3,
346 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
347 { .name = "mknodat", .ret_type = 1, .nargs = 4,
348 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
349 { .name = "mlock", .ret_type = 1, .nargs = 2,
350 .args = { { Ptr, 0 }, { Sizet, 1 } } },
351 { .name = "mlockall", .ret_type = 1, .nargs = 1,
352 .args = { { Mlockall, 0 } } },
353 { .name = "mmap", .ret_type = 1, .nargs = 6,
354 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
355 { Int, 4 }, { QuadHex, 5 } } },
356 { .name = "modfind", .ret_type = 1, .nargs = 1,
357 .args = { { Name | IN, 0 } } },
358 { .name = "mount", .ret_type = 1, .nargs = 4,
359 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
360 { .name = "mprotect", .ret_type = 1, .nargs = 3,
361 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
362 { .name = "msync", .ret_type = 1, .nargs = 3,
363 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
364 { .name = "munlock", .ret_type = 1, .nargs = 2,
365 .args = { { Ptr, 0 }, { Sizet, 1 } } },
366 { .name = "munmap", .ret_type = 1, .nargs = 2,
367 .args = { { Ptr, 0 }, { Sizet, 1 } } },
368 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
369 .args = { { Timespec, 0 } } },
370 { .name = "nmount", .ret_type = 1, .nargs = 3,
371 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
372 { .name = "open", .ret_type = 1, .nargs = 3,
373 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
374 { .name = "openat", .ret_type = 1, .nargs = 4,
375 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
377 { .name = "pathconf", .ret_type = 1, .nargs = 2,
378 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
379 { .name = "pipe", .ret_type = 1, .nargs = 1,
380 .args = { { PipeFds | OUT, 0 } } },
381 { .name = "pipe2", .ret_type = 1, .nargs = 2,
382 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
383 { .name = "poll", .ret_type = 1, .nargs = 3,
384 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
385 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
386 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
388 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
389 .args = { { Open, 0 } } },
390 { .name = "pread", .ret_type = 1, .nargs = 4,
391 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
393 { .name = "procctl", .ret_type = 1, .nargs = 4,
394 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
395 { .name = "ptrace", .ret_type = 1, .nargs = 4,
396 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
397 { .name = "pwrite", .ret_type = 1, .nargs = 4,
398 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
400 { .name = "quotactl", .ret_type = 1, .nargs = 4,
401 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
402 { .name = "read", .ret_type = 1, .nargs = 3,
403 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
404 { .name = "readlink", .ret_type = 1, .nargs = 3,
405 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
406 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
407 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
409 { .name = "readv", .ret_type = 1, .nargs = 3,
410 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
411 { .name = "reboot", .ret_type = 1, .nargs = 1,
412 .args = { { Reboothowto, 0 } } },
413 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
414 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
415 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
416 { Ptr | OUT, 5 } } },
417 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
418 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
419 { .name = "rename", .ret_type = 1, .nargs = 2,
420 .args = { { Name, 0 }, { Name, 1 } } },
421 { .name = "renameat", .ret_type = 1, .nargs = 4,
422 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
423 { .name = "rfork", .ret_type = 1, .nargs = 1,
424 .args = { { Rforkflags, 0 } } },
425 { .name = "rmdir", .ret_type = 1, .nargs = 1,
426 .args = { { Name, 0 } } },
427 { .name = "rtprio", .ret_type = 1, .nargs = 3,
428 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
429 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
430 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
431 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
432 .args = { { Schedpolicy, 0 } } },
433 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
434 .args = { { Schedpolicy, 0 } } },
435 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
436 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
437 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
438 .args = { { Int, 0 } } },
439 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
440 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
441 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
442 .args = { { Int, 0 }, { Schedparam, 1 } } },
443 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
444 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
445 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
446 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
447 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
448 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
449 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
450 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
451 { Sockaddr | IN, 3 }, { Socklent, 4 },
452 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
453 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
454 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
455 { Sockaddr | IN, 3 }, { Socklent, 4 },
456 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
457 { .name = "select", .ret_type = 1, .nargs = 5,
458 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
460 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
461 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
462 { .name = "sendto", .ret_type = 1, .nargs = 6,
463 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
464 { Msgflags, 3 }, { Sockaddr | IN, 4 },
465 { Socklent | IN, 5 } } },
466 { .name = "setitimer", .ret_type = 1, .nargs = 3,
467 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
468 { .name = "setpriority", .ret_type = 1, .nargs = 3,
469 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
470 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
471 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
472 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
473 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
474 { Ptr | IN, 3 }, { Socklent, 4 } } },
475 { .name = "shm_open", .ret_type = 1, .nargs = 3,
476 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
477 { .name = "shm_open2", .ret_type = 1, .nargs = 5,
478 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 },
479 { ShmFlags, 3 }, { Name | IN, 4 } } },
480 { .name = "shm_rename", .ret_type = 1, .nargs = 3,
481 .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } },
482 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
483 .args = { { Name | IN, 0 } } },
484 { .name = "shutdown", .ret_type = 1, .nargs = 2,
485 .args = { { Int, 0 }, { Shutdown, 1 } } },
486 { .name = "sigaction", .ret_type = 1, .nargs = 3,
487 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
488 { Sigaction | OUT, 2 } } },
489 { .name = "sigpending", .ret_type = 1, .nargs = 1,
490 .args = { { Sigset | OUT, 0 } } },
491 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
492 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
493 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
494 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
495 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
496 .args = { { Ptr, 0 } } },
497 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
498 .args = { { Sigset | IN, 0 } } },
499 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
500 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
501 { Timespec | IN, 2 } } },
502 { .name = "sigwait", .ret_type = 1, .nargs = 2,
503 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
504 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
505 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
506 { .name = "socket", .ret_type = 1, .nargs = 3,
507 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
508 { .name = "stat", .ret_type = 1, .nargs = 2,
509 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
510 { .name = "statfs", .ret_type = 1, .nargs = 2,
511 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
512 { .name = "symlink", .ret_type = 1, .nargs = 2,
513 .args = { { Name, 0 }, { Name, 1 } } },
514 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
515 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
516 { .name = "sysarch", .ret_type = 1, .nargs = 2,
517 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
518 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
519 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
520 { Ptr, 4 }, { Sizet, 5 } } },
521 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
522 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
523 { Ptr, 4}, { Sizet, 5 } } },
524 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
525 .args = { { Long, 0 }, { Signal, 1 } } },
526 { .name = "thr_self", .ret_type = 1, .nargs = 1,
527 .args = { { Ptr, 0 } } },
528 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
529 .args = { { Long, 0 }, { Name, 1 } } },
530 { .name = "truncate", .ret_type = 1, .nargs = 2,
531 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
534 { .name = "umount", .ret_type = 1, .nargs = 2,
535 .args = { { Name, 0 }, { Int, 2 } } },
537 { .name = "unlink", .ret_type = 1, .nargs = 1,
538 .args = { { Name, 0 } } },
539 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
540 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
541 { .name = "unmount", .ret_type = 1, .nargs = 2,
542 .args = { { Name, 0 }, { Mountflags, 1 } } },
543 { .name = "utimensat", .ret_type = 1, .nargs = 4,
544 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
546 { .name = "utimes", .ret_type = 1, .nargs = 2,
547 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
548 { .name = "utrace", .ret_type = 1, .nargs = 1,
549 .args = { { Utrace, 0 } } },
550 { .name = "wait4", .ret_type = 1, .nargs = 4,
551 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
552 { Rusage | OUT, 3 } } },
553 { .name = "wait6", .ret_type = 1, .nargs = 6,
554 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
555 { Waitoptions, 3 }, { Rusage | OUT, 4 },
556 { Siginfo | OUT, 5 } } },
557 { .name = "write", .ret_type = 1, .nargs = 3,
558 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
559 { .name = "writev", .ret_type = 1, .nargs = 3,
560 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
563 { .name = "linux_access", .ret_type = 1, .nargs = 2,
564 .args = { { Name, 0 }, { Accessmode, 1 } } },
565 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
566 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
567 { ExecEnv | IN, 2 } } },
568 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
569 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
570 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
571 .args = { { Name | IN, 0 }, { Int, 1 } } },
572 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
573 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
574 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
575 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
576 { .name = "linux_open", .ret_type = 1, .nargs = 3,
577 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
578 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
579 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
580 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
581 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
582 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
583 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
585 /* CloudABI system calls. */
586 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
587 .args = { { CloudABIClockID, 0 } } },
588 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
589 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
590 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
591 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
592 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
593 .args = { { Int, 0 } } },
594 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
595 .args = { { CloudABIFileType, 0 } } },
596 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
597 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
598 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
599 .args = { { Int, 0 } } },
600 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
601 .args = { { Int, 0 } } },
602 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
603 .args = { { Int, 0 }, { Int, 1 } } },
604 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
605 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
606 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
607 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
608 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
609 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
610 { CloudABIFDSFlags, 2 } } },
611 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
612 .args = { { Int, 0 } } },
613 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
614 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
615 { CloudABIAdvice, 3 } } },
616 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
617 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
618 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
619 .args = { { Int, 0 }, { BinString | IN, 1 },
620 { CloudABIFileType, 3 } } },
621 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
622 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
623 { Int, 3 }, { BinString | IN, 4 } } },
624 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
625 .args = { { Int, 0 }, { BinString | IN, 1 },
626 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
627 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
628 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
630 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
631 .args = { { Int, 0 }, { BinString | IN, 1 },
632 { BinString | OUT, 3 }, { Int, 4 } } },
633 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
634 .args = { { Int, 0 }, { BinString | IN, 1 },
635 { Int, 3 }, { BinString | IN, 4 } } },
636 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
637 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
638 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
639 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
640 { CloudABIFSFlags, 2 } } },
641 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
642 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
643 { CloudABIFileStat | OUT, 3 } } },
644 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
645 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
646 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
647 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
648 .args = { { BinString | IN, 0 },
649 { Int, 2 }, { BinString | IN, 3 } } },
650 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
651 .args = { { Int, 0 }, { BinString | IN, 1 },
652 { CloudABIULFlags, 3 } } },
653 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
654 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
655 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
656 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
657 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
658 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
659 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
660 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
661 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
662 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
663 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
664 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
665 .args = { { Ptr, 0 }, { Int, 1 } } },
666 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
667 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
668 { IntArray, 3 }, { Int, 4 } } },
669 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
670 .args = { { Int, 0 } } },
671 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
672 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
673 .args = { { CloudABISignal, 0 } } },
674 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
675 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
676 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
677 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
678 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
679 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
680 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
684 static STAILQ_HEAD(, syscall) syscalls;
686 /* Xlat idea taken from strace */
692 #define X(a) { a, #a },
693 #define XEND { 0, NULL }
695 static struct xlat poll_flags[] = {
696 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
697 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
698 X(POLLWRBAND) X(POLLINIGNEOF) XEND
701 static struct xlat sigaction_flags[] = {
702 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
703 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
706 static struct xlat linux_socketcall_ops[] = {
707 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
708 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
709 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
710 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
711 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
716 #define X(a) { CLOUDABI_##a, #a },
718 static struct xlat cloudabi_advice[] = {
719 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
720 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
724 static struct xlat cloudabi_clockid[] = {
725 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
726 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
730 static struct xlat cloudabi_fdflags[] = {
731 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
732 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
736 static struct xlat cloudabi_fdsflags[] = {
737 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
741 static struct xlat cloudabi_filetype[] = {
742 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
743 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
744 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
745 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
746 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
750 static struct xlat cloudabi_fsflags[] = {
751 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
752 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
756 static struct xlat cloudabi_mflags[] = {
757 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
761 static struct xlat cloudabi_mprot[] = {
762 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
766 static struct xlat cloudabi_msflags[] = {
767 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
771 static struct xlat cloudabi_oflags[] = {
772 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
776 static struct xlat cloudabi_sdflags[] = {
777 X(SHUT_RD) X(SHUT_WR)
781 static struct xlat cloudabi_signal[] = {
782 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
783 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
784 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
785 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
786 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
790 static struct xlat cloudabi_ulflags[] = {
795 static struct xlat cloudabi_whence[] = {
796 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
804 * Searches an xlat array for a value, and returns it if found. Otherwise
805 * return a string representation.
808 lookup(struct xlat *xlat, int val, int base)
812 for (; xlat->str != NULL; xlat++)
813 if (xlat->val == val)
817 sprintf(tmp, "0%o", val);
820 sprintf(tmp, "0x%x", val);
823 sprintf(tmp, "%u", val);
826 errx(1,"Unknown lookup base");
833 xlookup(struct xlat *xlat, int val)
836 return (lookup(xlat, val, 16));
840 * Searches an xlat array containing bitfield values. Remaining bits
841 * set after removing the known ones are printed at the end:
845 xlookup_bits(struct xlat *xlat, int val)
848 static char str[512];
852 for (; xlat->str != NULL; xlat++) {
853 if ((xlat->val & rem) == xlat->val) {
855 * Don't print the "all-bits-zero" string unless all
856 * bits are really zero.
858 if (xlat->val == 0 && val != 0)
860 len += sprintf(str + len, "%s|", xlat->str);
866 * If we have leftover bits or didn't match anything, print
870 len += sprintf(str + len, "0x%x", rem);
871 if (len && str[len - 1] == '|')
878 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
882 str = decoder(value);
886 fprintf(fp, "%d", value);
890 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
894 if (!decoder(fp, value, &rem))
895 fprintf(fp, "0x%x", rem);
897 fprintf(fp, "|0x%x", rem);
901 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
906 if (!decoder(fp, value, &rem))
907 fprintf(fp, "0x%x", rem);
909 fprintf(fp, "|0x%x", rem);
914 * Add argument padding to subsequent system calls after Quad
915 * syscall arguments as needed. This used to be done by hand in the
916 * decoded_syscalls table which was ugly and error prone. It is
917 * simpler to do the fixup of offsets at initialization time than when
918 * decoding arguments.
921 quad_fixup(struct syscall *sc)
928 for (i = 0; i < sc->nargs; i++) {
929 /* This arg type is a dummy that doesn't use offset. */
930 if ((sc->args[i].type & ARG_MASK) == PipeFds)
933 assert(prev < sc->args[i].offset);
934 prev = sc->args[i].offset;
935 sc->args[i].offset += offset;
936 switch (sc->args[i].type & ARG_MASK) {
941 * 64-bit arguments on 32-bit powerpc must be
942 * 64-bit aligned. If the current offset is
943 * not aligned, the calling convention inserts
944 * a 32-bit pad argument that should be skipped.
946 if (sc->args[i].offset % 2 == 1) {
947 sc->args[i].offset++;
964 STAILQ_INIT(&syscalls);
965 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
969 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
973 static struct syscall *
974 find_syscall(struct procabi *abi, u_int number)
976 struct extra_syscall *es;
978 if (number < nitems(abi->syscalls))
979 return (abi->syscalls[number]);
980 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
981 if (es->number == number)
988 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
990 struct extra_syscall *es;
992 if (number < nitems(abi->syscalls)) {
993 assert(abi->syscalls[number] == NULL);
994 abi->syscalls[number] = sc;
996 es = malloc(sizeof(*es));
999 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
1004 * If/when the list gets big, it might be desirable to do it
1005 * as a hash table or binary search.
1008 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1015 sc = find_syscall(t->proc->abi, number);
1019 name = sysdecode_syscallname(t->proc->abi->abi, number);
1021 asprintf(&new_name, "#%d", number);
1025 STAILQ_FOREACH(sc, &syscalls, entries) {
1026 if (strcmp(name, sc->name) == 0) {
1027 add_syscall(t->proc->abi, number, sc);
1033 /* It is unknown. Add it into the list. */
1035 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1039 sc = calloc(1, sizeof(struct syscall));
1041 if (new_name != NULL)
1045 for (i = 0; i < nargs; i++) {
1046 sc->args[i].offset = i;
1047 /* Treat all unknown arguments as LongHex. */
1048 sc->args[i].type = LongHex;
1050 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1051 add_syscall(t->proc->abi, number, sc);
1057 * Copy a fixed amount of bytes from the process.
1060 get_struct(pid_t pid, uintptr_t offset, void *buf, int len)
1062 struct ptrace_io_desc iorequest;
1064 iorequest.piod_op = PIOD_READ_D;
1065 iorequest.piod_offs = (void *)offset;
1066 iorequest.piod_addr = buf;
1067 iorequest.piod_len = len;
1068 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1073 #define MAXSIZE 4096
1076 * Copy a string from the process. Note that it is
1077 * expected to be a C string, but if max is set, it will
1078 * only get that much.
1081 get_string(pid_t pid, uintptr_t addr, int max)
1083 struct ptrace_io_desc iorequest;
1085 size_t offset, size, totalsize;
1091 /* Read up to the end of the current page. */
1092 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1097 buf = malloc(totalsize);
1101 iorequest.piod_op = PIOD_READ_D;
1102 iorequest.piod_offs = (void *)(addr + offset);
1103 iorequest.piod_addr = buf + offset;
1104 iorequest.piod_len = size;
1105 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1109 if (memchr(buf + offset, '\0', size) != NULL)
1112 if (totalsize < MAXSIZE && max == 0) {
1113 size = MAXSIZE - totalsize;
1114 if (size > PAGE_SIZE)
1116 nbuf = realloc(buf, totalsize + size);
1118 buf[totalsize - 1] = '\0';
1124 buf[totalsize - 1] = '\0';
1133 static char tmp[32];
1134 const char *signame;
1136 signame = sysdecode_signal(sig);
1137 if (signame == NULL) {
1138 snprintf(tmp, sizeof(tmp), "%d", sig);
1145 print_kevent(FILE *fp, struct kevent *ke)
1148 switch (ke->filter) {
1154 case EVFILT_PROCDESC:
1156 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1159 fputs(strsig2(ke->ident), fp);
1162 fprintf(fp, "%p", (void *)ke->ident);
1165 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1167 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1169 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1170 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1174 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1176 unsigned char *utrace_buffer;
1179 if (sysdecode_utrace(fp, utrace_addr, len)) {
1184 utrace_buffer = utrace_addr;
1185 fprintf(fp, "%zu:", len);
1187 fprintf(fp, " %02x", *utrace_buffer++);
1192 print_pointer(FILE *fp, uintptr_t arg)
1195 fprintf(fp, "%p", (void *)arg);
1199 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg,
1203 struct sockaddr_in *lsin;
1204 struct sockaddr_in6 *lsin6;
1205 struct sockaddr_un *sun;
1206 struct sockaddr *sa;
1208 pid_t pid = trussinfo->curthread->proc->pid;
1214 /* If the length is too small, just bail. */
1215 if (len < sizeof(*sa)) {
1216 print_pointer(fp, arg);
1220 sa = calloc(1, len);
1221 if (get_struct(pid, arg, sa, len) == -1) {
1223 print_pointer(fp, arg);
1227 switch (sa->sa_family) {
1229 if (len < sizeof(*lsin))
1230 goto sockaddr_short;
1231 lsin = (struct sockaddr_in *)(void *)sa;
1232 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1233 fprintf(fp, "{ AF_INET %s:%d }", addr,
1234 htons(lsin->sin_port));
1237 if (len < sizeof(*lsin6))
1238 goto sockaddr_short;
1239 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1240 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1242 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1243 htons(lsin6->sin6_port));
1246 sun = (struct sockaddr_un *)sa;
1247 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1248 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1254 "{ sa_len = %d, sa_family = %d, sa_data = {",
1255 (int)sa->sa_len, (int)sa->sa_family);
1256 for (q = (u_char *)sa->sa_data;
1257 q < (u_char *)sa + len; q++)
1258 fprintf(fp, "%s 0x%02x",
1259 q == (u_char *)sa->sa_data ? "" : ",",
1266 #define IOV_LIMIT 16
1269 print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
1271 struct iovec iov[IOV_LIMIT];
1272 size_t max_string = trussinfo->strsize;
1273 char tmp2[max_string + 1], *tmp3;
1275 pid_t pid = trussinfo->curthread->proc->pid;
1277 bool buf_truncated, iov_truncated;
1280 print_pointer(fp, arg);
1283 if (iovcnt > IOV_LIMIT) {
1285 iov_truncated = true;
1287 iov_truncated = false;
1289 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1290 print_pointer(fp, arg);
1295 for (i = 0; i < iovcnt; i++) {
1296 len = iov[i].iov_len;
1297 if (len > max_string) {
1299 buf_truncated = true;
1301 buf_truncated = false;
1303 fprintf(fp, "%s{", (i > 0) ? "," : "");
1304 if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
1305 tmp3 = malloc(len * 4 + 1);
1307 if (strvisx(tmp3, tmp2, len,
1308 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1312 buf_truncated = true;
1314 fprintf(fp, "\"%s\"%s", tmp3,
1315 buf_truncated ? "..." : "");
1318 print_pointer(fp, (uintptr_t)iov[i].iov_base);
1320 fprintf(fp, ",%zu}", iov[i].iov_len);
1322 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1326 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1331 for (q = CMSG_DATA(cmsghdr);
1332 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1333 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1339 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1341 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1342 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1343 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1344 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1348 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1350 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1352 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1355 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1356 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1358 fprintf(fp, "ctx=%u,", info->sinfo_context);
1359 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1362 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1363 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1365 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1369 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1371 fprintf(fp, "{sid=%u,", info->snd_sid);
1373 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1374 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1375 fprintf(fp, "ctx=%u,", info->snd_context);
1376 fprintf(fp, "id=%u}", info->snd_assoc_id);
1380 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1382 fprintf(fp, "{sid=%u,", info->rcv_sid);
1383 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1385 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1386 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1387 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1388 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1389 fprintf(fp, "ctx=%u,", info->rcv_context);
1390 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1394 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1396 fprintf(fp, "{sid=%u,", info->nxt_sid);
1398 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1399 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1400 fprintf(fp, "len=%u,", info->nxt_length);
1401 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1405 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1408 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1409 fprintf(fp, ",val=%u}", info->pr_value);
1413 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1415 fprintf(fp, "{num=%u}", info->auth_keynumber);
1419 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1421 char buf[INET_ADDRSTRLEN];
1424 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1426 fprintf(fp, "{addr=%s}", s);
1428 fputs("{addr=???}", fp);
1432 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1434 char buf[INET6_ADDRSTRLEN];
1437 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1439 fprintf(fp, "{addr=%s}", s);
1441 fputs("{addr=???}", fp);
1445 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1450 len = cmsghdr->cmsg_len;
1451 data = CMSG_DATA(cmsghdr);
1452 switch (cmsghdr->cmsg_type) {
1454 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1455 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1457 print_gen_cmsg(fp, cmsghdr);
1460 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1461 print_sctp_sndrcvinfo(fp, receive,
1462 (struct sctp_sndrcvinfo *)data);
1464 print_gen_cmsg(fp, cmsghdr);
1468 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1469 print_sctp_extrcvinfo(fp,
1470 (struct sctp_extrcvinfo *)data);
1472 print_gen_cmsg(fp, cmsghdr);
1476 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1477 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1479 print_gen_cmsg(fp, cmsghdr);
1482 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1483 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1485 print_gen_cmsg(fp, cmsghdr);
1488 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1489 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1491 print_gen_cmsg(fp, cmsghdr);
1494 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1495 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1497 print_gen_cmsg(fp, cmsghdr);
1500 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1501 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1503 print_gen_cmsg(fp, cmsghdr);
1505 case SCTP_DSTADDRV4:
1506 if (len == CMSG_LEN(sizeof(struct in_addr)))
1507 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1509 print_gen_cmsg(fp, cmsghdr);
1511 case SCTP_DSTADDRV6:
1512 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1513 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1515 print_gen_cmsg(fp, cmsghdr);
1518 print_gen_cmsg(fp, cmsghdr);
1523 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1525 struct cmsghdr *cmsghdr;
1532 len = msghdr->msg_controllen;
1537 cmsgbuf = calloc(1, len);
1538 if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
1539 print_pointer(fp, (uintptr_t)msghdr->msg_control);
1543 msghdr->msg_control = cmsgbuf;
1546 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1548 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1549 level = cmsghdr->cmsg_level;
1550 type = cmsghdr->cmsg_type;
1551 len = cmsghdr->cmsg_len;
1552 fprintf(fp, "%s{level=", first ? "" : ",");
1553 print_integer_arg(sysdecode_sockopt_level, fp, level);
1554 fputs(",type=", fp);
1555 temp = sysdecode_cmsg_type(level, type);
1559 fprintf(fp, "%d", type);
1561 fputs(",data=", fp);
1564 print_sctp_cmsg(fp, receive, cmsghdr);
1567 print_gen_cmsg(fp, cmsghdr);
1578 print_sysctl_oid(FILE *fp, int *oid, int len)
1582 for (i = 0; i < len; i++)
1583 fprintf(fp, ".%d", oid[i]);
1587 * Converts a syscall argument into a string. Said string is
1588 * allocated via malloc(), so needs to be free()'d. sc is
1589 * a pointer to the syscall description (see above); args is
1590 * an array of all of the system call arguments.
1593 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1594 struct trussinfo *trussinfo)
1601 fp = open_memstream(&tmp, &tmplen);
1602 pid = trussinfo->curthread->proc->pid;
1603 switch (sc->type & ARG_MASK) {
1605 fprintf(fp, "0x%x", (int)args[sc->offset]);
1608 fprintf(fp, "0%o", (int)args[sc->offset]);
1611 fprintf(fp, "%d", (int)args[sc->offset]);
1614 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1619 if (get_struct(pid, args[sc->offset], &val,
1621 fprintf(fp, "{ %u }", val);
1623 print_pointer(fp, args[sc->offset]);
1627 fprintf(fp, "0x%lx", args[sc->offset]);
1630 fprintf(fp, "%ld", args[sc->offset]);
1633 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1636 /* Handle special SHM_ANON value. */
1637 if ((char *)args[sc->offset] == SHM_ANON) {
1638 fprintf(fp, "SHM_ANON");
1643 /* NULL-terminated string. */
1646 tmp2 = get_string(pid, args[sc->offset], 0);
1647 fprintf(fp, "\"%s\"", tmp2);
1653 * Binary block of data that might have printable characters.
1654 * XXX If type|OUT, assume that the length is the syscall's
1655 * return value. Otherwise, assume that the length of the block
1656 * is in the next syscall argument.
1658 int max_string = trussinfo->strsize;
1659 char tmp2[max_string + 1], *tmp3;
1666 len = args[sc->offset + 1];
1669 * Don't print more than max_string characters, to avoid word
1670 * wrap. If we have to truncate put some ... after the string.
1672 if (len > max_string) {
1676 if (len && get_struct(pid, args[sc->offset], &tmp2, len)
1678 tmp3 = malloc(len * 4 + 1);
1680 if (strvisx(tmp3, tmp2, len,
1681 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1686 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1690 print_pointer(fp, args[sc->offset]);
1700 char buf[PAGE_SIZE];
1707 * Only parse argv[] and environment arrays from exec calls
1710 if (((sc->type & ARG_MASK) == ExecArgs &&
1711 (trussinfo->flags & EXECVEARGS) == 0) ||
1712 ((sc->type & ARG_MASK) == ExecEnv &&
1713 (trussinfo->flags & EXECVEENVS) == 0)) {
1714 print_pointer(fp, args[sc->offset]);
1719 * Read a page of pointers at a time. Punt if the top-level
1720 * pointer is not aligned. Note that the first read is of
1723 addr = args[sc->offset];
1724 if (addr % sizeof(char *) != 0) {
1725 print_pointer(fp, args[sc->offset]);
1729 len = PAGE_SIZE - (addr & PAGE_MASK);
1730 if (get_struct(pid, addr, u.buf, len) == -1) {
1731 print_pointer(fp, args[sc->offset]);
1738 while (u.strarray[i] != NULL) {
1739 string = get_string(pid, (uintptr_t)u.strarray[i], 0);
1740 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1745 if (i == len / sizeof(char *)) {
1748 if (get_struct(pid, addr, u.buf, len) ==
1750 fprintf(fp, ", <inval>");
1761 fprintf(fp, "%ld", args[sc->offset]);
1764 fprintf(fp, "0x%lx", args[sc->offset]);
1769 unsigned long long ll;
1771 #if _BYTE_ORDER == _LITTLE_ENDIAN
1772 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1775 ll = (unsigned long long)args[sc->offset] << 32 |
1776 args[sc->offset + 1];
1778 if ((sc->type & ARG_MASK) == Quad)
1779 fprintf(fp, "%lld", ll);
1781 fprintf(fp, "0x%llx", ll);
1788 if (get_struct(pid, args[sc->offset], &val,
1790 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1792 print_pointer(fp, args[sc->offset]);
1796 print_pointer(fp, args[sc->offset]);
1801 if (retval[0] == -1)
1803 tmp2 = get_string(pid, args[sc->offset], retval[0]);
1804 fprintf(fp, "\"%s\"", tmp2);
1812 cmd = args[sc->offset];
1813 temp = sysdecode_ioctlname(cmd);
1817 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1818 cmd, cmd & IOC_OUT ? "R" : "",
1819 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1820 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1821 cmd & 0xFF, IOCPARM_LEN(cmd));
1828 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
1829 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1832 print_pointer(fp, args[sc->offset]);
1836 struct timespec ts[2];
1840 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
1843 for (i = 0; i < nitems(ts); i++) {
1846 switch (ts[i].tv_nsec) {
1848 fprintf(fp, "UTIME_NOW");
1851 fprintf(fp, "UTIME_OMIT");
1854 fprintf(fp, "%jd.%09ld",
1855 (intmax_t)ts[i].tv_sec,
1862 print_pointer(fp, args[sc->offset]);
1868 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1869 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1872 print_pointer(fp, args[sc->offset]);
1876 struct timeval tv[2];
1878 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1879 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1880 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1881 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1883 print_pointer(fp, args[sc->offset]);
1887 struct itimerval itv;
1889 if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
1890 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1891 (intmax_t)itv.it_interval.tv_sec,
1892 itv.it_interval.tv_usec,
1893 (intmax_t)itv.it_value.tv_sec,
1894 itv.it_value.tv_usec);
1896 print_pointer(fp, args[sc->offset]);
1901 struct linux_socketcall_args largs;
1903 if (get_struct(pid, args[sc->offset], (void *)&largs,
1904 sizeof(largs)) != -1)
1905 fprintf(fp, "{ %s, 0x%lx }",
1906 lookup(linux_socketcall_ops, largs.what, 10),
1907 (long unsigned int)largs.args);
1909 print_pointer(fp, args[sc->offset]);
1914 * XXX: A Pollfd argument expects the /next/ syscall argument
1915 * to be the number of fds in the array. This matches the poll
1919 int numfds = args[sc->offset + 1];
1920 size_t bytes = sizeof(struct pollfd) * numfds;
1923 if ((pfd = malloc(bytes)) == NULL)
1924 err(1, "Cannot malloc %zu bytes for pollfd array",
1926 if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
1928 for (i = 0; i < numfds; i++) {
1929 fprintf(fp, " %d/%s", pfd[i].fd,
1930 xlookup_bits(poll_flags, pfd[i].events));
1934 print_pointer(fp, args[sc->offset]);
1941 * XXX: A Fd_set argument expects the /first/ syscall argument
1942 * to be the number of fds in the array. This matches the
1946 int numfds = args[0];
1947 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1950 if ((fds = malloc(bytes)) == NULL)
1951 err(1, "Cannot malloc %zu bytes for fd_set array",
1953 if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
1955 for (i = 0; i < numfds; i++) {
1956 if (FD_ISSET(i, fds))
1957 fprintf(fp, " %d", i);
1961 print_pointer(fp, args[sc->offset]);
1966 fputs(strsig2(args[sc->offset]), fp);
1973 sig = args[sc->offset];
1974 if (get_struct(pid, args[sc->offset], (void *)&ss,
1975 sizeof(ss)) == -1) {
1976 print_pointer(fp, args[sc->offset]);
1981 for (i = 1; i < sys_nsig; i++) {
1982 if (sigismember(&ss, i)) {
1983 fprintf(fp, "%s%s", !first ? "|" : "",
1994 print_integer_arg(sysdecode_sigprocmask_how, fp,
1998 /* XXX: Output depends on the value of the previous argument. */
1999 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
2000 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
2001 args[sc->offset], 16);
2004 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2007 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2010 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2013 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2016 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2019 print_mask_arg(sysdecode_shmflags, fp, args[sc->offset]);
2022 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2025 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2028 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2031 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2034 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2037 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2040 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2045 if (args[sc->offset] == 0) {
2051 * Extract the address length from the next argument. If
2052 * this is an output sockaddr (OUT is set), then the
2053 * next argument is a pointer to a socklen_t. Otherwise
2054 * the next argument contains a socklen_t by value.
2056 if (sc->type & OUT) {
2057 if (get_struct(pid, args[sc->offset + 1], &len,
2058 sizeof(len)) == -1) {
2059 print_pointer(fp, args[sc->offset]);
2063 len = args[sc->offset + 1];
2065 print_sockaddr(fp, trussinfo, args[sc->offset], len);
2069 struct sigaction sa;
2071 if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
2073 if (sa.sa_handler == SIG_DFL)
2074 fputs("SIG_DFL", fp);
2075 else if (sa.sa_handler == SIG_IGN)
2076 fputs("SIG_IGN", fp);
2078 fprintf(fp, "%p", sa.sa_handler);
2079 fprintf(fp, " %s ss_t }",
2080 xlookup_bits(sigaction_flags, sa.sa_flags));
2082 print_pointer(fp, args[sc->offset]);
2087 * XXX XXX: The size of the array is determined by either the
2088 * next syscall argument, or by the syscall return value,
2089 * depending on which argument number we are. This matches the
2090 * kevent syscall, but luckily that's the only syscall that uses
2098 if (sc->offset == 1)
2099 numevents = args[sc->offset+1];
2100 else if (sc->offset == 3 && retval[0] != -1)
2101 numevents = retval[0];
2103 if (numevents >= 0) {
2104 bytes = sizeof(struct kevent) * numevents;
2105 if ((ke = malloc(bytes)) == NULL)
2107 "Cannot malloc %zu bytes for kevent array",
2111 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2114 for (i = 0; i < numevents; i++) {
2116 print_kevent(fp, &ke[i]);
2120 print_pointer(fp, args[sc->offset]);
2126 struct kevent_freebsd11 *ke11;
2132 if (sc->offset == 1)
2133 numevents = args[sc->offset+1];
2134 else if (sc->offset == 3 && retval[0] != -1)
2135 numevents = retval[0];
2137 if (numevents >= 0) {
2138 bytes = sizeof(struct kevent_freebsd11) * numevents;
2139 if ((ke11 = malloc(bytes)) == NULL)
2141 "Cannot malloc %zu bytes for kevent array",
2145 memset(&ke, 0, sizeof(ke));
2146 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2147 ke11, bytes) != -1) {
2149 for (i = 0; i < numevents; i++) {
2151 ke.ident = ke11[i].ident;
2152 ke.filter = ke11[i].filter;
2153 ke.flags = ke11[i].flags;
2154 ke.fflags = ke11[i].fflags;
2155 ke.data = ke11[i].data;
2156 ke.udata = ke11[i].udata;
2157 print_kevent(fp, &ke);
2161 print_pointer(fp, args[sc->offset]);
2169 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2173 strmode(st.st_mode, mode);
2175 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2176 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2177 (long)st.st_blksize);
2179 print_pointer(fp, args[sc->offset]);
2184 struct freebsd11_stat st;
2186 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2190 strmode(st.st_mode, mode);
2192 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2193 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2194 (long)st.st_blksize);
2196 print_pointer(fp, args[sc->offset]);
2204 if (get_struct(pid, args[sc->offset], &buf,
2205 sizeof(buf)) != -1) {
2208 bzero(fsid, sizeof(fsid));
2209 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2210 for (i = 0; i < sizeof(buf.f_fsid); i++)
2211 snprintf(&fsid[i*2],
2212 sizeof(fsid) - (i*2), "%02x",
2213 ((u_char *)&buf.f_fsid)[i]);
2216 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2217 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2218 buf.f_mntfromname, fsid);
2220 print_pointer(fp, args[sc->offset]);
2227 if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
2230 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2231 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2232 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2233 ru.ru_inblock, ru.ru_oublock);
2235 print_pointer(fp, args[sc->offset]);
2241 if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
2243 fprintf(fp, "{ cur=%ju,max=%ju }",
2244 rl.rlim_cur, rl.rlim_max);
2246 print_pointer(fp, args[sc->offset]);
2252 if (get_struct(pid, args[sc->offset], &status,
2253 sizeof(status)) != -1) {
2255 if (WIFCONTINUED(status))
2256 fputs("CONTINUED", fp);
2257 else if (WIFEXITED(status))
2258 fprintf(fp, "EXITED,val=%d",
2259 WEXITSTATUS(status));
2260 else if (WIFSIGNALED(status))
2261 fprintf(fp, "SIGNALED,sig=%s%s",
2262 strsig2(WTERMSIG(status)),
2263 WCOREDUMP(status) ? ",cored" : "");
2265 fprintf(fp, "STOPPED,sig=%s",
2266 strsig2(WTERMSIG(status)));
2269 print_pointer(fp, args[sc->offset]);
2273 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2276 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2279 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2282 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2285 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2288 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2291 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2294 print_integer_arg(sysdecode_sysarch_number, fp,
2299 int oid[CTL_MAXNAME + 2], qoid[CTL_MAXNAME + 2];
2303 memset(name, 0, sizeof(name));
2304 len = args[sc->offset + 1];
2305 if (get_struct(pid, args[sc->offset], oid,
2306 len * sizeof(oid[0])) != -1) {
2308 if (oid[0] == CTL_SYSCTL) {
2309 fprintf(fp, "sysctl.");
2311 case CTL_SYSCTL_DEBUG:
2312 fprintf(fp, "debug");
2314 case CTL_SYSCTL_NAME:
2315 fprintf(fp, "name");
2316 print_sysctl_oid(fp, oid + 2, len - 2);
2318 case CTL_SYSCTL_NEXT:
2319 fprintf(fp, "next");
2321 case CTL_SYSCTL_NAME2OID:
2322 fprintf(fp, "name2oid");
2324 case CTL_SYSCTL_OIDFMT:
2325 fprintf(fp, "oidfmt");
2326 print_sysctl_oid(fp, oid + 2, len - 2);
2328 case CTL_SYSCTL_OIDDESCR:
2329 fprintf(fp, "oiddescr");
2330 print_sysctl_oid(fp, oid + 2, len - 2);
2332 case CTL_SYSCTL_OIDLABEL:
2333 fprintf(fp, "oidlabel");
2334 print_sysctl_oid(fp, oid + 2, len - 2);
2337 print_sysctl_oid(fp, oid + 1, len - 1);
2340 qoid[0] = CTL_SYSCTL;
2341 qoid[1] = CTL_SYSCTL_NAME;
2342 memcpy(qoid + 2, oid, len * sizeof(int));
2344 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
2345 print_sysctl_oid(fp, qoid + 2, len);
2347 fprintf(fp, "%s", name);
2355 * The pipe() system call in the kernel returns its
2356 * two file descriptors via return values. However,
2357 * the interface exposed by libc is that pipe()
2358 * accepts a pointer to an array of descriptors.
2359 * Format the output to match the libc API by printing
2360 * the returned file descriptors as a fake argument.
2362 * Overwrite the first retval to signal a successful
2365 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2372 len = args[sc->offset + 1];
2373 utrace_addr = calloc(1, len);
2374 if (get_struct(pid, args[sc->offset],
2375 (void *)utrace_addr, len) != -1)
2376 print_utrace(fp, utrace_addr, len);
2378 print_pointer(fp, args[sc->offset]);
2383 int descriptors[16];
2384 unsigned long i, ndescriptors;
2387 ndescriptors = args[sc->offset + 1];
2389 if (ndescriptors > nitems(descriptors)) {
2390 ndescriptors = nitems(descriptors);
2393 if (get_struct(pid, args[sc->offset],
2394 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2396 for (i = 0; i < ndescriptors; i++)
2397 fprintf(fp, i == 0 ? " %d" : ", %d",
2399 fprintf(fp, truncated ? ", ... }" : " }");
2401 print_pointer(fp, args[sc->offset]);
2405 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2407 case CapFcntlRights: {
2410 if (sc->type & OUT) {
2411 if (get_struct(pid, args[sc->offset], &rights,
2412 sizeof(rights)) == -1) {
2413 print_pointer(fp, args[sc->offset]);
2417 rights = args[sc->offset];
2418 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2422 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2427 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2428 fprintf(fp, "0x%x", rem);
2430 fprintf(fp, "|0x%x", rem);
2434 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2437 print_integer_arg(sysdecode_getfsstat_mode, fp,
2441 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2443 case Kldunloadflags:
2444 print_integer_arg(sysdecode_kldunload_flags, fp,
2448 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2451 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2453 case Sockprotocol: {
2455 int domain, protocol;
2457 domain = args[sc->offset - 2];
2458 protocol = args[sc->offset];
2459 if (protocol == 0) {
2462 temp = sysdecode_socket_protocol(domain, protocol);
2466 fprintf(fp, "%d", protocol);
2472 print_integer_arg(sysdecode_sockopt_level, fp,
2479 level = args[sc->offset - 1];
2480 name = args[sc->offset];
2481 temp = sysdecode_sockopt_name(level, name);
2485 fprintf(fp, "%d", name);
2490 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2493 cap_rights_t rights;
2495 if (get_struct(pid, args[sc->offset], &rights,
2496 sizeof(rights)) != -1) {
2498 sysdecode_cap_rights(fp, &rights);
2501 print_pointer(fp, args[sc->offset]);
2505 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2507 case Extattrnamespace:
2508 print_integer_arg(sysdecode_extattrnamespace, fp,
2512 print_integer_arg(sysdecode_minherit_inherit, fp,
2516 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2519 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2522 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2525 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2528 print_integer_arg(sysdecode_ptrace_request, fp,
2532 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2533 fprintf(fp, "%#x", (int)args[sc->offset]);
2536 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2539 print_integer_arg(sysdecode_rtprio_function, fp,
2543 print_integer_arg(sysdecode_scheduler_policy, fp,
2547 struct sched_param sp;
2549 if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
2550 fprintf(fp, "{ %d }", sp.sched_priority);
2552 print_pointer(fp, args[sc->offset]);
2558 if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
2559 fprintf(fp, "{ %s }", strsig2(sig));
2561 print_pointer(fp, args[sc->offset]);
2567 if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
2568 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2569 decode_siginfo(fp, &si);
2572 print_pointer(fp, args[sc->offset]);
2577 * Print argument as an array of struct iovec, where the next
2578 * syscall argument is the number of elements of the array.
2581 print_iovec(fp, trussinfo, args[sc->offset],
2582 (int)args[sc->offset + 1]);
2584 case Sctpsndrcvinfo: {
2585 struct sctp_sndrcvinfo info;
2587 if (get_struct(pid, args[sc->offset],
2588 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2589 print_pointer(fp, args[sc->offset]);
2592 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2596 struct msghdr msghdr;
2598 if (get_struct(pid, args[sc->offset],
2599 &msghdr, sizeof(struct msghdr)) == -1) {
2600 print_pointer(fp, args[sc->offset]);
2604 print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
2605 fprintf(fp, ",%d,", msghdr.msg_namelen);
2606 print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
2607 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2608 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2609 fprintf(fp, ",%u,", msghdr.msg_controllen);
2610 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2615 case CloudABIAdvice:
2616 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2618 case CloudABIClockID:
2619 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2621 case CloudABIFDSFlags:
2622 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2624 case CloudABIFDStat: {
2625 cloudabi_fdstat_t fds;
2626 if (get_struct(pid, args[sc->offset], &fds, sizeof(fds))
2628 fprintf(fp, "{ %s, ",
2629 xlookup(cloudabi_filetype, fds.fs_filetype));
2630 fprintf(fp, "%s, ... }",
2631 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2633 print_pointer(fp, args[sc->offset]);
2636 case CloudABIFileStat: {
2637 cloudabi_filestat_t fsb;
2638 if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb))
2640 fprintf(fp, "{ %s, %ju }",
2641 xlookup(cloudabi_filetype, fsb.st_filetype),
2642 (uintmax_t)fsb.st_size);
2644 print_pointer(fp, args[sc->offset]);
2647 case CloudABIFileType:
2648 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2650 case CloudABIFSFlags:
2651 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2653 case CloudABILookup:
2654 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2655 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2656 (int)args[sc->offset]);
2658 fprintf(fp, "%d", (int)args[sc->offset]);
2660 case CloudABIMFlags:
2661 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2664 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2666 case CloudABIMSFlags:
2667 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2669 case CloudABIOFlags:
2670 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2672 case CloudABISDFlags:
2673 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2675 case CloudABISignal:
2676 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2678 case CloudABITimestamp:
2679 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2680 args[sc->offset] % 1000000000);
2682 case CloudABIULFlags:
2683 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2685 case CloudABIWhence:
2686 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2690 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2697 * Print (to outfile) the system call and its arguments.
2700 print_syscall(struct trussinfo *trussinfo)
2702 struct threadinfo *t;
2707 t = trussinfo->curthread;
2709 name = t->cs.sc->name;
2710 nargs = t->cs.nargs;
2711 s_args = t->cs.s_args;
2713 len = print_line_prefix(trussinfo);
2714 len += fprintf(trussinfo->outfile, "%s(", name);
2716 for (i = 0; i < nargs; i++) {
2717 if (s_args[i] != NULL)
2718 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2720 len += fprintf(trussinfo->outfile,
2721 "<missing argument>");
2722 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2725 len += fprintf(trussinfo->outfile, ")");
2726 for (i = 0; i < 6 - (len / 8); i++)
2727 fprintf(trussinfo->outfile, "\t");
2731 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2733 struct timespec timediff;
2734 struct threadinfo *t;
2737 t = trussinfo->curthread;
2739 if (trussinfo->flags & COUNTONLY) {
2740 timespecsub(&t->after, &t->before, &timediff);
2741 timespecadd(&sc->time, &timediff, &sc->time);
2748 print_syscall(trussinfo);
2749 fflush(trussinfo->outfile);
2751 if (retval == NULL) {
2753 * This system call resulted in the current thread's exit,
2754 * so there is no return value or error to display.
2756 fprintf(trussinfo->outfile, "\n");
2760 if (error == ERESTART)
2761 fprintf(trussinfo->outfile, " ERESTART\n");
2762 else if (error == EJUSTRETURN)
2763 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2764 else if (error != 0) {
2765 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2766 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2770 else if (sc->ret_type == 2) {
2773 #if _BYTE_ORDER == _LITTLE_ENDIAN
2774 off = (off_t)retval[1] << 32 | retval[0];
2776 off = (off_t)retval[0] << 32 | retval[1];
2778 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2783 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2784 (intmax_t)retval[0], (intmax_t)retval[0]);
2788 print_summary(struct trussinfo *trussinfo)
2790 struct timespec total = {0, 0};
2794 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2795 "syscall", "seconds", "calls", "errors");
2797 STAILQ_FOREACH(sc, &syscalls, entries)
2799 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2800 sc->name, (intmax_t)sc->time.tv_sec,
2801 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2802 timespecadd(&total, &sc->time, &total);
2803 ncall += sc->ncalls;
2804 nerror += sc->nerror;
2806 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2807 "", "-------------", "-------", "-------");
2808 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2809 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);