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);
2364 print_sysctl(fp, oid + 1, len - 1);
2367 print_sysctl(fp, oid, len);
2375 * The pipe() system call in the kernel returns its
2376 * two file descriptors via return values. However,
2377 * the interface exposed by libc is that pipe()
2378 * accepts a pointer to an array of descriptors.
2379 * Format the output to match the libc API by printing
2380 * the returned file descriptors as a fake argument.
2382 * Overwrite the first retval to signal a successful
2385 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2392 len = args[sc->offset + 1];
2393 utrace_addr = calloc(1, len);
2394 if (get_struct(pid, args[sc->offset],
2395 (void *)utrace_addr, len) != -1)
2396 print_utrace(fp, utrace_addr, len);
2398 print_pointer(fp, args[sc->offset]);
2403 int descriptors[16];
2404 unsigned long i, ndescriptors;
2407 ndescriptors = args[sc->offset + 1];
2409 if (ndescriptors > nitems(descriptors)) {
2410 ndescriptors = nitems(descriptors);
2413 if (get_struct(pid, args[sc->offset],
2414 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2416 for (i = 0; i < ndescriptors; i++)
2417 fprintf(fp, i == 0 ? " %d" : ", %d",
2419 fprintf(fp, truncated ? ", ... }" : " }");
2421 print_pointer(fp, args[sc->offset]);
2425 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2427 case CapFcntlRights: {
2430 if (sc->type & OUT) {
2431 if (get_struct(pid, args[sc->offset], &rights,
2432 sizeof(rights)) == -1) {
2433 print_pointer(fp, args[sc->offset]);
2437 rights = args[sc->offset];
2438 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2442 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2447 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2448 fprintf(fp, "0x%x", rem);
2450 fprintf(fp, "|0x%x", rem);
2454 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2457 print_integer_arg(sysdecode_getfsstat_mode, fp,
2461 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2463 case Kldunloadflags:
2464 print_integer_arg(sysdecode_kldunload_flags, fp,
2468 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2471 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2473 case Sockprotocol: {
2475 int domain, protocol;
2477 domain = args[sc->offset - 2];
2478 protocol = args[sc->offset];
2479 if (protocol == 0) {
2482 temp = sysdecode_socket_protocol(domain, protocol);
2486 fprintf(fp, "%d", protocol);
2492 print_integer_arg(sysdecode_sockopt_level, fp,
2499 level = args[sc->offset - 1];
2500 name = args[sc->offset];
2501 temp = sysdecode_sockopt_name(level, name);
2505 fprintf(fp, "%d", name);
2510 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2513 cap_rights_t rights;
2515 if (get_struct(pid, args[sc->offset], &rights,
2516 sizeof(rights)) != -1) {
2518 sysdecode_cap_rights(fp, &rights);
2521 print_pointer(fp, args[sc->offset]);
2525 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2527 case Extattrnamespace:
2528 print_integer_arg(sysdecode_extattrnamespace, fp,
2532 print_integer_arg(sysdecode_minherit_inherit, fp,
2536 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2539 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2542 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2545 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2548 print_integer_arg(sysdecode_ptrace_request, fp,
2552 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2553 fprintf(fp, "%#x", (int)args[sc->offset]);
2556 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2559 print_integer_arg(sysdecode_rtprio_function, fp,
2563 print_integer_arg(sysdecode_scheduler_policy, fp,
2567 struct sched_param sp;
2569 if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
2570 fprintf(fp, "{ %d }", sp.sched_priority);
2572 print_pointer(fp, args[sc->offset]);
2578 if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
2579 fprintf(fp, "{ %s }", strsig2(sig));
2581 print_pointer(fp, args[sc->offset]);
2587 if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
2588 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2589 decode_siginfo(fp, &si);
2592 print_pointer(fp, args[sc->offset]);
2597 * Print argument as an array of struct iovec, where the next
2598 * syscall argument is the number of elements of the array.
2601 print_iovec(fp, trussinfo, args[sc->offset],
2602 (int)args[sc->offset + 1]);
2604 case Sctpsndrcvinfo: {
2605 struct sctp_sndrcvinfo info;
2607 if (get_struct(pid, args[sc->offset],
2608 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2609 print_pointer(fp, args[sc->offset]);
2612 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2616 struct msghdr msghdr;
2618 if (get_struct(pid, args[sc->offset],
2619 &msghdr, sizeof(struct msghdr)) == -1) {
2620 print_pointer(fp, args[sc->offset]);
2624 print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
2625 fprintf(fp, ",%d,", msghdr.msg_namelen);
2626 print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
2627 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2628 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2629 fprintf(fp, ",%u,", msghdr.msg_controllen);
2630 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2635 case CloudABIAdvice:
2636 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2638 case CloudABIClockID:
2639 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2641 case CloudABIFDSFlags:
2642 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2644 case CloudABIFDStat: {
2645 cloudabi_fdstat_t fds;
2646 if (get_struct(pid, args[sc->offset], &fds, sizeof(fds))
2648 fprintf(fp, "{ %s, ",
2649 xlookup(cloudabi_filetype, fds.fs_filetype));
2650 fprintf(fp, "%s, ... }",
2651 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2653 print_pointer(fp, args[sc->offset]);
2656 case CloudABIFileStat: {
2657 cloudabi_filestat_t fsb;
2658 if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb))
2660 fprintf(fp, "{ %s, %ju }",
2661 xlookup(cloudabi_filetype, fsb.st_filetype),
2662 (uintmax_t)fsb.st_size);
2664 print_pointer(fp, args[sc->offset]);
2667 case CloudABIFileType:
2668 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2670 case CloudABIFSFlags:
2671 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2673 case CloudABILookup:
2674 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2675 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2676 (int)args[sc->offset]);
2678 fprintf(fp, "%d", (int)args[sc->offset]);
2680 case CloudABIMFlags:
2681 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2684 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2686 case CloudABIMSFlags:
2687 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2689 case CloudABIOFlags:
2690 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2692 case CloudABISDFlags:
2693 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2695 case CloudABISignal:
2696 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2698 case CloudABITimestamp:
2699 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2700 args[sc->offset] % 1000000000);
2702 case CloudABIULFlags:
2703 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2705 case CloudABIWhence:
2706 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2710 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2717 * Print (to outfile) the system call and its arguments.
2720 print_syscall(struct trussinfo *trussinfo)
2722 struct threadinfo *t;
2727 t = trussinfo->curthread;
2729 name = t->cs.sc->name;
2730 nargs = t->cs.nargs;
2731 s_args = t->cs.s_args;
2733 len = print_line_prefix(trussinfo);
2734 len += fprintf(trussinfo->outfile, "%s(", name);
2736 for (i = 0; i < nargs; i++) {
2737 if (s_args[i] != NULL)
2738 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2740 len += fprintf(trussinfo->outfile,
2741 "<missing argument>");
2742 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2745 len += fprintf(trussinfo->outfile, ")");
2746 for (i = 0; i < 6 - (len / 8); i++)
2747 fprintf(trussinfo->outfile, "\t");
2751 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2753 struct timespec timediff;
2754 struct threadinfo *t;
2757 t = trussinfo->curthread;
2759 if (trussinfo->flags & COUNTONLY) {
2760 timespecsub(&t->after, &t->before, &timediff);
2761 timespecadd(&sc->time, &timediff, &sc->time);
2768 print_syscall(trussinfo);
2769 fflush(trussinfo->outfile);
2771 if (retval == NULL) {
2773 * This system call resulted in the current thread's exit,
2774 * so there is no return value or error to display.
2776 fprintf(trussinfo->outfile, "\n");
2780 if (error == ERESTART)
2781 fprintf(trussinfo->outfile, " ERESTART\n");
2782 else if (error == EJUSTRETURN)
2783 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2784 else if (error != 0) {
2785 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2786 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2790 else if (sc->ret_type == 2) {
2793 #if _BYTE_ORDER == _LITTLE_ENDIAN
2794 off = (off_t)retval[1] << 32 | retval[0];
2796 off = (off_t)retval[0] << 32 | retval[1];
2798 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2803 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2804 (intmax_t)retval[0], (intmax_t)retval[0]);
2808 print_summary(struct trussinfo *trussinfo)
2810 struct timespec total = {0, 0};
2814 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2815 "syscall", "seconds", "calls", "errors");
2817 STAILQ_FOREACH(sc, &syscalls, entries)
2819 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2820 sc->name, (intmax_t)sc->time.tv_sec,
2821 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2822 timespecadd(&total, &sc->time, &total);
2823 ncall += sc->ncalls;
2824 nerror += sc->nerror;
2826 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2827 "", "-------------", "-------", "-------");
2828 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2829 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);