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>
47 #include <sys/mount.h>
48 #include <sys/ptrace.h>
49 #include <sys/resource.h>
50 #include <sys/socket.h>
51 #define _WANT_FREEBSD11_STAT
53 #include <sys/sysctl.h>
57 #include <netinet/in.h>
58 #include <netinet/sctp.h>
59 #include <arpa/inet.h>
64 #define _WANT_KERNEL_ERRNO
74 #include <sysdecode.h>
78 #include <contrib/cloudabi/cloudabi_types_common.h>
85 * This should probably be in its own file, sorted alphabetically.
87 static struct syscall decoded_syscalls[] = {
89 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
90 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
91 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
92 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
93 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
94 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
95 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
96 .args = { { Int, 0 }, { Acltype, 1 } } },
97 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
98 .args = { { Name, 0 }, { Acltype, 1 } } },
99 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
100 .args = { { Name, 0 }, { Acltype, 1 } } },
101 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
102 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
103 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
104 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
106 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
108 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
110 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
111 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
112 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
113 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
114 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
115 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
116 .args = { { Name | OUT, 0 }, { Int, 1 } } },
117 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
118 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
120 { .name = "accept", .ret_type = 1, .nargs = 3,
121 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
122 { .name = "access", .ret_type = 1, .nargs = 2,
123 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
124 { .name = "bind", .ret_type = 1, .nargs = 3,
125 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
126 { .name = "bindat", .ret_type = 1, .nargs = 4,
127 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
129 { .name = "break", .ret_type = 1, .nargs = 1,
130 .args = { { Ptr, 0 } } },
131 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
132 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
133 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
134 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
135 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
136 .args = { { PUInt | OUT, 0 } } },
137 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
138 .args = { { Int, 0 }, { CapRights, 1 } } },
139 { .name = "chdir", .ret_type = 1, .nargs = 1,
140 .args = { { Name, 0 } } },
141 { .name = "chflags", .ret_type = 1, .nargs = 2,
142 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
143 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
144 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
146 { .name = "chmod", .ret_type = 1, .nargs = 2,
147 .args = { { Name, 0 }, { Octal, 1 } } },
148 { .name = "chown", .ret_type = 1, .nargs = 3,
149 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
150 { .name = "chroot", .ret_type = 1, .nargs = 1,
151 .args = { { Name, 0 } } },
152 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
153 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
154 { .name = "close", .ret_type = 1, .nargs = 1,
155 .args = { { Int, 0 } } },
156 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
157 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
158 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
159 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
161 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
162 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
163 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
164 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
165 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
166 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
167 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
168 { .name = "connect", .ret_type = 1, .nargs = 3,
169 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
170 { .name = "connectat", .ret_type = 1, .nargs = 4,
171 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
173 { .name = "dup", .ret_type = 1, .nargs = 1,
174 .args = { { Int, 0 } } },
175 { .name = "dup2", .ret_type = 1, .nargs = 2,
176 .args = { { Int, 0 }, { Int, 1 } } },
177 { .name = "eaccess", .ret_type = 1, .nargs = 2,
178 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
179 { .name = "execve", .ret_type = 1, .nargs = 3,
180 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
181 { ExecEnv | IN, 2 } } },
182 { .name = "exit", .ret_type = 0, .nargs = 1,
183 .args = { { Hex, 0 } } },
184 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
185 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
186 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
187 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
188 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
189 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
190 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
191 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
192 { BinString | OUT, 3 }, { Sizet, 4 } } },
193 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
194 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
195 { BinString | OUT, 3 }, { Sizet, 4 } } },
196 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
197 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
198 { BinString | OUT, 3 }, { Sizet, 4 } } },
199 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
200 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
202 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
203 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
205 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
206 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
208 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
209 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
210 { BinString | IN, 3 }, { Sizet, 4 } } },
211 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
213 { BinString | IN, 3 }, { Sizet, 4 } } },
214 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
215 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
216 { BinString | IN, 3 }, { Sizet, 4 } } },
217 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
218 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
219 { Extattrnamespace, 3 }, { Name, 4 } } },
220 { .name = "faccessat", .ret_type = 1, .nargs = 4,
221 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
223 { .name = "fchflags", .ret_type = 1, .nargs = 2,
224 .args = { { Int, 0 }, { FileFlags, 1 } } },
225 { .name = "fchmod", .ret_type = 1, .nargs = 2,
226 .args = { { Int, 0 }, { Octal, 1 } } },
227 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
228 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
229 { .name = "fchown", .ret_type = 1, .nargs = 3,
230 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
231 { .name = "fchownat", .ret_type = 1, .nargs = 5,
232 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
234 { .name = "fcntl", .ret_type = 1, .nargs = 3,
235 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
236 { .name = "flock", .ret_type = 1, .nargs = 2,
237 .args = { { Int, 0 }, { Flockop, 1 } } },
238 { .name = "fstat", .ret_type = 1, .nargs = 2,
239 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
240 { .name = "fstatat", .ret_type = 1, .nargs = 4,
241 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
243 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
244 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
245 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
246 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
247 { .name = "futimens", .ret_type = 1, .nargs = 2,
248 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
249 { .name = "futimes", .ret_type = 1, .nargs = 2,
250 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
251 { .name = "futimesat", .ret_type = 1, .nargs = 3,
252 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
253 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
254 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
255 { PQuadHex | OUT, 3 } } },
256 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
257 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
258 { .name = "getitimer", .ret_type = 1, .nargs = 2,
259 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
260 { .name = "getpeername", .ret_type = 1, .nargs = 3,
261 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
262 { .name = "getpgid", .ret_type = 1, .nargs = 1,
263 .args = { { Int, 0 } } },
264 { .name = "getpriority", .ret_type = 1, .nargs = 2,
265 .args = { { Priowhich, 0 }, { Int, 1 } } },
266 { .name = "getrandom", .ret_type = 1, .nargs = 3,
267 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
268 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
269 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
270 { .name = "getrusage", .ret_type = 1, .nargs = 2,
271 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
272 { .name = "getsid", .ret_type = 1, .nargs = 1,
273 .args = { { Int, 0 } } },
274 { .name = "getsockname", .ret_type = 1, .nargs = 3,
275 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
276 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
277 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
278 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
279 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
280 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
281 { .name = "ioctl", .ret_type = 1, .nargs = 3,
282 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
283 { .name = "kevent", .ret_type = 1, .nargs = 6,
284 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
285 { Int, 4 }, { Timespec, 5 } } },
286 { .name = "kill", .ret_type = 1, .nargs = 2,
287 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
288 { .name = "kldfind", .ret_type = 1, .nargs = 1,
289 .args = { { Name | IN, 0 } } },
290 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
291 .args = { { Int, 0 } } },
292 { .name = "kldload", .ret_type = 1, .nargs = 1,
293 .args = { { Name | IN, 0 } } },
294 { .name = "kldnext", .ret_type = 1, .nargs = 1,
295 .args = { { Int, 0 } } },
296 { .name = "kldstat", .ret_type = 1, .nargs = 2,
297 .args = { { Int, 0 }, { Ptr, 1 } } },
298 { .name = "kldsym", .ret_type = 1, .nargs = 3,
299 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
300 { .name = "kldunload", .ret_type = 1, .nargs = 1,
301 .args = { { Int, 0 } } },
302 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
303 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
304 { .name = "kse_release", .ret_type = 0, .nargs = 1,
305 .args = { { Timespec, 0 } } },
306 { .name = "lchflags", .ret_type = 1, .nargs = 2,
307 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
308 { .name = "lchmod", .ret_type = 1, .nargs = 2,
309 .args = { { Name, 0 }, { Octal, 1 } } },
310 { .name = "lchown", .ret_type = 1, .nargs = 3,
311 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
312 { .name = "link", .ret_type = 1, .nargs = 2,
313 .args = { { Name, 0 }, { Name, 1 } } },
314 { .name = "linkat", .ret_type = 1, .nargs = 5,
315 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
317 { .name = "listen", .ret_type = 1, .nargs = 2,
318 .args = { { Int, 0 }, { Int, 1 } } },
319 { .name = "lseek", .ret_type = 2, .nargs = 3,
320 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
321 { .name = "lstat", .ret_type = 1, .nargs = 2,
322 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
323 { .name = "lutimes", .ret_type = 1, .nargs = 2,
324 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
325 { .name = "madvise", .ret_type = 1, .nargs = 3,
326 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
327 { .name = "minherit", .ret_type = 1, .nargs = 3,
328 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
329 { .name = "mkdir", .ret_type = 1, .nargs = 2,
330 .args = { { Name, 0 }, { Octal, 1 } } },
331 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
332 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
333 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
334 .args = { { Name, 0 }, { Octal, 1 } } },
335 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
336 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
337 { .name = "mknod", .ret_type = 1, .nargs = 3,
338 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
339 { .name = "mknodat", .ret_type = 1, .nargs = 4,
340 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
341 { .name = "mlock", .ret_type = 1, .nargs = 2,
342 .args = { { Ptr, 0 }, { Sizet, 1 } } },
343 { .name = "mlockall", .ret_type = 1, .nargs = 1,
344 .args = { { Mlockall, 0 } } },
345 { .name = "mmap", .ret_type = 1, .nargs = 6,
346 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
347 { Int, 4 }, { QuadHex, 5 } } },
348 { .name = "modfind", .ret_type = 1, .nargs = 1,
349 .args = { { Name | IN, 0 } } },
350 { .name = "mount", .ret_type = 1, .nargs = 4,
351 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
352 { .name = "mprotect", .ret_type = 1, .nargs = 3,
353 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
354 { .name = "msync", .ret_type = 1, .nargs = 3,
355 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
356 { .name = "munlock", .ret_type = 1, .nargs = 2,
357 .args = { { Ptr, 0 }, { Sizet, 1 } } },
358 { .name = "munmap", .ret_type = 1, .nargs = 2,
359 .args = { { Ptr, 0 }, { Sizet, 1 } } },
360 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
361 .args = { { Timespec, 0 } } },
362 { .name = "nmount", .ret_type = 1, .nargs = 3,
363 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
364 { .name = "open", .ret_type = 1, .nargs = 3,
365 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
366 { .name = "openat", .ret_type = 1, .nargs = 4,
367 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
369 { .name = "pathconf", .ret_type = 1, .nargs = 2,
370 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
371 { .name = "pipe", .ret_type = 1, .nargs = 1,
372 .args = { { PipeFds | OUT, 0 } } },
373 { .name = "pipe2", .ret_type = 1, .nargs = 2,
374 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
375 { .name = "poll", .ret_type = 1, .nargs = 3,
376 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
377 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
378 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
380 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
381 .args = { { Open, 0 } } },
382 { .name = "pread", .ret_type = 1, .nargs = 4,
383 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
385 { .name = "procctl", .ret_type = 1, .nargs = 4,
386 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
387 { .name = "ptrace", .ret_type = 1, .nargs = 4,
388 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
389 { .name = "pwrite", .ret_type = 1, .nargs = 4,
390 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
392 { .name = "quotactl", .ret_type = 1, .nargs = 4,
393 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
394 { .name = "read", .ret_type = 1, .nargs = 3,
395 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
396 { .name = "readlink", .ret_type = 1, .nargs = 3,
397 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
398 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
399 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
401 { .name = "readv", .ret_type = 1, .nargs = 3,
402 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
403 { .name = "reboot", .ret_type = 1, .nargs = 1,
404 .args = { { Reboothowto, 0 } } },
405 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
406 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
407 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
408 { Ptr | OUT, 5 } } },
409 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
410 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
411 { .name = "rename", .ret_type = 1, .nargs = 2,
412 .args = { { Name, 0 }, { Name, 1 } } },
413 { .name = "renameat", .ret_type = 1, .nargs = 4,
414 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
415 { .name = "rfork", .ret_type = 1, .nargs = 1,
416 .args = { { Rforkflags, 0 } } },
417 { .name = "rmdir", .ret_type = 1, .nargs = 1,
418 .args = { { Name, 0 } } },
419 { .name = "rtprio", .ret_type = 1, .nargs = 3,
420 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
421 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
422 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
423 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
424 .args = { { Schedpolicy, 0 } } },
425 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
426 .args = { { Schedpolicy, 0 } } },
427 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
428 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
429 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
430 .args = { { Int, 0 } } },
431 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
432 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
433 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
434 .args = { { Int, 0 }, { Schedparam, 1 } } },
435 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
436 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
437 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
438 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
439 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
440 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
441 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
442 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
443 { Sockaddr | IN, 3 }, { Socklent, 4 },
444 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
445 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
446 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
447 { Sockaddr | IN, 3 }, { Socklent, 4 },
448 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
449 { .name = "select", .ret_type = 1, .nargs = 5,
450 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
452 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
453 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
454 { .name = "sendto", .ret_type = 1, .nargs = 6,
455 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
456 { Msgflags, 3 }, { Sockaddr | IN, 4 },
457 { Socklent | IN, 5 } } },
458 { .name = "setitimer", .ret_type = 1, .nargs = 3,
459 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
460 { .name = "setpriority", .ret_type = 1, .nargs = 3,
461 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
462 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
463 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
464 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
465 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
466 { Ptr | IN, 3 }, { Socklent, 4 } } },
467 { .name = "shm_open", .ret_type = 1, .nargs = 3,
468 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
469 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
470 .args = { { Name | IN, 0 } } },
471 { .name = "shutdown", .ret_type = 1, .nargs = 2,
472 .args = { { Int, 0 }, { Shutdown, 1 } } },
473 { .name = "sigaction", .ret_type = 1, .nargs = 3,
474 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
475 { Sigaction | OUT, 2 } } },
476 { .name = "sigpending", .ret_type = 1, .nargs = 1,
477 .args = { { Sigset | OUT, 0 } } },
478 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
479 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
480 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
481 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
482 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
483 .args = { { Ptr, 0 } } },
484 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
485 .args = { { Sigset | IN, 0 } } },
486 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
487 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
488 { Timespec | IN, 2 } } },
489 { .name = "sigwait", .ret_type = 1, .nargs = 2,
490 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
491 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
492 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
493 { .name = "socket", .ret_type = 1, .nargs = 3,
494 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
495 { .name = "stat", .ret_type = 1, .nargs = 2,
496 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
497 { .name = "statfs", .ret_type = 1, .nargs = 2,
498 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
499 { .name = "symlink", .ret_type = 1, .nargs = 2,
500 .args = { { Name, 0 }, { Name, 1 } } },
501 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
502 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
503 { .name = "sysarch", .ret_type = 1, .nargs = 2,
504 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
505 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
506 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
507 { Ptr, 4 }, { Sizet, 5 } } },
508 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
509 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
510 { Ptr, 4}, { Sizet, 5 } } },
511 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
512 .args = { { Long, 0 }, { Signal, 1 } } },
513 { .name = "thr_self", .ret_type = 1, .nargs = 1,
514 .args = { { Ptr, 0 } } },
515 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
516 .args = { { Long, 0 }, { Name, 1 } } },
517 { .name = "truncate", .ret_type = 1, .nargs = 2,
518 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
521 { .name = "umount", .ret_type = 1, .nargs = 2,
522 .args = { { Name, 0 }, { Int, 2 } } },
524 { .name = "unlink", .ret_type = 1, .nargs = 1,
525 .args = { { Name, 0 } } },
526 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
527 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
528 { .name = "unmount", .ret_type = 1, .nargs = 2,
529 .args = { { Name, 0 }, { Mountflags, 1 } } },
530 { .name = "utimensat", .ret_type = 1, .nargs = 4,
531 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
533 { .name = "utimes", .ret_type = 1, .nargs = 2,
534 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
535 { .name = "utrace", .ret_type = 1, .nargs = 1,
536 .args = { { Utrace, 0 } } },
537 { .name = "wait4", .ret_type = 1, .nargs = 4,
538 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
539 { Rusage | OUT, 3 } } },
540 { .name = "wait6", .ret_type = 1, .nargs = 6,
541 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
542 { Waitoptions, 3 }, { Rusage | OUT, 4 },
543 { Siginfo | OUT, 5 } } },
544 { .name = "write", .ret_type = 1, .nargs = 3,
545 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
546 { .name = "writev", .ret_type = 1, .nargs = 3,
547 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
550 { .name = "linux_access", .ret_type = 1, .nargs = 2,
551 .args = { { Name, 0 }, { Accessmode, 1 } } },
552 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
553 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
554 { ExecEnv | IN, 2 } } },
555 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
556 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
557 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
558 .args = { { Name | IN, 0 }, { Int, 1 } } },
559 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
560 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
561 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
562 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
563 { .name = "linux_open", .ret_type = 1, .nargs = 3,
564 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
565 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
566 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
567 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
568 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
569 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
570 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
572 /* CloudABI system calls. */
573 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
574 .args = { { CloudABIClockID, 0 } } },
575 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
576 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
577 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
578 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
579 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
580 .args = { { Int, 0 } } },
581 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
582 .args = { { CloudABIFileType, 0 } } },
583 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
584 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
585 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
586 .args = { { Int, 0 } } },
587 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
588 .args = { { Int, 0 } } },
589 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
590 .args = { { Int, 0 }, { Int, 1 } } },
591 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
592 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
593 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
594 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
595 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
596 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
597 { CloudABIFDSFlags, 2 } } },
598 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
599 .args = { { Int, 0 } } },
600 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
601 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
602 { CloudABIAdvice, 3 } } },
603 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
604 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
605 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
606 .args = { { Int, 0 }, { BinString | IN, 1 },
607 { CloudABIFileType, 3 } } },
608 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
609 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
610 { Int, 3 }, { BinString | IN, 4 } } },
611 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
612 .args = { { Int, 0 }, { BinString | IN, 1 },
613 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
614 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
615 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
617 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
618 .args = { { Int, 0 }, { BinString | IN, 1 },
619 { BinString | OUT, 3 }, { Int, 4 } } },
620 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
621 .args = { { Int, 0 }, { BinString | IN, 1 },
622 { Int, 3 }, { BinString | IN, 4 } } },
623 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
624 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
625 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
626 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
627 { CloudABIFSFlags, 2 } } },
628 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
629 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
630 { CloudABIFileStat | OUT, 3 } } },
631 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
632 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
633 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
634 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
635 .args = { { BinString | IN, 0 },
636 { Int, 2 }, { BinString | IN, 3 } } },
637 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
638 .args = { { Int, 0 }, { BinString | IN, 1 },
639 { CloudABIULFlags, 3 } } },
640 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
641 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
642 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
643 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
644 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
645 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
646 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
647 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
648 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
649 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
650 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
651 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
652 .args = { { Ptr, 0 }, { Int, 1 } } },
653 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
654 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
655 { IntArray, 3 }, { Int, 4 } } },
656 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
657 .args = { { Int, 0 } } },
658 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
659 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
660 .args = { { CloudABISignal, 0 } } },
661 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
662 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
663 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
664 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
665 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
666 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
667 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
671 static STAILQ_HEAD(, syscall) syscalls;
673 /* Xlat idea taken from strace */
679 #define X(a) { a, #a },
680 #define XEND { 0, NULL }
682 static struct xlat poll_flags[] = {
683 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
684 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
685 X(POLLWRBAND) X(POLLINIGNEOF) XEND
688 static struct xlat sigaction_flags[] = {
689 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
690 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
693 static struct xlat linux_socketcall_ops[] = {
694 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
695 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
696 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
697 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
698 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
703 #define X(a) { CLOUDABI_##a, #a },
705 static struct xlat cloudabi_advice[] = {
706 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
707 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
711 static struct xlat cloudabi_clockid[] = {
712 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
713 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
717 static struct xlat cloudabi_fdflags[] = {
718 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
719 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
723 static struct xlat cloudabi_fdsflags[] = {
724 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
728 static struct xlat cloudabi_filetype[] = {
729 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
730 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
731 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
732 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
733 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
737 static struct xlat cloudabi_fsflags[] = {
738 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
739 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
743 static struct xlat cloudabi_mflags[] = {
744 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
748 static struct xlat cloudabi_mprot[] = {
749 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
753 static struct xlat cloudabi_msflags[] = {
754 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
758 static struct xlat cloudabi_oflags[] = {
759 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
763 static struct xlat cloudabi_sdflags[] = {
764 X(SHUT_RD) X(SHUT_WR)
768 static struct xlat cloudabi_signal[] = {
769 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
770 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
771 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
772 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
773 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
777 static struct xlat cloudabi_ulflags[] = {
782 static struct xlat cloudabi_whence[] = {
783 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
791 * Searches an xlat array for a value, and returns it if found. Otherwise
792 * return a string representation.
795 lookup(struct xlat *xlat, int val, int base)
799 for (; xlat->str != NULL; xlat++)
800 if (xlat->val == val)
804 sprintf(tmp, "0%o", val);
807 sprintf(tmp, "0x%x", val);
810 sprintf(tmp, "%u", val);
813 errx(1,"Unknown lookup base");
820 xlookup(struct xlat *xlat, int val)
823 return (lookup(xlat, val, 16));
827 * Searches an xlat array containing bitfield values. Remaining bits
828 * set after removing the known ones are printed at the end:
832 xlookup_bits(struct xlat *xlat, int val)
835 static char str[512];
839 for (; xlat->str != NULL; xlat++) {
840 if ((xlat->val & rem) == xlat->val) {
842 * Don't print the "all-bits-zero" string unless all
843 * bits are really zero.
845 if (xlat->val == 0 && val != 0)
847 len += sprintf(str + len, "%s|", xlat->str);
853 * If we have leftover bits or didn't match anything, print
857 len += sprintf(str + len, "0x%x", rem);
858 if (len && str[len - 1] == '|')
865 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
869 str = decoder(value);
873 fprintf(fp, "%d", value);
877 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
881 if (!decoder(fp, value, &rem))
882 fprintf(fp, "0x%x", rem);
884 fprintf(fp, "|0x%x", rem);
888 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
893 if (!decoder(fp, value, &rem))
894 fprintf(fp, "0x%x", rem);
896 fprintf(fp, "|0x%x", rem);
901 * Add argument padding to subsequent system calls afater a Quad
902 * syscall arguments as needed. This used to be done by hand in the
903 * decoded_syscalls table which was ugly and error prone. It is
904 * simpler to do the fixup of offsets at initalization time than when
905 * decoding arguments.
908 quad_fixup(struct syscall *sc)
915 for (i = 0; i < sc->nargs; i++) {
916 /* This arg type is a dummy that doesn't use offset. */
917 if ((sc->args[i].type & ARG_MASK) == PipeFds)
920 assert(prev < sc->args[i].offset);
921 prev = sc->args[i].offset;
922 sc->args[i].offset += offset;
923 switch (sc->args[i].type & ARG_MASK) {
928 * 64-bit arguments on 32-bit powerpc must be
929 * 64-bit aligned. If the current offset is
930 * not aligned, the calling convention inserts
931 * a 32-bit pad argument that should be skipped.
933 if (sc->args[i].offset % 2 == 1) {
934 sc->args[i].offset++;
951 STAILQ_INIT(&syscalls);
952 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
956 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
960 static struct syscall *
961 find_syscall(struct procabi *abi, u_int number)
963 struct extra_syscall *es;
965 if (number < nitems(abi->syscalls))
966 return (abi->syscalls[number]);
967 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
968 if (es->number == number)
975 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
977 struct extra_syscall *es;
979 if (number < nitems(abi->syscalls)) {
980 assert(abi->syscalls[number] == NULL);
981 abi->syscalls[number] = sc;
983 es = malloc(sizeof(*es));
986 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
991 * If/when the list gets big, it might be desirable to do it
992 * as a hash table or binary search.
995 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1002 sc = find_syscall(t->proc->abi, number);
1006 name = sysdecode_syscallname(t->proc->abi->abi, number);
1008 asprintf(&new_name, "#%d", number);
1012 STAILQ_FOREACH(sc, &syscalls, entries) {
1013 if (strcmp(name, sc->name) == 0) {
1014 add_syscall(t->proc->abi, number, sc);
1020 /* It is unknown. Add it into the list. */
1022 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1026 sc = calloc(1, sizeof(struct syscall));
1028 if (new_name != NULL)
1032 for (i = 0; i < nargs; i++) {
1033 sc->args[i].offset = i;
1034 /* Treat all unknown arguments as LongHex. */
1035 sc->args[i].type = LongHex;
1037 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1038 add_syscall(t->proc->abi, number, sc);
1044 * Copy a fixed amount of bytes from the process.
1047 get_struct(pid_t pid, void *offset, void *buf, int len)
1049 struct ptrace_io_desc iorequest;
1051 iorequest.piod_op = PIOD_READ_D;
1052 iorequest.piod_offs = offset;
1053 iorequest.piod_addr = buf;
1054 iorequest.piod_len = len;
1055 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1060 #define MAXSIZE 4096
1063 * Copy a string from the process. Note that it is
1064 * expected to be a C string, but if max is set, it will
1065 * only get that much.
1068 get_string(pid_t pid, void *addr, int max)
1070 struct ptrace_io_desc iorequest;
1072 size_t offset, size, totalsize;
1078 /* Read up to the end of the current page. */
1079 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1084 buf = malloc(totalsize);
1088 iorequest.piod_op = PIOD_READ_D;
1089 iorequest.piod_offs = (char *)addr + offset;
1090 iorequest.piod_addr = buf + offset;
1091 iorequest.piod_len = size;
1092 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1096 if (memchr(buf + offset, '\0', size) != NULL)
1099 if (totalsize < MAXSIZE && max == 0) {
1100 size = MAXSIZE - totalsize;
1101 if (size > PAGE_SIZE)
1103 nbuf = realloc(buf, totalsize + size);
1105 buf[totalsize - 1] = '\0';
1111 buf[totalsize - 1] = '\0';
1120 static char tmp[32];
1121 const char *signame;
1123 signame = sysdecode_signal(sig);
1124 if (signame == NULL) {
1125 snprintf(tmp, sizeof(tmp), "%d", sig);
1132 print_kevent(FILE *fp, struct kevent *ke)
1135 switch (ke->filter) {
1141 case EVFILT_PROCDESC:
1143 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1146 fputs(strsig2(ke->ident), fp);
1149 fprintf(fp, "%p", (void *)ke->ident);
1152 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1154 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1156 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1157 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1161 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1163 unsigned char *utrace_buffer;
1166 if (sysdecode_utrace(fp, utrace_addr, len)) {
1171 utrace_buffer = utrace_addr;
1172 fprintf(fp, "%zu:", len);
1174 fprintf(fp, " %02x", *utrace_buffer++);
1179 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1182 struct sockaddr_in *lsin;
1183 struct sockaddr_in6 *lsin6;
1184 struct sockaddr_un *sun;
1185 struct sockaddr *sa;
1187 pid_t pid = trussinfo->curthread->proc->pid;
1193 /* If the length is too small, just bail. */
1194 if (len < sizeof(*sa)) {
1195 fprintf(fp, "%p", arg);
1199 sa = calloc(1, len);
1200 if (get_struct(pid, arg, sa, len) == -1) {
1202 fprintf(fp, "%p", arg);
1206 switch (sa->sa_family) {
1208 if (len < sizeof(*lsin))
1209 goto sockaddr_short;
1210 lsin = (struct sockaddr_in *)(void *)sa;
1211 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1212 fprintf(fp, "{ AF_INET %s:%d }", addr,
1213 htons(lsin->sin_port));
1216 if (len < sizeof(*lsin6))
1217 goto sockaddr_short;
1218 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1219 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1221 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1222 htons(lsin6->sin6_port));
1225 sun = (struct sockaddr_un *)sa;
1226 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1227 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1233 "{ sa_len = %d, sa_family = %d, sa_data = {",
1234 (int)sa->sa_len, (int)sa->sa_family);
1235 for (q = (u_char *)sa->sa_data;
1236 q < (u_char *)sa + len; q++)
1237 fprintf(fp, "%s 0x%02x",
1238 q == (u_char *)sa->sa_data ? "" : ",",
1245 #define IOV_LIMIT 16
1248 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1250 struct iovec iov[IOV_LIMIT];
1251 size_t max_string = trussinfo->strsize;
1252 char tmp2[max_string + 1], *tmp3;
1254 pid_t pid = trussinfo->curthread->proc->pid;
1256 bool buf_truncated, iov_truncated;
1259 fprintf(fp, "%p", arg);
1262 if (iovcnt > IOV_LIMIT) {
1264 iov_truncated = true;
1266 iov_truncated = false;
1268 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1269 fprintf(fp, "%p", arg);
1274 for (i = 0; i < iovcnt; i++) {
1275 len = iov[i].iov_len;
1276 if (len > max_string) {
1278 buf_truncated = true;
1280 buf_truncated = false;
1282 fprintf(fp, "%s{", (i > 0) ? "," : "");
1283 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1284 tmp3 = malloc(len * 4 + 1);
1286 if (strvisx(tmp3, tmp2, len,
1287 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1291 buf_truncated = true;
1293 fprintf(fp, "\"%s\"%s", tmp3,
1294 buf_truncated ? "..." : "");
1297 fprintf(fp, "%p", iov[i].iov_base);
1299 fprintf(fp, ",%zu}", iov[i].iov_len);
1301 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1305 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1310 for (q = CMSG_DATA(cmsghdr);
1311 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1312 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1318 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1320 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1321 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1322 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1323 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1327 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1329 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1331 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1334 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1335 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1337 fprintf(fp, "ctx=%u,", info->sinfo_context);
1338 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1341 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1342 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1344 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1348 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1350 fprintf(fp, "{sid=%u,", info->snd_sid);
1352 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1353 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1354 fprintf(fp, "ctx=%u,", info->snd_context);
1355 fprintf(fp, "id=%u}", info->snd_assoc_id);
1359 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1361 fprintf(fp, "{sid=%u,", info->rcv_sid);
1362 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1364 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1365 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1366 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1367 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1368 fprintf(fp, "ctx=%u,", info->rcv_context);
1369 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1373 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1375 fprintf(fp, "{sid=%u,", info->nxt_sid);
1377 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1378 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1379 fprintf(fp, "len=%u,", info->nxt_length);
1380 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1384 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1387 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1388 fprintf(fp, ",val=%u}", info->pr_value);
1392 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1394 fprintf(fp, "{num=%u}", info->auth_keynumber);
1398 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1400 char buf[INET_ADDRSTRLEN];
1403 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1405 fprintf(fp, "{addr=%s}", s);
1407 fputs("{addr=???}", fp);
1411 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1413 char buf[INET6_ADDRSTRLEN];
1416 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1418 fprintf(fp, "{addr=%s}", s);
1420 fputs("{addr=???}", fp);
1424 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1429 len = cmsghdr->cmsg_len;
1430 data = CMSG_DATA(cmsghdr);
1431 switch (cmsghdr->cmsg_type) {
1433 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1434 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1436 print_gen_cmsg(fp, cmsghdr);
1439 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1440 print_sctp_sndrcvinfo(fp, receive,
1441 (struct sctp_sndrcvinfo *)data);
1443 print_gen_cmsg(fp, cmsghdr);
1447 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1448 print_sctp_extrcvinfo(fp,
1449 (struct sctp_extrcvinfo *)data);
1451 print_gen_cmsg(fp, cmsghdr);
1455 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1456 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1458 print_gen_cmsg(fp, cmsghdr);
1461 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1462 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1464 print_gen_cmsg(fp, cmsghdr);
1467 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1468 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1470 print_gen_cmsg(fp, cmsghdr);
1473 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1474 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1476 print_gen_cmsg(fp, cmsghdr);
1479 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1480 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1482 print_gen_cmsg(fp, cmsghdr);
1484 case SCTP_DSTADDRV4:
1485 if (len == CMSG_LEN(sizeof(struct in_addr)))
1486 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1488 print_gen_cmsg(fp, cmsghdr);
1490 case SCTP_DSTADDRV6:
1491 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1492 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1494 print_gen_cmsg(fp, cmsghdr);
1497 print_gen_cmsg(fp, cmsghdr);
1502 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1504 struct cmsghdr *cmsghdr;
1511 len = msghdr->msg_controllen;
1516 cmsgbuf = calloc(1, len);
1517 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1518 fprintf(fp, "%p", msghdr->msg_control);
1522 msghdr->msg_control = cmsgbuf;
1525 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1527 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1528 level = cmsghdr->cmsg_level;
1529 type = cmsghdr->cmsg_type;
1530 len = cmsghdr->cmsg_len;
1531 fprintf(fp, "%s{level=", first ? "" : ",");
1532 print_integer_arg(sysdecode_sockopt_level, fp, level);
1533 fputs(",type=", fp);
1534 temp = sysdecode_cmsg_type(level, type);
1538 fprintf(fp, "%d", type);
1540 fputs(",data=", fp);
1543 print_sctp_cmsg(fp, receive, cmsghdr);
1546 print_gen_cmsg(fp, cmsghdr);
1557 print_sysctl_oid(FILE *fp, int *oid, int len)
1561 for (i = 0; i < len; i++)
1562 fprintf(fp, ".%d", oid[i]);
1566 * Converts a syscall argument into a string. Said string is
1567 * allocated via malloc(), so needs to be free()'d. sc is
1568 * a pointer to the syscall description (see above); args is
1569 * an array of all of the system call arguments.
1572 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1573 struct trussinfo *trussinfo)
1580 fp = open_memstream(&tmp, &tmplen);
1581 pid = trussinfo->curthread->proc->pid;
1582 switch (sc->type & ARG_MASK) {
1584 fprintf(fp, "0x%x", (int)args[sc->offset]);
1587 fprintf(fp, "0%o", (int)args[sc->offset]);
1590 fprintf(fp, "%d", (int)args[sc->offset]);
1593 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1598 if (get_struct(pid, (void *)args[sc->offset], &val,
1600 fprintf(fp, "{ %u }", val);
1602 fprintf(fp, "0x%lx", args[sc->offset]);
1606 fprintf(fp, "0x%lx", args[sc->offset]);
1609 fprintf(fp, "%ld", args[sc->offset]);
1612 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1615 /* NULL-terminated string. */
1618 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1619 fprintf(fp, "\"%s\"", tmp2);
1625 * Binary block of data that might have printable characters.
1626 * XXX If type|OUT, assume that the length is the syscall's
1627 * return value. Otherwise, assume that the length of the block
1628 * is in the next syscall argument.
1630 int max_string = trussinfo->strsize;
1631 char tmp2[max_string + 1], *tmp3;
1638 len = args[sc->offset + 1];
1641 * Don't print more than max_string characters, to avoid word
1642 * wrap. If we have to truncate put some ... after the string.
1644 if (len > max_string) {
1648 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1650 tmp3 = malloc(len * 4 + 1);
1652 if (strvisx(tmp3, tmp2, len,
1653 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1658 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1662 fprintf(fp, "0x%lx", args[sc->offset]);
1672 char buf[PAGE_SIZE];
1679 * Only parse argv[] and environment arrays from exec calls
1682 if (((sc->type & ARG_MASK) == ExecArgs &&
1683 (trussinfo->flags & EXECVEARGS) == 0) ||
1684 ((sc->type & ARG_MASK) == ExecEnv &&
1685 (trussinfo->flags & EXECVEENVS) == 0)) {
1686 fprintf(fp, "0x%lx", args[sc->offset]);
1691 * Read a page of pointers at a time. Punt if the top-level
1692 * pointer is not aligned. Note that the first read is of
1695 addr = args[sc->offset];
1696 if (addr % sizeof(char *) != 0) {
1697 fprintf(fp, "0x%lx", args[sc->offset]);
1701 len = PAGE_SIZE - (addr & PAGE_MASK);
1702 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1703 fprintf(fp, "0x%lx", args[sc->offset]);
1710 while (u.strarray[i] != NULL) {
1711 string = get_string(pid, u.strarray[i], 0);
1712 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1717 if (i == len / sizeof(char *)) {
1720 if (get_struct(pid, (void *)addr, u.buf, len) ==
1722 fprintf(fp, ", <inval>");
1733 fprintf(fp, "%ld", args[sc->offset]);
1736 fprintf(fp, "0x%lx", args[sc->offset]);
1741 unsigned long long ll;
1743 #if _BYTE_ORDER == _LITTLE_ENDIAN
1744 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1747 ll = (unsigned long long)args[sc->offset] << 32 |
1748 args[sc->offset + 1];
1750 if ((sc->type & ARG_MASK) == Quad)
1751 fprintf(fp, "%lld", ll);
1753 fprintf(fp, "0x%llx", ll);
1760 if (get_struct(pid, (void *)args[sc->offset], &val,
1762 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1764 fprintf(fp, "0x%lx", args[sc->offset]);
1768 fprintf(fp, "0x%lx", args[sc->offset]);
1773 if (retval[0] == -1)
1775 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1776 fprintf(fp, "\"%s\"", tmp2);
1784 cmd = args[sc->offset];
1785 temp = sysdecode_ioctlname(cmd);
1789 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1790 cmd, cmd & IOC_OUT ? "R" : "",
1791 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1792 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1793 cmd & 0xFF, IOCPARM_LEN(cmd));
1800 if (get_struct(pid, (void *)args[sc->offset], &ts,
1802 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1805 fprintf(fp, "0x%lx", args[sc->offset]);
1809 struct timespec ts[2];
1813 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1817 for (i = 0; i < nitems(ts); i++) {
1820 switch (ts[i].tv_nsec) {
1822 fprintf(fp, "UTIME_NOW");
1825 fprintf(fp, "UTIME_OMIT");
1828 fprintf(fp, "%jd.%09ld",
1829 (intmax_t)ts[i].tv_sec,
1836 fprintf(fp, "0x%lx", args[sc->offset]);
1842 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1844 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1847 fprintf(fp, "0x%lx", args[sc->offset]);
1851 struct timeval tv[2];
1853 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1855 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1856 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1857 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1859 fprintf(fp, "0x%lx", args[sc->offset]);
1863 struct itimerval itv;
1865 if (get_struct(pid, (void *)args[sc->offset], &itv,
1867 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1868 (intmax_t)itv.it_interval.tv_sec,
1869 itv.it_interval.tv_usec,
1870 (intmax_t)itv.it_value.tv_sec,
1871 itv.it_value.tv_usec);
1873 fprintf(fp, "0x%lx", args[sc->offset]);
1878 struct linux_socketcall_args largs;
1880 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1881 sizeof(largs)) != -1)
1882 fprintf(fp, "{ %s, 0x%lx }",
1883 lookup(linux_socketcall_ops, largs.what, 10),
1884 (long unsigned int)largs.args);
1886 fprintf(fp, "0x%lx", args[sc->offset]);
1891 * XXX: A Pollfd argument expects the /next/ syscall argument
1892 * to be the number of fds in the array. This matches the poll
1896 int numfds = args[sc->offset + 1];
1897 size_t bytes = sizeof(struct pollfd) * numfds;
1900 if ((pfd = malloc(bytes)) == NULL)
1901 err(1, "Cannot malloc %zu bytes for pollfd array",
1903 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1906 for (i = 0; i < numfds; i++) {
1907 fprintf(fp, " %d/%s", pfd[i].fd,
1908 xlookup_bits(poll_flags, pfd[i].events));
1912 fprintf(fp, "0x%lx", args[sc->offset]);
1919 * XXX: A Fd_set argument expects the /first/ syscall argument
1920 * to be the number of fds in the array. This matches the
1924 int numfds = args[0];
1925 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1928 if ((fds = malloc(bytes)) == NULL)
1929 err(1, "Cannot malloc %zu bytes for fd_set array",
1931 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1934 for (i = 0; i < numfds; i++) {
1935 if (FD_ISSET(i, fds))
1936 fprintf(fp, " %d", i);
1940 fprintf(fp, "0x%lx", args[sc->offset]);
1945 fputs(strsig2(args[sc->offset]), fp);
1952 sig = args[sc->offset];
1953 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1954 sizeof(ss)) == -1) {
1955 fprintf(fp, "0x%lx", args[sc->offset]);
1960 for (i = 1; i < sys_nsig; i++) {
1961 if (sigismember(&ss, i)) {
1962 fprintf(fp, "%s%s", !first ? "|" : "",
1973 print_integer_arg(sysdecode_sigprocmask_how, fp,
1977 /* XXX: Output depends on the value of the previous argument. */
1978 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1979 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1980 args[sc->offset], 16);
1983 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1986 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1989 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1992 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1995 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1998 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2001 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2004 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2007 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2010 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2013 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2016 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2021 if (args[sc->offset] == 0) {
2027 * Extract the address length from the next argument. If
2028 * this is an output sockaddr (OUT is set), then the
2029 * next argument is a pointer to a socklen_t. Otherwise
2030 * the next argument contains a socklen_t by value.
2032 if (sc->type & OUT) {
2033 if (get_struct(pid, (void *)args[sc->offset + 1],
2034 &len, sizeof(len)) == -1) {
2035 fprintf(fp, "0x%lx", args[sc->offset]);
2039 len = args[sc->offset + 1];
2041 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2045 struct sigaction sa;
2047 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2050 if (sa.sa_handler == SIG_DFL)
2051 fputs("SIG_DFL", fp);
2052 else if (sa.sa_handler == SIG_IGN)
2053 fputs("SIG_IGN", fp);
2055 fprintf(fp, "%p", sa.sa_handler);
2056 fprintf(fp, " %s ss_t }",
2057 xlookup_bits(sigaction_flags, sa.sa_flags));
2059 fprintf(fp, "0x%lx", args[sc->offset]);
2064 * XXX XXX: The size of the array is determined by either the
2065 * next syscall argument, or by the syscall return value,
2066 * depending on which argument number we are. This matches the
2067 * kevent syscall, but luckily that's the only syscall that uses
2075 if (sc->offset == 1)
2076 numevents = args[sc->offset+1];
2077 else if (sc->offset == 3 && retval[0] != -1)
2078 numevents = retval[0];
2080 if (numevents >= 0) {
2081 bytes = sizeof(struct kevent) * numevents;
2082 if ((ke = malloc(bytes)) == NULL)
2084 "Cannot malloc %zu bytes for kevent array",
2088 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2091 for (i = 0; i < numevents; i++) {
2093 print_kevent(fp, &ke[i]);
2097 fprintf(fp, "0x%lx", args[sc->offset]);
2103 struct kevent_freebsd11 *ke11;
2109 if (sc->offset == 1)
2110 numevents = args[sc->offset+1];
2111 else if (sc->offset == 3 && retval[0] != -1)
2112 numevents = retval[0];
2114 if (numevents >= 0) {
2115 bytes = sizeof(struct kevent_freebsd11) * numevents;
2116 if ((ke11 = malloc(bytes)) == NULL)
2118 "Cannot malloc %zu bytes for kevent array",
2122 memset(&ke, 0, sizeof(ke));
2123 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2124 ke11, bytes) != -1) {
2126 for (i = 0; i < numevents; i++) {
2128 ke.ident = ke11[i].ident;
2129 ke.filter = ke11[i].filter;
2130 ke.flags = ke11[i].flags;
2131 ke.fflags = ke11[i].fflags;
2132 ke.data = ke11[i].data;
2133 ke.udata = ke11[i].udata;
2134 print_kevent(fp, &ke);
2138 fprintf(fp, "0x%lx", args[sc->offset]);
2146 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2150 strmode(st.st_mode, mode);
2152 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2153 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2154 (long)st.st_blksize);
2156 fprintf(fp, "0x%lx", args[sc->offset]);
2161 struct freebsd11_stat st;
2163 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2167 strmode(st.st_mode, mode);
2169 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2170 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2171 (long)st.st_blksize);
2173 fprintf(fp, "0x%lx", args[sc->offset]);
2181 if (get_struct(pid, (void *)args[sc->offset], &buf,
2182 sizeof(buf)) != -1) {
2185 bzero(fsid, sizeof(fsid));
2186 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2187 for (i = 0; i < sizeof(buf.f_fsid); i++)
2188 snprintf(&fsid[i*2],
2189 sizeof(fsid) - (i*2), "%02x",
2190 ((u_char *)&buf.f_fsid)[i]);
2193 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2194 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2195 buf.f_mntfromname, fsid);
2197 fprintf(fp, "0x%lx", args[sc->offset]);
2204 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2207 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2208 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2209 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2210 ru.ru_inblock, ru.ru_oublock);
2212 fprintf(fp, "0x%lx", args[sc->offset]);
2218 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2220 fprintf(fp, "{ cur=%ju,max=%ju }",
2221 rl.rlim_cur, rl.rlim_max);
2223 fprintf(fp, "0x%lx", args[sc->offset]);
2229 if (get_struct(pid, (void *)args[sc->offset], &status,
2230 sizeof(status)) != -1) {
2232 if (WIFCONTINUED(status))
2233 fputs("CONTINUED", fp);
2234 else if (WIFEXITED(status))
2235 fprintf(fp, "EXITED,val=%d",
2236 WEXITSTATUS(status));
2237 else if (WIFSIGNALED(status))
2238 fprintf(fp, "SIGNALED,sig=%s%s",
2239 strsig2(WTERMSIG(status)),
2240 WCOREDUMP(status) ? ",cored" : "");
2242 fprintf(fp, "STOPPED,sig=%s",
2243 strsig2(WTERMSIG(status)));
2246 fprintf(fp, "0x%lx", args[sc->offset]);
2250 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2253 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2256 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2259 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2262 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2265 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2268 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2271 print_integer_arg(sysdecode_sysarch_number, fp,
2276 int oid[CTL_MAXNAME + 2], qoid[CTL_MAXNAME + 2];
2280 memset(name, 0, sizeof(name));
2281 len = args[sc->offset + 1];
2282 if (get_struct(pid, (void *)args[sc->offset], oid,
2283 len * sizeof(oid[0])) != -1) {
2285 if (oid[0] == CTL_SYSCTL) {
2286 fprintf(fp, "sysctl.");
2288 case CTL_SYSCTL_DEBUG:
2289 fprintf(fp, "debug");
2291 case CTL_SYSCTL_NAME:
2292 fprintf(fp, "name");
2293 print_sysctl_oid(fp, oid + 2, len - 2);
2295 case CTL_SYSCTL_NEXT:
2296 fprintf(fp, "next");
2298 case CTL_SYSCTL_NAME2OID:
2299 fprintf(fp, "name2oid");
2301 case CTL_SYSCTL_OIDFMT:
2302 fprintf(fp, "oidfmt");
2303 print_sysctl_oid(fp, oid + 2, len - 2);
2305 case CTL_SYSCTL_OIDDESCR:
2306 fprintf(fp, "oiddescr");
2307 print_sysctl_oid(fp, oid + 2, len - 2);
2309 case CTL_SYSCTL_OIDLABEL:
2310 fprintf(fp, "oidlabel");
2311 print_sysctl_oid(fp, oid + 2, len - 2);
2314 print_sysctl_oid(fp, oid + 1, len - 1);
2317 qoid[0] = CTL_SYSCTL;
2318 qoid[1] = CTL_SYSCTL_NAME;
2319 memcpy(qoid + 2, oid, len * sizeof(int));
2321 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
2322 print_sysctl_oid(fp, qoid + 2, len);
2324 fprintf(fp, "%s", name);
2332 * The pipe() system call in the kernel returns its
2333 * two file descriptors via return values. However,
2334 * the interface exposed by libc is that pipe()
2335 * accepts a pointer to an array of descriptors.
2336 * Format the output to match the libc API by printing
2337 * the returned file descriptors as a fake argument.
2339 * Overwrite the first retval to signal a successful
2342 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2349 len = args[sc->offset + 1];
2350 utrace_addr = calloc(1, len);
2351 if (get_struct(pid, (void *)args[sc->offset],
2352 (void *)utrace_addr, len) != -1)
2353 print_utrace(fp, utrace_addr, len);
2355 fprintf(fp, "0x%lx", args[sc->offset]);
2360 int descriptors[16];
2361 unsigned long i, ndescriptors;
2364 ndescriptors = args[sc->offset + 1];
2366 if (ndescriptors > nitems(descriptors)) {
2367 ndescriptors = nitems(descriptors);
2370 if (get_struct(pid, (void *)args[sc->offset],
2371 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2373 for (i = 0; i < ndescriptors; i++)
2374 fprintf(fp, i == 0 ? " %d" : ", %d",
2376 fprintf(fp, truncated ? ", ... }" : " }");
2378 fprintf(fp, "0x%lx", args[sc->offset]);
2382 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2384 case CapFcntlRights: {
2387 if (sc->type & OUT) {
2388 if (get_struct(pid, (void *)args[sc->offset], &rights,
2389 sizeof(rights)) == -1) {
2390 fprintf(fp, "0x%lx", args[sc->offset]);
2394 rights = args[sc->offset];
2395 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2399 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2404 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2405 fprintf(fp, "0x%x", rem);
2407 fprintf(fp, "|0x%x", rem);
2411 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2414 print_integer_arg(sysdecode_getfsstat_mode, fp,
2418 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2420 case Kldunloadflags:
2421 print_integer_arg(sysdecode_kldunload_flags, fp,
2425 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2428 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2430 case Sockprotocol: {
2432 int domain, protocol;
2434 domain = args[sc->offset - 2];
2435 protocol = args[sc->offset];
2436 if (protocol == 0) {
2439 temp = sysdecode_socket_protocol(domain, protocol);
2443 fprintf(fp, "%d", protocol);
2449 print_integer_arg(sysdecode_sockopt_level, fp,
2456 level = args[sc->offset - 1];
2457 name = args[sc->offset];
2458 temp = sysdecode_sockopt_name(level, name);
2462 fprintf(fp, "%d", name);
2467 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2470 cap_rights_t rights;
2472 if (get_struct(pid, (void *)args[sc->offset], &rights,
2473 sizeof(rights)) != -1) {
2475 sysdecode_cap_rights(fp, &rights);
2478 fprintf(fp, "0x%lx", args[sc->offset]);
2482 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2484 case Extattrnamespace:
2485 print_integer_arg(sysdecode_extattrnamespace, fp,
2489 print_integer_arg(sysdecode_minherit_inherit, fp,
2493 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2496 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2499 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2502 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2505 print_integer_arg(sysdecode_ptrace_request, fp,
2509 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2510 fprintf(fp, "%#x", (int)args[sc->offset]);
2513 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2516 print_integer_arg(sysdecode_rtprio_function, fp,
2520 print_integer_arg(sysdecode_scheduler_policy, fp,
2524 struct sched_param sp;
2526 if (get_struct(pid, (void *)args[sc->offset], &sp,
2528 fprintf(fp, "{ %d }", sp.sched_priority);
2530 fprintf(fp, "0x%lx", args[sc->offset]);
2536 if (get_struct(pid, (void *)args[sc->offset], &sig,
2538 fprintf(fp, "{ %s }", strsig2(sig));
2540 fprintf(fp, "0x%lx", args[sc->offset]);
2546 if (get_struct(pid, (void *)args[sc->offset], &si,
2547 sizeof(si)) != -1) {
2548 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2549 decode_siginfo(fp, &si);
2552 fprintf(fp, "0x%lx", args[sc->offset]);
2557 * Print argument as an array of struct iovec, where the next
2558 * syscall argument is the number of elements of the array.
2561 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2562 (int)args[sc->offset + 1]);
2564 case Sctpsndrcvinfo: {
2565 struct sctp_sndrcvinfo info;
2567 if (get_struct(pid, (void *)args[sc->offset],
2568 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2569 fprintf(fp, "0x%lx", args[sc->offset]);
2572 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2576 struct msghdr msghdr;
2578 if (get_struct(pid, (void *)args[sc->offset],
2579 &msghdr, sizeof(struct msghdr)) == -1) {
2580 fprintf(fp, "0x%lx", args[sc->offset]);
2584 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2585 fprintf(fp, ",%d,", msghdr.msg_namelen);
2586 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2587 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2588 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2589 fprintf(fp, ",%u,", msghdr.msg_controllen);
2590 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2595 case CloudABIAdvice:
2596 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2598 case CloudABIClockID:
2599 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2601 case CloudABIFDSFlags:
2602 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2604 case CloudABIFDStat: {
2605 cloudabi_fdstat_t fds;
2606 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2608 fprintf(fp, "{ %s, ",
2609 xlookup(cloudabi_filetype, fds.fs_filetype));
2610 fprintf(fp, "%s, ... }",
2611 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2613 fprintf(fp, "0x%lx", args[sc->offset]);
2616 case CloudABIFileStat: {
2617 cloudabi_filestat_t fsb;
2618 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2620 fprintf(fp, "{ %s, %ju }",
2621 xlookup(cloudabi_filetype, fsb.st_filetype),
2622 (uintmax_t)fsb.st_size);
2624 fprintf(fp, "0x%lx", args[sc->offset]);
2627 case CloudABIFileType:
2628 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2630 case CloudABIFSFlags:
2631 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2633 case CloudABILookup:
2634 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2635 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2636 (int)args[sc->offset]);
2638 fprintf(fp, "%d", (int)args[sc->offset]);
2640 case CloudABIMFlags:
2641 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2644 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2646 case CloudABIMSFlags:
2647 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2649 case CloudABIOFlags:
2650 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2652 case CloudABISDFlags:
2653 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2655 case CloudABISignal:
2656 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2658 case CloudABITimestamp:
2659 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2660 args[sc->offset] % 1000000000);
2662 case CloudABIULFlags:
2663 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2665 case CloudABIWhence:
2666 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2670 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2677 * Print (to outfile) the system call and its arguments.
2680 print_syscall(struct trussinfo *trussinfo)
2682 struct threadinfo *t;
2687 t = trussinfo->curthread;
2689 name = t->cs.sc->name;
2690 nargs = t->cs.nargs;
2691 s_args = t->cs.s_args;
2693 len = print_line_prefix(trussinfo);
2694 len += fprintf(trussinfo->outfile, "%s(", name);
2696 for (i = 0; i < nargs; i++) {
2697 if (s_args[i] != NULL)
2698 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2700 len += fprintf(trussinfo->outfile,
2701 "<missing argument>");
2702 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2705 len += fprintf(trussinfo->outfile, ")");
2706 for (i = 0; i < 6 - (len / 8); i++)
2707 fprintf(trussinfo->outfile, "\t");
2711 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2713 struct timespec timediff;
2714 struct threadinfo *t;
2717 t = trussinfo->curthread;
2719 if (trussinfo->flags & COUNTONLY) {
2720 timespecsub(&t->after, &t->before, &timediff);
2721 timespecadd(&sc->time, &timediff, &sc->time);
2728 print_syscall(trussinfo);
2729 fflush(trussinfo->outfile);
2731 if (retval == NULL) {
2733 * This system call resulted in the current thread's exit,
2734 * so there is no return value or error to display.
2736 fprintf(trussinfo->outfile, "\n");
2740 if (error == ERESTART)
2741 fprintf(trussinfo->outfile, " ERESTART\n");
2742 else if (error == EJUSTRETURN)
2743 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2744 else if (error != 0) {
2745 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2746 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2750 else if (sc->ret_type == 2) {
2753 #if _BYTE_ORDER == _LITTLE_ENDIAN
2754 off = (off_t)retval[1] << 32 | retval[0];
2756 off = (off_t)retval[0] << 32 | retval[1];
2758 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2763 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2764 (intmax_t)retval[0], (intmax_t)retval[0]);
2768 print_summary(struct trussinfo *trussinfo)
2770 struct timespec total = {0, 0};
2774 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2775 "syscall", "seconds", "calls", "errors");
2777 STAILQ_FOREACH(sc, &syscalls, entries)
2779 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2780 sc->name, (intmax_t)sc->time.tv_sec,
2781 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2782 timespecadd(&total, &sc->time, &total);
2783 ncall += sc->ncalls;
2784 nerror += sc->nerror;
2786 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2787 "", "-------------", "-------", "-------");
2788 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2789 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);