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
43 #include <sys/capsicum.h>
44 #include <sys/types.h>
45 #define _WANT_FREEBSD11_KEVENT
46 #include <sys/event.h>
47 #include <sys/ioccom.h>
49 #include <sys/mount.h>
50 #include <sys/ptrace.h>
51 #include <sys/resource.h>
52 #include <sys/socket.h>
53 #define _WANT_FREEBSD11_STAT
55 #include <sys/sysctl.h>
59 #include <netinet/in.h>
60 #include <netinet/sctp.h>
61 #include <arpa/inet.h>
66 #define _WANT_KERNEL_ERRNO
76 #include <sysdecode.h>
80 #include <contrib/cloudabi/cloudabi_types_common.h>
87 * This should probably be in its own file, sorted alphabetically.
89 static struct syscall decoded_syscalls[] = {
91 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
92 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
93 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
94 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
95 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
96 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
97 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
98 .args = { { Int, 0 }, { Acltype, 1 } } },
99 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
100 .args = { { Name, 0 }, { Acltype, 1 } } },
101 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
102 .args = { { Name, 0 }, { Acltype, 1 } } },
103 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
104 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
106 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
108 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
110 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
111 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
112 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
113 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
114 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
115 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
116 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
117 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
118 .args = { { Name | OUT, 0 }, { Int, 1 } } },
119 { .name = "__realpathat", .ret_type = 1, .nargs = 5,
120 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Name | OUT, 2 },
121 { Sizet, 3 }, { Int, 4} } },
122 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
123 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
125 { .name = "accept", .ret_type = 1, .nargs = 3,
126 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
127 { .name = "access", .ret_type = 1, .nargs = 2,
128 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
129 { .name = "aio_cancel", .ret_type = 1, .nargs = 2,
130 .args = { { Int, 0 }, { Aiocb, 1 } } },
131 { .name = "aio_error", .ret_type = 1, .nargs = 1,
132 .args = { { Aiocb, 0 } } },
133 { .name = "aio_fsync", .ret_type = 1, .nargs = 2,
134 .args = { { AiofsyncOp, 0 }, { Aiocb, 1 } } },
135 { .name = "aio_mlock", .ret_type = 1, .nargs = 1,
136 .args = { { Aiocb, 0 } } },
137 { .name = "aio_read", .ret_type = 1, .nargs = 1,
138 .args = { { Aiocb, 0 } } },
139 { .name = "aio_return", .ret_type = 1, .nargs = 1,
140 .args = { { Aiocb, 0 } } },
141 { .name = "aio_suspend", .ret_type = 1, .nargs = 3,
142 .args = { { AiocbArray, 0 }, { Int, 1 }, { Timespec, 2 } } },
143 { .name = "aio_waitcomplete", .ret_type = 1, .nargs = 2,
144 .args = { { AiocbPointer | OUT, 0 }, { Timespec, 1 } } },
145 { .name = "aio_write", .ret_type = 1, .nargs = 1,
146 .args = { { Aiocb, 0 } } },
147 { .name = "bind", .ret_type = 1, .nargs = 3,
148 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
149 { .name = "bindat", .ret_type = 1, .nargs = 4,
150 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
152 { .name = "break", .ret_type = 1, .nargs = 1,
153 .args = { { Ptr, 0 } } },
154 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
155 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
156 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
157 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
158 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
159 .args = { { PUInt | OUT, 0 } } },
160 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
161 .args = { { Int, 0 }, { CapRights, 1 } } },
162 { .name = "chdir", .ret_type = 1, .nargs = 1,
163 .args = { { Name, 0 } } },
164 { .name = "chflags", .ret_type = 1, .nargs = 2,
165 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
166 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
167 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
169 { .name = "chmod", .ret_type = 1, .nargs = 2,
170 .args = { { Name, 0 }, { Octal, 1 } } },
171 { .name = "chown", .ret_type = 1, .nargs = 3,
172 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
173 { .name = "chroot", .ret_type = 1, .nargs = 1,
174 .args = { { Name, 0 } } },
175 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
176 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
177 { .name = "close", .ret_type = 1, .nargs = 1,
178 .args = { { Int, 0 } } },
179 { .name = "closefrom", .ret_type = 1, .nargs = 1,
180 .args = { { Int, 0 } } },
181 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
182 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
183 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
184 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
186 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
187 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
188 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
189 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
190 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
191 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
192 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
193 { .name = "connect", .ret_type = 1, .nargs = 3,
194 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
195 { .name = "connectat", .ret_type = 1, .nargs = 4,
196 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
198 { .name = "dup", .ret_type = 1, .nargs = 1,
199 .args = { { Int, 0 } } },
200 { .name = "dup2", .ret_type = 1, .nargs = 2,
201 .args = { { Int, 0 }, { Int, 1 } } },
202 { .name = "eaccess", .ret_type = 1, .nargs = 2,
203 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
204 { .name = "execve", .ret_type = 1, .nargs = 3,
205 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
206 { ExecEnv | IN, 2 } } },
207 { .name = "exit", .ret_type = 0, .nargs = 1,
208 .args = { { Hex, 0 } } },
209 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
210 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
211 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
213 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
214 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
215 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
216 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
217 { BinString | OUT, 3 }, { Sizet, 4 } } },
218 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
219 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
220 { BinString | OUT, 3 }, { Sizet, 4 } } },
221 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
222 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
223 { BinString | OUT, 3 }, { Sizet, 4 } } },
224 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
225 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
227 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
228 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
230 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
231 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
233 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
234 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
235 { BinString | IN, 3 }, { Sizet, 4 } } },
236 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
237 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
238 { BinString | IN, 3 }, { Sizet, 4 } } },
239 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
240 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
241 { BinString | IN, 3 }, { Sizet, 4 } } },
242 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
243 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
244 { Extattrnamespace, 3 }, { Name, 4 } } },
245 { .name = "faccessat", .ret_type = 1, .nargs = 4,
246 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
248 { .name = "fchflags", .ret_type = 1, .nargs = 2,
249 .args = { { Int, 0 }, { FileFlags, 1 } } },
250 { .name = "fchmod", .ret_type = 1, .nargs = 2,
251 .args = { { Int, 0 }, { Octal, 1 } } },
252 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
253 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
254 { .name = "fchown", .ret_type = 1, .nargs = 3,
255 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
256 { .name = "fchownat", .ret_type = 1, .nargs = 5,
257 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
259 { .name = "fcntl", .ret_type = 1, .nargs = 3,
260 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
261 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
262 .args = { { Int, 0 } } },
263 { .name = "flock", .ret_type = 1, .nargs = 2,
264 .args = { { Int, 0 }, { Flockop, 1 } } },
265 { .name = "fstat", .ret_type = 1, .nargs = 2,
266 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
267 { .name = "fstatat", .ret_type = 1, .nargs = 4,
268 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
270 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
271 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
272 { .name = "fsync", .ret_type = 1, .nargs = 1,
273 .args = { { Int, 0 } } },
274 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
275 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
276 { .name = "futimens", .ret_type = 1, .nargs = 2,
277 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
278 { .name = "futimes", .ret_type = 1, .nargs = 2,
279 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
280 { .name = "futimesat", .ret_type = 1, .nargs = 3,
281 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
282 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
283 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
284 { PQuadHex | OUT, 3 } } },
285 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
286 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
287 { .name = "getitimer", .ret_type = 1, .nargs = 2,
288 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
289 { .name = "getpeername", .ret_type = 1, .nargs = 3,
290 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
291 { .name = "getpgid", .ret_type = 1, .nargs = 1,
292 .args = { { Int, 0 } } },
293 { .name = "getpriority", .ret_type = 1, .nargs = 2,
294 .args = { { Priowhich, 0 }, { Int, 1 } } },
295 { .name = "getrandom", .ret_type = 1, .nargs = 3,
296 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
297 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
298 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
299 { .name = "getrusage", .ret_type = 1, .nargs = 2,
300 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
301 { .name = "getsid", .ret_type = 1, .nargs = 1,
302 .args = { { Int, 0 } } },
303 { .name = "getsockname", .ret_type = 1, .nargs = 3,
304 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
305 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
306 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
307 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
308 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
309 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
310 { .name = "ioctl", .ret_type = 1, .nargs = 3,
311 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
312 { .name = "kevent", .ret_type = 1, .nargs = 6,
313 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
314 { Int, 4 }, { Timespec, 5 } } },
315 { .name = "kill", .ret_type = 1, .nargs = 2,
316 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
317 { .name = "kldfind", .ret_type = 1, .nargs = 1,
318 .args = { { Name | IN, 0 } } },
319 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
320 .args = { { Int, 0 } } },
321 { .name = "kldload", .ret_type = 1, .nargs = 1,
322 .args = { { Name | IN, 0 } } },
323 { .name = "kldnext", .ret_type = 1, .nargs = 1,
324 .args = { { Int, 0 } } },
325 { .name = "kldstat", .ret_type = 1, .nargs = 2,
326 .args = { { Int, 0 }, { Ptr, 1 } } },
327 { .name = "kldsym", .ret_type = 1, .nargs = 3,
328 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
329 { .name = "kldunload", .ret_type = 1, .nargs = 1,
330 .args = { { Int, 0 } } },
331 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
332 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
333 { .name = "kse_release", .ret_type = 0, .nargs = 1,
334 .args = { { Timespec, 0 } } },
335 { .name = "lchflags", .ret_type = 1, .nargs = 2,
336 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
337 { .name = "lchmod", .ret_type = 1, .nargs = 2,
338 .args = { { Name, 0 }, { Octal, 1 } } },
339 { .name = "lchown", .ret_type = 1, .nargs = 3,
340 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
341 { .name = "link", .ret_type = 1, .nargs = 2,
342 .args = { { Name, 0 }, { Name, 1 } } },
343 { .name = "linkat", .ret_type = 1, .nargs = 5,
344 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
346 { .name = "lio_listio", .ret_type = 1, .nargs = 4,
347 .args = { { LioMode, 0 }, { AiocbArray, 1 }, { Int, 2 },
349 { .name = "listen", .ret_type = 1, .nargs = 2,
350 .args = { { Int, 0 }, { Int, 1 } } },
351 { .name = "lseek", .ret_type = 2, .nargs = 3,
352 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
353 { .name = "lstat", .ret_type = 1, .nargs = 2,
354 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
355 { .name = "lutimes", .ret_type = 1, .nargs = 2,
356 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
357 { .name = "madvise", .ret_type = 1, .nargs = 3,
358 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
359 { .name = "minherit", .ret_type = 1, .nargs = 3,
360 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
361 { .name = "mkdir", .ret_type = 1, .nargs = 2,
362 .args = { { Name, 0 }, { Octal, 1 } } },
363 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
364 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
365 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
366 .args = { { Name, 0 }, { Octal, 1 } } },
367 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
368 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
369 { .name = "mknod", .ret_type = 1, .nargs = 3,
370 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
371 { .name = "mknodat", .ret_type = 1, .nargs = 4,
372 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
373 { .name = "mlock", .ret_type = 1, .nargs = 2,
374 .args = { { Ptr, 0 }, { Sizet, 1 } } },
375 { .name = "mlockall", .ret_type = 1, .nargs = 1,
376 .args = { { Mlockall, 0 } } },
377 { .name = "mmap", .ret_type = 1, .nargs = 6,
378 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
379 { Int, 4 }, { QuadHex, 5 } } },
380 { .name = "modfind", .ret_type = 1, .nargs = 1,
381 .args = { { Name | IN, 0 } } },
382 { .name = "mount", .ret_type = 1, .nargs = 4,
383 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
384 { .name = "mprotect", .ret_type = 1, .nargs = 3,
385 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
386 { .name = "msync", .ret_type = 1, .nargs = 3,
387 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
388 { .name = "munlock", .ret_type = 1, .nargs = 2,
389 .args = { { Ptr, 0 }, { Sizet, 1 } } },
390 { .name = "munmap", .ret_type = 1, .nargs = 2,
391 .args = { { Ptr, 0 }, { Sizet, 1 } } },
392 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
393 .args = { { Timespec, 0 } } },
394 { .name = "nmount", .ret_type = 1, .nargs = 3,
395 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
396 { .name = "open", .ret_type = 1, .nargs = 3,
397 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
398 { .name = "openat", .ret_type = 1, .nargs = 4,
399 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
401 { .name = "pathconf", .ret_type = 1, .nargs = 2,
402 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
403 { .name = "pipe", .ret_type = 1, .nargs = 1,
404 .args = { { PipeFds | OUT, 0 } } },
405 { .name = "pipe2", .ret_type = 1, .nargs = 2,
406 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
407 { .name = "poll", .ret_type = 1, .nargs = 3,
408 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
409 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
410 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
412 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
413 .args = { { Open, 0 } } },
414 { .name = "pread", .ret_type = 1, .nargs = 4,
415 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
417 { .name = "procctl", .ret_type = 1, .nargs = 4,
418 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
419 { .name = "ptrace", .ret_type = 1, .nargs = 4,
420 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
421 { .name = "pwrite", .ret_type = 1, .nargs = 4,
422 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
424 { .name = "quotactl", .ret_type = 1, .nargs = 4,
425 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
426 { .name = "read", .ret_type = 1, .nargs = 3,
427 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
428 { .name = "readlink", .ret_type = 1, .nargs = 3,
429 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
430 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
431 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
433 { .name = "readv", .ret_type = 1, .nargs = 3,
434 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
435 { .name = "reboot", .ret_type = 1, .nargs = 1,
436 .args = { { Reboothowto, 0 } } },
437 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
438 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
439 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
440 { Ptr | OUT, 5 } } },
441 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
442 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
443 { .name = "rename", .ret_type = 1, .nargs = 2,
444 .args = { { Name, 0 }, { Name, 1 } } },
445 { .name = "renameat", .ret_type = 1, .nargs = 4,
446 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
447 { .name = "rfork", .ret_type = 1, .nargs = 1,
448 .args = { { Rforkflags, 0 } } },
449 { .name = "rmdir", .ret_type = 1, .nargs = 1,
450 .args = { { Name, 0 } } },
451 { .name = "rtprio", .ret_type = 1, .nargs = 3,
452 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
453 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
454 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
455 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
456 .args = { { Schedpolicy, 0 } } },
457 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
458 .args = { { Schedpolicy, 0 } } },
459 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
460 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
461 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
462 .args = { { Int, 0 } } },
463 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
464 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
465 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
466 .args = { { Int, 0 }, { Schedparam, 1 } } },
467 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
468 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
469 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
470 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
471 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
472 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
473 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
474 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
475 { Sockaddr | IN, 3 }, { Socklent, 4 },
476 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
477 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
478 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
479 { Sockaddr | IN, 3 }, { Socklent, 4 },
480 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
481 { .name = "select", .ret_type = 1, .nargs = 5,
482 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
484 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
485 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
486 { .name = "sendto", .ret_type = 1, .nargs = 6,
487 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
488 { Msgflags, 3 }, { Sockaddr | IN, 4 },
489 { Socklent | IN, 5 } } },
490 { .name = "setitimer", .ret_type = 1, .nargs = 3,
491 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
492 { .name = "setpriority", .ret_type = 1, .nargs = 3,
493 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
494 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
495 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
496 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
497 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
498 { Ptr | IN, 3 }, { Socklent, 4 } } },
499 { .name = "shm_open", .ret_type = 1, .nargs = 3,
500 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
501 { .name = "shm_open2", .ret_type = 1, .nargs = 5,
502 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 },
503 { ShmFlags, 3 }, { Name | IN, 4 } } },
504 { .name = "shm_rename", .ret_type = 1, .nargs = 3,
505 .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } },
506 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
507 .args = { { Name | IN, 0 } } },
508 { .name = "shutdown", .ret_type = 1, .nargs = 2,
509 .args = { { Int, 0 }, { Shutdown, 1 } } },
510 { .name = "sigaction", .ret_type = 1, .nargs = 3,
511 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
512 { Sigaction | OUT, 2 } } },
513 { .name = "sigpending", .ret_type = 1, .nargs = 1,
514 .args = { { Sigset | OUT, 0 } } },
515 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
516 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
517 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
518 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
519 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
520 .args = { { Ptr, 0 } } },
521 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
522 .args = { { Sigset | IN, 0 } } },
523 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
524 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
525 { Timespec | IN, 2 } } },
526 { .name = "sigwait", .ret_type = 1, .nargs = 2,
527 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
528 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
529 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
530 { .name = "socket", .ret_type = 1, .nargs = 3,
531 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
532 { .name = "stat", .ret_type = 1, .nargs = 2,
533 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
534 { .name = "statfs", .ret_type = 1, .nargs = 2,
535 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
536 { .name = "symlink", .ret_type = 1, .nargs = 2,
537 .args = { { Name, 0 }, { Name, 1 } } },
538 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
539 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
540 { .name = "sysarch", .ret_type = 1, .nargs = 2,
541 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
542 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
543 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
544 { Ptr, 4 }, { Sizet, 5 } } },
545 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
546 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
547 { Ptr, 4}, { Sizet, 5 } } },
548 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
549 .args = { { Long, 0 }, { Signal, 1 } } },
550 { .name = "thr_self", .ret_type = 1, .nargs = 1,
551 .args = { { Ptr, 0 } } },
552 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
553 .args = { { Long, 0 }, { Name, 1 } } },
554 { .name = "truncate", .ret_type = 1, .nargs = 2,
555 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
558 { .name = "umount", .ret_type = 1, .nargs = 2,
559 .args = { { Name, 0 }, { Int, 2 } } },
561 { .name = "unlink", .ret_type = 1, .nargs = 1,
562 .args = { { Name, 0 } } },
563 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
564 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
565 { .name = "unmount", .ret_type = 1, .nargs = 2,
566 .args = { { Name, 0 }, { Mountflags, 1 } } },
567 { .name = "utimensat", .ret_type = 1, .nargs = 4,
568 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
570 { .name = "utimes", .ret_type = 1, .nargs = 2,
571 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
572 { .name = "utrace", .ret_type = 1, .nargs = 1,
573 .args = { { Utrace, 0 } } },
574 { .name = "wait4", .ret_type = 1, .nargs = 4,
575 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
576 { Rusage | OUT, 3 } } },
577 { .name = "wait6", .ret_type = 1, .nargs = 6,
578 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
579 { Waitoptions, 3 }, { Rusage | OUT, 4 },
580 { Siginfo | OUT, 5 } } },
581 { .name = "write", .ret_type = 1, .nargs = 3,
582 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
583 { .name = "writev", .ret_type = 1, .nargs = 3,
584 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
587 { .name = "linux_access", .ret_type = 1, .nargs = 2,
588 .args = { { Name, 0 }, { Accessmode, 1 } } },
589 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
590 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
591 { ExecEnv | IN, 2 } } },
592 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
593 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
594 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
595 .args = { { Name | IN, 0 }, { Int, 1 } } },
596 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
597 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
598 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
599 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
600 { .name = "linux_open", .ret_type = 1, .nargs = 3,
601 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
602 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
603 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
604 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
605 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
606 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
607 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
609 /* CloudABI system calls. */
610 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
611 .args = { { CloudABIClockID, 0 } } },
612 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
613 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
614 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
615 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
616 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
617 .args = { { Int, 0 } } },
618 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
619 .args = { { CloudABIFileType, 0 } } },
620 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
621 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
622 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
623 .args = { { Int, 0 } } },
624 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
625 .args = { { Int, 0 } } },
626 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
627 .args = { { Int, 0 }, { Int, 1 } } },
628 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
629 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
630 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
631 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
632 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
633 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
634 { CloudABIFDSFlags, 2 } } },
635 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
636 .args = { { Int, 0 } } },
637 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
638 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
639 { CloudABIAdvice, 3 } } },
640 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
641 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
642 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
643 .args = { { Int, 0 }, { BinString | IN, 1 },
644 { CloudABIFileType, 3 } } },
645 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
646 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
647 { Int, 3 }, { BinString | IN, 4 } } },
648 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
649 .args = { { Int, 0 }, { BinString | IN, 1 },
650 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
651 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
652 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
654 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
655 .args = { { Int, 0 }, { BinString | IN, 1 },
656 { BinString | OUT, 3 }, { Int, 4 } } },
657 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
658 .args = { { Int, 0 }, { BinString | IN, 1 },
659 { Int, 3 }, { BinString | IN, 4 } } },
660 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
661 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
662 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
663 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
664 { CloudABIFSFlags, 2 } } },
665 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
666 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
667 { CloudABIFileStat | OUT, 3 } } },
668 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
669 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
670 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
671 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
672 .args = { { BinString | IN, 0 },
673 { Int, 2 }, { BinString | IN, 3 } } },
674 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
675 .args = { { Int, 0 }, { BinString | IN, 1 },
676 { CloudABIULFlags, 3 } } },
677 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
678 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
679 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
680 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
681 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
682 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
683 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
684 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
685 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
686 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
687 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
688 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
689 .args = { { Ptr, 0 }, { Int, 1 } } },
690 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
691 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
692 { IntArray, 3 }, { Int, 4 } } },
693 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
694 .args = { { Int, 0 } } },
695 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
696 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
697 .args = { { CloudABISignal, 0 } } },
698 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
699 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
700 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
701 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
702 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
703 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
704 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
708 static STAILQ_HEAD(, syscall) syscalls;
710 /* Xlat idea taken from strace */
716 #define X(a) { a, #a },
717 #define XEND { 0, NULL }
719 static struct xlat poll_flags[] = {
720 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
721 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
722 X(POLLWRBAND) X(POLLINIGNEOF) XEND
725 static struct xlat sigaction_flags[] = {
726 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
727 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
730 static struct xlat linux_socketcall_ops[] = {
731 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
732 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
733 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
734 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
735 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
739 static struct xlat lio_modes[] = {
740 X(LIO_WAIT) X(LIO_NOWAIT)
744 static struct xlat lio_opcodes[] = {
745 X(LIO_WRITE) X(LIO_READ) X(LIO_NOP)
749 static struct xlat aio_fsync_ops[] = {
755 #define X(a) { CLOUDABI_##a, #a },
757 static struct xlat cloudabi_advice[] = {
758 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
759 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
763 static struct xlat cloudabi_clockid[] = {
764 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
765 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
769 static struct xlat cloudabi_fdflags[] = {
770 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
771 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
775 static struct xlat cloudabi_fdsflags[] = {
776 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
780 static struct xlat cloudabi_filetype[] = {
781 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
782 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
783 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
784 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
785 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
789 static struct xlat cloudabi_fsflags[] = {
790 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
791 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
795 static struct xlat cloudabi_mflags[] = {
796 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
800 static struct xlat cloudabi_mprot[] = {
801 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
805 static struct xlat cloudabi_msflags[] = {
806 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
810 static struct xlat cloudabi_oflags[] = {
811 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
815 static struct xlat cloudabi_sdflags[] = {
816 X(SHUT_RD) X(SHUT_WR)
820 static struct xlat cloudabi_signal[] = {
821 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
822 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
823 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
824 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
825 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
829 static struct xlat cloudabi_ulflags[] = {
834 static struct xlat cloudabi_whence[] = {
835 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
843 * Searches an xlat array for a value, and returns it if found. Otherwise
844 * return a string representation.
847 lookup(struct xlat *xlat, int val, int base)
851 for (; xlat->str != NULL; xlat++)
852 if (xlat->val == val)
856 sprintf(tmp, "0%o", val);
859 sprintf(tmp, "0x%x", val);
862 sprintf(tmp, "%u", val);
865 errx(1,"Unknown lookup base");
872 xlookup(struct xlat *xlat, int val)
875 return (lookup(xlat, val, 16));
879 * Searches an xlat array containing bitfield values. Remaining bits
880 * set after removing the known ones are printed at the end:
884 xlookup_bits(struct xlat *xlat, int val)
887 static char str[512];
891 for (; xlat->str != NULL; xlat++) {
892 if ((xlat->val & rem) == xlat->val) {
894 * Don't print the "all-bits-zero" string unless all
895 * bits are really zero.
897 if (xlat->val == 0 && val != 0)
899 len += sprintf(str + len, "%s|", xlat->str);
905 * If we have leftover bits or didn't match anything, print
909 len += sprintf(str + len, "0x%x", rem);
910 if (len && str[len - 1] == '|')
917 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
921 str = decoder(value);
925 fprintf(fp, "%d", value);
929 print_mask_arg_part(bool (*decoder)(FILE *, int, int *), FILE *fp, int value,
933 return (decoder(fp, value, rem));
937 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
941 if (!print_mask_arg_part(decoder, fp, value, &rem))
942 fprintf(fp, "0x%x", rem);
944 fprintf(fp, "|0x%x", rem);
948 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
953 if (!decoder(fp, value, &rem))
954 fprintf(fp, "0x%x", rem);
956 fprintf(fp, "|0x%x", rem);
961 * Add argument padding to subsequent system calls after Quad
962 * syscall arguments as needed. This used to be done by hand in the
963 * decoded_syscalls table which was ugly and error prone. It is
964 * simpler to do the fixup of offsets at initialization time than when
965 * decoding arguments.
968 quad_fixup(struct syscall *sc)
975 for (i = 0; i < sc->nargs; i++) {
976 /* This arg type is a dummy that doesn't use offset. */
977 if ((sc->args[i].type & ARG_MASK) == PipeFds)
980 assert(prev < sc->args[i].offset);
981 prev = sc->args[i].offset;
982 sc->args[i].offset += offset;
983 switch (sc->args[i].type & ARG_MASK) {
988 * 64-bit arguments on 32-bit powerpc must be
989 * 64-bit aligned. If the current offset is
990 * not aligned, the calling convention inserts
991 * a 32-bit pad argument that should be skipped.
993 if (sc->args[i].offset % 2 == 1) {
994 sc->args[i].offset++;
1011 STAILQ_INIT(&syscalls);
1012 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
1016 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1020 static struct syscall *
1021 find_syscall(struct procabi *abi, u_int number)
1023 struct extra_syscall *es;
1025 if (number < nitems(abi->syscalls))
1026 return (abi->syscalls[number]);
1027 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
1028 if (es->number == number)
1035 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
1037 struct extra_syscall *es;
1039 if (number < nitems(abi->syscalls)) {
1040 assert(abi->syscalls[number] == NULL);
1041 abi->syscalls[number] = sc;
1043 es = malloc(sizeof(*es));
1045 es->number = number;
1046 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
1051 * If/when the list gets big, it might be desirable to do it
1052 * as a hash table or binary search.
1055 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1062 sc = find_syscall(t->proc->abi, number);
1066 name = sysdecode_syscallname(t->proc->abi->abi, number);
1068 asprintf(&new_name, "#%d", number);
1072 STAILQ_FOREACH(sc, &syscalls, entries) {
1073 if (strcmp(name, sc->name) == 0) {
1074 add_syscall(t->proc->abi, number, sc);
1080 /* It is unknown. Add it into the list. */
1082 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1086 sc = calloc(1, sizeof(struct syscall));
1088 if (new_name != NULL)
1092 for (i = 0; i < nargs; i++) {
1093 sc->args[i].offset = i;
1094 /* Treat all unknown arguments as LongHex. */
1095 sc->args[i].type = LongHex;
1097 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1098 add_syscall(t->proc->abi, number, sc);
1104 * Copy a fixed amount of bytes from the process.
1107 get_struct(pid_t pid, uintptr_t offset, void *buf, int len)
1109 struct ptrace_io_desc iorequest;
1111 iorequest.piod_op = PIOD_READ_D;
1112 iorequest.piod_offs = (void *)offset;
1113 iorequest.piod_addr = buf;
1114 iorequest.piod_len = len;
1115 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1120 #define MAXSIZE 4096
1123 * Copy a string from the process. Note that it is
1124 * expected to be a C string, but if max is set, it will
1125 * only get that much.
1128 get_string(pid_t pid, uintptr_t addr, int max)
1130 struct ptrace_io_desc iorequest;
1132 size_t offset, size, totalsize;
1138 /* Read up to the end of the current page. */
1139 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1144 buf = malloc(totalsize);
1148 iorequest.piod_op = PIOD_READ_D;
1149 iorequest.piod_offs = (void *)(addr + offset);
1150 iorequest.piod_addr = buf + offset;
1151 iorequest.piod_len = size;
1152 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1156 if (memchr(buf + offset, '\0', size) != NULL)
1159 if (totalsize < MAXSIZE && max == 0) {
1160 size = MAXSIZE - totalsize;
1161 if (size > PAGE_SIZE)
1163 nbuf = realloc(buf, totalsize + size);
1165 buf[totalsize - 1] = '\0';
1171 buf[totalsize - 1] = '\0';
1180 static char tmp[32];
1181 const char *signame;
1183 signame = sysdecode_signal(sig);
1184 if (signame == NULL) {
1185 snprintf(tmp, sizeof(tmp), "%d", sig);
1192 print_kevent(FILE *fp, struct kevent *ke)
1195 switch (ke->filter) {
1201 case EVFILT_PROCDESC:
1203 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1206 fputs(strsig2(ke->ident), fp);
1209 fprintf(fp, "%p", (void *)ke->ident);
1212 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1214 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1216 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1217 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1221 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1223 unsigned char *utrace_buffer;
1226 if (sysdecode_utrace(fp, utrace_addr, len)) {
1231 utrace_buffer = utrace_addr;
1232 fprintf(fp, "%zu:", len);
1234 fprintf(fp, " %02x", *utrace_buffer++);
1239 print_pointer(FILE *fp, uintptr_t arg)
1242 fprintf(fp, "%p", (void *)arg);
1246 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg,
1250 struct sockaddr_in *lsin;
1251 struct sockaddr_in6 *lsin6;
1252 struct sockaddr_un *sun;
1253 struct sockaddr *sa;
1255 pid_t pid = trussinfo->curthread->proc->pid;
1261 /* If the length is too small, just bail. */
1262 if (len < sizeof(*sa)) {
1263 print_pointer(fp, arg);
1267 sa = calloc(1, len);
1268 if (get_struct(pid, arg, sa, len) == -1) {
1270 print_pointer(fp, arg);
1274 switch (sa->sa_family) {
1276 if (len < sizeof(*lsin))
1277 goto sockaddr_short;
1278 lsin = (struct sockaddr_in *)(void *)sa;
1279 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1280 fprintf(fp, "{ AF_INET %s:%d }", addr,
1281 htons(lsin->sin_port));
1284 if (len < sizeof(*lsin6))
1285 goto sockaddr_short;
1286 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1287 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1289 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1290 htons(lsin6->sin6_port));
1293 sun = (struct sockaddr_un *)sa;
1294 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1295 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1301 "{ sa_len = %d, sa_family = %d, sa_data = {",
1302 (int)sa->sa_len, (int)sa->sa_family);
1303 for (q = (u_char *)sa->sa_data;
1304 q < (u_char *)sa + len; q++)
1305 fprintf(fp, "%s 0x%02x",
1306 q == (u_char *)sa->sa_data ? "" : ",",
1313 #define IOV_LIMIT 16
1316 print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
1318 struct iovec iov[IOV_LIMIT];
1319 size_t max_string = trussinfo->strsize;
1320 char tmp2[max_string + 1], *tmp3;
1322 pid_t pid = trussinfo->curthread->proc->pid;
1324 bool buf_truncated, iov_truncated;
1327 print_pointer(fp, arg);
1330 if (iovcnt > IOV_LIMIT) {
1332 iov_truncated = true;
1334 iov_truncated = false;
1336 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1337 print_pointer(fp, arg);
1342 for (i = 0; i < iovcnt; i++) {
1343 len = iov[i].iov_len;
1344 if (len > max_string) {
1346 buf_truncated = true;
1348 buf_truncated = false;
1350 fprintf(fp, "%s{", (i > 0) ? "," : "");
1351 if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
1352 tmp3 = malloc(len * 4 + 1);
1354 if (strvisx(tmp3, tmp2, len,
1355 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1359 buf_truncated = true;
1361 fprintf(fp, "\"%s\"%s", tmp3,
1362 buf_truncated ? "..." : "");
1365 print_pointer(fp, (uintptr_t)iov[i].iov_base);
1367 fprintf(fp, ",%zu}", iov[i].iov_len);
1369 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1373 print_sigval(FILE *fp, union sigval *sv)
1375 fprintf(fp, "{ %d, %p }", sv->sival_int, sv->sival_ptr);
1379 print_sigevent(FILE *fp, struct sigevent *se)
1381 fputs("{ sigev_notify=", fp);
1382 switch (se->sigev_notify) {
1384 fputs("SIGEV_NONE", fp);
1387 fprintf(fp, "SIGEV_SIGNAL, sigev_signo=%s, sigev_value=",
1388 strsig2(se->sigev_signo));
1389 print_sigval(fp, &se->sigev_value);
1392 fputs("SIGEV_THREAD, sigev_value=", fp);
1393 print_sigval(fp, &se->sigev_value);
1396 fprintf(fp, "SIGEV_KEVENT, sigev_notify_kqueue=%d, sigev_notify_kevent_flags=",
1397 se->sigev_notify_kqueue);
1398 print_mask_arg(sysdecode_kevent_flags, fp, se->sigev_notify_kevent_flags);
1400 case SIGEV_THREAD_ID:
1401 fprintf(fp, "SIGEV_THREAD_ID, sigev_notify_thread_id=%d, sigev_signo=%s, sigev_value=",
1402 se->sigev_notify_thread_id, strsig2(se->sigev_signo));
1403 print_sigval(fp, &se->sigev_value);
1406 fprintf(fp, "%d", se->sigev_notify);
1413 print_aiocb(FILE *fp, struct aiocb *cb)
1415 fprintf(fp, "{ %d,%jd,%p,%zu,%s,",
1420 xlookup(lio_opcodes, cb->aio_lio_opcode));
1421 print_sigevent(fp, &cb->aio_sigevent);
1426 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1431 for (q = CMSG_DATA(cmsghdr);
1432 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1433 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1439 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1441 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1442 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1443 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1444 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1448 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1450 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1452 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1455 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1456 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1458 fprintf(fp, "ctx=%u,", info->sinfo_context);
1459 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1462 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1463 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1465 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1469 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1471 fprintf(fp, "{sid=%u,", info->snd_sid);
1473 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1474 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1475 fprintf(fp, "ctx=%u,", info->snd_context);
1476 fprintf(fp, "id=%u}", info->snd_assoc_id);
1480 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1482 fprintf(fp, "{sid=%u,", info->rcv_sid);
1483 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1485 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1486 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1487 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1488 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1489 fprintf(fp, "ctx=%u,", info->rcv_context);
1490 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1494 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1496 fprintf(fp, "{sid=%u,", info->nxt_sid);
1498 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1499 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1500 fprintf(fp, "len=%u,", info->nxt_length);
1501 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1505 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1508 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1509 fprintf(fp, ",val=%u}", info->pr_value);
1513 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1515 fprintf(fp, "{num=%u}", info->auth_keynumber);
1519 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1521 char buf[INET_ADDRSTRLEN];
1524 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1526 fprintf(fp, "{addr=%s}", s);
1528 fputs("{addr=???}", fp);
1532 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1534 char buf[INET6_ADDRSTRLEN];
1537 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1539 fprintf(fp, "{addr=%s}", s);
1541 fputs("{addr=???}", fp);
1545 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1550 len = cmsghdr->cmsg_len;
1551 data = CMSG_DATA(cmsghdr);
1552 switch (cmsghdr->cmsg_type) {
1554 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1555 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1557 print_gen_cmsg(fp, cmsghdr);
1560 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1561 print_sctp_sndrcvinfo(fp, receive,
1562 (struct sctp_sndrcvinfo *)data);
1564 print_gen_cmsg(fp, cmsghdr);
1568 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1569 print_sctp_extrcvinfo(fp,
1570 (struct sctp_extrcvinfo *)data);
1572 print_gen_cmsg(fp, cmsghdr);
1576 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1577 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1579 print_gen_cmsg(fp, cmsghdr);
1582 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1583 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1585 print_gen_cmsg(fp, cmsghdr);
1588 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1589 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1591 print_gen_cmsg(fp, cmsghdr);
1594 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1595 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1597 print_gen_cmsg(fp, cmsghdr);
1600 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1601 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1603 print_gen_cmsg(fp, cmsghdr);
1605 case SCTP_DSTADDRV4:
1606 if (len == CMSG_LEN(sizeof(struct in_addr)))
1607 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1609 print_gen_cmsg(fp, cmsghdr);
1611 case SCTP_DSTADDRV6:
1612 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1613 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1615 print_gen_cmsg(fp, cmsghdr);
1618 print_gen_cmsg(fp, cmsghdr);
1623 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1625 struct cmsghdr *cmsghdr;
1632 len = msghdr->msg_controllen;
1637 cmsgbuf = calloc(1, len);
1638 if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
1639 print_pointer(fp, (uintptr_t)msghdr->msg_control);
1643 msghdr->msg_control = cmsgbuf;
1646 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1648 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1649 level = cmsghdr->cmsg_level;
1650 type = cmsghdr->cmsg_type;
1651 len = cmsghdr->cmsg_len;
1652 fprintf(fp, "%s{level=", first ? "" : ",");
1653 print_integer_arg(sysdecode_sockopt_level, fp, level);
1654 fputs(",type=", fp);
1655 temp = sysdecode_cmsg_type(level, type);
1659 fprintf(fp, "%d", type);
1661 fputs(",data=", fp);
1664 print_sctp_cmsg(fp, receive, cmsghdr);
1667 print_gen_cmsg(fp, cmsghdr);
1678 print_sysctl_oid(FILE *fp, int *oid, size_t len)
1685 for (i = 0; i < len; i++) {
1686 fprintf(fp, "%s%d", first ? "" : ".", oid[i]);
1693 print_sysctl(FILE *fp, int *oid, size_t len)
1696 int qoid[CTL_MAXNAME + 2];
1699 qoid[0] = CTL_SYSCTL;
1700 qoid[1] = CTL_SYSCTL_NAME;
1701 memcpy(qoid + 2, oid, len * sizeof(int));
1703 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
1704 print_sysctl_oid(fp, oid, len);
1706 fprintf(fp, "%s", name);
1710 * Converts a syscall argument into a string. Said string is
1711 * allocated via malloc(), so needs to be free()'d. sc is
1712 * a pointer to the syscall description (see above); args is
1713 * an array of all of the system call arguments.
1716 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1717 struct trussinfo *trussinfo)
1724 fp = open_memstream(&tmp, &tmplen);
1725 pid = trussinfo->curthread->proc->pid;
1726 switch (sc->type & ARG_MASK) {
1728 fprintf(fp, "0x%x", (int)args[sc->offset]);
1731 fprintf(fp, "0%o", (int)args[sc->offset]);
1734 fprintf(fp, "%d", (int)args[sc->offset]);
1737 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1742 if (get_struct(pid, args[sc->offset], &val,
1744 fprintf(fp, "{ %u }", val);
1746 print_pointer(fp, args[sc->offset]);
1750 fprintf(fp, "0x%lx", args[sc->offset]);
1753 fprintf(fp, "%ld", args[sc->offset]);
1756 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1759 /* Handle special SHM_ANON value. */
1760 if ((char *)args[sc->offset] == SHM_ANON) {
1761 fprintf(fp, "SHM_ANON");
1766 /* NULL-terminated string. */
1769 tmp2 = get_string(pid, args[sc->offset], 0);
1770 fprintf(fp, "\"%s\"", tmp2);
1776 * Binary block of data that might have printable characters.
1777 * XXX If type|OUT, assume that the length is the syscall's
1778 * return value. Otherwise, assume that the length of the block
1779 * is in the next syscall argument.
1781 int max_string = trussinfo->strsize;
1782 char tmp2[max_string + 1], *tmp3;
1789 len = args[sc->offset + 1];
1792 * Don't print more than max_string characters, to avoid word
1793 * wrap. If we have to truncate put some ... after the string.
1795 if (len > max_string) {
1799 if (len && get_struct(pid, args[sc->offset], &tmp2, len)
1801 tmp3 = malloc(len * 4 + 1);
1803 if (strvisx(tmp3, tmp2, len,
1804 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1809 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1813 print_pointer(fp, args[sc->offset]);
1823 char buf[PAGE_SIZE];
1830 * Only parse argv[] and environment arrays from exec calls
1833 if (((sc->type & ARG_MASK) == ExecArgs &&
1834 (trussinfo->flags & EXECVEARGS) == 0) ||
1835 ((sc->type & ARG_MASK) == ExecEnv &&
1836 (trussinfo->flags & EXECVEENVS) == 0)) {
1837 print_pointer(fp, args[sc->offset]);
1842 * Read a page of pointers at a time. Punt if the top-level
1843 * pointer is not aligned. Note that the first read is of
1846 addr = args[sc->offset];
1847 if (addr % sizeof(char *) != 0) {
1848 print_pointer(fp, args[sc->offset]);
1852 len = PAGE_SIZE - (addr & PAGE_MASK);
1853 if (get_struct(pid, addr, u.buf, len) == -1) {
1854 print_pointer(fp, args[sc->offset]);
1861 while (u.strarray[i] != NULL) {
1862 string = get_string(pid, (uintptr_t)u.strarray[i], 0);
1863 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1868 if (i == len / sizeof(char *)) {
1871 if (get_struct(pid, addr, u.buf, len) ==
1873 fprintf(fp, ", <inval>");
1884 fprintf(fp, "%ld", args[sc->offset]);
1887 fprintf(fp, "0x%lx", args[sc->offset]);
1892 unsigned long long ll;
1894 #if _BYTE_ORDER == _LITTLE_ENDIAN
1895 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1898 ll = (unsigned long long)args[sc->offset] << 32 |
1899 args[sc->offset + 1];
1901 if ((sc->type & ARG_MASK) == Quad)
1902 fprintf(fp, "%lld", ll);
1904 fprintf(fp, "0x%llx", ll);
1911 if (get_struct(pid, args[sc->offset], &val,
1913 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1915 print_pointer(fp, args[sc->offset]);
1919 print_pointer(fp, args[sc->offset]);
1924 if (retval[0] == -1)
1926 tmp2 = get_string(pid, args[sc->offset], retval[0]);
1927 fprintf(fp, "\"%s\"", tmp2);
1935 cmd = args[sc->offset];
1936 temp = sysdecode_ioctlname(cmd);
1940 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1941 cmd, cmd & IOC_OUT ? "R" : "",
1942 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1943 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1944 cmd & 0xFF, IOCPARM_LEN(cmd));
1951 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
1952 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1955 print_pointer(fp, args[sc->offset]);
1959 struct timespec ts[2];
1963 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
1966 for (i = 0; i < nitems(ts); i++) {
1969 switch (ts[i].tv_nsec) {
1971 fprintf(fp, "UTIME_NOW");
1974 fprintf(fp, "UTIME_OMIT");
1977 fprintf(fp, "%jd.%09ld",
1978 (intmax_t)ts[i].tv_sec,
1985 print_pointer(fp, args[sc->offset]);
1991 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1992 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1995 print_pointer(fp, args[sc->offset]);
1999 struct timeval tv[2];
2001 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
2002 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
2003 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
2004 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
2006 print_pointer(fp, args[sc->offset]);
2010 struct itimerval itv;
2012 if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
2013 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
2014 (intmax_t)itv.it_interval.tv_sec,
2015 itv.it_interval.tv_usec,
2016 (intmax_t)itv.it_value.tv_sec,
2017 itv.it_value.tv_usec);
2019 print_pointer(fp, args[sc->offset]);
2024 struct linux_socketcall_args largs;
2026 if (get_struct(pid, args[sc->offset], (void *)&largs,
2027 sizeof(largs)) != -1)
2028 fprintf(fp, "{ %s, 0x%lx }",
2029 lookup(linux_socketcall_ops, largs.what, 10),
2030 (long unsigned int)largs.args);
2032 print_pointer(fp, args[sc->offset]);
2037 * XXX: A Pollfd argument expects the /next/ syscall argument
2038 * to be the number of fds in the array. This matches the poll
2042 int numfds = args[sc->offset + 1];
2043 size_t bytes = sizeof(struct pollfd) * numfds;
2046 if ((pfd = malloc(bytes)) == NULL)
2047 err(1, "Cannot malloc %zu bytes for pollfd array",
2049 if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
2051 for (i = 0; i < numfds; i++) {
2052 fprintf(fp, " %d/%s", pfd[i].fd,
2053 xlookup_bits(poll_flags, pfd[i].events));
2057 print_pointer(fp, args[sc->offset]);
2064 * XXX: A Fd_set argument expects the /first/ syscall argument
2065 * to be the number of fds in the array. This matches the
2069 int numfds = args[0];
2070 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
2073 if ((fds = malloc(bytes)) == NULL)
2074 err(1, "Cannot malloc %zu bytes for fd_set array",
2076 if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
2078 for (i = 0; i < numfds; i++) {
2079 if (FD_ISSET(i, fds))
2080 fprintf(fp, " %d", i);
2084 print_pointer(fp, args[sc->offset]);
2089 fputs(strsig2(args[sc->offset]), fp);
2096 sig = args[sc->offset];
2097 if (get_struct(pid, args[sc->offset], (void *)&ss,
2098 sizeof(ss)) == -1) {
2099 print_pointer(fp, args[sc->offset]);
2104 for (i = 1; i < sys_nsig; i++) {
2105 if (sigismember(&ss, i)) {
2106 fprintf(fp, "%s%s", !first ? "|" : "",
2117 print_integer_arg(sysdecode_sigprocmask_how, fp,
2121 /* XXX: Output depends on the value of the previous argument. */
2122 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
2123 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
2124 args[sc->offset], 16);
2127 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2130 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2133 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2136 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2139 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2142 print_mask_arg(sysdecode_shmflags, fp, args[sc->offset]);
2145 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2148 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2151 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2154 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2157 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2160 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2163 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2168 if (args[sc->offset] == 0) {
2174 * Extract the address length from the next argument. If
2175 * this is an output sockaddr (OUT is set), then the
2176 * next argument is a pointer to a socklen_t. Otherwise
2177 * the next argument contains a socklen_t by value.
2179 if (sc->type & OUT) {
2180 if (get_struct(pid, args[sc->offset + 1], &len,
2181 sizeof(len)) == -1) {
2182 print_pointer(fp, args[sc->offset]);
2186 len = args[sc->offset + 1];
2188 print_sockaddr(fp, trussinfo, args[sc->offset], len);
2192 struct sigaction sa;
2194 if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
2196 if (sa.sa_handler == SIG_DFL)
2197 fputs("SIG_DFL", fp);
2198 else if (sa.sa_handler == SIG_IGN)
2199 fputs("SIG_IGN", fp);
2201 fprintf(fp, "%p", sa.sa_handler);
2202 fprintf(fp, " %s ss_t }",
2203 xlookup_bits(sigaction_flags, sa.sa_flags));
2205 print_pointer(fp, args[sc->offset]);
2211 if (get_struct(pid, args[sc->offset], &se, sizeof(se)) != -1)
2212 print_sigevent(fp, &se);
2214 print_pointer(fp, args[sc->offset]);
2219 * XXX XXX: The size of the array is determined by either the
2220 * next syscall argument, or by the syscall return value,
2221 * depending on which argument number we are. This matches the
2222 * kevent syscall, but luckily that's the only syscall that uses
2230 if (sc->offset == 1)
2231 numevents = args[sc->offset+1];
2232 else if (sc->offset == 3 && retval[0] != -1)
2233 numevents = retval[0];
2235 if (numevents >= 0) {
2236 bytes = sizeof(struct kevent) * numevents;
2237 if ((ke = malloc(bytes)) == NULL)
2239 "Cannot malloc %zu bytes for kevent array",
2243 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2246 for (i = 0; i < numevents; i++) {
2248 print_kevent(fp, &ke[i]);
2252 print_pointer(fp, args[sc->offset]);
2258 struct kevent_freebsd11 *ke11;
2264 if (sc->offset == 1)
2265 numevents = args[sc->offset+1];
2266 else if (sc->offset == 3 && retval[0] != -1)
2267 numevents = retval[0];
2269 if (numevents >= 0) {
2270 bytes = sizeof(struct kevent_freebsd11) * numevents;
2271 if ((ke11 = malloc(bytes)) == NULL)
2273 "Cannot malloc %zu bytes for kevent array",
2277 memset(&ke, 0, sizeof(ke));
2278 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2279 ke11, bytes) != -1) {
2281 for (i = 0; i < numevents; i++) {
2283 ke.ident = ke11[i].ident;
2284 ke.filter = ke11[i].filter;
2285 ke.flags = ke11[i].flags;
2286 ke.fflags = ke11[i].fflags;
2287 ke.data = ke11[i].data;
2288 ke.udata = ke11[i].udata;
2289 print_kevent(fp, &ke);
2293 print_pointer(fp, args[sc->offset]);
2301 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2305 strmode(st.st_mode, mode);
2307 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2308 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2309 (long)st.st_blksize);
2311 print_pointer(fp, args[sc->offset]);
2316 struct freebsd11_stat st;
2318 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2322 strmode(st.st_mode, mode);
2324 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2325 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2326 (long)st.st_blksize);
2328 print_pointer(fp, args[sc->offset]);
2336 if (get_struct(pid, args[sc->offset], &buf,
2337 sizeof(buf)) != -1) {
2340 bzero(fsid, sizeof(fsid));
2341 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2342 for (i = 0; i < sizeof(buf.f_fsid); i++)
2343 snprintf(&fsid[i*2],
2344 sizeof(fsid) - (i*2), "%02x",
2345 ((u_char *)&buf.f_fsid)[i]);
2348 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2349 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2350 buf.f_mntfromname, fsid);
2352 print_pointer(fp, args[sc->offset]);
2359 if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
2362 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2363 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2364 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2365 ru.ru_inblock, ru.ru_oublock);
2367 print_pointer(fp, args[sc->offset]);
2373 if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
2375 fprintf(fp, "{ cur=%ju,max=%ju }",
2376 rl.rlim_cur, rl.rlim_max);
2378 print_pointer(fp, args[sc->offset]);
2384 if (get_struct(pid, args[sc->offset], &status,
2385 sizeof(status)) != -1) {
2387 if (WIFCONTINUED(status))
2388 fputs("CONTINUED", fp);
2389 else if (WIFEXITED(status))
2390 fprintf(fp, "EXITED,val=%d",
2391 WEXITSTATUS(status));
2392 else if (WIFSIGNALED(status))
2393 fprintf(fp, "SIGNALED,sig=%s%s",
2394 strsig2(WTERMSIG(status)),
2395 WCOREDUMP(status) ? ",cored" : "");
2397 fprintf(fp, "STOPPED,sig=%s",
2398 strsig2(WTERMSIG(status)));
2401 print_pointer(fp, args[sc->offset]);
2405 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2408 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2411 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2416 if (print_mask_arg_part(sysdecode_umtx_op_flags, fp,
2417 args[sc->offset], &rem))
2419 print_integer_arg(sysdecode_umtx_op, fp, rem);
2423 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2426 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2429 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2432 print_integer_arg(sysdecode_sysarch_number, fp,
2437 int oid[CTL_MAXNAME + 2];
2440 memset(name, 0, sizeof(name));
2441 len = args[sc->offset + 1];
2442 if (get_struct(pid, args[sc->offset], oid,
2443 len * sizeof(oid[0])) != -1) {
2445 if (oid[0] == CTL_SYSCTL) {
2446 fprintf(fp, "sysctl.");
2448 case CTL_SYSCTL_DEBUG:
2449 fprintf(fp, "debug");
2451 case CTL_SYSCTL_NAME:
2452 fprintf(fp, "name ");
2453 print_sysctl_oid(fp, oid + 2, len - 2);
2455 case CTL_SYSCTL_NEXT:
2456 fprintf(fp, "next");
2458 case CTL_SYSCTL_NAME2OID:
2459 fprintf(fp, "name2oid %s",
2461 args[sc->offset + 4],
2462 args[sc->offset + 5]));
2464 case CTL_SYSCTL_OIDFMT:
2465 fprintf(fp, "oidfmt ");
2466 print_sysctl(fp, oid + 2, len - 2);
2468 case CTL_SYSCTL_OIDDESCR:
2469 fprintf(fp, "oiddescr ");
2470 print_sysctl(fp, oid + 2, len - 2);
2472 case CTL_SYSCTL_OIDLABEL:
2473 fprintf(fp, "oidlabel ");
2474 print_sysctl(fp, oid + 2, len - 2);
2476 case CTL_SYSCTL_NEXTNOSKIP:
2477 fprintf(fp, "nextnoskip");
2480 print_sysctl(fp, oid + 1, len - 1);
2483 print_sysctl(fp, oid, len);
2491 * The pipe() system call in the kernel returns its
2492 * two file descriptors via return values. However,
2493 * the interface exposed by libc is that pipe()
2494 * accepts a pointer to an array of descriptors.
2495 * Format the output to match the libc API by printing
2496 * the returned file descriptors as a fake argument.
2498 * Overwrite the first retval to signal a successful
2501 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2508 len = args[sc->offset + 1];
2509 utrace_addr = calloc(1, len);
2510 if (get_struct(pid, args[sc->offset],
2511 (void *)utrace_addr, len) != -1)
2512 print_utrace(fp, utrace_addr, len);
2514 print_pointer(fp, args[sc->offset]);
2519 int descriptors[16];
2520 unsigned long i, ndescriptors;
2523 ndescriptors = args[sc->offset + 1];
2525 if (ndescriptors > nitems(descriptors)) {
2526 ndescriptors = nitems(descriptors);
2529 if (get_struct(pid, args[sc->offset],
2530 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2532 for (i = 0; i < ndescriptors; i++)
2533 fprintf(fp, i == 0 ? " %d" : ", %d",
2535 fprintf(fp, truncated ? ", ... }" : " }");
2537 print_pointer(fp, args[sc->offset]);
2541 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2543 case CapFcntlRights: {
2546 if (sc->type & OUT) {
2547 if (get_struct(pid, args[sc->offset], &rights,
2548 sizeof(rights)) == -1) {
2549 print_pointer(fp, args[sc->offset]);
2553 rights = args[sc->offset];
2554 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2558 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2563 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2564 fprintf(fp, "0x%x", rem);
2566 fprintf(fp, "|0x%x", rem);
2570 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2573 print_integer_arg(sysdecode_getfsstat_mode, fp,
2577 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2579 case Kldunloadflags:
2580 print_integer_arg(sysdecode_kldunload_flags, fp,
2584 fputs(xlookup(aio_fsync_ops, args[sc->offset]), fp);
2587 fputs(xlookup(lio_modes, args[sc->offset]), fp);
2590 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2593 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2595 case Sockprotocol: {
2597 int domain, protocol;
2599 domain = args[sc->offset - 2];
2600 protocol = args[sc->offset];
2601 if (protocol == 0) {
2604 temp = sysdecode_socket_protocol(domain, protocol);
2608 fprintf(fp, "%d", protocol);
2614 print_integer_arg(sysdecode_sockopt_level, fp,
2621 level = args[sc->offset - 1];
2622 name = args[sc->offset];
2623 temp = sysdecode_sockopt_name(level, name);
2627 fprintf(fp, "%d", name);
2632 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2635 cap_rights_t rights;
2637 if (get_struct(pid, args[sc->offset], &rights,
2638 sizeof(rights)) != -1) {
2640 sysdecode_cap_rights(fp, &rights);
2643 print_pointer(fp, args[sc->offset]);
2647 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2649 case Extattrnamespace:
2650 print_integer_arg(sysdecode_extattrnamespace, fp,
2654 print_integer_arg(sysdecode_minherit_inherit, fp,
2658 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2661 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2664 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2667 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2670 print_integer_arg(sysdecode_ptrace_request, fp,
2674 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2675 fprintf(fp, "%#x", (int)args[sc->offset]);
2678 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2681 print_integer_arg(sysdecode_rtprio_function, fp,
2685 print_integer_arg(sysdecode_scheduler_policy, fp,
2689 struct sched_param sp;
2691 if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
2692 fprintf(fp, "{ %d }", sp.sched_priority);
2694 print_pointer(fp, args[sc->offset]);
2700 if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
2701 fprintf(fp, "{ %s }", strsig2(sig));
2703 print_pointer(fp, args[sc->offset]);
2709 if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
2710 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2711 decode_siginfo(fp, &si);
2714 print_pointer(fp, args[sc->offset]);
2719 * Print argument as an array of struct iovec, where the next
2720 * syscall argument is the number of elements of the array.
2723 print_iovec(fp, trussinfo, args[sc->offset],
2724 (int)args[sc->offset + 1]);
2729 if (get_struct(pid, args[sc->offset], &cb, sizeof(cb)) != -1)
2730 print_aiocb(fp, &cb);
2732 print_pointer(fp, args[sc->offset]);
2737 * Print argment as an array of pointers to struct aiocb, where
2738 * the next syscall argument is the number of elements.
2744 nent = args[sc->offset + 1];
2746 if (nent > nitems(cbs)) {
2751 if (get_struct(pid, args[sc->offset], cbs, sizeof(uintptr_t) * nent) != -1) {
2754 for (i = 0; i < nent; ++i) {
2758 if (get_struct(pid, cbs[i], &cb, sizeof(cb)) != -1)
2759 print_aiocb(fp, &cb);
2761 print_pointer(fp, cbs[i]);
2767 print_pointer(fp, args[sc->offset]);
2770 case AiocbPointer: {
2772 * aio_waitcomplete(2) assigns a pointer to a pointer to struct
2773 * aiocb, so we need to handle the extra layer of indirection.
2778 if (get_struct(pid, args[sc->offset], &cbp, sizeof(cbp)) != -1) {
2779 if (get_struct(pid, cbp, &cb, sizeof(cb)) != -1)
2780 print_aiocb(fp, &cb);
2782 print_pointer(fp, cbp);
2784 print_pointer(fp, args[sc->offset]);
2787 case Sctpsndrcvinfo: {
2788 struct sctp_sndrcvinfo info;
2790 if (get_struct(pid, args[sc->offset],
2791 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2792 print_pointer(fp, args[sc->offset]);
2795 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2799 struct msghdr msghdr;
2801 if (get_struct(pid, args[sc->offset],
2802 &msghdr, sizeof(struct msghdr)) == -1) {
2803 print_pointer(fp, args[sc->offset]);
2807 print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
2808 fprintf(fp, ",%d,", msghdr.msg_namelen);
2809 print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
2810 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2811 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2812 fprintf(fp, ",%u,", msghdr.msg_controllen);
2813 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2818 case CloudABIAdvice:
2819 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2821 case CloudABIClockID:
2822 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2824 case CloudABIFDSFlags:
2825 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2827 case CloudABIFDStat: {
2828 cloudabi_fdstat_t fds;
2829 if (get_struct(pid, args[sc->offset], &fds, sizeof(fds))
2831 fprintf(fp, "{ %s, ",
2832 xlookup(cloudabi_filetype, fds.fs_filetype));
2833 fprintf(fp, "%s, ... }",
2834 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2836 print_pointer(fp, args[sc->offset]);
2839 case CloudABIFileStat: {
2840 cloudabi_filestat_t fsb;
2841 if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb))
2843 fprintf(fp, "{ %s, %ju }",
2844 xlookup(cloudabi_filetype, fsb.st_filetype),
2845 (uintmax_t)fsb.st_size);
2847 print_pointer(fp, args[sc->offset]);
2850 case CloudABIFileType:
2851 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2853 case CloudABIFSFlags:
2854 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2856 case CloudABILookup:
2857 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2858 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2859 (int)args[sc->offset]);
2861 fprintf(fp, "%d", (int)args[sc->offset]);
2863 case CloudABIMFlags:
2864 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2867 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2869 case CloudABIMSFlags:
2870 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2872 case CloudABIOFlags:
2873 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2875 case CloudABISDFlags:
2876 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2878 case CloudABISignal:
2879 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2881 case CloudABITimestamp:
2882 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2883 args[sc->offset] % 1000000000);
2885 case CloudABIULFlags:
2886 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2888 case CloudABIWhence:
2889 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2893 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2900 * Print (to outfile) the system call and its arguments.
2903 print_syscall(struct trussinfo *trussinfo)
2905 struct threadinfo *t;
2910 t = trussinfo->curthread;
2912 name = t->cs.sc->name;
2913 nargs = t->cs.nargs;
2914 s_args = t->cs.s_args;
2916 len = print_line_prefix(trussinfo);
2917 len += fprintf(trussinfo->outfile, "%s(", name);
2919 for (i = 0; i < nargs; i++) {
2920 if (s_args[i] != NULL)
2921 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2923 len += fprintf(trussinfo->outfile,
2924 "<missing argument>");
2925 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2928 len += fprintf(trussinfo->outfile, ")");
2929 for (i = 0; i < 6 - (len / 8); i++)
2930 fprintf(trussinfo->outfile, "\t");
2934 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2936 struct timespec timediff;
2937 struct threadinfo *t;
2940 t = trussinfo->curthread;
2942 if (trussinfo->flags & COUNTONLY) {
2943 timespecsub(&t->after, &t->before, &timediff);
2944 timespecadd(&sc->time, &timediff, &sc->time);
2951 print_syscall(trussinfo);
2952 fflush(trussinfo->outfile);
2954 if (retval == NULL) {
2956 * This system call resulted in the current thread's exit,
2957 * so there is no return value or error to display.
2959 fprintf(trussinfo->outfile, "\n");
2963 if (error == ERESTART)
2964 fprintf(trussinfo->outfile, " ERESTART\n");
2965 else if (error == EJUSTRETURN)
2966 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2967 else if (error != 0) {
2968 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2969 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2973 else if (sc->ret_type == 2) {
2976 #if _BYTE_ORDER == _LITTLE_ENDIAN
2977 off = (off_t)retval[1] << 32 | retval[0];
2979 off = (off_t)retval[0] << 32 | retval[1];
2981 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2986 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2987 (intmax_t)retval[0], (intmax_t)retval[0]);
2991 print_summary(struct trussinfo *trussinfo)
2993 struct timespec total = {0, 0};
2997 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2998 "syscall", "seconds", "calls", "errors");
3000 STAILQ_FOREACH(sc, &syscalls, entries)
3002 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
3003 sc->name, (intmax_t)sc->time.tv_sec,
3004 sc->time.tv_nsec, sc->ncalls, sc->nerror);
3005 timespecadd(&total, &sc->time, &total);
3006 ncall += sc->ncalls;
3007 nerror += sc->nerror;
3009 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
3010 "", "-------------", "-------", "-------");
3011 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
3012 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);