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 initalization 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, void *offset, void *buf, int len)
1056 struct ptrace_io_desc iorequest;
1058 iorequest.piod_op = PIOD_READ_D;
1059 iorequest.piod_offs = 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, void *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 = (char *)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_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1189 struct sockaddr_in *lsin;
1190 struct sockaddr_in6 *lsin6;
1191 struct sockaddr_un *sun;
1192 struct sockaddr *sa;
1194 pid_t pid = trussinfo->curthread->proc->pid;
1200 /* If the length is too small, just bail. */
1201 if (len < sizeof(*sa)) {
1202 fprintf(fp, "%p", arg);
1206 sa = calloc(1, len);
1207 if (get_struct(pid, arg, sa, len) == -1) {
1209 fprintf(fp, "%p", arg);
1213 switch (sa->sa_family) {
1215 if (len < sizeof(*lsin))
1216 goto sockaddr_short;
1217 lsin = (struct sockaddr_in *)(void *)sa;
1218 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1219 fprintf(fp, "{ AF_INET %s:%d }", addr,
1220 htons(lsin->sin_port));
1223 if (len < sizeof(*lsin6))
1224 goto sockaddr_short;
1225 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1226 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1228 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1229 htons(lsin6->sin6_port));
1232 sun = (struct sockaddr_un *)sa;
1233 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1234 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1240 "{ sa_len = %d, sa_family = %d, sa_data = {",
1241 (int)sa->sa_len, (int)sa->sa_family);
1242 for (q = (u_char *)sa->sa_data;
1243 q < (u_char *)sa + len; q++)
1244 fprintf(fp, "%s 0x%02x",
1245 q == (u_char *)sa->sa_data ? "" : ",",
1252 #define IOV_LIMIT 16
1255 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1257 struct iovec iov[IOV_LIMIT];
1258 size_t max_string = trussinfo->strsize;
1259 char tmp2[max_string + 1], *tmp3;
1261 pid_t pid = trussinfo->curthread->proc->pid;
1263 bool buf_truncated, iov_truncated;
1266 fprintf(fp, "%p", arg);
1269 if (iovcnt > IOV_LIMIT) {
1271 iov_truncated = true;
1273 iov_truncated = false;
1275 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1276 fprintf(fp, "%p", arg);
1281 for (i = 0; i < iovcnt; i++) {
1282 len = iov[i].iov_len;
1283 if (len > max_string) {
1285 buf_truncated = true;
1287 buf_truncated = false;
1289 fprintf(fp, "%s{", (i > 0) ? "," : "");
1290 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1291 tmp3 = malloc(len * 4 + 1);
1293 if (strvisx(tmp3, tmp2, len,
1294 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1298 buf_truncated = true;
1300 fprintf(fp, "\"%s\"%s", tmp3,
1301 buf_truncated ? "..." : "");
1304 fprintf(fp, "%p", iov[i].iov_base);
1306 fprintf(fp, ",%zu}", iov[i].iov_len);
1308 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1312 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1317 for (q = CMSG_DATA(cmsghdr);
1318 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1319 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1325 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1327 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1328 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1329 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1330 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1334 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1336 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1338 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1341 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1342 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1344 fprintf(fp, "ctx=%u,", info->sinfo_context);
1345 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1348 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1349 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1351 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1355 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1357 fprintf(fp, "{sid=%u,", info->snd_sid);
1359 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1360 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1361 fprintf(fp, "ctx=%u,", info->snd_context);
1362 fprintf(fp, "id=%u}", info->snd_assoc_id);
1366 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1368 fprintf(fp, "{sid=%u,", info->rcv_sid);
1369 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1371 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1372 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1373 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1374 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1375 fprintf(fp, "ctx=%u,", info->rcv_context);
1376 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1380 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1382 fprintf(fp, "{sid=%u,", info->nxt_sid);
1384 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1385 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1386 fprintf(fp, "len=%u,", info->nxt_length);
1387 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1391 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1394 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1395 fprintf(fp, ",val=%u}", info->pr_value);
1399 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1401 fprintf(fp, "{num=%u}", info->auth_keynumber);
1405 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1407 char buf[INET_ADDRSTRLEN];
1410 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1412 fprintf(fp, "{addr=%s}", s);
1414 fputs("{addr=???}", fp);
1418 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1420 char buf[INET6_ADDRSTRLEN];
1423 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1425 fprintf(fp, "{addr=%s}", s);
1427 fputs("{addr=???}", fp);
1431 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1436 len = cmsghdr->cmsg_len;
1437 data = CMSG_DATA(cmsghdr);
1438 switch (cmsghdr->cmsg_type) {
1440 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1441 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1443 print_gen_cmsg(fp, cmsghdr);
1446 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1447 print_sctp_sndrcvinfo(fp, receive,
1448 (struct sctp_sndrcvinfo *)data);
1450 print_gen_cmsg(fp, cmsghdr);
1454 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1455 print_sctp_extrcvinfo(fp,
1456 (struct sctp_extrcvinfo *)data);
1458 print_gen_cmsg(fp, cmsghdr);
1462 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1463 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1465 print_gen_cmsg(fp, cmsghdr);
1468 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1469 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1471 print_gen_cmsg(fp, cmsghdr);
1474 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1475 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1477 print_gen_cmsg(fp, cmsghdr);
1480 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1481 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1483 print_gen_cmsg(fp, cmsghdr);
1486 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1487 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1489 print_gen_cmsg(fp, cmsghdr);
1491 case SCTP_DSTADDRV4:
1492 if (len == CMSG_LEN(sizeof(struct in_addr)))
1493 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1495 print_gen_cmsg(fp, cmsghdr);
1497 case SCTP_DSTADDRV6:
1498 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1499 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1501 print_gen_cmsg(fp, cmsghdr);
1504 print_gen_cmsg(fp, cmsghdr);
1509 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1511 struct cmsghdr *cmsghdr;
1518 len = msghdr->msg_controllen;
1523 cmsgbuf = calloc(1, len);
1524 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1525 fprintf(fp, "%p", msghdr->msg_control);
1529 msghdr->msg_control = cmsgbuf;
1532 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1534 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1535 level = cmsghdr->cmsg_level;
1536 type = cmsghdr->cmsg_type;
1537 len = cmsghdr->cmsg_len;
1538 fprintf(fp, "%s{level=", first ? "" : ",");
1539 print_integer_arg(sysdecode_sockopt_level, fp, level);
1540 fputs(",type=", fp);
1541 temp = sysdecode_cmsg_type(level, type);
1545 fprintf(fp, "%d", type);
1547 fputs(",data=", fp);
1550 print_sctp_cmsg(fp, receive, cmsghdr);
1553 print_gen_cmsg(fp, cmsghdr);
1564 print_sysctl_oid(FILE *fp, int *oid, int len)
1568 for (i = 0; i < len; i++)
1569 fprintf(fp, ".%d", oid[i]);
1573 * Converts a syscall argument into a string. Said string is
1574 * allocated via malloc(), so needs to be free()'d. sc is
1575 * a pointer to the syscall description (see above); args is
1576 * an array of all of the system call arguments.
1579 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1580 struct trussinfo *trussinfo)
1587 fp = open_memstream(&tmp, &tmplen);
1588 pid = trussinfo->curthread->proc->pid;
1589 switch (sc->type & ARG_MASK) {
1591 fprintf(fp, "0x%x", (int)args[sc->offset]);
1594 fprintf(fp, "0%o", (int)args[sc->offset]);
1597 fprintf(fp, "%d", (int)args[sc->offset]);
1600 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1605 if (get_struct(pid, (void *)args[sc->offset], &val,
1607 fprintf(fp, "{ %u }", val);
1609 fprintf(fp, "0x%lx", args[sc->offset]);
1613 fprintf(fp, "0x%lx", args[sc->offset]);
1616 fprintf(fp, "%ld", args[sc->offset]);
1619 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1622 /* Handle special SHM_ANON value. */
1623 if ((char *)args[sc->offset] == SHM_ANON) {
1624 fprintf(fp, "SHM_ANON");
1629 /* NULL-terminated string. */
1632 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1633 fprintf(fp, "\"%s\"", tmp2);
1639 * Binary block of data that might have printable characters.
1640 * XXX If type|OUT, assume that the length is the syscall's
1641 * return value. Otherwise, assume that the length of the block
1642 * is in the next syscall argument.
1644 int max_string = trussinfo->strsize;
1645 char tmp2[max_string + 1], *tmp3;
1652 len = args[sc->offset + 1];
1655 * Don't print more than max_string characters, to avoid word
1656 * wrap. If we have to truncate put some ... after the string.
1658 if (len > max_string) {
1662 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1664 tmp3 = malloc(len * 4 + 1);
1666 if (strvisx(tmp3, tmp2, len,
1667 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1672 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1676 fprintf(fp, "0x%lx", args[sc->offset]);
1686 char buf[PAGE_SIZE];
1693 * Only parse argv[] and environment arrays from exec calls
1696 if (((sc->type & ARG_MASK) == ExecArgs &&
1697 (trussinfo->flags & EXECVEARGS) == 0) ||
1698 ((sc->type & ARG_MASK) == ExecEnv &&
1699 (trussinfo->flags & EXECVEENVS) == 0)) {
1700 fprintf(fp, "0x%lx", args[sc->offset]);
1705 * Read a page of pointers at a time. Punt if the top-level
1706 * pointer is not aligned. Note that the first read is of
1709 addr = args[sc->offset];
1710 if (addr % sizeof(char *) != 0) {
1711 fprintf(fp, "0x%lx", args[sc->offset]);
1715 len = PAGE_SIZE - (addr & PAGE_MASK);
1716 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1717 fprintf(fp, "0x%lx", args[sc->offset]);
1724 while (u.strarray[i] != NULL) {
1725 string = get_string(pid, u.strarray[i], 0);
1726 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1731 if (i == len / sizeof(char *)) {
1734 if (get_struct(pid, (void *)addr, u.buf, len) ==
1736 fprintf(fp, ", <inval>");
1747 fprintf(fp, "%ld", args[sc->offset]);
1750 fprintf(fp, "0x%lx", args[sc->offset]);
1755 unsigned long long ll;
1757 #if _BYTE_ORDER == _LITTLE_ENDIAN
1758 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1761 ll = (unsigned long long)args[sc->offset] << 32 |
1762 args[sc->offset + 1];
1764 if ((sc->type & ARG_MASK) == Quad)
1765 fprintf(fp, "%lld", ll);
1767 fprintf(fp, "0x%llx", ll);
1774 if (get_struct(pid, (void *)args[sc->offset], &val,
1776 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1778 fprintf(fp, "0x%lx", args[sc->offset]);
1782 fprintf(fp, "0x%lx", args[sc->offset]);
1787 if (retval[0] == -1)
1789 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1790 fprintf(fp, "\"%s\"", tmp2);
1798 cmd = args[sc->offset];
1799 temp = sysdecode_ioctlname(cmd);
1803 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1804 cmd, cmd & IOC_OUT ? "R" : "",
1805 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1806 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1807 cmd & 0xFF, IOCPARM_LEN(cmd));
1814 if (get_struct(pid, (void *)args[sc->offset], &ts,
1816 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1819 fprintf(fp, "0x%lx", args[sc->offset]);
1823 struct timespec ts[2];
1827 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1831 for (i = 0; i < nitems(ts); i++) {
1834 switch (ts[i].tv_nsec) {
1836 fprintf(fp, "UTIME_NOW");
1839 fprintf(fp, "UTIME_OMIT");
1842 fprintf(fp, "%jd.%09ld",
1843 (intmax_t)ts[i].tv_sec,
1850 fprintf(fp, "0x%lx", args[sc->offset]);
1856 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1858 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1861 fprintf(fp, "0x%lx", args[sc->offset]);
1865 struct timeval tv[2];
1867 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1869 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1870 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1871 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1873 fprintf(fp, "0x%lx", args[sc->offset]);
1877 struct itimerval itv;
1879 if (get_struct(pid, (void *)args[sc->offset], &itv,
1881 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1882 (intmax_t)itv.it_interval.tv_sec,
1883 itv.it_interval.tv_usec,
1884 (intmax_t)itv.it_value.tv_sec,
1885 itv.it_value.tv_usec);
1887 fprintf(fp, "0x%lx", args[sc->offset]);
1892 struct linux_socketcall_args largs;
1894 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1895 sizeof(largs)) != -1)
1896 fprintf(fp, "{ %s, 0x%lx }",
1897 lookup(linux_socketcall_ops, largs.what, 10),
1898 (long unsigned int)largs.args);
1900 fprintf(fp, "0x%lx", args[sc->offset]);
1905 * XXX: A Pollfd argument expects the /next/ syscall argument
1906 * to be the number of fds in the array. This matches the poll
1910 int numfds = args[sc->offset + 1];
1911 size_t bytes = sizeof(struct pollfd) * numfds;
1914 if ((pfd = malloc(bytes)) == NULL)
1915 err(1, "Cannot malloc %zu bytes for pollfd array",
1917 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1920 for (i = 0; i < numfds; i++) {
1921 fprintf(fp, " %d/%s", pfd[i].fd,
1922 xlookup_bits(poll_flags, pfd[i].events));
1926 fprintf(fp, "0x%lx", args[sc->offset]);
1933 * XXX: A Fd_set argument expects the /first/ syscall argument
1934 * to be the number of fds in the array. This matches the
1938 int numfds = args[0];
1939 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1942 if ((fds = malloc(bytes)) == NULL)
1943 err(1, "Cannot malloc %zu bytes for fd_set array",
1945 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1948 for (i = 0; i < numfds; i++) {
1949 if (FD_ISSET(i, fds))
1950 fprintf(fp, " %d", i);
1954 fprintf(fp, "0x%lx", args[sc->offset]);
1959 fputs(strsig2(args[sc->offset]), fp);
1966 sig = args[sc->offset];
1967 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1968 sizeof(ss)) == -1) {
1969 fprintf(fp, "0x%lx", args[sc->offset]);
1974 for (i = 1; i < sys_nsig; i++) {
1975 if (sigismember(&ss, i)) {
1976 fprintf(fp, "%s%s", !first ? "|" : "",
1987 print_integer_arg(sysdecode_sigprocmask_how, fp,
1991 /* XXX: Output depends on the value of the previous argument. */
1992 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1993 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1994 args[sc->offset], 16);
1997 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2000 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2003 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2006 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2009 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2012 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2015 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2018 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2021 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2024 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2027 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2030 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2035 if (args[sc->offset] == 0) {
2041 * Extract the address length from the next argument. If
2042 * this is an output sockaddr (OUT is set), then the
2043 * next argument is a pointer to a socklen_t. Otherwise
2044 * the next argument contains a socklen_t by value.
2046 if (sc->type & OUT) {
2047 if (get_struct(pid, (void *)args[sc->offset + 1],
2048 &len, sizeof(len)) == -1) {
2049 fprintf(fp, "0x%lx", args[sc->offset]);
2053 len = args[sc->offset + 1];
2055 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2059 struct sigaction sa;
2061 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
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 fprintf(fp, "0x%lx", 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, (void *)args[sc->offset],
2105 for (i = 0; i < numevents; i++) {
2107 print_kevent(fp, &ke[i]);
2111 fprintf(fp, "0x%lx", 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, (void *)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 fprintf(fp, "0x%lx", args[sc->offset]);
2160 if (get_struct(pid, (void *)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 fprintf(fp, "0x%lx", args[sc->offset]);
2175 struct freebsd11_stat st;
2177 if (get_struct(pid, (void *)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 fprintf(fp, "0x%lx", args[sc->offset]);
2195 if (get_struct(pid, (void *)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 fprintf(fp, "0x%lx", args[sc->offset]);
2218 if (get_struct(pid, (void *)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 fprintf(fp, "0x%lx", args[sc->offset]);
2232 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2234 fprintf(fp, "{ cur=%ju,max=%ju }",
2235 rl.rlim_cur, rl.rlim_max);
2237 fprintf(fp, "0x%lx", args[sc->offset]);
2243 if (get_struct(pid, (void *)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 fprintf(fp, "0x%lx", 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, (void *)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, (void *)args[sc->offset],
2366 (void *)utrace_addr, len) != -1)
2367 print_utrace(fp, utrace_addr, len);
2369 fprintf(fp, "0x%lx", 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, (void *)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 fprintf(fp, "0x%lx", 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, (void *)args[sc->offset], &rights,
2403 sizeof(rights)) == -1) {
2404 fprintf(fp, "0x%lx", 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, (void *)args[sc->offset], &rights,
2487 sizeof(rights)) != -1) {
2489 sysdecode_cap_rights(fp, &rights);
2492 fprintf(fp, "0x%lx", 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, (void *)args[sc->offset], &sp,
2542 fprintf(fp, "{ %d }", sp.sched_priority);
2544 fprintf(fp, "0x%lx", args[sc->offset]);
2550 if (get_struct(pid, (void *)args[sc->offset], &sig,
2552 fprintf(fp, "{ %s }", strsig2(sig));
2554 fprintf(fp, "0x%lx", args[sc->offset]);
2560 if (get_struct(pid, (void *)args[sc->offset], &si,
2561 sizeof(si)) != -1) {
2562 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2563 decode_siginfo(fp, &si);
2566 fprintf(fp, "0x%lx", args[sc->offset]);
2571 * Print argument as an array of struct iovec, where the next
2572 * syscall argument is the number of elements of the array.
2575 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2576 (int)args[sc->offset + 1]);
2578 case Sctpsndrcvinfo: {
2579 struct sctp_sndrcvinfo info;
2581 if (get_struct(pid, (void *)args[sc->offset],
2582 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2583 fprintf(fp, "0x%lx", args[sc->offset]);
2586 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2590 struct msghdr msghdr;
2592 if (get_struct(pid, (void *)args[sc->offset],
2593 &msghdr, sizeof(struct msghdr)) == -1) {
2594 fprintf(fp, "0x%lx", args[sc->offset]);
2598 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2599 fprintf(fp, ",%d,", msghdr.msg_namelen);
2600 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2601 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2602 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2603 fprintf(fp, ",%u,", msghdr.msg_controllen);
2604 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2609 case CloudABIAdvice:
2610 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2612 case CloudABIClockID:
2613 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2615 case CloudABIFDSFlags:
2616 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2618 case CloudABIFDStat: {
2619 cloudabi_fdstat_t fds;
2620 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2622 fprintf(fp, "{ %s, ",
2623 xlookup(cloudabi_filetype, fds.fs_filetype));
2624 fprintf(fp, "%s, ... }",
2625 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2627 fprintf(fp, "0x%lx", args[sc->offset]);
2630 case CloudABIFileStat: {
2631 cloudabi_filestat_t fsb;
2632 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2634 fprintf(fp, "{ %s, %ju }",
2635 xlookup(cloudabi_filetype, fsb.st_filetype),
2636 (uintmax_t)fsb.st_size);
2638 fprintf(fp, "0x%lx", args[sc->offset]);
2641 case CloudABIFileType:
2642 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2644 case CloudABIFSFlags:
2645 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2647 case CloudABILookup:
2648 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2649 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2650 (int)args[sc->offset]);
2652 fprintf(fp, "%d", (int)args[sc->offset]);
2654 case CloudABIMFlags:
2655 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2658 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2660 case CloudABIMSFlags:
2661 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2663 case CloudABIOFlags:
2664 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2666 case CloudABISDFlags:
2667 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2669 case CloudABISignal:
2670 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2672 case CloudABITimestamp:
2673 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2674 args[sc->offset] % 1000000000);
2676 case CloudABIULFlags:
2677 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2679 case CloudABIWhence:
2680 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2684 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2691 * Print (to outfile) the system call and its arguments.
2694 print_syscall(struct trussinfo *trussinfo)
2696 struct threadinfo *t;
2701 t = trussinfo->curthread;
2703 name = t->cs.sc->name;
2704 nargs = t->cs.nargs;
2705 s_args = t->cs.s_args;
2707 len = print_line_prefix(trussinfo);
2708 len += fprintf(trussinfo->outfile, "%s(", name);
2710 for (i = 0; i < nargs; i++) {
2711 if (s_args[i] != NULL)
2712 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2714 len += fprintf(trussinfo->outfile,
2715 "<missing argument>");
2716 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2719 len += fprintf(trussinfo->outfile, ")");
2720 for (i = 0; i < 6 - (len / 8); i++)
2721 fprintf(trussinfo->outfile, "\t");
2725 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2727 struct timespec timediff;
2728 struct threadinfo *t;
2731 t = trussinfo->curthread;
2733 if (trussinfo->flags & COUNTONLY) {
2734 timespecsub(&t->after, &t->before, &timediff);
2735 timespecadd(&sc->time, &timediff, &sc->time);
2742 print_syscall(trussinfo);
2743 fflush(trussinfo->outfile);
2745 if (retval == NULL) {
2747 * This system call resulted in the current thread's exit,
2748 * so there is no return value or error to display.
2750 fprintf(trussinfo->outfile, "\n");
2754 if (error == ERESTART)
2755 fprintf(trussinfo->outfile, " ERESTART\n");
2756 else if (error == EJUSTRETURN)
2757 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2758 else if (error != 0) {
2759 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2760 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2764 else if (sc->ret_type == 2) {
2767 #if _BYTE_ORDER == _LITTLE_ENDIAN
2768 off = (off_t)retval[1] << 32 | retval[0];
2770 off = (off_t)retval[0] << 32 | retval[1];
2772 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2777 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2778 (intmax_t)retval[0], (intmax_t)retval[0]);
2782 print_summary(struct trussinfo *trussinfo)
2784 struct timespec total = {0, 0};
2788 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2789 "syscall", "seconds", "calls", "errors");
2791 STAILQ_FOREACH(sc, &syscalls, entries)
2793 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2794 sc->name, (intmax_t)sc->time.tv_sec,
2795 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2796 timespecadd(&total, &sc->time, &total);
2797 ncall += sc->ncalls;
2798 nerror += sc->nerror;
2800 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2801 "", "-------------", "-------", "-------");
2802 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2803 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);