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 = "closefrom", .ret_type = 1, .nargs = 1,
161 .args = { { Int, 0 } } },
162 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
163 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
164 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
165 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
167 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
168 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
169 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
170 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
171 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
172 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
173 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
174 { .name = "connect", .ret_type = 1, .nargs = 3,
175 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
176 { .name = "connectat", .ret_type = 1, .nargs = 4,
177 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
179 { .name = "dup", .ret_type = 1, .nargs = 1,
180 .args = { { Int, 0 } } },
181 { .name = "dup2", .ret_type = 1, .nargs = 2,
182 .args = { { Int, 0 }, { Int, 1 } } },
183 { .name = "eaccess", .ret_type = 1, .nargs = 2,
184 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
185 { .name = "execve", .ret_type = 1, .nargs = 3,
186 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
187 { ExecEnv | IN, 2 } } },
188 { .name = "exit", .ret_type = 0, .nargs = 1,
189 .args = { { Hex, 0 } } },
190 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
191 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
192 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
193 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
194 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
195 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
196 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
197 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
198 { BinString | OUT, 3 }, { Sizet, 4 } } },
199 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
200 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
201 { BinString | OUT, 3 }, { Sizet, 4 } } },
202 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
203 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
204 { BinString | OUT, 3 }, { Sizet, 4 } } },
205 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
206 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
208 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
209 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
211 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
214 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
215 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
216 { BinString | IN, 3 }, { Sizet, 4 } } },
217 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
218 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
219 { BinString | IN, 3 }, { Sizet, 4 } } },
220 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
221 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
222 { BinString | IN, 3 }, { Sizet, 4 } } },
223 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
224 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
225 { Extattrnamespace, 3 }, { Name, 4 } } },
226 { .name = "faccessat", .ret_type = 1, .nargs = 4,
227 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
229 { .name = "fchflags", .ret_type = 1, .nargs = 2,
230 .args = { { Int, 0 }, { FileFlags, 1 } } },
231 { .name = "fchmod", .ret_type = 1, .nargs = 2,
232 .args = { { Int, 0 }, { Octal, 1 } } },
233 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
234 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
235 { .name = "fchown", .ret_type = 1, .nargs = 3,
236 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
237 { .name = "fchownat", .ret_type = 1, .nargs = 5,
238 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
240 { .name = "fcntl", .ret_type = 1, .nargs = 3,
241 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
242 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
243 .args = { { Int, 0 } } },
244 { .name = "flock", .ret_type = 1, .nargs = 2,
245 .args = { { Int, 0 }, { Flockop, 1 } } },
246 { .name = "fstat", .ret_type = 1, .nargs = 2,
247 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
248 { .name = "fstatat", .ret_type = 1, .nargs = 4,
249 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
251 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
252 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
253 { .name = "fsync", .ret_type = 1, .nargs = 1,
254 .args = { { Int, 0 } } },
255 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
256 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
257 { .name = "futimens", .ret_type = 1, .nargs = 2,
258 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
259 { .name = "futimes", .ret_type = 1, .nargs = 2,
260 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
261 { .name = "futimesat", .ret_type = 1, .nargs = 3,
262 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
263 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
264 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
265 { PQuadHex | OUT, 3 } } },
266 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
267 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
268 { .name = "getitimer", .ret_type = 1, .nargs = 2,
269 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
270 { .name = "getpeername", .ret_type = 1, .nargs = 3,
271 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
272 { .name = "getpgid", .ret_type = 1, .nargs = 1,
273 .args = { { Int, 0 } } },
274 { .name = "getpriority", .ret_type = 1, .nargs = 2,
275 .args = { { Priowhich, 0 }, { Int, 1 } } },
276 { .name = "getrandom", .ret_type = 1, .nargs = 3,
277 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
278 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
279 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
280 { .name = "getrusage", .ret_type = 1, .nargs = 2,
281 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
282 { .name = "getsid", .ret_type = 1, .nargs = 1,
283 .args = { { Int, 0 } } },
284 { .name = "getsockname", .ret_type = 1, .nargs = 3,
285 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
286 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
287 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
288 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
289 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
290 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
291 { .name = "ioctl", .ret_type = 1, .nargs = 3,
292 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
293 { .name = "kevent", .ret_type = 1, .nargs = 6,
294 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
295 { Int, 4 }, { Timespec, 5 } } },
296 { .name = "kill", .ret_type = 1, .nargs = 2,
297 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
298 { .name = "kldfind", .ret_type = 1, .nargs = 1,
299 .args = { { Name | IN, 0 } } },
300 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
301 .args = { { Int, 0 } } },
302 { .name = "kldload", .ret_type = 1, .nargs = 1,
303 .args = { { Name | IN, 0 } } },
304 { .name = "kldnext", .ret_type = 1, .nargs = 1,
305 .args = { { Int, 0 } } },
306 { .name = "kldstat", .ret_type = 1, .nargs = 2,
307 .args = { { Int, 0 }, { Ptr, 1 } } },
308 { .name = "kldsym", .ret_type = 1, .nargs = 3,
309 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
310 { .name = "kldunload", .ret_type = 1, .nargs = 1,
311 .args = { { Int, 0 } } },
312 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
313 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
314 { .name = "kse_release", .ret_type = 0, .nargs = 1,
315 .args = { { Timespec, 0 } } },
316 { .name = "lchflags", .ret_type = 1, .nargs = 2,
317 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
318 { .name = "lchmod", .ret_type = 1, .nargs = 2,
319 .args = { { Name, 0 }, { Octal, 1 } } },
320 { .name = "lchown", .ret_type = 1, .nargs = 3,
321 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
322 { .name = "link", .ret_type = 1, .nargs = 2,
323 .args = { { Name, 0 }, { Name, 1 } } },
324 { .name = "linkat", .ret_type = 1, .nargs = 5,
325 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
327 { .name = "listen", .ret_type = 1, .nargs = 2,
328 .args = { { Int, 0 }, { Int, 1 } } },
329 { .name = "lseek", .ret_type = 2, .nargs = 3,
330 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
331 { .name = "lstat", .ret_type = 1, .nargs = 2,
332 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
333 { .name = "lutimes", .ret_type = 1, .nargs = 2,
334 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
335 { .name = "madvise", .ret_type = 1, .nargs = 3,
336 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
337 { .name = "minherit", .ret_type = 1, .nargs = 3,
338 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
339 { .name = "mkdir", .ret_type = 1, .nargs = 2,
340 .args = { { Name, 0 }, { Octal, 1 } } },
341 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
342 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
343 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
344 .args = { { Name, 0 }, { Octal, 1 } } },
345 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
346 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
347 { .name = "mknod", .ret_type = 1, .nargs = 3,
348 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
349 { .name = "mknodat", .ret_type = 1, .nargs = 4,
350 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
351 { .name = "mlock", .ret_type = 1, .nargs = 2,
352 .args = { { Ptr, 0 }, { Sizet, 1 } } },
353 { .name = "mlockall", .ret_type = 1, .nargs = 1,
354 .args = { { Mlockall, 0 } } },
355 { .name = "mmap", .ret_type = 1, .nargs = 6,
356 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
357 { Int, 4 }, { QuadHex, 5 } } },
358 { .name = "modfind", .ret_type = 1, .nargs = 1,
359 .args = { { Name | IN, 0 } } },
360 { .name = "mount", .ret_type = 1, .nargs = 4,
361 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
362 { .name = "mprotect", .ret_type = 1, .nargs = 3,
363 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
364 { .name = "msync", .ret_type = 1, .nargs = 3,
365 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
366 { .name = "munlock", .ret_type = 1, .nargs = 2,
367 .args = { { Ptr, 0 }, { Sizet, 1 } } },
368 { .name = "munmap", .ret_type = 1, .nargs = 2,
369 .args = { { Ptr, 0 }, { Sizet, 1 } } },
370 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
371 .args = { { Timespec, 0 } } },
372 { .name = "nmount", .ret_type = 1, .nargs = 3,
373 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
374 { .name = "open", .ret_type = 1, .nargs = 3,
375 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
376 { .name = "openat", .ret_type = 1, .nargs = 4,
377 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
379 { .name = "pathconf", .ret_type = 1, .nargs = 2,
380 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
381 { .name = "pipe", .ret_type = 1, .nargs = 1,
382 .args = { { PipeFds | OUT, 0 } } },
383 { .name = "pipe2", .ret_type = 1, .nargs = 2,
384 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
385 { .name = "poll", .ret_type = 1, .nargs = 3,
386 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
387 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
388 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
390 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
391 .args = { { Open, 0 } } },
392 { .name = "pread", .ret_type = 1, .nargs = 4,
393 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
395 { .name = "procctl", .ret_type = 1, .nargs = 4,
396 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
397 { .name = "ptrace", .ret_type = 1, .nargs = 4,
398 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
399 { .name = "pwrite", .ret_type = 1, .nargs = 4,
400 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
402 { .name = "quotactl", .ret_type = 1, .nargs = 4,
403 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
404 { .name = "read", .ret_type = 1, .nargs = 3,
405 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
406 { .name = "readlink", .ret_type = 1, .nargs = 3,
407 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
408 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
409 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
411 { .name = "readv", .ret_type = 1, .nargs = 3,
412 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
413 { .name = "reboot", .ret_type = 1, .nargs = 1,
414 .args = { { Reboothowto, 0 } } },
415 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
416 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
417 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
418 { Ptr | OUT, 5 } } },
419 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
420 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
421 { .name = "rename", .ret_type = 1, .nargs = 2,
422 .args = { { Name, 0 }, { Name, 1 } } },
423 { .name = "renameat", .ret_type = 1, .nargs = 4,
424 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
425 { .name = "rfork", .ret_type = 1, .nargs = 1,
426 .args = { { Rforkflags, 0 } } },
427 { .name = "rmdir", .ret_type = 1, .nargs = 1,
428 .args = { { Name, 0 } } },
429 { .name = "rtprio", .ret_type = 1, .nargs = 3,
430 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
431 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
432 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
433 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
434 .args = { { Schedpolicy, 0 } } },
435 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
436 .args = { { Schedpolicy, 0 } } },
437 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
438 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
439 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
440 .args = { { Int, 0 } } },
441 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
442 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
443 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
444 .args = { { Int, 0 }, { Schedparam, 1 } } },
445 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
446 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
447 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
448 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
449 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
450 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
451 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
452 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
453 { Sockaddr | IN, 3 }, { Socklent, 4 },
454 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
455 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
456 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
457 { Sockaddr | IN, 3 }, { Socklent, 4 },
458 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
459 { .name = "select", .ret_type = 1, .nargs = 5,
460 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
462 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
463 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
464 { .name = "sendto", .ret_type = 1, .nargs = 6,
465 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
466 { Msgflags, 3 }, { Sockaddr | IN, 4 },
467 { Socklent | IN, 5 } } },
468 { .name = "setitimer", .ret_type = 1, .nargs = 3,
469 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
470 { .name = "setpriority", .ret_type = 1, .nargs = 3,
471 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
472 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
473 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
474 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
475 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
476 { Ptr | IN, 3 }, { Socklent, 4 } } },
477 { .name = "shm_open", .ret_type = 1, .nargs = 3,
478 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
479 { .name = "shm_open2", .ret_type = 1, .nargs = 5,
480 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 },
481 { ShmFlags, 3 }, { Name | IN, 4 } } },
482 { .name = "shm_rename", .ret_type = 1, .nargs = 3,
483 .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } },
484 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
485 .args = { { Name | IN, 0 } } },
486 { .name = "shutdown", .ret_type = 1, .nargs = 2,
487 .args = { { Int, 0 }, { Shutdown, 1 } } },
488 { .name = "sigaction", .ret_type = 1, .nargs = 3,
489 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
490 { Sigaction | OUT, 2 } } },
491 { .name = "sigpending", .ret_type = 1, .nargs = 1,
492 .args = { { Sigset | OUT, 0 } } },
493 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
494 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
495 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
496 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
497 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
498 .args = { { Ptr, 0 } } },
499 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
500 .args = { { Sigset | IN, 0 } } },
501 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
502 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
503 { Timespec | IN, 2 } } },
504 { .name = "sigwait", .ret_type = 1, .nargs = 2,
505 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
506 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
507 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
508 { .name = "socket", .ret_type = 1, .nargs = 3,
509 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
510 { .name = "stat", .ret_type = 1, .nargs = 2,
511 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
512 { .name = "statfs", .ret_type = 1, .nargs = 2,
513 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
514 { .name = "symlink", .ret_type = 1, .nargs = 2,
515 .args = { { Name, 0 }, { Name, 1 } } },
516 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
517 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
518 { .name = "sysarch", .ret_type = 1, .nargs = 2,
519 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
520 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
521 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
522 { Ptr, 4 }, { Sizet, 5 } } },
523 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
524 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
525 { Ptr, 4}, { Sizet, 5 } } },
526 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
527 .args = { { Long, 0 }, { Signal, 1 } } },
528 { .name = "thr_self", .ret_type = 1, .nargs = 1,
529 .args = { { Ptr, 0 } } },
530 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
531 .args = { { Long, 0 }, { Name, 1 } } },
532 { .name = "truncate", .ret_type = 1, .nargs = 2,
533 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
536 { .name = "umount", .ret_type = 1, .nargs = 2,
537 .args = { { Name, 0 }, { Int, 2 } } },
539 { .name = "unlink", .ret_type = 1, .nargs = 1,
540 .args = { { Name, 0 } } },
541 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
542 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
543 { .name = "unmount", .ret_type = 1, .nargs = 2,
544 .args = { { Name, 0 }, { Mountflags, 1 } } },
545 { .name = "utimensat", .ret_type = 1, .nargs = 4,
546 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
548 { .name = "utimes", .ret_type = 1, .nargs = 2,
549 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
550 { .name = "utrace", .ret_type = 1, .nargs = 1,
551 .args = { { Utrace, 0 } } },
552 { .name = "wait4", .ret_type = 1, .nargs = 4,
553 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
554 { Rusage | OUT, 3 } } },
555 { .name = "wait6", .ret_type = 1, .nargs = 6,
556 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
557 { Waitoptions, 3 }, { Rusage | OUT, 4 },
558 { Siginfo | OUT, 5 } } },
559 { .name = "write", .ret_type = 1, .nargs = 3,
560 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
561 { .name = "writev", .ret_type = 1, .nargs = 3,
562 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
565 { .name = "linux_access", .ret_type = 1, .nargs = 2,
566 .args = { { Name, 0 }, { Accessmode, 1 } } },
567 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
568 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
569 { ExecEnv | IN, 2 } } },
570 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
571 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
572 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
573 .args = { { Name | IN, 0 }, { Int, 1 } } },
574 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
575 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
576 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
577 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
578 { .name = "linux_open", .ret_type = 1, .nargs = 3,
579 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
580 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
581 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
582 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
583 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
584 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
585 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
587 /* CloudABI system calls. */
588 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
589 .args = { { CloudABIClockID, 0 } } },
590 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
591 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
592 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
593 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
594 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
595 .args = { { Int, 0 } } },
596 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
597 .args = { { CloudABIFileType, 0 } } },
598 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
599 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
600 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
601 .args = { { Int, 0 } } },
602 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
603 .args = { { Int, 0 } } },
604 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
605 .args = { { Int, 0 }, { Int, 1 } } },
606 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
607 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
608 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
609 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
610 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
611 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
612 { CloudABIFDSFlags, 2 } } },
613 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
614 .args = { { Int, 0 } } },
615 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
616 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
617 { CloudABIAdvice, 3 } } },
618 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
619 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
620 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
621 .args = { { Int, 0 }, { BinString | IN, 1 },
622 { CloudABIFileType, 3 } } },
623 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
624 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
625 { Int, 3 }, { BinString | IN, 4 } } },
626 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
627 .args = { { Int, 0 }, { BinString | IN, 1 },
628 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
629 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
630 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
632 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
633 .args = { { Int, 0 }, { BinString | IN, 1 },
634 { BinString | OUT, 3 }, { Int, 4 } } },
635 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
636 .args = { { Int, 0 }, { BinString | IN, 1 },
637 { Int, 3 }, { BinString | IN, 4 } } },
638 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
639 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
640 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
641 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
642 { CloudABIFSFlags, 2 } } },
643 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
644 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
645 { CloudABIFileStat | OUT, 3 } } },
646 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
647 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
648 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
649 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
650 .args = { { BinString | IN, 0 },
651 { Int, 2 }, { BinString | IN, 3 } } },
652 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
653 .args = { { Int, 0 }, { BinString | IN, 1 },
654 { CloudABIULFlags, 3 } } },
655 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
656 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
657 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
658 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
659 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
660 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
661 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
662 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
663 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
664 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
665 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
666 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
667 .args = { { Ptr, 0 }, { Int, 1 } } },
668 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
669 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
670 { IntArray, 3 }, { Int, 4 } } },
671 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
672 .args = { { Int, 0 } } },
673 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
674 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
675 .args = { { CloudABISignal, 0 } } },
676 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
677 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
678 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
679 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
680 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
681 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
682 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
686 static STAILQ_HEAD(, syscall) syscalls;
688 /* Xlat idea taken from strace */
694 #define X(a) { a, #a },
695 #define XEND { 0, NULL }
697 static struct xlat poll_flags[] = {
698 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
699 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
700 X(POLLWRBAND) X(POLLINIGNEOF) XEND
703 static struct xlat sigaction_flags[] = {
704 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
705 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
708 static struct xlat linux_socketcall_ops[] = {
709 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
710 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
711 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
712 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
713 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
718 #define X(a) { CLOUDABI_##a, #a },
720 static struct xlat cloudabi_advice[] = {
721 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
722 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
726 static struct xlat cloudabi_clockid[] = {
727 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
728 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
732 static struct xlat cloudabi_fdflags[] = {
733 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
734 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
738 static struct xlat cloudabi_fdsflags[] = {
739 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
743 static struct xlat cloudabi_filetype[] = {
744 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
745 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
746 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
747 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
748 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
752 static struct xlat cloudabi_fsflags[] = {
753 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
754 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
758 static struct xlat cloudabi_mflags[] = {
759 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
763 static struct xlat cloudabi_mprot[] = {
764 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
768 static struct xlat cloudabi_msflags[] = {
769 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
773 static struct xlat cloudabi_oflags[] = {
774 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
778 static struct xlat cloudabi_sdflags[] = {
779 X(SHUT_RD) X(SHUT_WR)
783 static struct xlat cloudabi_signal[] = {
784 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
785 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
786 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
787 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
788 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
792 static struct xlat cloudabi_ulflags[] = {
797 static struct xlat cloudabi_whence[] = {
798 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
806 * Searches an xlat array for a value, and returns it if found. Otherwise
807 * return a string representation.
810 lookup(struct xlat *xlat, int val, int base)
814 for (; xlat->str != NULL; xlat++)
815 if (xlat->val == val)
819 sprintf(tmp, "0%o", val);
822 sprintf(tmp, "0x%x", val);
825 sprintf(tmp, "%u", val);
828 errx(1,"Unknown lookup base");
835 xlookup(struct xlat *xlat, int val)
838 return (lookup(xlat, val, 16));
842 * Searches an xlat array containing bitfield values. Remaining bits
843 * set after removing the known ones are printed at the end:
847 xlookup_bits(struct xlat *xlat, int val)
850 static char str[512];
854 for (; xlat->str != NULL; xlat++) {
855 if ((xlat->val & rem) == xlat->val) {
857 * Don't print the "all-bits-zero" string unless all
858 * bits are really zero.
860 if (xlat->val == 0 && val != 0)
862 len += sprintf(str + len, "%s|", xlat->str);
868 * If we have leftover bits or didn't match anything, print
872 len += sprintf(str + len, "0x%x", rem);
873 if (len && str[len - 1] == '|')
880 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
884 str = decoder(value);
888 fprintf(fp, "%d", value);
892 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
896 if (!decoder(fp, value, &rem))
897 fprintf(fp, "0x%x", rem);
899 fprintf(fp, "|0x%x", rem);
903 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
908 if (!decoder(fp, value, &rem))
909 fprintf(fp, "0x%x", rem);
911 fprintf(fp, "|0x%x", rem);
916 * Add argument padding to subsequent system calls after Quad
917 * syscall arguments as needed. This used to be done by hand in the
918 * decoded_syscalls table which was ugly and error prone. It is
919 * simpler to do the fixup of offsets at initialization time than when
920 * decoding arguments.
923 quad_fixup(struct syscall *sc)
930 for (i = 0; i < sc->nargs; i++) {
931 /* This arg type is a dummy that doesn't use offset. */
932 if ((sc->args[i].type & ARG_MASK) == PipeFds)
935 assert(prev < sc->args[i].offset);
936 prev = sc->args[i].offset;
937 sc->args[i].offset += offset;
938 switch (sc->args[i].type & ARG_MASK) {
943 * 64-bit arguments on 32-bit powerpc must be
944 * 64-bit aligned. If the current offset is
945 * not aligned, the calling convention inserts
946 * a 32-bit pad argument that should be skipped.
948 if (sc->args[i].offset % 2 == 1) {
949 sc->args[i].offset++;
966 STAILQ_INIT(&syscalls);
967 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
971 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
975 static struct syscall *
976 find_syscall(struct procabi *abi, u_int number)
978 struct extra_syscall *es;
980 if (number < nitems(abi->syscalls))
981 return (abi->syscalls[number]);
982 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
983 if (es->number == number)
990 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
992 struct extra_syscall *es;
994 if (number < nitems(abi->syscalls)) {
995 assert(abi->syscalls[number] == NULL);
996 abi->syscalls[number] = sc;
998 es = malloc(sizeof(*es));
1000 es->number = number;
1001 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
1006 * If/when the list gets big, it might be desirable to do it
1007 * as a hash table or binary search.
1010 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1017 sc = find_syscall(t->proc->abi, number);
1021 name = sysdecode_syscallname(t->proc->abi->abi, number);
1023 asprintf(&new_name, "#%d", number);
1027 STAILQ_FOREACH(sc, &syscalls, entries) {
1028 if (strcmp(name, sc->name) == 0) {
1029 add_syscall(t->proc->abi, number, sc);
1035 /* It is unknown. Add it into the list. */
1037 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1041 sc = calloc(1, sizeof(struct syscall));
1043 if (new_name != NULL)
1047 for (i = 0; i < nargs; i++) {
1048 sc->args[i].offset = i;
1049 /* Treat all unknown arguments as LongHex. */
1050 sc->args[i].type = LongHex;
1052 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1053 add_syscall(t->proc->abi, number, sc);
1059 * Copy a fixed amount of bytes from the process.
1062 get_struct(pid_t pid, uintptr_t offset, void *buf, int len)
1064 struct ptrace_io_desc iorequest;
1066 iorequest.piod_op = PIOD_READ_D;
1067 iorequest.piod_offs = (void *)offset;
1068 iorequest.piod_addr = buf;
1069 iorequest.piod_len = len;
1070 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1075 #define MAXSIZE 4096
1078 * Copy a string from the process. Note that it is
1079 * expected to be a C string, but if max is set, it will
1080 * only get that much.
1083 get_string(pid_t pid, uintptr_t addr, int max)
1085 struct ptrace_io_desc iorequest;
1087 size_t offset, size, totalsize;
1093 /* Read up to the end of the current page. */
1094 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1099 buf = malloc(totalsize);
1103 iorequest.piod_op = PIOD_READ_D;
1104 iorequest.piod_offs = (void *)(addr + offset);
1105 iorequest.piod_addr = buf + offset;
1106 iorequest.piod_len = size;
1107 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1111 if (memchr(buf + offset, '\0', size) != NULL)
1114 if (totalsize < MAXSIZE && max == 0) {
1115 size = MAXSIZE - totalsize;
1116 if (size > PAGE_SIZE)
1118 nbuf = realloc(buf, totalsize + size);
1120 buf[totalsize - 1] = '\0';
1126 buf[totalsize - 1] = '\0';
1135 static char tmp[32];
1136 const char *signame;
1138 signame = sysdecode_signal(sig);
1139 if (signame == NULL) {
1140 snprintf(tmp, sizeof(tmp), "%d", sig);
1147 print_kevent(FILE *fp, struct kevent *ke)
1150 switch (ke->filter) {
1156 case EVFILT_PROCDESC:
1158 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1161 fputs(strsig2(ke->ident), fp);
1164 fprintf(fp, "%p", (void *)ke->ident);
1167 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1169 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1171 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1172 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1176 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1178 unsigned char *utrace_buffer;
1181 if (sysdecode_utrace(fp, utrace_addr, len)) {
1186 utrace_buffer = utrace_addr;
1187 fprintf(fp, "%zu:", len);
1189 fprintf(fp, " %02x", *utrace_buffer++);
1194 print_pointer(FILE *fp, uintptr_t arg)
1197 fprintf(fp, "%p", (void *)arg);
1201 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg,
1205 struct sockaddr_in *lsin;
1206 struct sockaddr_in6 *lsin6;
1207 struct sockaddr_un *sun;
1208 struct sockaddr *sa;
1210 pid_t pid = trussinfo->curthread->proc->pid;
1216 /* If the length is too small, just bail. */
1217 if (len < sizeof(*sa)) {
1218 print_pointer(fp, arg);
1222 sa = calloc(1, len);
1223 if (get_struct(pid, arg, sa, len) == -1) {
1225 print_pointer(fp, arg);
1229 switch (sa->sa_family) {
1231 if (len < sizeof(*lsin))
1232 goto sockaddr_short;
1233 lsin = (struct sockaddr_in *)(void *)sa;
1234 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1235 fprintf(fp, "{ AF_INET %s:%d }", addr,
1236 htons(lsin->sin_port));
1239 if (len < sizeof(*lsin6))
1240 goto sockaddr_short;
1241 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1242 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1244 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1245 htons(lsin6->sin6_port));
1248 sun = (struct sockaddr_un *)sa;
1249 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1250 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1256 "{ sa_len = %d, sa_family = %d, sa_data = {",
1257 (int)sa->sa_len, (int)sa->sa_family);
1258 for (q = (u_char *)sa->sa_data;
1259 q < (u_char *)sa + len; q++)
1260 fprintf(fp, "%s 0x%02x",
1261 q == (u_char *)sa->sa_data ? "" : ",",
1268 #define IOV_LIMIT 16
1271 print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
1273 struct iovec iov[IOV_LIMIT];
1274 size_t max_string = trussinfo->strsize;
1275 char tmp2[max_string + 1], *tmp3;
1277 pid_t pid = trussinfo->curthread->proc->pid;
1279 bool buf_truncated, iov_truncated;
1282 print_pointer(fp, arg);
1285 if (iovcnt > IOV_LIMIT) {
1287 iov_truncated = true;
1289 iov_truncated = false;
1291 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1292 print_pointer(fp, arg);
1297 for (i = 0; i < iovcnt; i++) {
1298 len = iov[i].iov_len;
1299 if (len > max_string) {
1301 buf_truncated = true;
1303 buf_truncated = false;
1305 fprintf(fp, "%s{", (i > 0) ? "," : "");
1306 if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
1307 tmp3 = malloc(len * 4 + 1);
1309 if (strvisx(tmp3, tmp2, len,
1310 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1314 buf_truncated = true;
1316 fprintf(fp, "\"%s\"%s", tmp3,
1317 buf_truncated ? "..." : "");
1320 print_pointer(fp, (uintptr_t)iov[i].iov_base);
1322 fprintf(fp, ",%zu}", iov[i].iov_len);
1324 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1328 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1333 for (q = CMSG_DATA(cmsghdr);
1334 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1335 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1341 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1343 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1344 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1345 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1346 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1350 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1352 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1354 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1357 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1358 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1360 fprintf(fp, "ctx=%u,", info->sinfo_context);
1361 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1364 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1365 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1367 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1371 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1373 fprintf(fp, "{sid=%u,", info->snd_sid);
1375 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1376 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1377 fprintf(fp, "ctx=%u,", info->snd_context);
1378 fprintf(fp, "id=%u}", info->snd_assoc_id);
1382 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1384 fprintf(fp, "{sid=%u,", info->rcv_sid);
1385 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1387 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1388 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1389 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1390 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1391 fprintf(fp, "ctx=%u,", info->rcv_context);
1392 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1396 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1398 fprintf(fp, "{sid=%u,", info->nxt_sid);
1400 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1401 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1402 fprintf(fp, "len=%u,", info->nxt_length);
1403 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1407 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1410 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1411 fprintf(fp, ",val=%u}", info->pr_value);
1415 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1417 fprintf(fp, "{num=%u}", info->auth_keynumber);
1421 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1423 char buf[INET_ADDRSTRLEN];
1426 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1428 fprintf(fp, "{addr=%s}", s);
1430 fputs("{addr=???}", fp);
1434 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1436 char buf[INET6_ADDRSTRLEN];
1439 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1441 fprintf(fp, "{addr=%s}", s);
1443 fputs("{addr=???}", fp);
1447 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1452 len = cmsghdr->cmsg_len;
1453 data = CMSG_DATA(cmsghdr);
1454 switch (cmsghdr->cmsg_type) {
1456 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1457 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1459 print_gen_cmsg(fp, cmsghdr);
1462 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1463 print_sctp_sndrcvinfo(fp, receive,
1464 (struct sctp_sndrcvinfo *)data);
1466 print_gen_cmsg(fp, cmsghdr);
1470 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1471 print_sctp_extrcvinfo(fp,
1472 (struct sctp_extrcvinfo *)data);
1474 print_gen_cmsg(fp, cmsghdr);
1478 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1479 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1481 print_gen_cmsg(fp, cmsghdr);
1484 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1485 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1487 print_gen_cmsg(fp, cmsghdr);
1490 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1491 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1493 print_gen_cmsg(fp, cmsghdr);
1496 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1497 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1499 print_gen_cmsg(fp, cmsghdr);
1502 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1503 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1505 print_gen_cmsg(fp, cmsghdr);
1507 case SCTP_DSTADDRV4:
1508 if (len == CMSG_LEN(sizeof(struct in_addr)))
1509 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1511 print_gen_cmsg(fp, cmsghdr);
1513 case SCTP_DSTADDRV6:
1514 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1515 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1517 print_gen_cmsg(fp, cmsghdr);
1520 print_gen_cmsg(fp, cmsghdr);
1525 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1527 struct cmsghdr *cmsghdr;
1534 len = msghdr->msg_controllen;
1539 cmsgbuf = calloc(1, len);
1540 if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
1541 print_pointer(fp, (uintptr_t)msghdr->msg_control);
1545 msghdr->msg_control = cmsgbuf;
1548 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1550 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1551 level = cmsghdr->cmsg_level;
1552 type = cmsghdr->cmsg_type;
1553 len = cmsghdr->cmsg_len;
1554 fprintf(fp, "%s{level=", first ? "" : ",");
1555 print_integer_arg(sysdecode_sockopt_level, fp, level);
1556 fputs(",type=", fp);
1557 temp = sysdecode_cmsg_type(level, type);
1561 fprintf(fp, "%d", type);
1563 fputs(",data=", fp);
1566 print_sctp_cmsg(fp, receive, cmsghdr);
1569 print_gen_cmsg(fp, cmsghdr);
1580 print_sysctl_oid(FILE *fp, int *oid, size_t len)
1587 for (i = 0; i < len; i++) {
1588 fprintf(fp, "%s%d", first ? "" : ".", oid[i]);
1595 print_sysctl(FILE *fp, int *oid, size_t len)
1598 int qoid[CTL_MAXNAME + 2];
1601 qoid[0] = CTL_SYSCTL;
1602 qoid[1] = CTL_SYSCTL_NAME;
1603 memcpy(qoid + 2, oid, len * sizeof(int));
1605 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
1606 print_sysctl_oid(fp, oid, len);
1608 fprintf(fp, "%s", name);
1612 * Converts a syscall argument into a string. Said string is
1613 * allocated via malloc(), so needs to be free()'d. sc is
1614 * a pointer to the syscall description (see above); args is
1615 * an array of all of the system call arguments.
1618 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1619 struct trussinfo *trussinfo)
1626 fp = open_memstream(&tmp, &tmplen);
1627 pid = trussinfo->curthread->proc->pid;
1628 switch (sc->type & ARG_MASK) {
1630 fprintf(fp, "0x%x", (int)args[sc->offset]);
1633 fprintf(fp, "0%o", (int)args[sc->offset]);
1636 fprintf(fp, "%d", (int)args[sc->offset]);
1639 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1644 if (get_struct(pid, args[sc->offset], &val,
1646 fprintf(fp, "{ %u }", val);
1648 print_pointer(fp, args[sc->offset]);
1652 fprintf(fp, "0x%lx", args[sc->offset]);
1655 fprintf(fp, "%ld", args[sc->offset]);
1658 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1661 /* Handle special SHM_ANON value. */
1662 if ((char *)args[sc->offset] == SHM_ANON) {
1663 fprintf(fp, "SHM_ANON");
1668 /* NULL-terminated string. */
1671 tmp2 = get_string(pid, args[sc->offset], 0);
1672 fprintf(fp, "\"%s\"", tmp2);
1678 * Binary block of data that might have printable characters.
1679 * XXX If type|OUT, assume that the length is the syscall's
1680 * return value. Otherwise, assume that the length of the block
1681 * is in the next syscall argument.
1683 int max_string = trussinfo->strsize;
1684 char tmp2[max_string + 1], *tmp3;
1691 len = args[sc->offset + 1];
1694 * Don't print more than max_string characters, to avoid word
1695 * wrap. If we have to truncate put some ... after the string.
1697 if (len > max_string) {
1701 if (len && get_struct(pid, args[sc->offset], &tmp2, len)
1703 tmp3 = malloc(len * 4 + 1);
1705 if (strvisx(tmp3, tmp2, len,
1706 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1711 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1715 print_pointer(fp, args[sc->offset]);
1725 char buf[PAGE_SIZE];
1732 * Only parse argv[] and environment arrays from exec calls
1735 if (((sc->type & ARG_MASK) == ExecArgs &&
1736 (trussinfo->flags & EXECVEARGS) == 0) ||
1737 ((sc->type & ARG_MASK) == ExecEnv &&
1738 (trussinfo->flags & EXECVEENVS) == 0)) {
1739 print_pointer(fp, args[sc->offset]);
1744 * Read a page of pointers at a time. Punt if the top-level
1745 * pointer is not aligned. Note that the first read is of
1748 addr = args[sc->offset];
1749 if (addr % sizeof(char *) != 0) {
1750 print_pointer(fp, args[sc->offset]);
1754 len = PAGE_SIZE - (addr & PAGE_MASK);
1755 if (get_struct(pid, addr, u.buf, len) == -1) {
1756 print_pointer(fp, args[sc->offset]);
1763 while (u.strarray[i] != NULL) {
1764 string = get_string(pid, (uintptr_t)u.strarray[i], 0);
1765 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1770 if (i == len / sizeof(char *)) {
1773 if (get_struct(pid, addr, u.buf, len) ==
1775 fprintf(fp, ", <inval>");
1786 fprintf(fp, "%ld", args[sc->offset]);
1789 fprintf(fp, "0x%lx", args[sc->offset]);
1794 unsigned long long ll;
1796 #if _BYTE_ORDER == _LITTLE_ENDIAN
1797 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1800 ll = (unsigned long long)args[sc->offset] << 32 |
1801 args[sc->offset + 1];
1803 if ((sc->type & ARG_MASK) == Quad)
1804 fprintf(fp, "%lld", ll);
1806 fprintf(fp, "0x%llx", ll);
1813 if (get_struct(pid, args[sc->offset], &val,
1815 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1817 print_pointer(fp, args[sc->offset]);
1821 print_pointer(fp, args[sc->offset]);
1826 if (retval[0] == -1)
1828 tmp2 = get_string(pid, args[sc->offset], retval[0]);
1829 fprintf(fp, "\"%s\"", tmp2);
1837 cmd = args[sc->offset];
1838 temp = sysdecode_ioctlname(cmd);
1842 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1843 cmd, cmd & IOC_OUT ? "R" : "",
1844 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1845 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1846 cmd & 0xFF, IOCPARM_LEN(cmd));
1853 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
1854 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1857 print_pointer(fp, args[sc->offset]);
1861 struct timespec ts[2];
1865 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
1868 for (i = 0; i < nitems(ts); i++) {
1871 switch (ts[i].tv_nsec) {
1873 fprintf(fp, "UTIME_NOW");
1876 fprintf(fp, "UTIME_OMIT");
1879 fprintf(fp, "%jd.%09ld",
1880 (intmax_t)ts[i].tv_sec,
1887 print_pointer(fp, args[sc->offset]);
1893 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1894 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1897 print_pointer(fp, args[sc->offset]);
1901 struct timeval tv[2];
1903 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1904 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1905 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1906 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1908 print_pointer(fp, args[sc->offset]);
1912 struct itimerval itv;
1914 if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
1915 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1916 (intmax_t)itv.it_interval.tv_sec,
1917 itv.it_interval.tv_usec,
1918 (intmax_t)itv.it_value.tv_sec,
1919 itv.it_value.tv_usec);
1921 print_pointer(fp, args[sc->offset]);
1926 struct linux_socketcall_args largs;
1928 if (get_struct(pid, args[sc->offset], (void *)&largs,
1929 sizeof(largs)) != -1)
1930 fprintf(fp, "{ %s, 0x%lx }",
1931 lookup(linux_socketcall_ops, largs.what, 10),
1932 (long unsigned int)largs.args);
1934 print_pointer(fp, args[sc->offset]);
1939 * XXX: A Pollfd argument expects the /next/ syscall argument
1940 * to be the number of fds in the array. This matches the poll
1944 int numfds = args[sc->offset + 1];
1945 size_t bytes = sizeof(struct pollfd) * numfds;
1948 if ((pfd = malloc(bytes)) == NULL)
1949 err(1, "Cannot malloc %zu bytes for pollfd array",
1951 if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
1953 for (i = 0; i < numfds; i++) {
1954 fprintf(fp, " %d/%s", pfd[i].fd,
1955 xlookup_bits(poll_flags, pfd[i].events));
1959 print_pointer(fp, args[sc->offset]);
1966 * XXX: A Fd_set argument expects the /first/ syscall argument
1967 * to be the number of fds in the array. This matches the
1971 int numfds = args[0];
1972 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1975 if ((fds = malloc(bytes)) == NULL)
1976 err(1, "Cannot malloc %zu bytes for fd_set array",
1978 if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
1980 for (i = 0; i < numfds; i++) {
1981 if (FD_ISSET(i, fds))
1982 fprintf(fp, " %d", i);
1986 print_pointer(fp, args[sc->offset]);
1991 fputs(strsig2(args[sc->offset]), fp);
1998 sig = args[sc->offset];
1999 if (get_struct(pid, args[sc->offset], (void *)&ss,
2000 sizeof(ss)) == -1) {
2001 print_pointer(fp, args[sc->offset]);
2006 for (i = 1; i < sys_nsig; i++) {
2007 if (sigismember(&ss, i)) {
2008 fprintf(fp, "%s%s", !first ? "|" : "",
2019 print_integer_arg(sysdecode_sigprocmask_how, fp,
2023 /* XXX: Output depends on the value of the previous argument. */
2024 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
2025 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
2026 args[sc->offset], 16);
2029 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2032 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2035 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2038 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2041 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2044 print_mask_arg(sysdecode_shmflags, fp, args[sc->offset]);
2047 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2050 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2053 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2056 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2059 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2062 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2065 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2070 if (args[sc->offset] == 0) {
2076 * Extract the address length from the next argument. If
2077 * this is an output sockaddr (OUT is set), then the
2078 * next argument is a pointer to a socklen_t. Otherwise
2079 * the next argument contains a socklen_t by value.
2081 if (sc->type & OUT) {
2082 if (get_struct(pid, args[sc->offset + 1], &len,
2083 sizeof(len)) == -1) {
2084 print_pointer(fp, args[sc->offset]);
2088 len = args[sc->offset + 1];
2090 print_sockaddr(fp, trussinfo, args[sc->offset], len);
2094 struct sigaction sa;
2096 if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
2098 if (sa.sa_handler == SIG_DFL)
2099 fputs("SIG_DFL", fp);
2100 else if (sa.sa_handler == SIG_IGN)
2101 fputs("SIG_IGN", fp);
2103 fprintf(fp, "%p", sa.sa_handler);
2104 fprintf(fp, " %s ss_t }",
2105 xlookup_bits(sigaction_flags, sa.sa_flags));
2107 print_pointer(fp, args[sc->offset]);
2112 * XXX XXX: The size of the array is determined by either the
2113 * next syscall argument, or by the syscall return value,
2114 * depending on which argument number we are. This matches the
2115 * kevent syscall, but luckily that's the only syscall that uses
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) * numevents;
2130 if ((ke = malloc(bytes)) == NULL)
2132 "Cannot malloc %zu bytes for kevent array",
2136 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2139 for (i = 0; i < numevents; i++) {
2141 print_kevent(fp, &ke[i]);
2145 print_pointer(fp, args[sc->offset]);
2151 struct kevent_freebsd11 *ke11;
2157 if (sc->offset == 1)
2158 numevents = args[sc->offset+1];
2159 else if (sc->offset == 3 && retval[0] != -1)
2160 numevents = retval[0];
2162 if (numevents >= 0) {
2163 bytes = sizeof(struct kevent_freebsd11) * numevents;
2164 if ((ke11 = malloc(bytes)) == NULL)
2166 "Cannot malloc %zu bytes for kevent array",
2170 memset(&ke, 0, sizeof(ke));
2171 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2172 ke11, bytes) != -1) {
2174 for (i = 0; i < numevents; i++) {
2176 ke.ident = ke11[i].ident;
2177 ke.filter = ke11[i].filter;
2178 ke.flags = ke11[i].flags;
2179 ke.fflags = ke11[i].fflags;
2180 ke.data = ke11[i].data;
2181 ke.udata = ke11[i].udata;
2182 print_kevent(fp, &ke);
2186 print_pointer(fp, args[sc->offset]);
2194 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2198 strmode(st.st_mode, mode);
2200 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2201 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2202 (long)st.st_blksize);
2204 print_pointer(fp, args[sc->offset]);
2209 struct freebsd11_stat st;
2211 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2215 strmode(st.st_mode, mode);
2217 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2218 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2219 (long)st.st_blksize);
2221 print_pointer(fp, args[sc->offset]);
2229 if (get_struct(pid, args[sc->offset], &buf,
2230 sizeof(buf)) != -1) {
2233 bzero(fsid, sizeof(fsid));
2234 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2235 for (i = 0; i < sizeof(buf.f_fsid); i++)
2236 snprintf(&fsid[i*2],
2237 sizeof(fsid) - (i*2), "%02x",
2238 ((u_char *)&buf.f_fsid)[i]);
2241 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2242 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2243 buf.f_mntfromname, fsid);
2245 print_pointer(fp, args[sc->offset]);
2252 if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
2255 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2256 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2257 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2258 ru.ru_inblock, ru.ru_oublock);
2260 print_pointer(fp, args[sc->offset]);
2266 if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
2268 fprintf(fp, "{ cur=%ju,max=%ju }",
2269 rl.rlim_cur, rl.rlim_max);
2271 print_pointer(fp, args[sc->offset]);
2277 if (get_struct(pid, args[sc->offset], &status,
2278 sizeof(status)) != -1) {
2280 if (WIFCONTINUED(status))
2281 fputs("CONTINUED", fp);
2282 else if (WIFEXITED(status))
2283 fprintf(fp, "EXITED,val=%d",
2284 WEXITSTATUS(status));
2285 else if (WIFSIGNALED(status))
2286 fprintf(fp, "SIGNALED,sig=%s%s",
2287 strsig2(WTERMSIG(status)),
2288 WCOREDUMP(status) ? ",cored" : "");
2290 fprintf(fp, "STOPPED,sig=%s",
2291 strsig2(WTERMSIG(status)));
2294 print_pointer(fp, args[sc->offset]);
2298 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2301 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2304 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2307 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2310 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2313 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2316 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2319 print_integer_arg(sysdecode_sysarch_number, fp,
2324 int oid[CTL_MAXNAME + 2];
2327 memset(name, 0, sizeof(name));
2328 len = args[sc->offset + 1];
2329 if (get_struct(pid, args[sc->offset], oid,
2330 len * sizeof(oid[0])) != -1) {
2332 if (oid[0] == CTL_SYSCTL) {
2333 fprintf(fp, "sysctl.");
2335 case CTL_SYSCTL_DEBUG:
2336 fprintf(fp, "debug");
2338 case CTL_SYSCTL_NAME:
2339 fprintf(fp, "name ");
2340 print_sysctl_oid(fp, oid + 2, len - 2);
2342 case CTL_SYSCTL_NEXT:
2343 fprintf(fp, "next");
2345 case CTL_SYSCTL_NAME2OID:
2346 fprintf(fp, "name2oid %s",
2348 args[sc->offset + 4],
2349 args[sc->offset + 5]));
2351 case CTL_SYSCTL_OIDFMT:
2352 fprintf(fp, "oidfmt ");
2353 print_sysctl(fp, oid + 2, len - 2);
2355 case CTL_SYSCTL_OIDDESCR:
2356 fprintf(fp, "oiddescr ");
2357 print_sysctl(fp, oid + 2, len - 2);
2359 case CTL_SYSCTL_OIDLABEL:
2360 fprintf(fp, "oidlabel ");
2361 print_sysctl(fp, oid + 2, len - 2);
2363 case CTL_SYSCTL_NEXTNOSKIP:
2364 fprintf(fp, "nextnoskip");
2367 print_sysctl(fp, oid + 1, len - 1);
2370 print_sysctl(fp, oid, len);
2378 * The pipe() system call in the kernel returns its
2379 * two file descriptors via return values. However,
2380 * the interface exposed by libc is that pipe()
2381 * accepts a pointer to an array of descriptors.
2382 * Format the output to match the libc API by printing
2383 * the returned file descriptors as a fake argument.
2385 * Overwrite the first retval to signal a successful
2388 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2395 len = args[sc->offset + 1];
2396 utrace_addr = calloc(1, len);
2397 if (get_struct(pid, args[sc->offset],
2398 (void *)utrace_addr, len) != -1)
2399 print_utrace(fp, utrace_addr, len);
2401 print_pointer(fp, args[sc->offset]);
2406 int descriptors[16];
2407 unsigned long i, ndescriptors;
2410 ndescriptors = args[sc->offset + 1];
2412 if (ndescriptors > nitems(descriptors)) {
2413 ndescriptors = nitems(descriptors);
2416 if (get_struct(pid, args[sc->offset],
2417 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2419 for (i = 0; i < ndescriptors; i++)
2420 fprintf(fp, i == 0 ? " %d" : ", %d",
2422 fprintf(fp, truncated ? ", ... }" : " }");
2424 print_pointer(fp, args[sc->offset]);
2428 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2430 case CapFcntlRights: {
2433 if (sc->type & OUT) {
2434 if (get_struct(pid, args[sc->offset], &rights,
2435 sizeof(rights)) == -1) {
2436 print_pointer(fp, args[sc->offset]);
2440 rights = args[sc->offset];
2441 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2445 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2450 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2451 fprintf(fp, "0x%x", rem);
2453 fprintf(fp, "|0x%x", rem);
2457 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2460 print_integer_arg(sysdecode_getfsstat_mode, fp,
2464 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2466 case Kldunloadflags:
2467 print_integer_arg(sysdecode_kldunload_flags, fp,
2471 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2474 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2476 case Sockprotocol: {
2478 int domain, protocol;
2480 domain = args[sc->offset - 2];
2481 protocol = args[sc->offset];
2482 if (protocol == 0) {
2485 temp = sysdecode_socket_protocol(domain, protocol);
2489 fprintf(fp, "%d", protocol);
2495 print_integer_arg(sysdecode_sockopt_level, fp,
2502 level = args[sc->offset - 1];
2503 name = args[sc->offset];
2504 temp = sysdecode_sockopt_name(level, name);
2508 fprintf(fp, "%d", name);
2513 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2516 cap_rights_t rights;
2518 if (get_struct(pid, args[sc->offset], &rights,
2519 sizeof(rights)) != -1) {
2521 sysdecode_cap_rights(fp, &rights);
2524 print_pointer(fp, args[sc->offset]);
2528 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2530 case Extattrnamespace:
2531 print_integer_arg(sysdecode_extattrnamespace, fp,
2535 print_integer_arg(sysdecode_minherit_inherit, fp,
2539 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2542 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2545 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2548 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2551 print_integer_arg(sysdecode_ptrace_request, fp,
2555 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2556 fprintf(fp, "%#x", (int)args[sc->offset]);
2559 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2562 print_integer_arg(sysdecode_rtprio_function, fp,
2566 print_integer_arg(sysdecode_scheduler_policy, fp,
2570 struct sched_param sp;
2572 if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
2573 fprintf(fp, "{ %d }", sp.sched_priority);
2575 print_pointer(fp, args[sc->offset]);
2581 if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
2582 fprintf(fp, "{ %s }", strsig2(sig));
2584 print_pointer(fp, args[sc->offset]);
2590 if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
2591 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2592 decode_siginfo(fp, &si);
2595 print_pointer(fp, args[sc->offset]);
2600 * Print argument as an array of struct iovec, where the next
2601 * syscall argument is the number of elements of the array.
2604 print_iovec(fp, trussinfo, args[sc->offset],
2605 (int)args[sc->offset + 1]);
2607 case Sctpsndrcvinfo: {
2608 struct sctp_sndrcvinfo info;
2610 if (get_struct(pid, args[sc->offset],
2611 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2612 print_pointer(fp, args[sc->offset]);
2615 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2619 struct msghdr msghdr;
2621 if (get_struct(pid, args[sc->offset],
2622 &msghdr, sizeof(struct msghdr)) == -1) {
2623 print_pointer(fp, args[sc->offset]);
2627 print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
2628 fprintf(fp, ",%d,", msghdr.msg_namelen);
2629 print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
2630 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2631 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2632 fprintf(fp, ",%u,", msghdr.msg_controllen);
2633 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2638 case CloudABIAdvice:
2639 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2641 case CloudABIClockID:
2642 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2644 case CloudABIFDSFlags:
2645 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2647 case CloudABIFDStat: {
2648 cloudabi_fdstat_t fds;
2649 if (get_struct(pid, args[sc->offset], &fds, sizeof(fds))
2651 fprintf(fp, "{ %s, ",
2652 xlookup(cloudabi_filetype, fds.fs_filetype));
2653 fprintf(fp, "%s, ... }",
2654 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2656 print_pointer(fp, args[sc->offset]);
2659 case CloudABIFileStat: {
2660 cloudabi_filestat_t fsb;
2661 if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb))
2663 fprintf(fp, "{ %s, %ju }",
2664 xlookup(cloudabi_filetype, fsb.st_filetype),
2665 (uintmax_t)fsb.st_size);
2667 print_pointer(fp, args[sc->offset]);
2670 case CloudABIFileType:
2671 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2673 case CloudABIFSFlags:
2674 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2676 case CloudABILookup:
2677 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2678 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2679 (int)args[sc->offset]);
2681 fprintf(fp, "%d", (int)args[sc->offset]);
2683 case CloudABIMFlags:
2684 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2687 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2689 case CloudABIMSFlags:
2690 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2692 case CloudABIOFlags:
2693 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2695 case CloudABISDFlags:
2696 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2698 case CloudABISignal:
2699 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2701 case CloudABITimestamp:
2702 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2703 args[sc->offset] % 1000000000);
2705 case CloudABIULFlags:
2706 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2708 case CloudABIWhence:
2709 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2713 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2720 * Print (to outfile) the system call and its arguments.
2723 print_syscall(struct trussinfo *trussinfo)
2725 struct threadinfo *t;
2730 t = trussinfo->curthread;
2732 name = t->cs.sc->name;
2733 nargs = t->cs.nargs;
2734 s_args = t->cs.s_args;
2736 len = print_line_prefix(trussinfo);
2737 len += fprintf(trussinfo->outfile, "%s(", name);
2739 for (i = 0; i < nargs; i++) {
2740 if (s_args[i] != NULL)
2741 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2743 len += fprintf(trussinfo->outfile,
2744 "<missing argument>");
2745 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2748 len += fprintf(trussinfo->outfile, ")");
2749 for (i = 0; i < 6 - (len / 8); i++)
2750 fprintf(trussinfo->outfile, "\t");
2754 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2756 struct timespec timediff;
2757 struct threadinfo *t;
2760 t = trussinfo->curthread;
2762 if (trussinfo->flags & COUNTONLY) {
2763 timespecsub(&t->after, &t->before, &timediff);
2764 timespecadd(&sc->time, &timediff, &sc->time);
2771 print_syscall(trussinfo);
2772 fflush(trussinfo->outfile);
2774 if (retval == NULL) {
2776 * This system call resulted in the current thread's exit,
2777 * so there is no return value or error to display.
2779 fprintf(trussinfo->outfile, "\n");
2783 if (error == ERESTART)
2784 fprintf(trussinfo->outfile, " ERESTART\n");
2785 else if (error == EJUSTRETURN)
2786 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2787 else if (error != 0) {
2788 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2789 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2793 else if (sc->ret_type == 2) {
2796 #if _BYTE_ORDER == _LITTLE_ENDIAN
2797 off = (off_t)retval[1] << 32 | retval[0];
2799 off = (off_t)retval[0] << 32 | retval[1];
2801 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2806 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2807 (intmax_t)retval[0], (intmax_t)retval[0]);
2811 print_summary(struct trussinfo *trussinfo)
2813 struct timespec total = {0, 0};
2817 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2818 "syscall", "seconds", "calls", "errors");
2820 STAILQ_FOREACH(sc, &syscalls, entries)
2822 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2823 sc->name, (intmax_t)sc->time.tv_sec,
2824 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2825 timespecadd(&total, &sc->time, &total);
2826 ncall += sc->ncalls;
2827 nerror += sc->nerror;
2829 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2830 "", "-------------", "-------", "-------");
2831 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2832 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);