2 * SPDX-License-Identifier: BSD-4-Clause
4 * Copyright 1997 Sean Eric Fagan
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Sean Eric Fagan
17 * 4. Neither the name of the author may be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * This file has routines used to print out system calls and their
42 #include <sys/capsicum.h>
43 #include <sys/types.h>
44 #define _WANT_FREEBSD11_KEVENT
45 #include <sys/event.h>
46 #include <sys/ioccom.h>
48 #include <sys/mount.h>
49 #include <sys/ptrace.h>
50 #include <sys/resource.h>
51 #include <sys/socket.h>
52 #define _WANT_FREEBSD11_STAT
54 #include <sys/sysctl.h>
58 #include <netinet/in.h>
59 #include <netinet/sctp.h>
60 #include <arpa/inet.h>
65 #define _WANT_KERNEL_ERRNO
75 #include <sysdecode.h>
79 #include <contrib/cloudabi/cloudabi_types_common.h>
86 * This should probably be in its own file, sorted alphabetically.
88 static struct syscall decoded_syscalls[] = {
90 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
91 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
92 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
93 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
94 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
95 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
96 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
97 .args = { { Int, 0 }, { Acltype, 1 } } },
98 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
99 .args = { { Name, 0 }, { Acltype, 1 } } },
100 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
101 .args = { { Name, 0 }, { Acltype, 1 } } },
102 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
103 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
104 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
105 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
106 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
107 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
108 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
109 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
110 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
111 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
112 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
113 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
114 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
115 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
116 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
117 .args = { { Name | OUT, 0 }, { Int, 1 } } },
118 { .name = "__realpathat", .ret_type = 1, .nargs = 5,
119 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Name | OUT, 2 },
120 { Sizet, 3 }, { Int, 4} } },
121 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
122 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
124 { .name = "accept", .ret_type = 1, .nargs = 3,
125 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
126 { .name = "access", .ret_type = 1, .nargs = 2,
127 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
128 { .name = "bind", .ret_type = 1, .nargs = 3,
129 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
130 { .name = "bindat", .ret_type = 1, .nargs = 4,
131 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
133 { .name = "break", .ret_type = 1, .nargs = 1,
134 .args = { { Ptr, 0 } } },
135 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
136 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
137 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
138 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
139 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
140 .args = { { PUInt | OUT, 0 } } },
141 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
142 .args = { { Int, 0 }, { CapRights, 1 } } },
143 { .name = "chdir", .ret_type = 1, .nargs = 1,
144 .args = { { Name, 0 } } },
145 { .name = "chflags", .ret_type = 1, .nargs = 2,
146 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
147 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
148 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
150 { .name = "chmod", .ret_type = 1, .nargs = 2,
151 .args = { { Name, 0 }, { Octal, 1 } } },
152 { .name = "chown", .ret_type = 1, .nargs = 3,
153 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
154 { .name = "chroot", .ret_type = 1, .nargs = 1,
155 .args = { { Name, 0 } } },
156 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
157 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
158 { .name = "close", .ret_type = 1, .nargs = 1,
159 .args = { { Int, 0 } } },
160 { .name = "closefrom", .ret_type = 1, .nargs = 1,
161 .args = { { Int, 0 } } },
162 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
163 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
164 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
165 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
167 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
168 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
169 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
170 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
171 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
172 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
173 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
174 { .name = "connect", .ret_type = 1, .nargs = 3,
175 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
176 { .name = "connectat", .ret_type = 1, .nargs = 4,
177 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
179 { .name = "dup", .ret_type = 1, .nargs = 1,
180 .args = { { Int, 0 } } },
181 { .name = "dup2", .ret_type = 1, .nargs = 2,
182 .args = { { Int, 0 }, { Int, 1 } } },
183 { .name = "eaccess", .ret_type = 1, .nargs = 2,
184 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
185 { .name = "execve", .ret_type = 1, .nargs = 3,
186 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
187 { ExecEnv | IN, 2 } } },
188 { .name = "exit", .ret_type = 0, .nargs = 1,
189 .args = { { Hex, 0 } } },
190 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
191 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
192 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
193 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
194 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
195 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
196 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
197 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
198 { BinString | OUT, 3 }, { Sizet, 4 } } },
199 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
200 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
201 { BinString | OUT, 3 }, { Sizet, 4 } } },
202 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
203 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
204 { BinString | OUT, 3 }, { Sizet, 4 } } },
205 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
206 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
208 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
209 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
211 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
214 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
215 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
216 { BinString | IN, 3 }, { Sizet, 4 } } },
217 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
218 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
219 { BinString | IN, 3 }, { Sizet, 4 } } },
220 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
221 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
222 { BinString | IN, 3 }, { Sizet, 4 } } },
223 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
224 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
225 { Extattrnamespace, 3 }, { Name, 4 } } },
226 { .name = "faccessat", .ret_type = 1, .nargs = 4,
227 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
229 { .name = "fchflags", .ret_type = 1, .nargs = 2,
230 .args = { { Int, 0 }, { FileFlags, 1 } } },
231 { .name = "fchmod", .ret_type = 1, .nargs = 2,
232 .args = { { Int, 0 }, { Octal, 1 } } },
233 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
234 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
235 { .name = "fchown", .ret_type = 1, .nargs = 3,
236 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
237 { .name = "fchownat", .ret_type = 1, .nargs = 5,
238 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
240 { .name = "fcntl", .ret_type = 1, .nargs = 3,
241 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
242 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
243 .args = { { Int, 0 } } },
244 { .name = "flock", .ret_type = 1, .nargs = 2,
245 .args = { { Int, 0 }, { Flockop, 1 } } },
246 { .name = "fstat", .ret_type = 1, .nargs = 2,
247 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
248 { .name = "fstatat", .ret_type = 1, .nargs = 4,
249 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
251 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
252 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
253 { .name = "fsync", .ret_type = 1, .nargs = 1,
254 .args = { { Int, 0 } } },
255 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
256 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
257 { .name = "futimens", .ret_type = 1, .nargs = 2,
258 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
259 { .name = "futimes", .ret_type = 1, .nargs = 2,
260 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
261 { .name = "futimesat", .ret_type = 1, .nargs = 3,
262 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
263 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
264 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
265 { PQuadHex | OUT, 3 } } },
266 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
267 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
268 { .name = "getitimer", .ret_type = 1, .nargs = 2,
269 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
270 { .name = "getpeername", .ret_type = 1, .nargs = 3,
271 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
272 { .name = "getpgid", .ret_type = 1, .nargs = 1,
273 .args = { { Int, 0 } } },
274 { .name = "getpriority", .ret_type = 1, .nargs = 2,
275 .args = { { Priowhich, 0 }, { Int, 1 } } },
276 { .name = "getrandom", .ret_type = 1, .nargs = 3,
277 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
278 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
279 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
280 { .name = "getrusage", .ret_type = 1, .nargs = 2,
281 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
282 { .name = "getsid", .ret_type = 1, .nargs = 1,
283 .args = { { Int, 0 } } },
284 { .name = "getsockname", .ret_type = 1, .nargs = 3,
285 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
286 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
287 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
288 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
289 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
290 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
291 { .name = "ioctl", .ret_type = 1, .nargs = 3,
292 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
293 { .name = "kevent", .ret_type = 1, .nargs = 6,
294 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
295 { Int, 4 }, { Timespec, 5 } } },
296 { .name = "kill", .ret_type = 1, .nargs = 2,
297 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
298 { .name = "kldfind", .ret_type = 1, .nargs = 1,
299 .args = { { Name | IN, 0 } } },
300 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
301 .args = { { Int, 0 } } },
302 { .name = "kldload", .ret_type = 1, .nargs = 1,
303 .args = { { Name | IN, 0 } } },
304 { .name = "kldnext", .ret_type = 1, .nargs = 1,
305 .args = { { Int, 0 } } },
306 { .name = "kldstat", .ret_type = 1, .nargs = 2,
307 .args = { { Int, 0 }, { Ptr, 1 } } },
308 { .name = "kldsym", .ret_type = 1, .nargs = 3,
309 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
310 { .name = "kldunload", .ret_type = 1, .nargs = 1,
311 .args = { { Int, 0 } } },
312 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
313 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
314 { .name = "kse_release", .ret_type = 0, .nargs = 1,
315 .args = { { Timespec, 0 } } },
316 { .name = "lchflags", .ret_type = 1, .nargs = 2,
317 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
318 { .name = "lchmod", .ret_type = 1, .nargs = 2,
319 .args = { { Name, 0 }, { Octal, 1 } } },
320 { .name = "lchown", .ret_type = 1, .nargs = 3,
321 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
322 { .name = "link", .ret_type = 1, .nargs = 2,
323 .args = { { Name, 0 }, { Name, 1 } } },
324 { .name = "linkat", .ret_type = 1, .nargs = 5,
325 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
327 { .name = "listen", .ret_type = 1, .nargs = 2,
328 .args = { { Int, 0 }, { Int, 1 } } },
329 { .name = "lseek", .ret_type = 2, .nargs = 3,
330 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
331 { .name = "lstat", .ret_type = 1, .nargs = 2,
332 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
333 { .name = "lutimes", .ret_type = 1, .nargs = 2,
334 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
335 { .name = "madvise", .ret_type = 1, .nargs = 3,
336 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
337 { .name = "minherit", .ret_type = 1, .nargs = 3,
338 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
339 { .name = "mkdir", .ret_type = 1, .nargs = 2,
340 .args = { { Name, 0 }, { Octal, 1 } } },
341 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
342 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
343 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
344 .args = { { Name, 0 }, { Octal, 1 } } },
345 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
346 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
347 { .name = "mknod", .ret_type = 1, .nargs = 3,
348 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
349 { .name = "mknodat", .ret_type = 1, .nargs = 4,
350 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
351 { .name = "mlock", .ret_type = 1, .nargs = 2,
352 .args = { { Ptr, 0 }, { Sizet, 1 } } },
353 { .name = "mlockall", .ret_type = 1, .nargs = 1,
354 .args = { { Mlockall, 0 } } },
355 { .name = "mmap", .ret_type = 1, .nargs = 6,
356 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
357 { Int, 4 }, { QuadHex, 5 } } },
358 { .name = "modfind", .ret_type = 1, .nargs = 1,
359 .args = { { Name | IN, 0 } } },
360 { .name = "mount", .ret_type = 1, .nargs = 4,
361 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
362 { .name = "mprotect", .ret_type = 1, .nargs = 3,
363 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
364 { .name = "msync", .ret_type = 1, .nargs = 3,
365 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
366 { .name = "munlock", .ret_type = 1, .nargs = 2,
367 .args = { { Ptr, 0 }, { Sizet, 1 } } },
368 { .name = "munmap", .ret_type = 1, .nargs = 2,
369 .args = { { Ptr, 0 }, { Sizet, 1 } } },
370 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
371 .args = { { Timespec, 0 } } },
372 { .name = "nmount", .ret_type = 1, .nargs = 3,
373 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
374 { .name = "open", .ret_type = 1, .nargs = 3,
375 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
376 { .name = "openat", .ret_type = 1, .nargs = 4,
377 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
379 { .name = "pathconf", .ret_type = 1, .nargs = 2,
380 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
381 { .name = "pipe", .ret_type = 1, .nargs = 1,
382 .args = { { PipeFds | OUT, 0 } } },
383 { .name = "pipe2", .ret_type = 1, .nargs = 2,
384 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
385 { .name = "poll", .ret_type = 1, .nargs = 3,
386 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
387 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
388 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
390 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
391 .args = { { Open, 0 } } },
392 { .name = "pread", .ret_type = 1, .nargs = 4,
393 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
395 { .name = "procctl", .ret_type = 1, .nargs = 4,
396 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
397 { .name = "ptrace", .ret_type = 1, .nargs = 4,
398 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
399 { .name = "pwrite", .ret_type = 1, .nargs = 4,
400 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
402 { .name = "quotactl", .ret_type = 1, .nargs = 4,
403 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
404 { .name = "read", .ret_type = 1, .nargs = 3,
405 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
406 { .name = "readlink", .ret_type = 1, .nargs = 3,
407 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
408 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
409 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
411 { .name = "readv", .ret_type = 1, .nargs = 3,
412 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
413 { .name = "reboot", .ret_type = 1, .nargs = 1,
414 .args = { { Reboothowto, 0 } } },
415 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
416 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
417 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
418 { Ptr | OUT, 5 } } },
419 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
420 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
421 { .name = "rename", .ret_type = 1, .nargs = 2,
422 .args = { { Name, 0 }, { Name, 1 } } },
423 { .name = "renameat", .ret_type = 1, .nargs = 4,
424 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
425 { .name = "rfork", .ret_type = 1, .nargs = 1,
426 .args = { { Rforkflags, 0 } } },
427 { .name = "rmdir", .ret_type = 1, .nargs = 1,
428 .args = { { Name, 0 } } },
429 { .name = "rtprio", .ret_type = 1, .nargs = 3,
430 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
431 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
432 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
433 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
434 .args = { { Schedpolicy, 0 } } },
435 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
436 .args = { { Schedpolicy, 0 } } },
437 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
438 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
439 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
440 .args = { { Int, 0 } } },
441 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
442 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
443 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
444 .args = { { Int, 0 }, { Schedparam, 1 } } },
445 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
446 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
447 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
448 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
449 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
450 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
451 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
452 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
453 { Sockaddr | IN, 3 }, { Socklent, 4 },
454 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
455 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
456 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
457 { Sockaddr | IN, 3 }, { Socklent, 4 },
458 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
459 { .name = "select", .ret_type = 1, .nargs = 5,
460 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
462 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
463 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
464 { .name = "sendto", .ret_type = 1, .nargs = 6,
465 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
466 { Msgflags, 3 }, { Sockaddr | IN, 4 },
467 { Socklent | IN, 5 } } },
468 { .name = "setitimer", .ret_type = 1, .nargs = 3,
469 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
470 { .name = "setpriority", .ret_type = 1, .nargs = 3,
471 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
472 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
473 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
474 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
475 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
476 { Ptr | IN, 3 }, { Socklent, 4 } } },
477 { .name = "shm_open", .ret_type = 1, .nargs = 3,
478 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
479 { .name = "shm_open2", .ret_type = 1, .nargs = 5,
480 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 },
481 { ShmFlags, 3 }, { Name | IN, 4 } } },
482 { .name = "shm_rename", .ret_type = 1, .nargs = 3,
483 .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } },
484 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
485 .args = { { Name | IN, 0 } } },
486 { .name = "shutdown", .ret_type = 1, .nargs = 2,
487 .args = { { Int, 0 }, { Shutdown, 1 } } },
488 { .name = "sigaction", .ret_type = 1, .nargs = 3,
489 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
490 { Sigaction | OUT, 2 } } },
491 { .name = "sigpending", .ret_type = 1, .nargs = 1,
492 .args = { { Sigset | OUT, 0 } } },
493 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
494 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
495 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
496 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
497 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
498 .args = { { Ptr, 0 } } },
499 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
500 .args = { { Sigset | IN, 0 } } },
501 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
502 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
503 { Timespec | IN, 2 } } },
504 { .name = "sigwait", .ret_type = 1, .nargs = 2,
505 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
506 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
507 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
508 { .name = "socket", .ret_type = 1, .nargs = 3,
509 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
510 { .name = "stat", .ret_type = 1, .nargs = 2,
511 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
512 { .name = "statfs", .ret_type = 1, .nargs = 2,
513 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
514 { .name = "symlink", .ret_type = 1, .nargs = 2,
515 .args = { { Name, 0 }, { Name, 1 } } },
516 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
517 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
518 { .name = "sysarch", .ret_type = 1, .nargs = 2,
519 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
520 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
521 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
522 { Ptr, 4 }, { Sizet, 5 } } },
523 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
524 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
525 { Ptr, 4}, { Sizet, 5 } } },
526 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
527 .args = { { Long, 0 }, { Signal, 1 } } },
528 { .name = "thr_self", .ret_type = 1, .nargs = 1,
529 .args = { { Ptr, 0 } } },
530 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
531 .args = { { Long, 0 }, { Name, 1 } } },
532 { .name = "truncate", .ret_type = 1, .nargs = 2,
533 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
536 { .name = "umount", .ret_type = 1, .nargs = 2,
537 .args = { { Name, 0 }, { Int, 2 } } },
539 { .name = "unlink", .ret_type = 1, .nargs = 1,
540 .args = { { Name, 0 } } },
541 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
542 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
543 { .name = "unmount", .ret_type = 1, .nargs = 2,
544 .args = { { Name, 0 }, { Mountflags, 1 } } },
545 { .name = "utimensat", .ret_type = 1, .nargs = 4,
546 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
548 { .name = "utimes", .ret_type = 1, .nargs = 2,
549 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
550 { .name = "utrace", .ret_type = 1, .nargs = 1,
551 .args = { { Utrace, 0 } } },
552 { .name = "wait4", .ret_type = 1, .nargs = 4,
553 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
554 { Rusage | OUT, 3 } } },
555 { .name = "wait6", .ret_type = 1, .nargs = 6,
556 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
557 { Waitoptions, 3 }, { Rusage | OUT, 4 },
558 { Siginfo | OUT, 5 } } },
559 { .name = "write", .ret_type = 1, .nargs = 3,
560 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
561 { .name = "writev", .ret_type = 1, .nargs = 3,
562 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
565 { .name = "linux_access", .ret_type = 1, .nargs = 2,
566 .args = { { Name, 0 }, { Accessmode, 1 } } },
567 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
568 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
569 { ExecEnv | IN, 2 } } },
570 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
571 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
572 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
573 .args = { { Name | IN, 0 }, { Int, 1 } } },
574 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
575 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
576 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
577 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
578 { .name = "linux_open", .ret_type = 1, .nargs = 3,
579 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
580 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
581 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
582 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
583 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
584 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
585 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
587 /* CloudABI system calls. */
588 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
589 .args = { { CloudABIClockID, 0 } } },
590 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
591 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
592 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
593 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
594 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
595 .args = { { Int, 0 } } },
596 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
597 .args = { { CloudABIFileType, 0 } } },
598 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
599 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
600 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
601 .args = { { Int, 0 } } },
602 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
603 .args = { { Int, 0 } } },
604 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
605 .args = { { Int, 0 }, { Int, 1 } } },
606 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
607 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
608 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
609 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
610 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
611 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
612 { CloudABIFDSFlags, 2 } } },
613 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
614 .args = { { Int, 0 } } },
615 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
616 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
617 { CloudABIAdvice, 3 } } },
618 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
619 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
620 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
621 .args = { { Int, 0 }, { BinString | IN, 1 },
622 { CloudABIFileType, 3 } } },
623 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
624 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
625 { Int, 3 }, { BinString | IN, 4 } } },
626 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
627 .args = { { Int, 0 }, { BinString | IN, 1 },
628 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
629 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
630 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
632 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
633 .args = { { Int, 0 }, { BinString | IN, 1 },
634 { BinString | OUT, 3 }, { Int, 4 } } },
635 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
636 .args = { { Int, 0 }, { BinString | IN, 1 },
637 { Int, 3 }, { BinString | IN, 4 } } },
638 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
639 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
640 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
641 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
642 { CloudABIFSFlags, 2 } } },
643 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
644 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
645 { CloudABIFileStat | OUT, 3 } } },
646 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
647 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
648 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
649 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
650 .args = { { BinString | IN, 0 },
651 { Int, 2 }, { BinString | IN, 3 } } },
652 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
653 .args = { { Int, 0 }, { BinString | IN, 1 },
654 { CloudABIULFlags, 3 } } },
655 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
656 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
657 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
658 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
659 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
660 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
661 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
662 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
663 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
664 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
665 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
666 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
667 .args = { { Ptr, 0 }, { Int, 1 } } },
668 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
669 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
670 { IntArray, 3 }, { Int, 4 } } },
671 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
672 .args = { { Int, 0 } } },
673 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
674 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
675 .args = { { CloudABISignal, 0 } } },
676 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
677 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
678 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
679 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
680 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
681 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
682 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
686 static STAILQ_HEAD(, syscall) syscalls;
688 /* Xlat idea taken from strace */
694 #define X(a) { a, #a },
695 #define XEND { 0, NULL }
697 static struct xlat poll_flags[] = {
698 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
699 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
700 X(POLLWRBAND) X(POLLINIGNEOF) XEND
703 static struct xlat sigaction_flags[] = {
704 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
705 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
708 static struct xlat linux_socketcall_ops[] = {
709 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
710 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
711 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
712 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
713 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
718 #define X(a) { CLOUDABI_##a, #a },
720 static struct xlat cloudabi_advice[] = {
721 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
722 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
726 static struct xlat cloudabi_clockid[] = {
727 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
728 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
732 static struct xlat cloudabi_fdflags[] = {
733 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
734 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
738 static struct xlat cloudabi_fdsflags[] = {
739 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
743 static struct xlat cloudabi_filetype[] = {
744 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
745 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
746 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
747 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
748 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
752 static struct xlat cloudabi_fsflags[] = {
753 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
754 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
758 static struct xlat cloudabi_mflags[] = {
759 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
763 static struct xlat cloudabi_mprot[] = {
764 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
768 static struct xlat cloudabi_msflags[] = {
769 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
773 static struct xlat cloudabi_oflags[] = {
774 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
778 static struct xlat cloudabi_sdflags[] = {
779 X(SHUT_RD) X(SHUT_WR)
783 static struct xlat cloudabi_signal[] = {
784 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
785 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
786 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
787 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
788 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
792 static struct xlat cloudabi_ulflags[] = {
797 static struct xlat cloudabi_whence[] = {
798 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
806 * Searches an xlat array for a value, and returns it if found. Otherwise
807 * return a string representation.
810 lookup(struct xlat *xlat, int val, int base)
814 for (; xlat->str != NULL; xlat++)
815 if (xlat->val == val)
819 sprintf(tmp, "0%o", val);
822 sprintf(tmp, "0x%x", val);
825 sprintf(tmp, "%u", val);
828 errx(1,"Unknown lookup base");
835 xlookup(struct xlat *xlat, int val)
838 return (lookup(xlat, val, 16));
842 * Searches an xlat array containing bitfield values. Remaining bits
843 * set after removing the known ones are printed at the end:
847 xlookup_bits(struct xlat *xlat, int val)
850 static char str[512];
854 for (; xlat->str != NULL; xlat++) {
855 if ((xlat->val & rem) == xlat->val) {
857 * Don't print the "all-bits-zero" string unless all
858 * bits are really zero.
860 if (xlat->val == 0 && val != 0)
862 len += sprintf(str + len, "%s|", xlat->str);
868 * If we have leftover bits or didn't match anything, print
872 len += sprintf(str + len, "0x%x", rem);
873 if (len && str[len - 1] == '|')
880 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
884 str = decoder(value);
888 fprintf(fp, "%d", value);
892 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
896 if (!decoder(fp, value, &rem))
897 fprintf(fp, "0x%x", rem);
899 fprintf(fp, "|0x%x", rem);
903 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
908 if (!decoder(fp, value, &rem))
909 fprintf(fp, "0x%x", rem);
911 fprintf(fp, "|0x%x", rem);
916 * Add argument padding to subsequent system calls after Quad
917 * syscall arguments as needed. This used to be done by hand in the
918 * decoded_syscalls table which was ugly and error prone. It is
919 * simpler to do the fixup of offsets at initialization time than when
920 * decoding arguments.
923 quad_fixup(struct syscall *sc)
930 for (i = 0; i < sc->nargs; i++) {
931 /* This arg type is a dummy that doesn't use offset. */
932 if ((sc->args[i].type & ARG_MASK) == PipeFds)
935 assert(prev < sc->args[i].offset);
936 prev = sc->args[i].offset;
937 sc->args[i].offset += offset;
938 switch (sc->args[i].type & ARG_MASK) {
943 * 64-bit arguments on 32-bit powerpc must be
944 * 64-bit aligned. If the current offset is
945 * not aligned, the calling convention inserts
946 * a 32-bit pad argument that should be skipped.
948 if (sc->args[i].offset % 2 == 1) {
949 sc->args[i].offset++;
966 STAILQ_INIT(&syscalls);
967 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
971 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
975 static struct syscall *
976 find_syscall(struct procabi *abi, u_int number)
978 struct extra_syscall *es;
980 if (number < nitems(abi->syscalls))
981 return (abi->syscalls[number]);
982 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
983 if (es->number == number)
990 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
992 struct extra_syscall *es;
994 if (number < nitems(abi->syscalls)) {
995 assert(abi->syscalls[number] == NULL);
996 abi->syscalls[number] = sc;
998 es = malloc(sizeof(*es));
1000 es->number = number;
1001 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
1006 * If/when the list gets big, it might be desirable to do it
1007 * as a hash table or binary search.
1010 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1017 sc = find_syscall(t->proc->abi, number);
1021 name = sysdecode_syscallname(t->proc->abi->abi, number);
1023 asprintf(&new_name, "#%d", number);
1027 STAILQ_FOREACH(sc, &syscalls, entries) {
1028 if (strcmp(name, sc->name) == 0) {
1029 add_syscall(t->proc->abi, number, sc);
1035 /* It is unknown. Add it into the list. */
1037 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1041 sc = calloc(1, sizeof(struct syscall));
1043 if (new_name != NULL)
1047 for (i = 0; i < nargs; i++) {
1048 sc->args[i].offset = i;
1049 /* Treat all unknown arguments as LongHex. */
1050 sc->args[i].type = LongHex;
1052 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1053 add_syscall(t->proc->abi, number, sc);
1059 * Copy a fixed amount of bytes from the process.
1062 get_struct(pid_t pid, uintptr_t offset, void *buf, int len)
1064 struct ptrace_io_desc iorequest;
1066 iorequest.piod_op = PIOD_READ_D;
1067 iorequest.piod_offs = (void *)offset;
1068 iorequest.piod_addr = buf;
1069 iorequest.piod_len = len;
1070 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1075 #define MAXSIZE 4096
1078 * Copy a string from the process. Note that it is
1079 * expected to be a C string, but if max is set, it will
1080 * only get that much.
1083 get_string(pid_t pid, uintptr_t addr, int max)
1085 struct ptrace_io_desc iorequest;
1087 size_t offset, size, totalsize;
1093 /* Read up to the end of the current page. */
1094 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1099 buf = malloc(totalsize);
1103 iorequest.piod_op = PIOD_READ_D;
1104 iorequest.piod_offs = (void *)(addr + offset);
1105 iorequest.piod_addr = buf + offset;
1106 iorequest.piod_len = size;
1107 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1111 if (memchr(buf + offset, '\0', size) != NULL)
1114 if (totalsize < MAXSIZE && max == 0) {
1115 size = MAXSIZE - totalsize;
1116 if (size > PAGE_SIZE)
1118 nbuf = realloc(buf, totalsize + size);
1120 buf[totalsize - 1] = '\0';
1126 buf[totalsize - 1] = '\0';
1135 static char tmp[32];
1136 const char *signame;
1138 signame = sysdecode_signal(sig);
1139 if (signame == NULL) {
1140 snprintf(tmp, sizeof(tmp), "%d", sig);
1147 print_kevent(FILE *fp, struct kevent *ke)
1150 switch (ke->filter) {
1156 case EVFILT_PROCDESC:
1158 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1161 fputs(strsig2(ke->ident), fp);
1164 fprintf(fp, "%p", (void *)ke->ident);
1167 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1169 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1171 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1172 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1176 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1178 unsigned char *utrace_buffer;
1181 if (sysdecode_utrace(fp, utrace_addr, len)) {
1186 utrace_buffer = utrace_addr;
1187 fprintf(fp, "%zu:", len);
1189 fprintf(fp, " %02x", *utrace_buffer++);
1194 print_pointer(FILE *fp, uintptr_t arg)
1197 fprintf(fp, "%p", (void *)arg);
1201 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg,
1205 struct sockaddr_in *lsin;
1206 struct sockaddr_in6 *lsin6;
1207 struct sockaddr_un *sun;
1208 struct sockaddr *sa;
1210 pid_t pid = trussinfo->curthread->proc->pid;
1216 /* If the length is too small, just bail. */
1217 if (len < sizeof(*sa)) {
1218 print_pointer(fp, arg);
1222 sa = calloc(1, len);
1223 if (get_struct(pid, arg, sa, len) == -1) {
1225 print_pointer(fp, arg);
1229 switch (sa->sa_family) {
1231 if (len < sizeof(*lsin))
1232 goto sockaddr_short;
1233 lsin = (struct sockaddr_in *)(void *)sa;
1234 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1235 fprintf(fp, "{ AF_INET %s:%d }", addr,
1236 htons(lsin->sin_port));
1239 if (len < sizeof(*lsin6))
1240 goto sockaddr_short;
1241 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1242 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1244 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1245 htons(lsin6->sin6_port));
1248 sun = (struct sockaddr_un *)sa;
1249 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1250 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1256 "{ sa_len = %d, sa_family = %d, sa_data = {",
1257 (int)sa->sa_len, (int)sa->sa_family);
1258 for (q = (u_char *)sa->sa_data;
1259 q < (u_char *)sa + len; q++)
1260 fprintf(fp, "%s 0x%02x",
1261 q == (u_char *)sa->sa_data ? "" : ",",
1268 #define IOV_LIMIT 16
1271 print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
1273 struct iovec iov[IOV_LIMIT];
1274 size_t max_string = trussinfo->strsize;
1275 char tmp2[max_string + 1], *tmp3;
1277 pid_t pid = trussinfo->curthread->proc->pid;
1279 bool buf_truncated, iov_truncated;
1282 print_pointer(fp, arg);
1285 if (iovcnt > IOV_LIMIT) {
1287 iov_truncated = true;
1289 iov_truncated = false;
1291 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1292 print_pointer(fp, arg);
1297 for (i = 0; i < iovcnt; i++) {
1298 len = iov[i].iov_len;
1299 if (len > max_string) {
1301 buf_truncated = true;
1303 buf_truncated = false;
1305 fprintf(fp, "%s{", (i > 0) ? "," : "");
1306 if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
1307 tmp3 = malloc(len * 4 + 1);
1309 if (strvisx(tmp3, tmp2, len,
1310 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1314 buf_truncated = true;
1316 fprintf(fp, "\"%s\"%s", tmp3,
1317 buf_truncated ? "..." : "");
1320 print_pointer(fp, (uintptr_t)iov[i].iov_base);
1322 fprintf(fp, ",%zu}", iov[i].iov_len);
1324 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1328 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1333 for (q = CMSG_DATA(cmsghdr);
1334 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1335 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1341 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1343 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1344 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1345 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1346 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1350 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1352 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1354 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1357 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1358 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1360 fprintf(fp, "ctx=%u,", info->sinfo_context);
1361 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1364 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1365 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1367 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1371 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1373 fprintf(fp, "{sid=%u,", info->snd_sid);
1375 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1376 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1377 fprintf(fp, "ctx=%u,", info->snd_context);
1378 fprintf(fp, "id=%u}", info->snd_assoc_id);
1382 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1384 fprintf(fp, "{sid=%u,", info->rcv_sid);
1385 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1387 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1388 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1389 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1390 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1391 fprintf(fp, "ctx=%u,", info->rcv_context);
1392 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1396 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1398 fprintf(fp, "{sid=%u,", info->nxt_sid);
1400 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1401 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1402 fprintf(fp, "len=%u,", info->nxt_length);
1403 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1407 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1410 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1411 fprintf(fp, ",val=%u}", info->pr_value);
1415 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1417 fprintf(fp, "{num=%u}", info->auth_keynumber);
1421 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1423 char buf[INET_ADDRSTRLEN];
1426 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1428 fprintf(fp, "{addr=%s}", s);
1430 fputs("{addr=???}", fp);
1434 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1436 char buf[INET6_ADDRSTRLEN];
1439 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1441 fprintf(fp, "{addr=%s}", s);
1443 fputs("{addr=???}", fp);
1447 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1452 len = cmsghdr->cmsg_len;
1453 data = CMSG_DATA(cmsghdr);
1454 switch (cmsghdr->cmsg_type) {
1456 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1457 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1459 print_gen_cmsg(fp, cmsghdr);
1462 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1463 print_sctp_sndrcvinfo(fp, receive,
1464 (struct sctp_sndrcvinfo *)data);
1466 print_gen_cmsg(fp, cmsghdr);
1470 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1471 print_sctp_extrcvinfo(fp,
1472 (struct sctp_extrcvinfo *)data);
1474 print_gen_cmsg(fp, cmsghdr);
1478 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1479 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1481 print_gen_cmsg(fp, cmsghdr);
1484 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1485 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1487 print_gen_cmsg(fp, cmsghdr);
1490 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1491 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1493 print_gen_cmsg(fp, cmsghdr);
1496 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1497 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1499 print_gen_cmsg(fp, cmsghdr);
1502 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1503 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1505 print_gen_cmsg(fp, cmsghdr);
1507 case SCTP_DSTADDRV4:
1508 if (len == CMSG_LEN(sizeof(struct in_addr)))
1509 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1511 print_gen_cmsg(fp, cmsghdr);
1513 case SCTP_DSTADDRV6:
1514 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1515 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1517 print_gen_cmsg(fp, cmsghdr);
1520 print_gen_cmsg(fp, cmsghdr);
1525 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1527 struct cmsghdr *cmsghdr;
1534 len = msghdr->msg_controllen;
1539 cmsgbuf = calloc(1, len);
1540 if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
1541 print_pointer(fp, (uintptr_t)msghdr->msg_control);
1545 msghdr->msg_control = cmsgbuf;
1548 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1550 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1551 level = cmsghdr->cmsg_level;
1552 type = cmsghdr->cmsg_type;
1553 len = cmsghdr->cmsg_len;
1554 fprintf(fp, "%s{level=", first ? "" : ",");
1555 print_integer_arg(sysdecode_sockopt_level, fp, level);
1556 fputs(",type=", fp);
1557 temp = sysdecode_cmsg_type(level, type);
1561 fprintf(fp, "%d", type);
1563 fputs(",data=", fp);
1566 print_sctp_cmsg(fp, receive, cmsghdr);
1569 print_gen_cmsg(fp, cmsghdr);
1580 print_sysctl_oid(FILE *fp, int *oid, int len)
1584 for (i = 0; i < len; i++)
1585 fprintf(fp, ".%d", oid[i]);
1589 * Converts a syscall argument into a string. Said string is
1590 * allocated via malloc(), so needs to be free()'d. sc is
1591 * a pointer to the syscall description (see above); args is
1592 * an array of all of the system call arguments.
1595 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1596 struct trussinfo *trussinfo)
1603 fp = open_memstream(&tmp, &tmplen);
1604 pid = trussinfo->curthread->proc->pid;
1605 switch (sc->type & ARG_MASK) {
1607 fprintf(fp, "0x%x", (int)args[sc->offset]);
1610 fprintf(fp, "0%o", (int)args[sc->offset]);
1613 fprintf(fp, "%d", (int)args[sc->offset]);
1616 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1621 if (get_struct(pid, args[sc->offset], &val,
1623 fprintf(fp, "{ %u }", val);
1625 print_pointer(fp, args[sc->offset]);
1629 fprintf(fp, "0x%lx", args[sc->offset]);
1632 fprintf(fp, "%ld", args[sc->offset]);
1635 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1638 /* Handle special SHM_ANON value. */
1639 if ((char *)args[sc->offset] == SHM_ANON) {
1640 fprintf(fp, "SHM_ANON");
1645 /* NULL-terminated string. */
1648 tmp2 = get_string(pid, args[sc->offset], 0);
1649 fprintf(fp, "\"%s\"", tmp2);
1655 * Binary block of data that might have printable characters.
1656 * XXX If type|OUT, assume that the length is the syscall's
1657 * return value. Otherwise, assume that the length of the block
1658 * is in the next syscall argument.
1660 int max_string = trussinfo->strsize;
1661 char tmp2[max_string + 1], *tmp3;
1668 len = args[sc->offset + 1];
1671 * Don't print more than max_string characters, to avoid word
1672 * wrap. If we have to truncate put some ... after the string.
1674 if (len > max_string) {
1678 if (len && get_struct(pid, args[sc->offset], &tmp2, len)
1680 tmp3 = malloc(len * 4 + 1);
1682 if (strvisx(tmp3, tmp2, len,
1683 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1688 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1692 print_pointer(fp, args[sc->offset]);
1702 char buf[PAGE_SIZE];
1709 * Only parse argv[] and environment arrays from exec calls
1712 if (((sc->type & ARG_MASK) == ExecArgs &&
1713 (trussinfo->flags & EXECVEARGS) == 0) ||
1714 ((sc->type & ARG_MASK) == ExecEnv &&
1715 (trussinfo->flags & EXECVEENVS) == 0)) {
1716 print_pointer(fp, args[sc->offset]);
1721 * Read a page of pointers at a time. Punt if the top-level
1722 * pointer is not aligned. Note that the first read is of
1725 addr = args[sc->offset];
1726 if (addr % sizeof(char *) != 0) {
1727 print_pointer(fp, args[sc->offset]);
1731 len = PAGE_SIZE - (addr & PAGE_MASK);
1732 if (get_struct(pid, addr, u.buf, len) == -1) {
1733 print_pointer(fp, args[sc->offset]);
1740 while (u.strarray[i] != NULL) {
1741 string = get_string(pid, (uintptr_t)u.strarray[i], 0);
1742 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1747 if (i == len / sizeof(char *)) {
1750 if (get_struct(pid, addr, u.buf, len) ==
1752 fprintf(fp, ", <inval>");
1763 fprintf(fp, "%ld", args[sc->offset]);
1766 fprintf(fp, "0x%lx", args[sc->offset]);
1771 unsigned long long ll;
1773 #if _BYTE_ORDER == _LITTLE_ENDIAN
1774 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1777 ll = (unsigned long long)args[sc->offset] << 32 |
1778 args[sc->offset + 1];
1780 if ((sc->type & ARG_MASK) == Quad)
1781 fprintf(fp, "%lld", ll);
1783 fprintf(fp, "0x%llx", ll);
1790 if (get_struct(pid, args[sc->offset], &val,
1792 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1794 print_pointer(fp, args[sc->offset]);
1798 print_pointer(fp, args[sc->offset]);
1803 if (retval[0] == -1)
1805 tmp2 = get_string(pid, args[sc->offset], retval[0]);
1806 fprintf(fp, "\"%s\"", tmp2);
1814 cmd = args[sc->offset];
1815 temp = sysdecode_ioctlname(cmd);
1819 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1820 cmd, cmd & IOC_OUT ? "R" : "",
1821 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1822 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1823 cmd & 0xFF, IOCPARM_LEN(cmd));
1830 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
1831 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1834 print_pointer(fp, args[sc->offset]);
1838 struct timespec ts[2];
1842 if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
1845 for (i = 0; i < nitems(ts); i++) {
1848 switch (ts[i].tv_nsec) {
1850 fprintf(fp, "UTIME_NOW");
1853 fprintf(fp, "UTIME_OMIT");
1856 fprintf(fp, "%jd.%09ld",
1857 (intmax_t)ts[i].tv_sec,
1864 print_pointer(fp, args[sc->offset]);
1870 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1871 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1874 print_pointer(fp, args[sc->offset]);
1878 struct timeval tv[2];
1880 if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
1881 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1882 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1883 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1885 print_pointer(fp, args[sc->offset]);
1889 struct itimerval itv;
1891 if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
1892 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1893 (intmax_t)itv.it_interval.tv_sec,
1894 itv.it_interval.tv_usec,
1895 (intmax_t)itv.it_value.tv_sec,
1896 itv.it_value.tv_usec);
1898 print_pointer(fp, args[sc->offset]);
1903 struct linux_socketcall_args largs;
1905 if (get_struct(pid, args[sc->offset], (void *)&largs,
1906 sizeof(largs)) != -1)
1907 fprintf(fp, "{ %s, 0x%lx }",
1908 lookup(linux_socketcall_ops, largs.what, 10),
1909 (long unsigned int)largs.args);
1911 print_pointer(fp, args[sc->offset]);
1916 * XXX: A Pollfd argument expects the /next/ syscall argument
1917 * to be the number of fds in the array. This matches the poll
1921 int numfds = args[sc->offset + 1];
1922 size_t bytes = sizeof(struct pollfd) * numfds;
1925 if ((pfd = malloc(bytes)) == NULL)
1926 err(1, "Cannot malloc %zu bytes for pollfd array",
1928 if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
1930 for (i = 0; i < numfds; i++) {
1931 fprintf(fp, " %d/%s", pfd[i].fd,
1932 xlookup_bits(poll_flags, pfd[i].events));
1936 print_pointer(fp, args[sc->offset]);
1943 * XXX: A Fd_set argument expects the /first/ syscall argument
1944 * to be the number of fds in the array. This matches the
1948 int numfds = args[0];
1949 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1952 if ((fds = malloc(bytes)) == NULL)
1953 err(1, "Cannot malloc %zu bytes for fd_set array",
1955 if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
1957 for (i = 0; i < numfds; i++) {
1958 if (FD_ISSET(i, fds))
1959 fprintf(fp, " %d", i);
1963 print_pointer(fp, args[sc->offset]);
1968 fputs(strsig2(args[sc->offset]), fp);
1975 sig = args[sc->offset];
1976 if (get_struct(pid, args[sc->offset], (void *)&ss,
1977 sizeof(ss)) == -1) {
1978 print_pointer(fp, args[sc->offset]);
1983 for (i = 1; i < sys_nsig; i++) {
1984 if (sigismember(&ss, i)) {
1985 fprintf(fp, "%s%s", !first ? "|" : "",
1996 print_integer_arg(sysdecode_sigprocmask_how, fp,
2000 /* XXX: Output depends on the value of the previous argument. */
2001 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
2002 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
2003 args[sc->offset], 16);
2006 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2009 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2012 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2015 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2018 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2021 print_mask_arg(sysdecode_shmflags, fp, args[sc->offset]);
2024 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2027 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2030 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2033 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2036 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2039 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2042 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2047 if (args[sc->offset] == 0) {
2053 * Extract the address length from the next argument. If
2054 * this is an output sockaddr (OUT is set), then the
2055 * next argument is a pointer to a socklen_t. Otherwise
2056 * the next argument contains a socklen_t by value.
2058 if (sc->type & OUT) {
2059 if (get_struct(pid, args[sc->offset + 1], &len,
2060 sizeof(len)) == -1) {
2061 print_pointer(fp, args[sc->offset]);
2065 len = args[sc->offset + 1];
2067 print_sockaddr(fp, trussinfo, args[sc->offset], len);
2071 struct sigaction sa;
2073 if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
2075 if (sa.sa_handler == SIG_DFL)
2076 fputs("SIG_DFL", fp);
2077 else if (sa.sa_handler == SIG_IGN)
2078 fputs("SIG_IGN", fp);
2080 fprintf(fp, "%p", sa.sa_handler);
2081 fprintf(fp, " %s ss_t }",
2082 xlookup_bits(sigaction_flags, sa.sa_flags));
2084 print_pointer(fp, args[sc->offset]);
2089 * XXX XXX: The size of the array is determined by either the
2090 * next syscall argument, or by the syscall return value,
2091 * depending on which argument number we are. This matches the
2092 * kevent syscall, but luckily that's the only syscall that uses
2100 if (sc->offset == 1)
2101 numevents = args[sc->offset+1];
2102 else if (sc->offset == 3 && retval[0] != -1)
2103 numevents = retval[0];
2105 if (numevents >= 0) {
2106 bytes = sizeof(struct kevent) * numevents;
2107 if ((ke = malloc(bytes)) == NULL)
2109 "Cannot malloc %zu bytes for kevent array",
2113 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2116 for (i = 0; i < numevents; i++) {
2118 print_kevent(fp, &ke[i]);
2122 print_pointer(fp, args[sc->offset]);
2128 struct kevent_freebsd11 *ke11;
2134 if (sc->offset == 1)
2135 numevents = args[sc->offset+1];
2136 else if (sc->offset == 3 && retval[0] != -1)
2137 numevents = retval[0];
2139 if (numevents >= 0) {
2140 bytes = sizeof(struct kevent_freebsd11) * numevents;
2141 if ((ke11 = malloc(bytes)) == NULL)
2143 "Cannot malloc %zu bytes for kevent array",
2147 memset(&ke, 0, sizeof(ke));
2148 if (numevents >= 0 && get_struct(pid, args[sc->offset],
2149 ke11, bytes) != -1) {
2151 for (i = 0; i < numevents; i++) {
2153 ke.ident = ke11[i].ident;
2154 ke.filter = ke11[i].filter;
2155 ke.flags = ke11[i].flags;
2156 ke.fflags = ke11[i].fflags;
2157 ke.data = ke11[i].data;
2158 ke.udata = ke11[i].udata;
2159 print_kevent(fp, &ke);
2163 print_pointer(fp, args[sc->offset]);
2171 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2175 strmode(st.st_mode, mode);
2177 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2178 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2179 (long)st.st_blksize);
2181 print_pointer(fp, args[sc->offset]);
2186 struct freebsd11_stat st;
2188 if (get_struct(pid, args[sc->offset], &st, sizeof(st))
2192 strmode(st.st_mode, mode);
2194 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2195 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2196 (long)st.st_blksize);
2198 print_pointer(fp, args[sc->offset]);
2206 if (get_struct(pid, args[sc->offset], &buf,
2207 sizeof(buf)) != -1) {
2210 bzero(fsid, sizeof(fsid));
2211 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2212 for (i = 0; i < sizeof(buf.f_fsid); i++)
2213 snprintf(&fsid[i*2],
2214 sizeof(fsid) - (i*2), "%02x",
2215 ((u_char *)&buf.f_fsid)[i]);
2218 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2219 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2220 buf.f_mntfromname, fsid);
2222 print_pointer(fp, args[sc->offset]);
2229 if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
2232 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2233 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2234 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2235 ru.ru_inblock, ru.ru_oublock);
2237 print_pointer(fp, args[sc->offset]);
2243 if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
2245 fprintf(fp, "{ cur=%ju,max=%ju }",
2246 rl.rlim_cur, rl.rlim_max);
2248 print_pointer(fp, args[sc->offset]);
2254 if (get_struct(pid, args[sc->offset], &status,
2255 sizeof(status)) != -1) {
2257 if (WIFCONTINUED(status))
2258 fputs("CONTINUED", fp);
2259 else if (WIFEXITED(status))
2260 fprintf(fp, "EXITED,val=%d",
2261 WEXITSTATUS(status));
2262 else if (WIFSIGNALED(status))
2263 fprintf(fp, "SIGNALED,sig=%s%s",
2264 strsig2(WTERMSIG(status)),
2265 WCOREDUMP(status) ? ",cored" : "");
2267 fprintf(fp, "STOPPED,sig=%s",
2268 strsig2(WTERMSIG(status)));
2271 print_pointer(fp, args[sc->offset]);
2275 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2278 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2281 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2284 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2287 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2290 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2293 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2296 print_integer_arg(sysdecode_sysarch_number, fp,
2301 int oid[CTL_MAXNAME + 2], qoid[CTL_MAXNAME + 2];
2305 memset(name, 0, sizeof(name));
2306 len = args[sc->offset + 1];
2307 if (get_struct(pid, args[sc->offset], oid,
2308 len * sizeof(oid[0])) != -1) {
2310 if (oid[0] == CTL_SYSCTL) {
2311 fprintf(fp, "sysctl.");
2313 case CTL_SYSCTL_DEBUG:
2314 fprintf(fp, "debug");
2316 case CTL_SYSCTL_NAME:
2317 fprintf(fp, "name");
2318 print_sysctl_oid(fp, oid + 2, len - 2);
2320 case CTL_SYSCTL_NEXT:
2321 fprintf(fp, "next");
2323 case CTL_SYSCTL_NAME2OID:
2324 fprintf(fp, "name2oid");
2326 case CTL_SYSCTL_OIDFMT:
2327 fprintf(fp, "oidfmt");
2328 print_sysctl_oid(fp, oid + 2, len - 2);
2330 case CTL_SYSCTL_OIDDESCR:
2331 fprintf(fp, "oiddescr");
2332 print_sysctl_oid(fp, oid + 2, len - 2);
2334 case CTL_SYSCTL_OIDLABEL:
2335 fprintf(fp, "oidlabel");
2336 print_sysctl_oid(fp, oid + 2, len - 2);
2339 print_sysctl_oid(fp, oid + 1, len - 1);
2342 qoid[0] = CTL_SYSCTL;
2343 qoid[1] = CTL_SYSCTL_NAME;
2344 memcpy(qoid + 2, oid, len * sizeof(int));
2346 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
2347 print_sysctl_oid(fp, qoid + 2, len);
2349 fprintf(fp, "%s", name);
2357 * The pipe() system call in the kernel returns its
2358 * two file descriptors via return values. However,
2359 * the interface exposed by libc is that pipe()
2360 * accepts a pointer to an array of descriptors.
2361 * Format the output to match the libc API by printing
2362 * the returned file descriptors as a fake argument.
2364 * Overwrite the first retval to signal a successful
2367 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2374 len = args[sc->offset + 1];
2375 utrace_addr = calloc(1, len);
2376 if (get_struct(pid, args[sc->offset],
2377 (void *)utrace_addr, len) != -1)
2378 print_utrace(fp, utrace_addr, len);
2380 print_pointer(fp, args[sc->offset]);
2385 int descriptors[16];
2386 unsigned long i, ndescriptors;
2389 ndescriptors = args[sc->offset + 1];
2391 if (ndescriptors > nitems(descriptors)) {
2392 ndescriptors = nitems(descriptors);
2395 if (get_struct(pid, args[sc->offset],
2396 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2398 for (i = 0; i < ndescriptors; i++)
2399 fprintf(fp, i == 0 ? " %d" : ", %d",
2401 fprintf(fp, truncated ? ", ... }" : " }");
2403 print_pointer(fp, args[sc->offset]);
2407 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2409 case CapFcntlRights: {
2412 if (sc->type & OUT) {
2413 if (get_struct(pid, args[sc->offset], &rights,
2414 sizeof(rights)) == -1) {
2415 print_pointer(fp, args[sc->offset]);
2419 rights = args[sc->offset];
2420 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2424 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2429 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2430 fprintf(fp, "0x%x", rem);
2432 fprintf(fp, "|0x%x", rem);
2436 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2439 print_integer_arg(sysdecode_getfsstat_mode, fp,
2443 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2445 case Kldunloadflags:
2446 print_integer_arg(sysdecode_kldunload_flags, fp,
2450 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2453 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2455 case Sockprotocol: {
2457 int domain, protocol;
2459 domain = args[sc->offset - 2];
2460 protocol = args[sc->offset];
2461 if (protocol == 0) {
2464 temp = sysdecode_socket_protocol(domain, protocol);
2468 fprintf(fp, "%d", protocol);
2474 print_integer_arg(sysdecode_sockopt_level, fp,
2481 level = args[sc->offset - 1];
2482 name = args[sc->offset];
2483 temp = sysdecode_sockopt_name(level, name);
2487 fprintf(fp, "%d", name);
2492 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2495 cap_rights_t rights;
2497 if (get_struct(pid, args[sc->offset], &rights,
2498 sizeof(rights)) != -1) {
2500 sysdecode_cap_rights(fp, &rights);
2503 print_pointer(fp, args[sc->offset]);
2507 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2509 case Extattrnamespace:
2510 print_integer_arg(sysdecode_extattrnamespace, fp,
2514 print_integer_arg(sysdecode_minherit_inherit, fp,
2518 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2521 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2524 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2527 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2530 print_integer_arg(sysdecode_ptrace_request, fp,
2534 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2535 fprintf(fp, "%#x", (int)args[sc->offset]);
2538 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2541 print_integer_arg(sysdecode_rtprio_function, fp,
2545 print_integer_arg(sysdecode_scheduler_policy, fp,
2549 struct sched_param sp;
2551 if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
2552 fprintf(fp, "{ %d }", sp.sched_priority);
2554 print_pointer(fp, args[sc->offset]);
2560 if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
2561 fprintf(fp, "{ %s }", strsig2(sig));
2563 print_pointer(fp, args[sc->offset]);
2569 if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
2570 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2571 decode_siginfo(fp, &si);
2574 print_pointer(fp, args[sc->offset]);
2579 * Print argument as an array of struct iovec, where the next
2580 * syscall argument is the number of elements of the array.
2583 print_iovec(fp, trussinfo, args[sc->offset],
2584 (int)args[sc->offset + 1]);
2586 case Sctpsndrcvinfo: {
2587 struct sctp_sndrcvinfo info;
2589 if (get_struct(pid, args[sc->offset],
2590 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2591 print_pointer(fp, args[sc->offset]);
2594 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2598 struct msghdr msghdr;
2600 if (get_struct(pid, args[sc->offset],
2601 &msghdr, sizeof(struct msghdr)) == -1) {
2602 print_pointer(fp, args[sc->offset]);
2606 print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
2607 fprintf(fp, ",%d,", msghdr.msg_namelen);
2608 print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
2609 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2610 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2611 fprintf(fp, ",%u,", msghdr.msg_controllen);
2612 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2617 case CloudABIAdvice:
2618 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2620 case CloudABIClockID:
2621 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2623 case CloudABIFDSFlags:
2624 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2626 case CloudABIFDStat: {
2627 cloudabi_fdstat_t fds;
2628 if (get_struct(pid, args[sc->offset], &fds, sizeof(fds))
2630 fprintf(fp, "{ %s, ",
2631 xlookup(cloudabi_filetype, fds.fs_filetype));
2632 fprintf(fp, "%s, ... }",
2633 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2635 print_pointer(fp, args[sc->offset]);
2638 case CloudABIFileStat: {
2639 cloudabi_filestat_t fsb;
2640 if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb))
2642 fprintf(fp, "{ %s, %ju }",
2643 xlookup(cloudabi_filetype, fsb.st_filetype),
2644 (uintmax_t)fsb.st_size);
2646 print_pointer(fp, args[sc->offset]);
2649 case CloudABIFileType:
2650 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2652 case CloudABIFSFlags:
2653 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2655 case CloudABILookup:
2656 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2657 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2658 (int)args[sc->offset]);
2660 fprintf(fp, "%d", (int)args[sc->offset]);
2662 case CloudABIMFlags:
2663 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2666 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2668 case CloudABIMSFlags:
2669 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2671 case CloudABIOFlags:
2672 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2674 case CloudABISDFlags:
2675 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2677 case CloudABISignal:
2678 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2680 case CloudABITimestamp:
2681 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2682 args[sc->offset] % 1000000000);
2684 case CloudABIULFlags:
2685 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2687 case CloudABIWhence:
2688 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2692 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2699 * Print (to outfile) the system call and its arguments.
2702 print_syscall(struct trussinfo *trussinfo)
2704 struct threadinfo *t;
2709 t = trussinfo->curthread;
2711 name = t->cs.sc->name;
2712 nargs = t->cs.nargs;
2713 s_args = t->cs.s_args;
2715 len = print_line_prefix(trussinfo);
2716 len += fprintf(trussinfo->outfile, "%s(", name);
2718 for (i = 0; i < nargs; i++) {
2719 if (s_args[i] != NULL)
2720 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2722 len += fprintf(trussinfo->outfile,
2723 "<missing argument>");
2724 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2727 len += fprintf(trussinfo->outfile, ")");
2728 for (i = 0; i < 6 - (len / 8); i++)
2729 fprintf(trussinfo->outfile, "\t");
2733 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2735 struct timespec timediff;
2736 struct threadinfo *t;
2739 t = trussinfo->curthread;
2741 if (trussinfo->flags & COUNTONLY) {
2742 timespecsub(&t->after, &t->before, &timediff);
2743 timespecadd(&sc->time, &timediff, &sc->time);
2750 print_syscall(trussinfo);
2751 fflush(trussinfo->outfile);
2753 if (retval == NULL) {
2755 * This system call resulted in the current thread's exit,
2756 * so there is no return value or error to display.
2758 fprintf(trussinfo->outfile, "\n");
2762 if (error == ERESTART)
2763 fprintf(trussinfo->outfile, " ERESTART\n");
2764 else if (error == EJUSTRETURN)
2765 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2766 else if (error != 0) {
2767 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2768 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2772 else if (sc->ret_type == 2) {
2775 #if _BYTE_ORDER == _LITTLE_ENDIAN
2776 off = (off_t)retval[1] << 32 | retval[0];
2778 off = (off_t)retval[0] << 32 | retval[1];
2780 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2785 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2786 (intmax_t)retval[0], (intmax_t)retval[0]);
2790 print_summary(struct trussinfo *trussinfo)
2792 struct timespec total = {0, 0};
2796 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2797 "syscall", "seconds", "calls", "errors");
2799 STAILQ_FOREACH(sc, &syscalls, entries)
2801 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2802 sc->name, (intmax_t)sc->time.tv_sec,
2803 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2804 timespecadd(&total, &sc->time, &total);
2805 ncall += sc->ncalls;
2806 nerror += sc->nerror;
2808 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2809 "", "-------------", "-------", "-------");
2810 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2811 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);