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
57 #include <netinet/in.h>
58 #include <netinet/sctp.h>
59 #include <arpa/inet.h>
72 #include <sysdecode.h>
76 #include <contrib/cloudabi/cloudabi_types_common.h>
83 * This should probably be in its own file, sorted alphabetically.
85 static struct syscall decoded_syscalls[] = {
87 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
88 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
89 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
90 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
91 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
92 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
93 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
94 .args = { { Int, 0 }, { Acltype, 1 } } },
95 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
96 .args = { { Name, 0 }, { Acltype, 1 } } },
97 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
98 .args = { { Name, 0 }, { Acltype, 1 } } },
99 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
100 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
101 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
102 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
103 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
104 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
106 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
108 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
110 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
111 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
112 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
113 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
114 .args = { { Name | OUT, 0 }, { Int, 1 } } },
115 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
116 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
118 { .name = "accept", .ret_type = 1, .nargs = 3,
119 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
120 { .name = "access", .ret_type = 1, .nargs = 2,
121 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
122 { .name = "bind", .ret_type = 1, .nargs = 3,
123 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
124 { .name = "bindat", .ret_type = 1, .nargs = 4,
125 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
127 { .name = "break", .ret_type = 1, .nargs = 1,
128 .args = { { Ptr, 0 } } },
129 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
130 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
131 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
132 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
133 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
134 .args = { { PUInt | OUT, 0 } } },
135 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
136 .args = { { Int, 0 }, { CapRights, 1 } } },
137 { .name = "chdir", .ret_type = 1, .nargs = 1,
138 .args = { { Name, 0 } } },
139 { .name = "chflags", .ret_type = 1, .nargs = 2,
140 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
141 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
142 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
144 { .name = "chmod", .ret_type = 1, .nargs = 2,
145 .args = { { Name, 0 }, { Octal, 1 } } },
146 { .name = "chown", .ret_type = 1, .nargs = 3,
147 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
148 { .name = "chroot", .ret_type = 1, .nargs = 1,
149 .args = { { Name, 0 } } },
150 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
151 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
152 { .name = "close", .ret_type = 1, .nargs = 1,
153 .args = { { Int, 0 } } },
154 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
155 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
156 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
157 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
159 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
160 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
161 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
162 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
163 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
164 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
165 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
166 { .name = "connect", .ret_type = 1, .nargs = 3,
167 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
168 { .name = "connectat", .ret_type = 1, .nargs = 4,
169 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
171 { .name = "dup", .ret_type = 1, .nargs = 1,
172 .args = { { Int, 0 } } },
173 { .name = "dup2", .ret_type = 1, .nargs = 2,
174 .args = { { Int, 0 }, { Int, 1 } } },
175 { .name = "eaccess", .ret_type = 1, .nargs = 2,
176 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
177 { .name = "execve", .ret_type = 1, .nargs = 3,
178 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
179 { ExecEnv | IN, 2 } } },
180 { .name = "exit", .ret_type = 0, .nargs = 1,
181 .args = { { Hex, 0 } } },
182 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
183 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
184 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
185 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
186 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
187 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
188 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
189 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
190 { BinString | OUT, 3 }, { Sizet, 4 } } },
191 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
192 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
193 { BinString | OUT, 3 }, { Sizet, 4 } } },
194 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
195 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
196 { BinString | OUT, 3 }, { Sizet, 4 } } },
197 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
198 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
200 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
201 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
203 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
204 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
206 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
207 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
208 { BinString | IN, 3 }, { Sizet, 4 } } },
209 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
210 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
211 { BinString | IN, 3 }, { Sizet, 4 } } },
212 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
213 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
214 { BinString | IN, 3 }, { Sizet, 4 } } },
215 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
216 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
217 { Extattrnamespace, 3 }, { Name, 4 } } },
218 { .name = "faccessat", .ret_type = 1, .nargs = 4,
219 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
221 { .name = "fchflags", .ret_type = 1, .nargs = 2,
222 .args = { { Int, 0 }, { FileFlags, 1 } } },
223 { .name = "fchmod", .ret_type = 1, .nargs = 2,
224 .args = { { Int, 0 }, { Octal, 1 } } },
225 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
226 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
227 { .name = "fchown", .ret_type = 1, .nargs = 3,
228 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
229 { .name = "fchownat", .ret_type = 1, .nargs = 5,
230 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
232 { .name = "fcntl", .ret_type = 1, .nargs = 3,
233 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
234 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
235 .args = { { Int, 0 } } },
236 { .name = "flock", .ret_type = 1, .nargs = 2,
237 .args = { { Int, 0 }, { Flockop, 1 } } },
238 { .name = "fstat", .ret_type = 1, .nargs = 2,
239 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
240 { .name = "fstatat", .ret_type = 1, .nargs = 4,
241 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
243 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
244 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
245 { .name = "fsync", .ret_type = 1, .nargs = 1,
246 .args = { { Int, 0 } } },
247 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
248 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
249 { .name = "futimens", .ret_type = 1, .nargs = 2,
250 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
251 { .name = "futimes", .ret_type = 1, .nargs = 2,
252 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
253 { .name = "futimesat", .ret_type = 1, .nargs = 3,
254 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
255 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
256 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
257 { PQuadHex | OUT, 3 } } },
258 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
259 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
260 { .name = "getitimer", .ret_type = 1, .nargs = 2,
261 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
262 { .name = "getpeername", .ret_type = 1, .nargs = 3,
263 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
264 { .name = "getpgid", .ret_type = 1, .nargs = 1,
265 .args = { { Int, 0 } } },
266 { .name = "getpriority", .ret_type = 1, .nargs = 2,
267 .args = { { Priowhich, 0 }, { Int, 1 } } },
268 { .name = "getrandom", .ret_type = 1, .nargs = 3,
269 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
270 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
271 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
272 { .name = "getrusage", .ret_type = 1, .nargs = 2,
273 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
274 { .name = "getsid", .ret_type = 1, .nargs = 1,
275 .args = { { Int, 0 } } },
276 { .name = "getsockname", .ret_type = 1, .nargs = 3,
277 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
278 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
279 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
280 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
281 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
282 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
283 { .name = "ioctl", .ret_type = 1, .nargs = 3,
284 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
285 { .name = "kevent", .ret_type = 1, .nargs = 6,
286 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
287 { Int, 4 }, { Timespec, 5 } } },
288 { .name = "kill", .ret_type = 1, .nargs = 2,
289 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
290 { .name = "kldfind", .ret_type = 1, .nargs = 1,
291 .args = { { Name | IN, 0 } } },
292 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
293 .args = { { Int, 0 } } },
294 { .name = "kldload", .ret_type = 1, .nargs = 1,
295 .args = { { Name | IN, 0 } } },
296 { .name = "kldnext", .ret_type = 1, .nargs = 1,
297 .args = { { Int, 0 } } },
298 { .name = "kldstat", .ret_type = 1, .nargs = 2,
299 .args = { { Int, 0 }, { Ptr, 1 } } },
300 { .name = "kldsym", .ret_type = 1, .nargs = 3,
301 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
302 { .name = "kldunload", .ret_type = 1, .nargs = 1,
303 .args = { { Int, 0 } } },
304 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
305 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
306 { .name = "kse_release", .ret_type = 0, .nargs = 1,
307 .args = { { Timespec, 0 } } },
308 { .name = "lchflags", .ret_type = 1, .nargs = 2,
309 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
310 { .name = "lchmod", .ret_type = 1, .nargs = 2,
311 .args = { { Name, 0 }, { Octal, 1 } } },
312 { .name = "lchown", .ret_type = 1, .nargs = 3,
313 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
314 { .name = "link", .ret_type = 1, .nargs = 2,
315 .args = { { Name, 0 }, { Name, 1 } } },
316 { .name = "linkat", .ret_type = 1, .nargs = 5,
317 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
319 { .name = "listen", .ret_type = 1, .nargs = 2,
320 .args = { { Int, 0 }, { Int, 1 } } },
321 { .name = "lseek", .ret_type = 2, .nargs = 3,
322 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
323 { .name = "lstat", .ret_type = 1, .nargs = 2,
324 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
325 { .name = "lutimes", .ret_type = 1, .nargs = 2,
326 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
327 { .name = "madvise", .ret_type = 1, .nargs = 3,
328 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
329 { .name = "minherit", .ret_type = 1, .nargs = 3,
330 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
331 { .name = "mkdir", .ret_type = 1, .nargs = 2,
332 .args = { { Name, 0 }, { Octal, 1 } } },
333 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
334 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
335 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
336 .args = { { Name, 0 }, { Octal, 1 } } },
337 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
338 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
339 { .name = "mknod", .ret_type = 1, .nargs = 3,
340 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
341 { .name = "mknodat", .ret_type = 1, .nargs = 4,
342 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
343 { .name = "mlock", .ret_type = 1, .nargs = 2,
344 .args = { { Ptr, 0 }, { Sizet, 1 } } },
345 { .name = "mlockall", .ret_type = 1, .nargs = 1,
346 .args = { { Mlockall, 0 } } },
347 { .name = "mmap", .ret_type = 1, .nargs = 6,
348 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
349 { Int, 4 }, { QuadHex, 5 } } },
350 { .name = "modfind", .ret_type = 1, .nargs = 1,
351 .args = { { Name | IN, 0 } } },
352 { .name = "mount", .ret_type = 1, .nargs = 4,
353 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
354 { .name = "mprotect", .ret_type = 1, .nargs = 3,
355 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
356 { .name = "msync", .ret_type = 1, .nargs = 3,
357 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
358 { .name = "munlock", .ret_type = 1, .nargs = 2,
359 .args = { { Ptr, 0 }, { Sizet, 1 } } },
360 { .name = "munmap", .ret_type = 1, .nargs = 2,
361 .args = { { Ptr, 0 }, { Sizet, 1 } } },
362 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
363 .args = { { Timespec, 0 } } },
364 { .name = "nmount", .ret_type = 1, .nargs = 3,
365 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
366 { .name = "open", .ret_type = 1, .nargs = 3,
367 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
368 { .name = "openat", .ret_type = 1, .nargs = 4,
369 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
371 { .name = "pathconf", .ret_type = 1, .nargs = 2,
372 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
373 { .name = "pipe", .ret_type = 1, .nargs = 1,
374 .args = { { PipeFds | OUT, 0 } } },
375 { .name = "pipe2", .ret_type = 1, .nargs = 2,
376 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
377 { .name = "poll", .ret_type = 1, .nargs = 3,
378 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
379 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
380 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
382 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
383 .args = { { Open, 0 } } },
384 { .name = "pread", .ret_type = 1, .nargs = 4,
385 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
387 { .name = "procctl", .ret_type = 1, .nargs = 4,
388 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
389 { .name = "ptrace", .ret_type = 1, .nargs = 4,
390 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
391 { .name = "pwrite", .ret_type = 1, .nargs = 4,
392 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
394 { .name = "quotactl", .ret_type = 1, .nargs = 4,
395 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
396 { .name = "read", .ret_type = 1, .nargs = 3,
397 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
398 { .name = "readlink", .ret_type = 1, .nargs = 3,
399 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
400 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
401 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
403 { .name = "readv", .ret_type = 1, .nargs = 3,
404 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
405 { .name = "reboot", .ret_type = 1, .nargs = 1,
406 .args = { { Reboothowto, 0 } } },
407 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
408 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
409 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
410 { Ptr | OUT, 5 } } },
411 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
412 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
413 { .name = "rename", .ret_type = 1, .nargs = 2,
414 .args = { { Name, 0 }, { Name, 1 } } },
415 { .name = "renameat", .ret_type = 1, .nargs = 4,
416 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
417 { .name = "rfork", .ret_type = 1, .nargs = 1,
418 .args = { { Rforkflags, 0 } } },
419 { .name = "rmdir", .ret_type = 1, .nargs = 1,
420 .args = { { Name, 0 } } },
421 { .name = "rtprio", .ret_type = 1, .nargs = 3,
422 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
423 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
424 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
425 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
426 .args = { { Schedpolicy, 0 } } },
427 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
428 .args = { { Schedpolicy, 0 } } },
429 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
430 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
431 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
432 .args = { { Int, 0 } } },
433 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
434 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
435 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
436 .args = { { Int, 0 }, { Schedparam, 1 } } },
437 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
438 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
439 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
440 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
441 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
442 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
443 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
444 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
445 { Sockaddr | IN, 3 }, { Socklent, 4 },
446 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
447 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
448 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
449 { Sockaddr | IN, 3 }, { Socklent, 4 },
450 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
451 { .name = "select", .ret_type = 1, .nargs = 5,
452 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
454 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
455 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
456 { .name = "sendto", .ret_type = 1, .nargs = 6,
457 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
458 { Msgflags, 3 }, { Sockaddr | IN, 4 },
459 { Socklent | IN, 5 } } },
460 { .name = "setitimer", .ret_type = 1, .nargs = 3,
461 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
462 { .name = "setpriority", .ret_type = 1, .nargs = 3,
463 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
464 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
465 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
466 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
467 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
468 { Ptr | IN, 3 }, { Socklent, 4 } } },
469 { .name = "shm_open", .ret_type = 1, .nargs = 3,
470 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
471 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
472 .args = { { Name | IN, 0 } } },
473 { .name = "shutdown", .ret_type = 1, .nargs = 2,
474 .args = { { Int, 0 }, { Shutdown, 1 } } },
475 { .name = "sigaction", .ret_type = 1, .nargs = 3,
476 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
477 { Sigaction | OUT, 2 } } },
478 { .name = "sigpending", .ret_type = 1, .nargs = 1,
479 .args = { { Sigset | OUT, 0 } } },
480 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
481 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
482 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
483 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
484 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
485 .args = { { Ptr, 0 } } },
486 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
487 .args = { { Sigset | IN, 0 } } },
488 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
489 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
490 { Timespec | IN, 2 } } },
491 { .name = "sigwait", .ret_type = 1, .nargs = 2,
492 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
493 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
494 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
495 { .name = "socket", .ret_type = 1, .nargs = 3,
496 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
497 { .name = "stat", .ret_type = 1, .nargs = 2,
498 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
499 { .name = "statfs", .ret_type = 1, .nargs = 2,
500 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
501 { .name = "symlink", .ret_type = 1, .nargs = 2,
502 .args = { { Name, 0 }, { Name, 1 } } },
503 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
504 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
505 { .name = "sysarch", .ret_type = 1, .nargs = 2,
506 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
507 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
508 .args = { { Long, 0 }, { Signal, 1 } } },
509 { .name = "thr_self", .ret_type = 1, .nargs = 1,
510 .args = { { Ptr, 0 } } },
511 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
512 .args = { { Long, 0 }, { Name, 1 } } },
513 { .name = "truncate", .ret_type = 1, .nargs = 2,
514 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
517 { .name = "umount", .ret_type = 1, .nargs = 2,
518 .args = { { Name, 0 }, { Int, 2 } } },
520 { .name = "unlink", .ret_type = 1, .nargs = 1,
521 .args = { { Name, 0 } } },
522 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
523 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
524 { .name = "unmount", .ret_type = 1, .nargs = 2,
525 .args = { { Name, 0 }, { Mountflags, 1 } } },
526 { .name = "utimensat", .ret_type = 1, .nargs = 4,
527 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
529 { .name = "utimes", .ret_type = 1, .nargs = 2,
530 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
531 { .name = "utrace", .ret_type = 1, .nargs = 1,
532 .args = { { Utrace, 0 } } },
533 { .name = "wait4", .ret_type = 1, .nargs = 4,
534 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
535 { Rusage | OUT, 3 } } },
536 { .name = "wait6", .ret_type = 1, .nargs = 6,
537 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
538 { Waitoptions, 3 }, { Rusage | OUT, 4 },
539 { Siginfo | OUT, 5 } } },
540 { .name = "write", .ret_type = 1, .nargs = 3,
541 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
542 { .name = "writev", .ret_type = 1, .nargs = 3,
543 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
546 { .name = "linux_access", .ret_type = 1, .nargs = 2,
547 .args = { { Name, 0 }, { Accessmode, 1 } } },
548 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
549 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
550 { ExecEnv | IN, 2 } } },
551 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
552 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
553 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
554 .args = { { Name | IN, 0 }, { Int, 1 } } },
555 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
556 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
557 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
558 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
559 { .name = "linux_open", .ret_type = 1, .nargs = 3,
560 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
561 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
562 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
563 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
564 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
565 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
566 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
568 /* CloudABI system calls. */
569 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
570 .args = { { CloudABIClockID, 0 } } },
571 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
572 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
573 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
574 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
575 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
576 .args = { { Int, 0 } } },
577 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
578 .args = { { CloudABIFileType, 0 } } },
579 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
580 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
581 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
582 .args = { { Int, 0 } } },
583 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
584 .args = { { Int, 0 } } },
585 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
586 .args = { { Int, 0 }, { Int, 1 } } },
587 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
588 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
589 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
590 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
591 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
592 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
593 { CloudABIFDSFlags, 2 } } },
594 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
595 .args = { { Int, 0 } } },
596 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
597 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
598 { CloudABIAdvice, 3 } } },
599 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
600 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
601 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
602 .args = { { Int, 0 }, { BinString | IN, 1 },
603 { CloudABIFileType, 3 } } },
604 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
605 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
606 { Int, 3 }, { BinString | IN, 4 } } },
607 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
608 .args = { { Int, 0 }, { BinString | IN, 1 },
609 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
610 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
611 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
613 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
614 .args = { { Int, 0 }, { BinString | IN, 1 },
615 { BinString | OUT, 3 }, { Int, 4 } } },
616 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
617 .args = { { Int, 0 }, { BinString | IN, 1 },
618 { Int, 3 }, { BinString | IN, 4 } } },
619 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
620 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
621 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
622 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
623 { CloudABIFSFlags, 2 } } },
624 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
625 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
626 { CloudABIFileStat | OUT, 3 } } },
627 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
628 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
629 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
630 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
631 .args = { { BinString | IN, 0 },
632 { Int, 2 }, { BinString | IN, 3 } } },
633 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
634 .args = { { Int, 0 }, { BinString | IN, 1 },
635 { CloudABIULFlags, 3 } } },
636 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
637 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
638 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
639 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
640 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
641 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
642 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
643 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
644 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
645 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
646 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
647 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
648 .args = { { Ptr, 0 }, { Int, 1 } } },
649 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
650 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
651 { IntArray, 3 }, { Int, 4 } } },
652 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
653 .args = { { Int, 0 } } },
654 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
655 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
656 .args = { { CloudABISignal, 0 } } },
657 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
658 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
659 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
660 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
661 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
662 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
663 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
667 static STAILQ_HEAD(, syscall) syscalls;
669 /* Xlat idea taken from strace */
675 #define X(a) { a, #a },
676 #define XEND { 0, NULL }
678 static struct xlat poll_flags[] = {
679 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
680 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
681 X(POLLWRBAND) X(POLLINIGNEOF) XEND
684 static struct xlat sigaction_flags[] = {
685 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
686 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
689 static struct xlat linux_socketcall_ops[] = {
690 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
691 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
692 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
693 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
694 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
699 #define X(a) { CLOUDABI_##a, #a },
701 static struct xlat cloudabi_advice[] = {
702 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
703 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
707 static struct xlat cloudabi_clockid[] = {
708 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
709 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
713 static struct xlat cloudabi_fdflags[] = {
714 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
715 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
719 static struct xlat cloudabi_fdsflags[] = {
720 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
724 static struct xlat cloudabi_filetype[] = {
725 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
726 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
727 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
728 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
729 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
733 static struct xlat cloudabi_fsflags[] = {
734 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
735 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
739 static struct xlat cloudabi_mflags[] = {
740 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
744 static struct xlat cloudabi_mprot[] = {
745 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
749 static struct xlat cloudabi_msflags[] = {
750 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
754 static struct xlat cloudabi_oflags[] = {
755 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
759 static struct xlat cloudabi_sdflags[] = {
760 X(SHUT_RD) X(SHUT_WR)
764 static struct xlat cloudabi_signal[] = {
765 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
766 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
767 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
768 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
769 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
773 static struct xlat cloudabi_ulflags[] = {
778 static struct xlat cloudabi_whence[] = {
779 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
787 * Searches an xlat array for a value, and returns it if found. Otherwise
788 * return a string representation.
791 lookup(struct xlat *xlat, int val, int base)
795 for (; xlat->str != NULL; xlat++)
796 if (xlat->val == val)
800 sprintf(tmp, "0%o", val);
803 sprintf(tmp, "0x%x", val);
806 sprintf(tmp, "%u", val);
809 errx(1,"Unknown lookup base");
816 xlookup(struct xlat *xlat, int val)
819 return (lookup(xlat, val, 16));
823 * Searches an xlat array containing bitfield values. Remaining bits
824 * set after removing the known ones are printed at the end:
828 xlookup_bits(struct xlat *xlat, int val)
831 static char str[512];
835 for (; xlat->str != NULL; xlat++) {
836 if ((xlat->val & rem) == xlat->val) {
838 * Don't print the "all-bits-zero" string unless all
839 * bits are really zero.
841 if (xlat->val == 0 && val != 0)
843 len += sprintf(str + len, "%s|", xlat->str);
849 * If we have leftover bits or didn't match anything, print
853 len += sprintf(str + len, "0x%x", rem);
854 if (len && str[len - 1] == '|')
861 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
865 str = decoder(value);
869 fprintf(fp, "%d", value);
873 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
877 if (!decoder(fp, value, &rem))
878 fprintf(fp, "0x%x", rem);
880 fprintf(fp, "|0x%x", rem);
884 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
889 if (!decoder(fp, value, &rem))
890 fprintf(fp, "0x%x", rem);
892 fprintf(fp, "|0x%x", rem);
897 * Add argument padding to subsequent system calls afater a Quad
898 * syscall arguments as needed. This used to be done by hand in the
899 * decoded_syscalls table which was ugly and error prone. It is
900 * simpler to do the fixup of offsets at initalization time than when
901 * decoding arguments.
904 quad_fixup(struct syscall *sc)
911 for (i = 0; i < sc->nargs; i++) {
912 /* This arg type is a dummy that doesn't use offset. */
913 if ((sc->args[i].type & ARG_MASK) == PipeFds)
916 assert(prev < sc->args[i].offset);
917 prev = sc->args[i].offset;
918 sc->args[i].offset += offset;
919 switch (sc->args[i].type & ARG_MASK) {
924 * 64-bit arguments on 32-bit powerpc must be
925 * 64-bit aligned. If the current offset is
926 * not aligned, the calling convention inserts
927 * a 32-bit pad argument that should be skipped.
929 if (sc->args[i].offset % 2 == 1) {
930 sc->args[i].offset++;
947 STAILQ_INIT(&syscalls);
948 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
952 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
956 static struct syscall *
957 find_syscall(struct procabi *abi, u_int number)
959 struct extra_syscall *es;
961 if (number < nitems(abi->syscalls))
962 return (abi->syscalls[number]);
963 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
964 if (es->number == number)
971 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
973 struct extra_syscall *es;
975 if (number < nitems(abi->syscalls)) {
976 assert(abi->syscalls[number] == NULL);
977 abi->syscalls[number] = sc;
979 es = malloc(sizeof(*es));
982 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
987 * If/when the list gets big, it might be desirable to do it
988 * as a hash table or binary search.
991 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
998 sc = find_syscall(t->proc->abi, number);
1002 name = sysdecode_syscallname(t->proc->abi->abi, number);
1004 asprintf(&new_name, "#%d", number);
1008 STAILQ_FOREACH(sc, &syscalls, entries) {
1009 if (strcmp(name, sc->name) == 0) {
1010 add_syscall(t->proc->abi, number, sc);
1016 /* It is unknown. Add it into the list. */
1018 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1022 sc = calloc(1, sizeof(struct syscall));
1024 if (new_name != NULL)
1028 for (i = 0; i < nargs; i++) {
1029 sc->args[i].offset = i;
1030 /* Treat all unknown arguments as LongHex. */
1031 sc->args[i].type = LongHex;
1033 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1034 add_syscall(t->proc->abi, number, sc);
1040 * Copy a fixed amount of bytes from the process.
1043 get_struct(pid_t pid, void *offset, void *buf, int len)
1045 struct ptrace_io_desc iorequest;
1047 iorequest.piod_op = PIOD_READ_D;
1048 iorequest.piod_offs = offset;
1049 iorequest.piod_addr = buf;
1050 iorequest.piod_len = len;
1051 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1056 #define MAXSIZE 4096
1059 * Copy a string from the process. Note that it is
1060 * expected to be a C string, but if max is set, it will
1061 * only get that much.
1064 get_string(pid_t pid, void *addr, int max)
1066 struct ptrace_io_desc iorequest;
1068 size_t offset, size, totalsize;
1074 /* Read up to the end of the current page. */
1075 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1080 buf = malloc(totalsize);
1084 iorequest.piod_op = PIOD_READ_D;
1085 iorequest.piod_offs = (char *)addr + offset;
1086 iorequest.piod_addr = buf + offset;
1087 iorequest.piod_len = size;
1088 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1092 if (memchr(buf + offset, '\0', size) != NULL)
1095 if (totalsize < MAXSIZE && max == 0) {
1096 size = MAXSIZE - totalsize;
1097 if (size > PAGE_SIZE)
1099 nbuf = realloc(buf, totalsize + size);
1101 buf[totalsize - 1] = '\0';
1107 buf[totalsize - 1] = '\0';
1116 static char tmp[32];
1117 const char *signame;
1119 signame = sysdecode_signal(sig);
1120 if (signame == NULL) {
1121 snprintf(tmp, sizeof(tmp), "%d", sig);
1128 print_kevent(FILE *fp, struct kevent *ke)
1131 switch (ke->filter) {
1137 case EVFILT_PROCDESC:
1139 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1142 fputs(strsig2(ke->ident), fp);
1145 fprintf(fp, "%p", (void *)ke->ident);
1148 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1150 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1152 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1153 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1157 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1159 unsigned char *utrace_buffer;
1162 if (sysdecode_utrace(fp, utrace_addr, len)) {
1167 utrace_buffer = utrace_addr;
1168 fprintf(fp, "%zu:", len);
1170 fprintf(fp, " %02x", *utrace_buffer++);
1175 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1178 struct sockaddr_in *lsin;
1179 struct sockaddr_in6 *lsin6;
1180 struct sockaddr_un *sun;
1181 struct sockaddr *sa;
1183 pid_t pid = trussinfo->curthread->proc->pid;
1189 /* If the length is too small, just bail. */
1190 if (len < sizeof(*sa)) {
1191 fprintf(fp, "%p", arg);
1195 sa = calloc(1, len);
1196 if (get_struct(pid, arg, sa, len) == -1) {
1198 fprintf(fp, "%p", arg);
1202 switch (sa->sa_family) {
1204 if (len < sizeof(*lsin))
1205 goto sockaddr_short;
1206 lsin = (struct sockaddr_in *)(void *)sa;
1207 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1208 fprintf(fp, "{ AF_INET %s:%d }", addr,
1209 htons(lsin->sin_port));
1212 if (len < sizeof(*lsin6))
1213 goto sockaddr_short;
1214 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1215 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1217 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1218 htons(lsin6->sin6_port));
1221 sun = (struct sockaddr_un *)sa;
1222 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1223 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1229 "{ sa_len = %d, sa_family = %d, sa_data = {",
1230 (int)sa->sa_len, (int)sa->sa_family);
1231 for (q = (u_char *)sa->sa_data;
1232 q < (u_char *)sa + len; q++)
1233 fprintf(fp, "%s 0x%02x",
1234 q == (u_char *)sa->sa_data ? "" : ",",
1241 #define IOV_LIMIT 16
1244 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1246 struct iovec iov[IOV_LIMIT];
1247 size_t max_string = trussinfo->strsize;
1248 char tmp2[max_string + 1], *tmp3;
1250 pid_t pid = trussinfo->curthread->proc->pid;
1252 bool buf_truncated, iov_truncated;
1255 fprintf(fp, "%p", arg);
1258 if (iovcnt > IOV_LIMIT) {
1260 iov_truncated = true;
1262 iov_truncated = false;
1264 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1265 fprintf(fp, "%p", arg);
1270 for (i = 0; i < iovcnt; i++) {
1271 len = iov[i].iov_len;
1272 if (len > max_string) {
1274 buf_truncated = true;
1276 buf_truncated = false;
1278 fprintf(fp, "%s{", (i > 0) ? "," : "");
1279 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1280 tmp3 = malloc(len * 4 + 1);
1282 if (strvisx(tmp3, tmp2, len,
1283 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1287 buf_truncated = true;
1289 fprintf(fp, "\"%s\"%s", tmp3,
1290 buf_truncated ? "..." : "");
1293 fprintf(fp, "%p", iov[i].iov_base);
1295 fprintf(fp, ",%zu}", iov[i].iov_len);
1297 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1301 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1306 for (q = CMSG_DATA(cmsghdr);
1307 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1308 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1314 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1316 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1317 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1318 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1319 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1323 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1325 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1327 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1330 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1331 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1333 fprintf(fp, "ctx=%u,", info->sinfo_context);
1334 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1337 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1338 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1340 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1344 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1346 fprintf(fp, "{sid=%u,", info->snd_sid);
1348 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1349 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1350 fprintf(fp, "ctx=%u,", info->snd_context);
1351 fprintf(fp, "id=%u}", info->snd_assoc_id);
1355 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1357 fprintf(fp, "{sid=%u,", info->rcv_sid);
1358 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1360 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1361 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1362 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1363 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1364 fprintf(fp, "ctx=%u,", info->rcv_context);
1365 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1369 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1371 fprintf(fp, "{sid=%u,", info->nxt_sid);
1373 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1374 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1375 fprintf(fp, "len=%u,", info->nxt_length);
1376 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1380 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1383 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1384 fprintf(fp, ",val=%u}", info->pr_value);
1388 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1390 fprintf(fp, "{num=%u}", info->auth_keynumber);
1394 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1396 char buf[INET_ADDRSTRLEN];
1399 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1401 fprintf(fp, "{addr=%s}", s);
1403 fputs("{addr=???}", fp);
1407 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1409 char buf[INET6_ADDRSTRLEN];
1412 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1414 fprintf(fp, "{addr=%s}", s);
1416 fputs("{addr=???}", fp);
1420 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1425 len = cmsghdr->cmsg_len;
1426 data = CMSG_DATA(cmsghdr);
1427 switch (cmsghdr->cmsg_type) {
1429 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1430 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1432 print_gen_cmsg(fp, cmsghdr);
1435 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1436 print_sctp_sndrcvinfo(fp, receive,
1437 (struct sctp_sndrcvinfo *)data);
1439 print_gen_cmsg(fp, cmsghdr);
1443 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1444 print_sctp_extrcvinfo(fp,
1445 (struct sctp_extrcvinfo *)data);
1447 print_gen_cmsg(fp, cmsghdr);
1451 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1452 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1454 print_gen_cmsg(fp, cmsghdr);
1457 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1458 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1460 print_gen_cmsg(fp, cmsghdr);
1463 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1464 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1466 print_gen_cmsg(fp, cmsghdr);
1469 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1470 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1472 print_gen_cmsg(fp, cmsghdr);
1475 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1476 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1478 print_gen_cmsg(fp, cmsghdr);
1480 case SCTP_DSTADDRV4:
1481 if (len == CMSG_LEN(sizeof(struct in_addr)))
1482 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1484 print_gen_cmsg(fp, cmsghdr);
1486 case SCTP_DSTADDRV6:
1487 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1488 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1490 print_gen_cmsg(fp, cmsghdr);
1493 print_gen_cmsg(fp, cmsghdr);
1498 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1500 struct cmsghdr *cmsghdr;
1507 len = msghdr->msg_controllen;
1512 cmsgbuf = calloc(1, len);
1513 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1514 fprintf(fp, "%p", msghdr->msg_control);
1518 msghdr->msg_control = cmsgbuf;
1521 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1523 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1524 level = cmsghdr->cmsg_level;
1525 type = cmsghdr->cmsg_type;
1526 len = cmsghdr->cmsg_len;
1527 fprintf(fp, "%s{level=", first ? "" : ",");
1528 print_integer_arg(sysdecode_sockopt_level, fp, level);
1529 fputs(",type=", fp);
1530 temp = sysdecode_cmsg_type(level, type);
1534 fprintf(fp, "%d", type);
1536 fputs(",data=", fp);
1539 print_sctp_cmsg(fp, receive, cmsghdr);
1542 print_gen_cmsg(fp, cmsghdr);
1553 * Converts a syscall argument into a string. Said string is
1554 * allocated via malloc(), so needs to be free()'d. sc is
1555 * a pointer to the syscall description (see above); args is
1556 * an array of all of the system call arguments.
1559 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1560 struct trussinfo *trussinfo)
1567 fp = open_memstream(&tmp, &tmplen);
1568 pid = trussinfo->curthread->proc->pid;
1569 switch (sc->type & ARG_MASK) {
1571 fprintf(fp, "0x%x", (int)args[sc->offset]);
1574 fprintf(fp, "0%o", (int)args[sc->offset]);
1577 fprintf(fp, "%d", (int)args[sc->offset]);
1580 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1585 if (get_struct(pid, (void *)args[sc->offset], &val,
1587 fprintf(fp, "{ %u }", val);
1589 fprintf(fp, "0x%lx", args[sc->offset]);
1593 fprintf(fp, "0x%lx", args[sc->offset]);
1596 fprintf(fp, "%ld", args[sc->offset]);
1599 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1602 /* Handle special SHM_ANON value. */
1603 if ((char *)args[sc->offset] == SHM_ANON) {
1604 fprintf(fp, "SHM_ANON");
1609 /* NULL-terminated string. */
1612 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1613 fprintf(fp, "\"%s\"", tmp2);
1619 * Binary block of data that might have printable characters.
1620 * XXX If type|OUT, assume that the length is the syscall's
1621 * return value. Otherwise, assume that the length of the block
1622 * is in the next syscall argument.
1624 int max_string = trussinfo->strsize;
1625 char tmp2[max_string + 1], *tmp3;
1632 len = args[sc->offset + 1];
1635 * Don't print more than max_string characters, to avoid word
1636 * wrap. If we have to truncate put some ... after the string.
1638 if (len > max_string) {
1642 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1644 tmp3 = malloc(len * 4 + 1);
1646 if (strvisx(tmp3, tmp2, len,
1647 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1652 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1656 fprintf(fp, "0x%lx", args[sc->offset]);
1666 char buf[PAGE_SIZE];
1673 * Only parse argv[] and environment arrays from exec calls
1676 if (((sc->type & ARG_MASK) == ExecArgs &&
1677 (trussinfo->flags & EXECVEARGS) == 0) ||
1678 ((sc->type & ARG_MASK) == ExecEnv &&
1679 (trussinfo->flags & EXECVEENVS) == 0)) {
1680 fprintf(fp, "0x%lx", args[sc->offset]);
1685 * Read a page of pointers at a time. Punt if the top-level
1686 * pointer is not aligned. Note that the first read is of
1689 addr = args[sc->offset];
1690 if (addr % sizeof(char *) != 0) {
1691 fprintf(fp, "0x%lx", args[sc->offset]);
1695 len = PAGE_SIZE - (addr & PAGE_MASK);
1696 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1697 fprintf(fp, "0x%lx", args[sc->offset]);
1704 while (u.strarray[i] != NULL) {
1705 string = get_string(pid, u.strarray[i], 0);
1706 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1711 if (i == len / sizeof(char *)) {
1714 if (get_struct(pid, (void *)addr, u.buf, len) ==
1716 fprintf(fp, ", <inval>");
1727 fprintf(fp, "%ld", args[sc->offset]);
1730 fprintf(fp, "0x%lx", args[sc->offset]);
1735 unsigned long long ll;
1737 #if _BYTE_ORDER == _LITTLE_ENDIAN
1738 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1741 ll = (unsigned long long)args[sc->offset] << 32 |
1742 args[sc->offset + 1];
1744 if ((sc->type & ARG_MASK) == Quad)
1745 fprintf(fp, "%lld", ll);
1747 fprintf(fp, "0x%llx", ll);
1754 if (get_struct(pid, (void *)args[sc->offset], &val,
1756 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1758 fprintf(fp, "0x%lx", args[sc->offset]);
1762 fprintf(fp, "0x%lx", args[sc->offset]);
1767 if (retval[0] == -1)
1769 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1770 fprintf(fp, "\"%s\"", tmp2);
1778 cmd = args[sc->offset];
1779 temp = sysdecode_ioctlname(cmd);
1783 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1784 cmd, cmd & IOC_OUT ? "R" : "",
1785 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1786 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1787 cmd & 0xFF, IOCPARM_LEN(cmd));
1794 if (get_struct(pid, (void *)args[sc->offset], &ts,
1796 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1799 fprintf(fp, "0x%lx", args[sc->offset]);
1803 struct timespec ts[2];
1807 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1811 for (i = 0; i < nitems(ts); i++) {
1814 switch (ts[i].tv_nsec) {
1816 fprintf(fp, "UTIME_NOW");
1819 fprintf(fp, "UTIME_OMIT");
1822 fprintf(fp, "%jd.%09ld",
1823 (intmax_t)ts[i].tv_sec,
1830 fprintf(fp, "0x%lx", args[sc->offset]);
1836 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1838 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1841 fprintf(fp, "0x%lx", args[sc->offset]);
1845 struct timeval tv[2];
1847 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1849 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1850 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1851 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1853 fprintf(fp, "0x%lx", args[sc->offset]);
1857 struct itimerval itv;
1859 if (get_struct(pid, (void *)args[sc->offset], &itv,
1861 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1862 (intmax_t)itv.it_interval.tv_sec,
1863 itv.it_interval.tv_usec,
1864 (intmax_t)itv.it_value.tv_sec,
1865 itv.it_value.tv_usec);
1867 fprintf(fp, "0x%lx", args[sc->offset]);
1872 struct linux_socketcall_args largs;
1874 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1875 sizeof(largs)) != -1)
1876 fprintf(fp, "{ %s, 0x%lx }",
1877 lookup(linux_socketcall_ops, largs.what, 10),
1878 (long unsigned int)largs.args);
1880 fprintf(fp, "0x%lx", args[sc->offset]);
1885 * XXX: A Pollfd argument expects the /next/ syscall argument
1886 * to be the number of fds in the array. This matches the poll
1890 int numfds = args[sc->offset + 1];
1891 size_t bytes = sizeof(struct pollfd) * numfds;
1894 if ((pfd = malloc(bytes)) == NULL)
1895 err(1, "Cannot malloc %zu bytes for pollfd array",
1897 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1900 for (i = 0; i < numfds; i++) {
1901 fprintf(fp, " %d/%s", pfd[i].fd,
1902 xlookup_bits(poll_flags, pfd[i].events));
1906 fprintf(fp, "0x%lx", args[sc->offset]);
1913 * XXX: A Fd_set argument expects the /first/ syscall argument
1914 * to be the number of fds in the array. This matches the
1918 int numfds = args[0];
1919 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1922 if ((fds = malloc(bytes)) == NULL)
1923 err(1, "Cannot malloc %zu bytes for fd_set array",
1925 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1928 for (i = 0; i < numfds; i++) {
1929 if (FD_ISSET(i, fds))
1930 fprintf(fp, " %d", i);
1934 fprintf(fp, "0x%lx", args[sc->offset]);
1939 fputs(strsig2(args[sc->offset]), fp);
1946 sig = args[sc->offset];
1947 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1948 sizeof(ss)) == -1) {
1949 fprintf(fp, "0x%lx", args[sc->offset]);
1954 for (i = 1; i < sys_nsig; i++) {
1955 if (sigismember(&ss, i)) {
1956 fprintf(fp, "%s%s", !first ? "|" : "",
1967 print_integer_arg(sysdecode_sigprocmask_how, fp,
1971 /* XXX: Output depends on the value of the previous argument. */
1972 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1973 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1974 args[sc->offset], 16);
1977 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1980 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1983 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1986 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1989 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1992 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1995 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1998 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2001 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2004 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2007 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2010 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2015 if (args[sc->offset] == 0) {
2021 * Extract the address length from the next argument. If
2022 * this is an output sockaddr (OUT is set), then the
2023 * next argument is a pointer to a socklen_t. Otherwise
2024 * the next argument contains a socklen_t by value.
2026 if (sc->type & OUT) {
2027 if (get_struct(pid, (void *)args[sc->offset + 1],
2028 &len, sizeof(len)) == -1) {
2029 fprintf(fp, "0x%lx", args[sc->offset]);
2033 len = args[sc->offset + 1];
2035 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2039 struct sigaction sa;
2041 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2044 if (sa.sa_handler == SIG_DFL)
2045 fputs("SIG_DFL", fp);
2046 else if (sa.sa_handler == SIG_IGN)
2047 fputs("SIG_IGN", fp);
2049 fprintf(fp, "%p", sa.sa_handler);
2050 fprintf(fp, " %s ss_t }",
2051 xlookup_bits(sigaction_flags, sa.sa_flags));
2053 fprintf(fp, "0x%lx", args[sc->offset]);
2058 * XXX XXX: The size of the array is determined by either the
2059 * next syscall argument, or by the syscall return value,
2060 * depending on which argument number we are. This matches the
2061 * kevent syscall, but luckily that's the only syscall that uses
2069 if (sc->offset == 1)
2070 numevents = args[sc->offset+1];
2071 else if (sc->offset == 3 && retval[0] != -1)
2072 numevents = retval[0];
2074 if (numevents >= 0) {
2075 bytes = sizeof(struct kevent) * numevents;
2076 if ((ke = malloc(bytes)) == NULL)
2078 "Cannot malloc %zu bytes for kevent array",
2082 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2085 for (i = 0; i < numevents; i++) {
2087 print_kevent(fp, &ke[i]);
2091 fprintf(fp, "0x%lx", args[sc->offset]);
2097 struct kevent_freebsd11 *ke11;
2103 if (sc->offset == 1)
2104 numevents = args[sc->offset+1];
2105 else if (sc->offset == 3 && retval[0] != -1)
2106 numevents = retval[0];
2108 if (numevents >= 0) {
2109 bytes = sizeof(struct kevent_freebsd11) * numevents;
2110 if ((ke11 = malloc(bytes)) == NULL)
2112 "Cannot malloc %zu bytes for kevent array",
2116 memset(&ke, 0, sizeof(ke));
2117 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2118 ke11, bytes) != -1) {
2120 for (i = 0; i < numevents; i++) {
2122 ke.ident = ke11[i].ident;
2123 ke.filter = ke11[i].filter;
2124 ke.flags = ke11[i].flags;
2125 ke.fflags = ke11[i].fflags;
2126 ke.data = ke11[i].data;
2127 ke.udata = ke11[i].udata;
2128 print_kevent(fp, &ke);
2132 fprintf(fp, "0x%lx", args[sc->offset]);
2140 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2144 strmode(st.st_mode, mode);
2146 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2147 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2148 (long)st.st_blksize);
2150 fprintf(fp, "0x%lx", args[sc->offset]);
2155 struct freebsd11_stat st;
2157 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2161 strmode(st.st_mode, mode);
2163 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2164 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2165 (long)st.st_blksize);
2167 fprintf(fp, "0x%lx", args[sc->offset]);
2175 if (get_struct(pid, (void *)args[sc->offset], &buf,
2176 sizeof(buf)) != -1) {
2179 bzero(fsid, sizeof(fsid));
2180 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2181 for (i = 0; i < sizeof(buf.f_fsid); i++)
2182 snprintf(&fsid[i*2],
2183 sizeof(fsid) - (i*2), "%02x",
2184 ((u_char *)&buf.f_fsid)[i]);
2187 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2188 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2189 buf.f_mntfromname, fsid);
2191 fprintf(fp, "0x%lx", args[sc->offset]);
2198 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2201 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2202 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2203 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2204 ru.ru_inblock, ru.ru_oublock);
2206 fprintf(fp, "0x%lx", args[sc->offset]);
2212 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2214 fprintf(fp, "{ cur=%ju,max=%ju }",
2215 rl.rlim_cur, rl.rlim_max);
2217 fprintf(fp, "0x%lx", args[sc->offset]);
2223 if (get_struct(pid, (void *)args[sc->offset], &status,
2224 sizeof(status)) != -1) {
2226 if (WIFCONTINUED(status))
2227 fputs("CONTINUED", fp);
2228 else if (WIFEXITED(status))
2229 fprintf(fp, "EXITED,val=%d",
2230 WEXITSTATUS(status));
2231 else if (WIFSIGNALED(status))
2232 fprintf(fp, "SIGNALED,sig=%s%s",
2233 strsig2(WTERMSIG(status)),
2234 WCOREDUMP(status) ? ",cored" : "");
2236 fprintf(fp, "STOPPED,sig=%s",
2237 strsig2(WTERMSIG(status)));
2240 fprintf(fp, "0x%lx", args[sc->offset]);
2244 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2247 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2250 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2253 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2256 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2259 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2262 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2265 print_integer_arg(sysdecode_sysarch_number, fp,
2270 * The pipe() system call in the kernel returns its
2271 * two file descriptors via return values. However,
2272 * the interface exposed by libc is that pipe()
2273 * accepts a pointer to an array of descriptors.
2274 * Format the output to match the libc API by printing
2275 * the returned file descriptors as a fake argument.
2277 * Overwrite the first retval to signal a successful
2280 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
2287 len = args[sc->offset + 1];
2288 utrace_addr = calloc(1, len);
2289 if (get_struct(pid, (void *)args[sc->offset],
2290 (void *)utrace_addr, len) != -1)
2291 print_utrace(fp, utrace_addr, len);
2293 fprintf(fp, "0x%lx", args[sc->offset]);
2298 int descriptors[16];
2299 unsigned long i, ndescriptors;
2302 ndescriptors = args[sc->offset + 1];
2304 if (ndescriptors > nitems(descriptors)) {
2305 ndescriptors = nitems(descriptors);
2308 if (get_struct(pid, (void *)args[sc->offset],
2309 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2311 for (i = 0; i < ndescriptors; i++)
2312 fprintf(fp, i == 0 ? " %d" : ", %d",
2314 fprintf(fp, truncated ? ", ... }" : " }");
2316 fprintf(fp, "0x%lx", args[sc->offset]);
2320 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2322 case CapFcntlRights: {
2325 if (sc->type & OUT) {
2326 if (get_struct(pid, (void *)args[sc->offset], &rights,
2327 sizeof(rights)) == -1) {
2328 fprintf(fp, "0x%lx", args[sc->offset]);
2332 rights = args[sc->offset];
2333 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2337 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2342 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2343 fprintf(fp, "0x%x", rem);
2345 fprintf(fp, "|0x%x", rem);
2349 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2352 print_integer_arg(sysdecode_getfsstat_mode, fp,
2356 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2358 case Kldunloadflags:
2359 print_integer_arg(sysdecode_kldunload_flags, fp,
2363 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2366 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2368 case Sockprotocol: {
2370 int domain, protocol;
2372 domain = args[sc->offset - 2];
2373 protocol = args[sc->offset];
2374 if (protocol == 0) {
2377 temp = sysdecode_socket_protocol(domain, protocol);
2381 fprintf(fp, "%d", protocol);
2387 print_integer_arg(sysdecode_sockopt_level, fp,
2394 level = args[sc->offset - 1];
2395 name = args[sc->offset];
2396 temp = sysdecode_sockopt_name(level, name);
2400 fprintf(fp, "%d", name);
2405 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2408 cap_rights_t rights;
2410 if (get_struct(pid, (void *)args[sc->offset], &rights,
2411 sizeof(rights)) != -1) {
2413 sysdecode_cap_rights(fp, &rights);
2416 fprintf(fp, "0x%lx", args[sc->offset]);
2420 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2422 case Extattrnamespace:
2423 print_integer_arg(sysdecode_extattrnamespace, fp,
2427 print_integer_arg(sysdecode_minherit_inherit, fp,
2431 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2434 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2437 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2440 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2443 print_integer_arg(sysdecode_ptrace_request, fp,
2447 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2448 fprintf(fp, "%#x", (int)args[sc->offset]);
2451 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2454 print_integer_arg(sysdecode_rtprio_function, fp,
2458 print_integer_arg(sysdecode_scheduler_policy, fp,
2462 struct sched_param sp;
2464 if (get_struct(pid, (void *)args[sc->offset], &sp,
2466 fprintf(fp, "{ %d }", sp.sched_priority);
2468 fprintf(fp, "0x%lx", args[sc->offset]);
2474 if (get_struct(pid, (void *)args[sc->offset], &sig,
2476 fprintf(fp, "{ %s }", strsig2(sig));
2478 fprintf(fp, "0x%lx", args[sc->offset]);
2484 if (get_struct(pid, (void *)args[sc->offset], &si,
2485 sizeof(si)) != -1) {
2486 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2487 decode_siginfo(fp, &si);
2490 fprintf(fp, "0x%lx", args[sc->offset]);
2495 * Print argument as an array of struct iovec, where the next
2496 * syscall argument is the number of elements of the array.
2499 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2500 (int)args[sc->offset + 1]);
2502 case Sctpsndrcvinfo: {
2503 struct sctp_sndrcvinfo info;
2505 if (get_struct(pid, (void *)args[sc->offset],
2506 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2507 fprintf(fp, "0x%lx", args[sc->offset]);
2510 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2514 struct msghdr msghdr;
2516 if (get_struct(pid, (void *)args[sc->offset],
2517 &msghdr, sizeof(struct msghdr)) == -1) {
2518 fprintf(fp, "0x%lx", args[sc->offset]);
2522 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2523 fprintf(fp, ",%d,", msghdr.msg_namelen);
2524 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2525 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2526 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2527 fprintf(fp, ",%u,", msghdr.msg_controllen);
2528 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2533 case CloudABIAdvice:
2534 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2536 case CloudABIClockID:
2537 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2539 case CloudABIFDSFlags:
2540 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2542 case CloudABIFDStat: {
2543 cloudabi_fdstat_t fds;
2544 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2546 fprintf(fp, "{ %s, ",
2547 xlookup(cloudabi_filetype, fds.fs_filetype));
2548 fprintf(fp, "%s, ... }",
2549 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2551 fprintf(fp, "0x%lx", args[sc->offset]);
2554 case CloudABIFileStat: {
2555 cloudabi_filestat_t fsb;
2556 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2558 fprintf(fp, "{ %s, %ju }",
2559 xlookup(cloudabi_filetype, fsb.st_filetype),
2560 (uintmax_t)fsb.st_size);
2562 fprintf(fp, "0x%lx", args[sc->offset]);
2565 case CloudABIFileType:
2566 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2568 case CloudABIFSFlags:
2569 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2571 case CloudABILookup:
2572 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2573 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2574 (int)args[sc->offset]);
2576 fprintf(fp, "%d", (int)args[sc->offset]);
2578 case CloudABIMFlags:
2579 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2582 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2584 case CloudABIMSFlags:
2585 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2587 case CloudABIOFlags:
2588 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2590 case CloudABISDFlags:
2591 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2593 case CloudABISignal:
2594 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2596 case CloudABITimestamp:
2597 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2598 args[sc->offset] % 1000000000);
2600 case CloudABIULFlags:
2601 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2603 case CloudABIWhence:
2604 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2608 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2615 * Print (to outfile) the system call and its arguments.
2618 print_syscall(struct trussinfo *trussinfo)
2620 struct threadinfo *t;
2625 t = trussinfo->curthread;
2627 name = t->cs.sc->name;
2628 nargs = t->cs.nargs;
2629 s_args = t->cs.s_args;
2631 len = print_line_prefix(trussinfo);
2632 len += fprintf(trussinfo->outfile, "%s(", name);
2634 for (i = 0; i < nargs; i++) {
2635 if (s_args[i] != NULL)
2636 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2638 len += fprintf(trussinfo->outfile,
2639 "<missing argument>");
2640 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2643 len += fprintf(trussinfo->outfile, ")");
2644 for (i = 0; i < 6 - (len / 8); i++)
2645 fprintf(trussinfo->outfile, "\t");
2649 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2651 struct timespec timediff;
2652 struct threadinfo *t;
2656 t = trussinfo->curthread;
2658 if (trussinfo->flags & COUNTONLY) {
2659 timespecsub(&t->after, &t->before, &timediff);
2660 timespecadd(&sc->time, &timediff, &sc->time);
2667 print_syscall(trussinfo);
2668 fflush(trussinfo->outfile);
2670 if (retval == NULL) {
2672 * This system call resulted in the current thread's exit,
2673 * so there is no return value or error to display.
2675 fprintf(trussinfo->outfile, "\n");
2680 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2682 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2683 error == INT_MAX ? "Unknown error" : strerror(error));
2686 else if (sc->ret_type == 2) {
2689 #if _BYTE_ORDER == _LITTLE_ENDIAN
2690 off = (off_t)retval[1] << 32 | retval[0];
2692 off = (off_t)retval[0] << 32 | retval[1];
2694 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2699 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2704 print_summary(struct trussinfo *trussinfo)
2706 struct timespec total = {0, 0};
2710 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2711 "syscall", "seconds", "calls", "errors");
2713 STAILQ_FOREACH(sc, &syscalls, entries)
2715 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2716 sc->name, (intmax_t)sc->time.tv_sec,
2717 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2718 timespecadd(&total, &sc->time, &total);
2719 ncall += sc->ncalls;
2720 nerror += sc->nerror;
2722 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2723 "", "-------------", "-------", "-------");
2724 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2725 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);