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 = "fdatasync", .ret_type = 1, .nargs = 1,
237 .args = { { Int, 0 } } },
238 { .name = "flock", .ret_type = 1, .nargs = 2,
239 .args = { { Int, 0 }, { Flockop, 1 } } },
240 { .name = "fstat", .ret_type = 1, .nargs = 2,
241 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
242 { .name = "fstatat", .ret_type = 1, .nargs = 4,
243 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
245 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
246 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
247 { .name = "fsync", .ret_type = 1, .nargs = 1,
248 .args = { { Int, 0 } } },
249 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
250 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
251 { .name = "futimens", .ret_type = 1, .nargs = 2,
252 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
253 { .name = "futimes", .ret_type = 1, .nargs = 2,
254 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
255 { .name = "futimesat", .ret_type = 1, .nargs = 3,
256 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
257 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
258 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
259 { PQuadHex | OUT, 3 } } },
260 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
261 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
262 { .name = "getitimer", .ret_type = 1, .nargs = 2,
263 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
264 { .name = "getpeername", .ret_type = 1, .nargs = 3,
265 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
266 { .name = "getpgid", .ret_type = 1, .nargs = 1,
267 .args = { { Int, 0 } } },
268 { .name = "getpriority", .ret_type = 1, .nargs = 2,
269 .args = { { Priowhich, 0 }, { Int, 1 } } },
270 { .name = "getrandom", .ret_type = 1, .nargs = 3,
271 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
272 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
273 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
274 { .name = "getrusage", .ret_type = 1, .nargs = 2,
275 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
276 { .name = "getsid", .ret_type = 1, .nargs = 1,
277 .args = { { Int, 0 } } },
278 { .name = "getsockname", .ret_type = 1, .nargs = 3,
279 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
280 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
281 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
282 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
283 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
284 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
285 { .name = "ioctl", .ret_type = 1, .nargs = 3,
286 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
287 { .name = "kevent", .ret_type = 1, .nargs = 6,
288 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
289 { Int, 4 }, { Timespec, 5 } } },
290 { .name = "kill", .ret_type = 1, .nargs = 2,
291 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
292 { .name = "kldfind", .ret_type = 1, .nargs = 1,
293 .args = { { Name | IN, 0 } } },
294 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
295 .args = { { Int, 0 } } },
296 { .name = "kldload", .ret_type = 1, .nargs = 1,
297 .args = { { Name | IN, 0 } } },
298 { .name = "kldnext", .ret_type = 1, .nargs = 1,
299 .args = { { Int, 0 } } },
300 { .name = "kldstat", .ret_type = 1, .nargs = 2,
301 .args = { { Int, 0 }, { Ptr, 1 } } },
302 { .name = "kldsym", .ret_type = 1, .nargs = 3,
303 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
304 { .name = "kldunload", .ret_type = 1, .nargs = 1,
305 .args = { { Int, 0 } } },
306 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
307 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
308 { .name = "kse_release", .ret_type = 0, .nargs = 1,
309 .args = { { Timespec, 0 } } },
310 { .name = "lchflags", .ret_type = 1, .nargs = 2,
311 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
312 { .name = "lchmod", .ret_type = 1, .nargs = 2,
313 .args = { { Name, 0 }, { Octal, 1 } } },
314 { .name = "lchown", .ret_type = 1, .nargs = 3,
315 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
316 { .name = "link", .ret_type = 1, .nargs = 2,
317 .args = { { Name, 0 }, { Name, 1 } } },
318 { .name = "linkat", .ret_type = 1, .nargs = 5,
319 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
321 { .name = "listen", .ret_type = 1, .nargs = 2,
322 .args = { { Int, 0 }, { Int, 1 } } },
323 { .name = "lseek", .ret_type = 2, .nargs = 3,
324 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
325 { .name = "lstat", .ret_type = 1, .nargs = 2,
326 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
327 { .name = "lutimes", .ret_type = 1, .nargs = 2,
328 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
329 { .name = "madvise", .ret_type = 1, .nargs = 3,
330 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
331 { .name = "minherit", .ret_type = 1, .nargs = 3,
332 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
333 { .name = "mkdir", .ret_type = 1, .nargs = 2,
334 .args = { { Name, 0 }, { Octal, 1 } } },
335 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
336 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
337 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
338 .args = { { Name, 0 }, { Octal, 1 } } },
339 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
340 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
341 { .name = "mknod", .ret_type = 1, .nargs = 3,
342 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
343 { .name = "mknodat", .ret_type = 1, .nargs = 4,
344 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
345 { .name = "mlock", .ret_type = 1, .nargs = 2,
346 .args = { { Ptr, 0 }, { Sizet, 1 } } },
347 { .name = "mlockall", .ret_type = 1, .nargs = 1,
348 .args = { { Mlockall, 0 } } },
349 { .name = "mmap", .ret_type = 1, .nargs = 6,
350 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
351 { Int, 4 }, { QuadHex, 5 } } },
352 { .name = "modfind", .ret_type = 1, .nargs = 1,
353 .args = { { Name | IN, 0 } } },
354 { .name = "mount", .ret_type = 1, .nargs = 4,
355 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
356 { .name = "mprotect", .ret_type = 1, .nargs = 3,
357 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
358 { .name = "msync", .ret_type = 1, .nargs = 3,
359 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
360 { .name = "munlock", .ret_type = 1, .nargs = 2,
361 .args = { { Ptr, 0 }, { Sizet, 1 } } },
362 { .name = "munmap", .ret_type = 1, .nargs = 2,
363 .args = { { Ptr, 0 }, { Sizet, 1 } } },
364 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
365 .args = { { Timespec, 0 } } },
366 { .name = "nmount", .ret_type = 1, .nargs = 3,
367 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
368 { .name = "open", .ret_type = 1, .nargs = 3,
369 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
370 { .name = "openat", .ret_type = 1, .nargs = 4,
371 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
373 { .name = "pathconf", .ret_type = 1, .nargs = 2,
374 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
375 { .name = "pipe", .ret_type = 1, .nargs = 1,
376 .args = { { PipeFds | OUT, 0 } } },
377 { .name = "pipe2", .ret_type = 1, .nargs = 2,
378 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
379 { .name = "poll", .ret_type = 1, .nargs = 3,
380 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
381 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
382 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
384 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
385 .args = { { Open, 0 } } },
386 { .name = "pread", .ret_type = 1, .nargs = 4,
387 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
389 { .name = "procctl", .ret_type = 1, .nargs = 4,
390 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
391 { .name = "ptrace", .ret_type = 1, .nargs = 4,
392 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
393 { .name = "pwrite", .ret_type = 1, .nargs = 4,
394 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
396 { .name = "quotactl", .ret_type = 1, .nargs = 4,
397 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
398 { .name = "read", .ret_type = 1, .nargs = 3,
399 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
400 { .name = "readlink", .ret_type = 1, .nargs = 3,
401 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
402 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
403 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
405 { .name = "readv", .ret_type = 1, .nargs = 3,
406 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
407 { .name = "reboot", .ret_type = 1, .nargs = 1,
408 .args = { { Reboothowto, 0 } } },
409 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
410 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
411 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
412 { Ptr | OUT, 5 } } },
413 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
414 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
415 { .name = "rename", .ret_type = 1, .nargs = 2,
416 .args = { { Name, 0 }, { Name, 1 } } },
417 { .name = "renameat", .ret_type = 1, .nargs = 4,
418 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
419 { .name = "rfork", .ret_type = 1, .nargs = 1,
420 .args = { { Rforkflags, 0 } } },
421 { .name = "rmdir", .ret_type = 1, .nargs = 1,
422 .args = { { Name, 0 } } },
423 { .name = "rtprio", .ret_type = 1, .nargs = 3,
424 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
425 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
426 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
427 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
428 .args = { { Schedpolicy, 0 } } },
429 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
430 .args = { { Schedpolicy, 0 } } },
431 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
432 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
433 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
434 .args = { { Int, 0 } } },
435 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
436 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
437 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
438 .args = { { Int, 0 }, { Schedparam, 1 } } },
439 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
440 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
441 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
442 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
443 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
444 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
445 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
446 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
447 { Sockaddr | IN, 3 }, { Socklent, 4 },
448 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
449 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
450 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
451 { Sockaddr | IN, 3 }, { Socklent, 4 },
452 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
453 { .name = "select", .ret_type = 1, .nargs = 5,
454 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
456 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
457 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
458 { .name = "sendto", .ret_type = 1, .nargs = 6,
459 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
460 { Msgflags, 3 }, { Sockaddr | IN, 4 },
461 { Socklent | IN, 5 } } },
462 { .name = "setitimer", .ret_type = 1, .nargs = 3,
463 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
464 { .name = "setpriority", .ret_type = 1, .nargs = 3,
465 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
466 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
467 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
468 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
469 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
470 { Ptr | IN, 3 }, { Socklent, 4 } } },
471 { .name = "shm_open", .ret_type = 1, .nargs = 3,
472 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
473 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
474 .args = { { Name | IN, 0 } } },
475 { .name = "shutdown", .ret_type = 1, .nargs = 2,
476 .args = { { Int, 0 }, { Shutdown, 1 } } },
477 { .name = "sigaction", .ret_type = 1, .nargs = 3,
478 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
479 { Sigaction | OUT, 2 } } },
480 { .name = "sigpending", .ret_type = 1, .nargs = 1,
481 .args = { { Sigset | OUT, 0 } } },
482 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
483 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
484 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
485 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
486 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
487 .args = { { Ptr, 0 } } },
488 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
489 .args = { { Sigset | IN, 0 } } },
490 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
491 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
492 { Timespec | IN, 2 } } },
493 { .name = "sigwait", .ret_type = 1, .nargs = 2,
494 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
495 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
496 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
497 { .name = "socket", .ret_type = 1, .nargs = 3,
498 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
499 { .name = "stat", .ret_type = 1, .nargs = 2,
500 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
501 { .name = "statfs", .ret_type = 1, .nargs = 2,
502 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
503 { .name = "symlink", .ret_type = 1, .nargs = 2,
504 .args = { { Name, 0 }, { Name, 1 } } },
505 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
506 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
507 { .name = "sysarch", .ret_type = 1, .nargs = 2,
508 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
509 { .name = "__sysctl", .ret_type = 1, .nargs = 6,
510 .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
511 { Ptr, 4 }, { Sizet, 5 } } },
512 { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
513 .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
514 { Ptr, 4}, { Sizet, 5 } } },
515 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
516 .args = { { Long, 0 }, { Signal, 1 } } },
517 { .name = "thr_self", .ret_type = 1, .nargs = 1,
518 .args = { { Ptr, 0 } } },
519 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
520 .args = { { Long, 0 }, { Name, 1 } } },
521 { .name = "truncate", .ret_type = 1, .nargs = 2,
522 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
525 { .name = "umount", .ret_type = 1, .nargs = 2,
526 .args = { { Name, 0 }, { Int, 2 } } },
528 { .name = "unlink", .ret_type = 1, .nargs = 1,
529 .args = { { Name, 0 } } },
530 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
531 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
532 { .name = "unmount", .ret_type = 1, .nargs = 2,
533 .args = { { Name, 0 }, { Mountflags, 1 } } },
534 { .name = "utimensat", .ret_type = 1, .nargs = 4,
535 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
537 { .name = "utimes", .ret_type = 1, .nargs = 2,
538 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
539 { .name = "utrace", .ret_type = 1, .nargs = 1,
540 .args = { { Utrace, 0 } } },
541 { .name = "wait4", .ret_type = 1, .nargs = 4,
542 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
543 { Rusage | OUT, 3 } } },
544 { .name = "wait6", .ret_type = 1, .nargs = 6,
545 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
546 { Waitoptions, 3 }, { Rusage | OUT, 4 },
547 { Siginfo | OUT, 5 } } },
548 { .name = "write", .ret_type = 1, .nargs = 3,
549 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
550 { .name = "writev", .ret_type = 1, .nargs = 3,
551 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
554 { .name = "linux_access", .ret_type = 1, .nargs = 2,
555 .args = { { Name, 0 }, { Accessmode, 1 } } },
556 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
557 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
558 { ExecEnv | IN, 2 } } },
559 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
560 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
561 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
562 .args = { { Name | IN, 0 }, { Int, 1 } } },
563 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
564 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
565 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
566 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
567 { .name = "linux_open", .ret_type = 1, .nargs = 3,
568 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
569 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
570 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
571 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
572 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
573 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
574 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
576 /* CloudABI system calls. */
577 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
578 .args = { { CloudABIClockID, 0 } } },
579 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
580 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
581 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
582 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
583 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
584 .args = { { Int, 0 } } },
585 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
586 .args = { { CloudABIFileType, 0 } } },
587 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
588 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
589 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
590 .args = { { Int, 0 } } },
591 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
592 .args = { { Int, 0 } } },
593 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
594 .args = { { Int, 0 }, { Int, 1 } } },
595 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
596 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
597 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
598 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
599 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
600 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
601 { CloudABIFDSFlags, 2 } } },
602 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
603 .args = { { Int, 0 } } },
604 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
605 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
606 { CloudABIAdvice, 3 } } },
607 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
608 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
609 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
610 .args = { { Int, 0 }, { BinString | IN, 1 },
611 { CloudABIFileType, 3 } } },
612 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
613 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
614 { Int, 3 }, { BinString | IN, 4 } } },
615 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
616 .args = { { Int, 0 }, { BinString | IN, 1 },
617 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
618 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
619 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
621 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
622 .args = { { Int, 0 }, { BinString | IN, 1 },
623 { BinString | OUT, 3 }, { Int, 4 } } },
624 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
625 .args = { { Int, 0 }, { BinString | IN, 1 },
626 { Int, 3 }, { BinString | IN, 4 } } },
627 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
628 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
629 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
630 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
631 { CloudABIFSFlags, 2 } } },
632 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
633 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
634 { CloudABIFileStat | OUT, 3 } } },
635 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
636 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
637 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
638 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
639 .args = { { BinString | IN, 0 },
640 { Int, 2 }, { BinString | IN, 3 } } },
641 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
642 .args = { { Int, 0 }, { BinString | IN, 1 },
643 { CloudABIULFlags, 3 } } },
644 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
645 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
646 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
647 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
648 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
649 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
650 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
651 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
652 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
653 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
654 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
655 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
656 .args = { { Ptr, 0 }, { Int, 1 } } },
657 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
658 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
659 { IntArray, 3 }, { Int, 4 } } },
660 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
661 .args = { { Int, 0 } } },
662 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
663 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
664 .args = { { CloudABISignal, 0 } } },
665 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
666 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
667 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
668 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
669 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
670 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
671 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
675 static STAILQ_HEAD(, syscall) syscalls;
677 /* Xlat idea taken from strace */
683 #define X(a) { a, #a },
684 #define XEND { 0, NULL }
686 static struct xlat poll_flags[] = {
687 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
688 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
689 X(POLLWRBAND) X(POLLINIGNEOF) XEND
692 static struct xlat sigaction_flags[] = {
693 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
694 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
697 static struct xlat linux_socketcall_ops[] = {
698 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
699 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
700 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
701 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
702 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
707 #define X(a) { CLOUDABI_##a, #a },
709 static struct xlat cloudabi_advice[] = {
710 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
711 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
715 static struct xlat cloudabi_clockid[] = {
716 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
717 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
721 static struct xlat cloudabi_fdflags[] = {
722 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
723 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
727 static struct xlat cloudabi_fdsflags[] = {
728 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
732 static struct xlat cloudabi_filetype[] = {
733 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
734 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
735 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
736 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
737 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
741 static struct xlat cloudabi_fsflags[] = {
742 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
743 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
747 static struct xlat cloudabi_mflags[] = {
748 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
752 static struct xlat cloudabi_mprot[] = {
753 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
757 static struct xlat cloudabi_msflags[] = {
758 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
762 static struct xlat cloudabi_oflags[] = {
763 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
767 static struct xlat cloudabi_sdflags[] = {
768 X(SHUT_RD) X(SHUT_WR)
772 static struct xlat cloudabi_signal[] = {
773 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
774 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
775 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
776 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
777 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
781 static struct xlat cloudabi_ulflags[] = {
786 static struct xlat cloudabi_whence[] = {
787 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
795 * Searches an xlat array for a value, and returns it if found. Otherwise
796 * return a string representation.
799 lookup(struct xlat *xlat, int val, int base)
803 for (; xlat->str != NULL; xlat++)
804 if (xlat->val == val)
808 sprintf(tmp, "0%o", val);
811 sprintf(tmp, "0x%x", val);
814 sprintf(tmp, "%u", val);
817 errx(1,"Unknown lookup base");
824 xlookup(struct xlat *xlat, int val)
827 return (lookup(xlat, val, 16));
831 * Searches an xlat array containing bitfield values. Remaining bits
832 * set after removing the known ones are printed at the end:
836 xlookup_bits(struct xlat *xlat, int val)
839 static char str[512];
843 for (; xlat->str != NULL; xlat++) {
844 if ((xlat->val & rem) == xlat->val) {
846 * Don't print the "all-bits-zero" string unless all
847 * bits are really zero.
849 if (xlat->val == 0 && val != 0)
851 len += sprintf(str + len, "%s|", xlat->str);
857 * If we have leftover bits or didn't match anything, print
861 len += sprintf(str + len, "0x%x", rem);
862 if (len && str[len - 1] == '|')
869 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
873 str = decoder(value);
877 fprintf(fp, "%d", value);
881 print_mask_arg_part(bool (*decoder)(FILE *, int, int *), FILE *fp, int value,
885 return (decoder(fp, value, rem));
889 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
893 if (!print_mask_arg_part(decoder, fp, value, &rem))
894 fprintf(fp, "0x%x", rem);
896 fprintf(fp, "|0x%x", rem);
900 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
905 if (!decoder(fp, value, &rem))
906 fprintf(fp, "0x%x", rem);
908 fprintf(fp, "|0x%x", rem);
913 * Add argument padding to subsequent system calls afater a Quad
914 * syscall arguments as needed. This used to be done by hand in the
915 * decoded_syscalls table which was ugly and error prone. It is
916 * simpler to do the fixup of offsets at initalization time than when
917 * decoding arguments.
920 quad_fixup(struct syscall *sc)
927 for (i = 0; i < sc->nargs; i++) {
928 /* This arg type is a dummy that doesn't use offset. */
929 if ((sc->args[i].type & ARG_MASK) == PipeFds)
932 assert(prev < sc->args[i].offset);
933 prev = sc->args[i].offset;
934 sc->args[i].offset += offset;
935 switch (sc->args[i].type & ARG_MASK) {
940 * 64-bit arguments on 32-bit powerpc must be
941 * 64-bit aligned. If the current offset is
942 * not aligned, the calling convention inserts
943 * a 32-bit pad argument that should be skipped.
945 if (sc->args[i].offset % 2 == 1) {
946 sc->args[i].offset++;
963 STAILQ_INIT(&syscalls);
964 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
968 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
972 static struct syscall *
973 find_syscall(struct procabi *abi, u_int number)
975 struct extra_syscall *es;
977 if (number < nitems(abi->syscalls))
978 return (abi->syscalls[number]);
979 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
980 if (es->number == number)
987 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
989 struct extra_syscall *es;
991 if (number < nitems(abi->syscalls)) {
992 assert(abi->syscalls[number] == NULL);
993 abi->syscalls[number] = sc;
995 es = malloc(sizeof(*es));
998 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
1003 * If/when the list gets big, it might be desirable to do it
1004 * as a hash table or binary search.
1007 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1014 sc = find_syscall(t->proc->abi, number);
1018 name = sysdecode_syscallname(t->proc->abi->abi, number);
1020 asprintf(&new_name, "#%d", number);
1024 STAILQ_FOREACH(sc, &syscalls, entries) {
1025 if (strcmp(name, sc->name) == 0) {
1026 add_syscall(t->proc->abi, number, sc);
1032 /* It is unknown. Add it into the list. */
1034 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1038 sc = calloc(1, sizeof(struct syscall));
1040 if (new_name != NULL)
1044 for (i = 0; i < nargs; i++) {
1045 sc->args[i].offset = i;
1046 /* Treat all unknown arguments as LongHex. */
1047 sc->args[i].type = LongHex;
1049 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1050 add_syscall(t->proc->abi, number, sc);
1056 * Copy a fixed amount of bytes from the process.
1059 get_struct(pid_t pid, void *offset, void *buf, int len)
1061 struct ptrace_io_desc iorequest;
1063 iorequest.piod_op = PIOD_READ_D;
1064 iorequest.piod_offs = offset;
1065 iorequest.piod_addr = buf;
1066 iorequest.piod_len = len;
1067 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1072 #define MAXSIZE 4096
1075 * Copy a string from the process. Note that it is
1076 * expected to be a C string, but if max is set, it will
1077 * only get that much.
1080 get_string(pid_t pid, void *addr, int max)
1082 struct ptrace_io_desc iorequest;
1084 size_t offset, size, totalsize;
1090 /* Read up to the end of the current page. */
1091 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1096 buf = malloc(totalsize);
1100 iorequest.piod_op = PIOD_READ_D;
1101 iorequest.piod_offs = (char *)addr + offset;
1102 iorequest.piod_addr = buf + offset;
1103 iorequest.piod_len = size;
1104 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1108 if (memchr(buf + offset, '\0', size) != NULL)
1111 if (totalsize < MAXSIZE && max == 0) {
1112 size = MAXSIZE - totalsize;
1113 if (size > PAGE_SIZE)
1115 nbuf = realloc(buf, totalsize + size);
1117 buf[totalsize - 1] = '\0';
1123 buf[totalsize - 1] = '\0';
1132 static char tmp[32];
1133 const char *signame;
1135 signame = sysdecode_signal(sig);
1136 if (signame == NULL) {
1137 snprintf(tmp, sizeof(tmp), "%d", sig);
1144 print_kevent(FILE *fp, struct kevent *ke)
1147 switch (ke->filter) {
1153 case EVFILT_PROCDESC:
1155 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1158 fputs(strsig2(ke->ident), fp);
1161 fprintf(fp, "%p", (void *)ke->ident);
1164 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1166 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1168 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1169 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1173 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1175 unsigned char *utrace_buffer;
1178 if (sysdecode_utrace(fp, utrace_addr, len)) {
1183 utrace_buffer = utrace_addr;
1184 fprintf(fp, "%zu:", len);
1186 fprintf(fp, " %02x", *utrace_buffer++);
1191 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1194 struct sockaddr_in *lsin;
1195 struct sockaddr_in6 *lsin6;
1196 struct sockaddr_un *sun;
1197 struct sockaddr *sa;
1199 pid_t pid = trussinfo->curthread->proc->pid;
1205 /* If the length is too small, just bail. */
1206 if (len < sizeof(*sa)) {
1207 fprintf(fp, "%p", arg);
1211 sa = calloc(1, len);
1212 if (get_struct(pid, arg, sa, len) == -1) {
1214 fprintf(fp, "%p", arg);
1218 switch (sa->sa_family) {
1220 if (len < sizeof(*lsin))
1221 goto sockaddr_short;
1222 lsin = (struct sockaddr_in *)(void *)sa;
1223 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1224 fprintf(fp, "{ AF_INET %s:%d }", addr,
1225 htons(lsin->sin_port));
1228 if (len < sizeof(*lsin6))
1229 goto sockaddr_short;
1230 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1231 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1233 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1234 htons(lsin6->sin6_port));
1237 sun = (struct sockaddr_un *)sa;
1238 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1239 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1245 "{ sa_len = %d, sa_family = %d, sa_data = {",
1246 (int)sa->sa_len, (int)sa->sa_family);
1247 for (q = (u_char *)sa->sa_data;
1248 q < (u_char *)sa + len; q++)
1249 fprintf(fp, "%s 0x%02x",
1250 q == (u_char *)sa->sa_data ? "" : ",",
1257 #define IOV_LIMIT 16
1260 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1262 struct iovec iov[IOV_LIMIT];
1263 size_t max_string = trussinfo->strsize;
1264 char tmp2[max_string + 1], *tmp3;
1266 pid_t pid = trussinfo->curthread->proc->pid;
1268 bool buf_truncated, iov_truncated;
1271 fprintf(fp, "%p", arg);
1274 if (iovcnt > IOV_LIMIT) {
1276 iov_truncated = true;
1278 iov_truncated = false;
1280 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1281 fprintf(fp, "%p", arg);
1286 for (i = 0; i < iovcnt; i++) {
1287 len = iov[i].iov_len;
1288 if (len > max_string) {
1290 buf_truncated = true;
1292 buf_truncated = false;
1294 fprintf(fp, "%s{", (i > 0) ? "," : "");
1295 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1296 tmp3 = malloc(len * 4 + 1);
1298 if (strvisx(tmp3, tmp2, len,
1299 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1303 buf_truncated = true;
1305 fprintf(fp, "\"%s\"%s", tmp3,
1306 buf_truncated ? "..." : "");
1309 fprintf(fp, "%p", iov[i].iov_base);
1311 fprintf(fp, ",%zu}", iov[i].iov_len);
1313 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1317 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1322 for (q = CMSG_DATA(cmsghdr);
1323 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1324 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1330 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1332 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1333 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1334 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1335 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1339 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1341 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1343 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1346 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1347 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1349 fprintf(fp, "ctx=%u,", info->sinfo_context);
1350 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1353 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1354 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1356 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1360 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1362 fprintf(fp, "{sid=%u,", info->snd_sid);
1364 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1365 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1366 fprintf(fp, "ctx=%u,", info->snd_context);
1367 fprintf(fp, "id=%u}", info->snd_assoc_id);
1371 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1373 fprintf(fp, "{sid=%u,", info->rcv_sid);
1374 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1376 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1377 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1378 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1379 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1380 fprintf(fp, "ctx=%u,", info->rcv_context);
1381 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1385 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1387 fprintf(fp, "{sid=%u,", info->nxt_sid);
1389 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1390 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1391 fprintf(fp, "len=%u,", info->nxt_length);
1392 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1396 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1399 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1400 fprintf(fp, ",val=%u}", info->pr_value);
1404 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1406 fprintf(fp, "{num=%u}", info->auth_keynumber);
1410 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1412 char buf[INET_ADDRSTRLEN];
1415 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1417 fprintf(fp, "{addr=%s}", s);
1419 fputs("{addr=???}", fp);
1423 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1425 char buf[INET6_ADDRSTRLEN];
1428 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1430 fprintf(fp, "{addr=%s}", s);
1432 fputs("{addr=???}", fp);
1436 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1441 len = cmsghdr->cmsg_len;
1442 data = CMSG_DATA(cmsghdr);
1443 switch (cmsghdr->cmsg_type) {
1445 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1446 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1448 print_gen_cmsg(fp, cmsghdr);
1451 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1452 print_sctp_sndrcvinfo(fp, receive,
1453 (struct sctp_sndrcvinfo *)data);
1455 print_gen_cmsg(fp, cmsghdr);
1459 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1460 print_sctp_extrcvinfo(fp,
1461 (struct sctp_extrcvinfo *)data);
1463 print_gen_cmsg(fp, cmsghdr);
1467 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1468 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1470 print_gen_cmsg(fp, cmsghdr);
1473 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1474 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1476 print_gen_cmsg(fp, cmsghdr);
1479 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1480 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1482 print_gen_cmsg(fp, cmsghdr);
1485 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1486 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1488 print_gen_cmsg(fp, cmsghdr);
1491 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1492 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1494 print_gen_cmsg(fp, cmsghdr);
1496 case SCTP_DSTADDRV4:
1497 if (len == CMSG_LEN(sizeof(struct in_addr)))
1498 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1500 print_gen_cmsg(fp, cmsghdr);
1502 case SCTP_DSTADDRV6:
1503 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1504 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1506 print_gen_cmsg(fp, cmsghdr);
1509 print_gen_cmsg(fp, cmsghdr);
1514 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1516 struct cmsghdr *cmsghdr;
1523 len = msghdr->msg_controllen;
1528 cmsgbuf = calloc(1, len);
1529 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1530 fprintf(fp, "%p", msghdr->msg_control);
1534 msghdr->msg_control = cmsgbuf;
1537 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1539 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1540 level = cmsghdr->cmsg_level;
1541 type = cmsghdr->cmsg_type;
1542 len = cmsghdr->cmsg_len;
1543 fprintf(fp, "%s{level=", first ? "" : ",");
1544 print_integer_arg(sysdecode_sockopt_level, fp, level);
1545 fputs(",type=", fp);
1546 temp = sysdecode_cmsg_type(level, type);
1550 fprintf(fp, "%d", type);
1552 fputs(",data=", fp);
1555 print_sctp_cmsg(fp, receive, cmsghdr);
1558 print_gen_cmsg(fp, cmsghdr);
1569 print_sysctl_oid(FILE *fp, int *oid, size_t len)
1576 for (i = 0; i < len; i++) {
1577 fprintf(fp, "%s%d", first ? "" : ".", oid[i]);
1584 print_sysctl(FILE *fp, int *oid, size_t len)
1587 int qoid[CTL_MAXNAME + 2];
1590 qoid[0] = CTL_SYSCTL;
1591 qoid[1] = CTL_SYSCTL_NAME;
1592 memcpy(qoid + 2, oid, len * sizeof(int));
1594 if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
1595 print_sysctl_oid(fp, oid, len);
1597 fprintf(fp, "%s", name);
1601 * Converts a syscall argument into a string. Said string is
1602 * allocated via malloc(), so needs to be free()'d. sc is
1603 * a pointer to the syscall description (see above); args is
1604 * an array of all of the system call arguments.
1607 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1608 struct trussinfo *trussinfo)
1615 fp = open_memstream(&tmp, &tmplen);
1616 pid = trussinfo->curthread->proc->pid;
1617 switch (sc->type & ARG_MASK) {
1619 fprintf(fp, "0x%x", (int)args[sc->offset]);
1622 fprintf(fp, "0%o", (int)args[sc->offset]);
1625 fprintf(fp, "%d", (int)args[sc->offset]);
1628 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1633 if (get_struct(pid, (void *)args[sc->offset], &val,
1635 fprintf(fp, "{ %u }", val);
1637 fprintf(fp, "0x%lx", args[sc->offset]);
1641 fprintf(fp, "0x%lx", args[sc->offset]);
1644 fprintf(fp, "%ld", args[sc->offset]);
1647 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1650 /* NULL-terminated string. */
1653 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1654 fprintf(fp, "\"%s\"", tmp2);
1660 * Binary block of data that might have printable characters.
1661 * XXX If type|OUT, assume that the length is the syscall's
1662 * return value. Otherwise, assume that the length of the block
1663 * is in the next syscall argument.
1665 int max_string = trussinfo->strsize;
1666 char tmp2[max_string + 1], *tmp3;
1673 len = args[sc->offset + 1];
1676 * Don't print more than max_string characters, to avoid word
1677 * wrap. If we have to truncate put some ... after the string.
1679 if (len > max_string) {
1683 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1685 tmp3 = malloc(len * 4 + 1);
1687 if (strvisx(tmp3, tmp2, len,
1688 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1693 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1697 fprintf(fp, "0x%lx", args[sc->offset]);
1707 char buf[PAGE_SIZE];
1714 * Only parse argv[] and environment arrays from exec calls
1717 if (((sc->type & ARG_MASK) == ExecArgs &&
1718 (trussinfo->flags & EXECVEARGS) == 0) ||
1719 ((sc->type & ARG_MASK) == ExecEnv &&
1720 (trussinfo->flags & EXECVEENVS) == 0)) {
1721 fprintf(fp, "0x%lx", args[sc->offset]);
1726 * Read a page of pointers at a time. Punt if the top-level
1727 * pointer is not aligned. Note that the first read is of
1730 addr = args[sc->offset];
1731 if (addr % sizeof(char *) != 0) {
1732 fprintf(fp, "0x%lx", args[sc->offset]);
1736 len = PAGE_SIZE - (addr & PAGE_MASK);
1737 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1738 fprintf(fp, "0x%lx", args[sc->offset]);
1745 while (u.strarray[i] != NULL) {
1746 string = get_string(pid, u.strarray[i], 0);
1747 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1752 if (i == len / sizeof(char *)) {
1755 if (get_struct(pid, (void *)addr, u.buf, len) ==
1757 fprintf(fp, ", <inval>");
1768 fprintf(fp, "%ld", args[sc->offset]);
1771 fprintf(fp, "0x%lx", args[sc->offset]);
1776 unsigned long long ll;
1778 #if _BYTE_ORDER == _LITTLE_ENDIAN
1779 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1782 ll = (unsigned long long)args[sc->offset] << 32 |
1783 args[sc->offset + 1];
1785 if ((sc->type & ARG_MASK) == Quad)
1786 fprintf(fp, "%lld", ll);
1788 fprintf(fp, "0x%llx", ll);
1795 if (get_struct(pid, (void *)args[sc->offset], &val,
1797 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1799 fprintf(fp, "0x%lx", args[sc->offset]);
1803 fprintf(fp, "0x%lx", args[sc->offset]);
1808 if (retval[0] == -1)
1810 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1811 fprintf(fp, "\"%s\"", tmp2);
1819 cmd = args[sc->offset];
1820 temp = sysdecode_ioctlname(cmd);
1824 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1825 cmd, cmd & IOC_OUT ? "R" : "",
1826 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1827 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1828 cmd & 0xFF, IOCPARM_LEN(cmd));
1835 if (get_struct(pid, (void *)args[sc->offset], &ts,
1837 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1840 fprintf(fp, "0x%lx", args[sc->offset]);
1844 struct timespec ts[2];
1848 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1852 for (i = 0; i < nitems(ts); i++) {
1855 switch (ts[i].tv_nsec) {
1857 fprintf(fp, "UTIME_NOW");
1860 fprintf(fp, "UTIME_OMIT");
1863 fprintf(fp, "%jd.%09ld",
1864 (intmax_t)ts[i].tv_sec,
1871 fprintf(fp, "0x%lx", args[sc->offset]);
1877 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1879 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1882 fprintf(fp, "0x%lx", args[sc->offset]);
1886 struct timeval tv[2];
1888 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1890 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1891 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1892 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1894 fprintf(fp, "0x%lx", args[sc->offset]);
1898 struct itimerval itv;
1900 if (get_struct(pid, (void *)args[sc->offset], &itv,
1902 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1903 (intmax_t)itv.it_interval.tv_sec,
1904 itv.it_interval.tv_usec,
1905 (intmax_t)itv.it_value.tv_sec,
1906 itv.it_value.tv_usec);
1908 fprintf(fp, "0x%lx", args[sc->offset]);
1913 struct linux_socketcall_args largs;
1915 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1916 sizeof(largs)) != -1)
1917 fprintf(fp, "{ %s, 0x%lx }",
1918 lookup(linux_socketcall_ops, largs.what, 10),
1919 (long unsigned int)largs.args);
1921 fprintf(fp, "0x%lx", args[sc->offset]);
1926 * XXX: A Pollfd argument expects the /next/ syscall argument
1927 * to be the number of fds in the array. This matches the poll
1931 int numfds = args[sc->offset + 1];
1932 size_t bytes = sizeof(struct pollfd) * numfds;
1935 if ((pfd = malloc(bytes)) == NULL)
1936 err(1, "Cannot malloc %zu bytes for pollfd array",
1938 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1941 for (i = 0; i < numfds; i++) {
1942 fprintf(fp, " %d/%s", pfd[i].fd,
1943 xlookup_bits(poll_flags, pfd[i].events));
1947 fprintf(fp, "0x%lx", args[sc->offset]);
1954 * XXX: A Fd_set argument expects the /first/ syscall argument
1955 * to be the number of fds in the array. This matches the
1959 int numfds = args[0];
1960 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1963 if ((fds = malloc(bytes)) == NULL)
1964 err(1, "Cannot malloc %zu bytes for fd_set array",
1966 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1969 for (i = 0; i < numfds; i++) {
1970 if (FD_ISSET(i, fds))
1971 fprintf(fp, " %d", i);
1975 fprintf(fp, "0x%lx", args[sc->offset]);
1980 fputs(strsig2(args[sc->offset]), fp);
1987 sig = args[sc->offset];
1988 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1989 sizeof(ss)) == -1) {
1990 fprintf(fp, "0x%lx", args[sc->offset]);
1995 for (i = 1; i < sys_nsig; i++) {
1996 if (sigismember(&ss, i)) {
1997 fprintf(fp, "%s%s", !first ? "|" : "",
2008 print_integer_arg(sysdecode_sigprocmask_how, fp,
2012 /* XXX: Output depends on the value of the previous argument. */
2013 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
2014 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
2015 args[sc->offset], 16);
2018 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
2021 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
2024 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
2027 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
2030 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
2033 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
2036 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2039 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2042 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2045 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2048 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2051 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2056 if (args[sc->offset] == 0) {
2062 * Extract the address length from the next argument. If
2063 * this is an output sockaddr (OUT is set), then the
2064 * next argument is a pointer to a socklen_t. Otherwise
2065 * the next argument contains a socklen_t by value.
2067 if (sc->type & OUT) {
2068 if (get_struct(pid, (void *)args[sc->offset + 1],
2069 &len, sizeof(len)) == -1) {
2070 fprintf(fp, "0x%lx", args[sc->offset]);
2074 len = args[sc->offset + 1];
2076 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2080 struct sigaction sa;
2082 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2085 if (sa.sa_handler == SIG_DFL)
2086 fputs("SIG_DFL", fp);
2087 else if (sa.sa_handler == SIG_IGN)
2088 fputs("SIG_IGN", fp);
2090 fprintf(fp, "%p", sa.sa_handler);
2091 fprintf(fp, " %s ss_t }",
2092 xlookup_bits(sigaction_flags, sa.sa_flags));
2094 fprintf(fp, "0x%lx", args[sc->offset]);
2099 * XXX XXX: The size of the array is determined by either the
2100 * next syscall argument, or by the syscall return value,
2101 * depending on which argument number we are. This matches the
2102 * kevent syscall, but luckily that's the only syscall that uses
2110 if (sc->offset == 1)
2111 numevents = args[sc->offset+1];
2112 else if (sc->offset == 3 && retval[0] != -1)
2113 numevents = retval[0];
2115 if (numevents >= 0) {
2116 bytes = sizeof(struct kevent) * numevents;
2117 if ((ke = malloc(bytes)) == NULL)
2119 "Cannot malloc %zu bytes for kevent array",
2123 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2126 for (i = 0; i < numevents; i++) {
2128 print_kevent(fp, &ke[i]);
2132 fprintf(fp, "0x%lx", args[sc->offset]);
2138 struct kevent_freebsd11 *ke11;
2144 if (sc->offset == 1)
2145 numevents = args[sc->offset+1];
2146 else if (sc->offset == 3 && retval[0] != -1)
2147 numevents = retval[0];
2149 if (numevents >= 0) {
2150 bytes = sizeof(struct kevent_freebsd11) * numevents;
2151 if ((ke11 = malloc(bytes)) == NULL)
2153 "Cannot malloc %zu bytes for kevent array",
2157 memset(&ke, 0, sizeof(ke));
2158 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2159 ke11, bytes) != -1) {
2161 for (i = 0; i < numevents; i++) {
2163 ke.ident = ke11[i].ident;
2164 ke.filter = ke11[i].filter;
2165 ke.flags = ke11[i].flags;
2166 ke.fflags = ke11[i].fflags;
2167 ke.data = ke11[i].data;
2168 ke.udata = ke11[i].udata;
2169 print_kevent(fp, &ke);
2173 fprintf(fp, "0x%lx", args[sc->offset]);
2181 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2185 strmode(st.st_mode, mode);
2187 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2188 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2189 (long)st.st_blksize);
2191 fprintf(fp, "0x%lx", args[sc->offset]);
2196 struct freebsd11_stat st;
2198 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2202 strmode(st.st_mode, mode);
2204 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2205 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2206 (long)st.st_blksize);
2208 fprintf(fp, "0x%lx", args[sc->offset]);
2216 if (get_struct(pid, (void *)args[sc->offset], &buf,
2217 sizeof(buf)) != -1) {
2220 bzero(fsid, sizeof(fsid));
2221 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2222 for (i = 0; i < sizeof(buf.f_fsid); i++)
2223 snprintf(&fsid[i*2],
2224 sizeof(fsid) - (i*2), "%02x",
2225 ((u_char *)&buf.f_fsid)[i]);
2228 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2229 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2230 buf.f_mntfromname, fsid);
2232 fprintf(fp, "0x%lx", args[sc->offset]);
2239 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2242 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2243 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2244 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2245 ru.ru_inblock, ru.ru_oublock);
2247 fprintf(fp, "0x%lx", args[sc->offset]);
2253 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2255 fprintf(fp, "{ cur=%ju,max=%ju }",
2256 rl.rlim_cur, rl.rlim_max);
2258 fprintf(fp, "0x%lx", args[sc->offset]);
2264 if (get_struct(pid, (void *)args[sc->offset], &status,
2265 sizeof(status)) != -1) {
2267 if (WIFCONTINUED(status))
2268 fputs("CONTINUED", fp);
2269 else if (WIFEXITED(status))
2270 fprintf(fp, "EXITED,val=%d",
2271 WEXITSTATUS(status));
2272 else if (WIFSIGNALED(status))
2273 fprintf(fp, "SIGNALED,sig=%s%s",
2274 strsig2(WTERMSIG(status)),
2275 WCOREDUMP(status) ? ",cored" : "");
2277 fprintf(fp, "STOPPED,sig=%s",
2278 strsig2(WTERMSIG(status)));
2281 fprintf(fp, "0x%lx", args[sc->offset]);
2285 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2288 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2291 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2296 if (print_mask_arg_part(sysdecode_umtx_op_flags, fp,
2297 args[sc->offset], &rem))
2299 print_integer_arg(sysdecode_umtx_op, fp, rem);
2303 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2306 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2309 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2312 print_integer_arg(sysdecode_sysarch_number, fp,
2317 int oid[CTL_MAXNAME + 2];
2320 memset(name, 0, sizeof(name));
2321 len = args[sc->offset + 1];
2322 if (get_struct(pid, (void *)args[sc->offset], oid,
2323 len * sizeof(oid[0])) != -1) {
2325 if (oid[0] == CTL_SYSCTL) {
2326 fprintf(fp, "sysctl.");
2328 case CTL_SYSCTL_DEBUG:
2329 fprintf(fp, "debug");
2331 case CTL_SYSCTL_NAME:
2332 fprintf(fp, "name ");
2333 print_sysctl_oid(fp, oid + 2, len - 2);
2335 case CTL_SYSCTL_NEXT:
2336 fprintf(fp, "next");
2338 case CTL_SYSCTL_NAME2OID:
2339 fprintf(fp, "name2oid %s",
2341 (void *)args[sc->offset + 4],
2342 args[sc->offset + 5]));
2344 case CTL_SYSCTL_OIDFMT:
2345 fprintf(fp, "oidfmt ");
2346 print_sysctl(fp, oid + 2, len - 2);
2348 case CTL_SYSCTL_OIDDESCR:
2349 fprintf(fp, "oiddescr ");
2350 print_sysctl(fp, oid + 2, len - 2);
2352 case CTL_SYSCTL_OIDLABEL:
2353 fprintf(fp, "oidlabel ");
2354 print_sysctl(fp, oid + 2, len - 2);
2356 case CTL_SYSCTL_NEXTNOSKIP:
2357 fprintf(fp, "nextnoskip");
2360 print_sysctl(fp, oid + 1, len - 1);
2363 print_sysctl(fp, oid, len);
2371 * The pipe() system call in the kernel returns its
2372 * two file descriptors via return values. However,
2373 * the interface exposed by libc is that pipe()
2374 * accepts a pointer to an array of descriptors.
2375 * Format the output to match the libc API by printing
2376 * the returned file descriptors as a fake argument.
2378 * Overwrite the first retval to signal a successful
2381 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2388 len = args[sc->offset + 1];
2389 utrace_addr = calloc(1, len);
2390 if (get_struct(pid, (void *)args[sc->offset],
2391 (void *)utrace_addr, len) != -1)
2392 print_utrace(fp, utrace_addr, len);
2394 fprintf(fp, "0x%lx", args[sc->offset]);
2399 int descriptors[16];
2400 unsigned long i, ndescriptors;
2403 ndescriptors = args[sc->offset + 1];
2405 if (ndescriptors > nitems(descriptors)) {
2406 ndescriptors = nitems(descriptors);
2409 if (get_struct(pid, (void *)args[sc->offset],
2410 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2412 for (i = 0; i < ndescriptors; i++)
2413 fprintf(fp, i == 0 ? " %d" : ", %d",
2415 fprintf(fp, truncated ? ", ... }" : " }");
2417 fprintf(fp, "0x%lx", args[sc->offset]);
2421 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2423 case CapFcntlRights: {
2426 if (sc->type & OUT) {
2427 if (get_struct(pid, (void *)args[sc->offset], &rights,
2428 sizeof(rights)) == -1) {
2429 fprintf(fp, "0x%lx", args[sc->offset]);
2433 rights = args[sc->offset];
2434 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2438 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2443 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2444 fprintf(fp, "0x%x", rem);
2446 fprintf(fp, "|0x%x", rem);
2450 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2453 print_integer_arg(sysdecode_getfsstat_mode, fp,
2457 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2459 case Kldunloadflags:
2460 print_integer_arg(sysdecode_kldunload_flags, fp,
2464 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2467 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2469 case Sockprotocol: {
2471 int domain, protocol;
2473 domain = args[sc->offset - 2];
2474 protocol = args[sc->offset];
2475 if (protocol == 0) {
2478 temp = sysdecode_socket_protocol(domain, protocol);
2482 fprintf(fp, "%d", protocol);
2488 print_integer_arg(sysdecode_sockopt_level, fp,
2495 level = args[sc->offset - 1];
2496 name = args[sc->offset];
2497 temp = sysdecode_sockopt_name(level, name);
2501 fprintf(fp, "%d", name);
2506 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2509 cap_rights_t rights;
2511 if (get_struct(pid, (void *)args[sc->offset], &rights,
2512 sizeof(rights)) != -1) {
2514 sysdecode_cap_rights(fp, &rights);
2517 fprintf(fp, "0x%lx", args[sc->offset]);
2521 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2523 case Extattrnamespace:
2524 print_integer_arg(sysdecode_extattrnamespace, fp,
2528 print_integer_arg(sysdecode_minherit_inherit, fp,
2532 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2535 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2538 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2541 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2544 print_integer_arg(sysdecode_ptrace_request, fp,
2548 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2549 fprintf(fp, "%#x", (int)args[sc->offset]);
2552 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2555 print_integer_arg(sysdecode_rtprio_function, fp,
2559 print_integer_arg(sysdecode_scheduler_policy, fp,
2563 struct sched_param sp;
2565 if (get_struct(pid, (void *)args[sc->offset], &sp,
2567 fprintf(fp, "{ %d }", sp.sched_priority);
2569 fprintf(fp, "0x%lx", args[sc->offset]);
2575 if (get_struct(pid, (void *)args[sc->offset], &sig,
2577 fprintf(fp, "{ %s }", strsig2(sig));
2579 fprintf(fp, "0x%lx", args[sc->offset]);
2585 if (get_struct(pid, (void *)args[sc->offset], &si,
2586 sizeof(si)) != -1) {
2587 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2588 decode_siginfo(fp, &si);
2591 fprintf(fp, "0x%lx", args[sc->offset]);
2596 * Print argument as an array of struct iovec, where the next
2597 * syscall argument is the number of elements of the array.
2600 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2601 (int)args[sc->offset + 1]);
2603 case Sctpsndrcvinfo: {
2604 struct sctp_sndrcvinfo info;
2606 if (get_struct(pid, (void *)args[sc->offset],
2607 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2608 fprintf(fp, "0x%lx", args[sc->offset]);
2611 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2615 struct msghdr msghdr;
2617 if (get_struct(pid, (void *)args[sc->offset],
2618 &msghdr, sizeof(struct msghdr)) == -1) {
2619 fprintf(fp, "0x%lx", args[sc->offset]);
2623 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2624 fprintf(fp, ",%d,", msghdr.msg_namelen);
2625 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2626 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2627 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2628 fprintf(fp, ",%u,", msghdr.msg_controllen);
2629 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2634 case CloudABIAdvice:
2635 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2637 case CloudABIClockID:
2638 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2640 case CloudABIFDSFlags:
2641 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2643 case CloudABIFDStat: {
2644 cloudabi_fdstat_t fds;
2645 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2647 fprintf(fp, "{ %s, ",
2648 xlookup(cloudabi_filetype, fds.fs_filetype));
2649 fprintf(fp, "%s, ... }",
2650 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2652 fprintf(fp, "0x%lx", args[sc->offset]);
2655 case CloudABIFileStat: {
2656 cloudabi_filestat_t fsb;
2657 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2659 fprintf(fp, "{ %s, %ju }",
2660 xlookup(cloudabi_filetype, fsb.st_filetype),
2661 (uintmax_t)fsb.st_size);
2663 fprintf(fp, "0x%lx", args[sc->offset]);
2666 case CloudABIFileType:
2667 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2669 case CloudABIFSFlags:
2670 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2672 case CloudABILookup:
2673 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2674 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2675 (int)args[sc->offset]);
2677 fprintf(fp, "%d", (int)args[sc->offset]);
2679 case CloudABIMFlags:
2680 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2683 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2685 case CloudABIMSFlags:
2686 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2688 case CloudABIOFlags:
2689 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2691 case CloudABISDFlags:
2692 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2694 case CloudABISignal:
2695 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2697 case CloudABITimestamp:
2698 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2699 args[sc->offset] % 1000000000);
2701 case CloudABIULFlags:
2702 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2704 case CloudABIWhence:
2705 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2709 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2716 * Print (to outfile) the system call and its arguments.
2719 print_syscall(struct trussinfo *trussinfo)
2721 struct threadinfo *t;
2726 t = trussinfo->curthread;
2728 name = t->cs.sc->name;
2729 nargs = t->cs.nargs;
2730 s_args = t->cs.s_args;
2732 len = print_line_prefix(trussinfo);
2733 len += fprintf(trussinfo->outfile, "%s(", name);
2735 for (i = 0; i < nargs; i++) {
2736 if (s_args[i] != NULL)
2737 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2739 len += fprintf(trussinfo->outfile,
2740 "<missing argument>");
2741 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2744 len += fprintf(trussinfo->outfile, ")");
2745 for (i = 0; i < 6 - (len / 8); i++)
2746 fprintf(trussinfo->outfile, "\t");
2750 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2752 struct timespec timediff;
2753 struct threadinfo *t;
2756 t = trussinfo->curthread;
2758 if (trussinfo->flags & COUNTONLY) {
2759 timespecsub(&t->after, &t->before, &timediff);
2760 timespecadd(&sc->time, &timediff, &sc->time);
2767 print_syscall(trussinfo);
2768 fflush(trussinfo->outfile);
2770 if (retval == NULL) {
2772 * This system call resulted in the current thread's exit,
2773 * so there is no return value or error to display.
2775 fprintf(trussinfo->outfile, "\n");
2779 if (error == ERESTART)
2780 fprintf(trussinfo->outfile, " ERESTART\n");
2781 else if (error == EJUSTRETURN)
2782 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2783 else if (error != 0) {
2784 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2785 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2789 else if (sc->ret_type == 2) {
2792 #if _BYTE_ORDER == _LITTLE_ENDIAN
2793 off = (off_t)retval[1] << 32 | retval[0];
2795 off = (off_t)retval[0] << 32 | retval[1];
2797 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2802 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2803 (intmax_t)retval[0], (intmax_t)retval[0]);
2807 print_summary(struct trussinfo *trussinfo)
2809 struct timespec total = {0, 0};
2813 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2814 "syscall", "seconds", "calls", "errors");
2816 STAILQ_FOREACH(sc, &syscalls, entries)
2818 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2819 sc->name, (intmax_t)sc->time.tv_sec,
2820 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2821 timespecadd(&total, &sc->time, &total);
2822 ncall += sc->ncalls;
2823 nerror += sc->nerror;
2825 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2826 "", "-------------", "-------", "-------");
2827 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2828 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);