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
56 #include <netinet/in.h>
57 #include <netinet/sctp.h>
58 #include <arpa/inet.h>
71 #include <sysdecode.h>
75 #include <contrib/cloudabi/cloudabi_types_common.h>
82 * This should probably be in its own file, sorted alphabetically.
84 static struct syscall decoded_syscalls[] = {
86 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
87 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
88 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
89 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
90 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
91 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
92 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
93 .args = { { Int, 0 }, { Acltype, 1 } } },
94 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
95 .args = { { Name, 0 }, { Acltype, 1 } } },
96 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
97 .args = { { Name, 0 }, { Acltype, 1 } } },
98 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
99 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
100 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
101 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
102 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
103 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
104 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
105 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
106 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
107 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
108 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
109 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
110 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
111 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
112 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
113 .args = { { Name | OUT, 0 }, { Int, 1 } } },
114 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
115 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
117 { .name = "accept", .ret_type = 1, .nargs = 3,
118 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
119 { .name = "access", .ret_type = 1, .nargs = 2,
120 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
121 { .name = "bind", .ret_type = 1, .nargs = 3,
122 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
123 { .name = "bindat", .ret_type = 1, .nargs = 4,
124 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
126 { .name = "break", .ret_type = 1, .nargs = 1,
127 .args = { { Ptr, 0 } } },
128 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
129 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
130 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
131 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
132 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
133 .args = { { PUInt | OUT, 0 } } },
134 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
135 .args = { { Int, 0 }, { CapRights, 1 } } },
136 { .name = "chdir", .ret_type = 1, .nargs = 1,
137 .args = { { Name, 0 } } },
138 { .name = "chflags", .ret_type = 1, .nargs = 2,
139 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
140 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
141 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
143 { .name = "chmod", .ret_type = 1, .nargs = 2,
144 .args = { { Name, 0 }, { Octal, 1 } } },
145 { .name = "chown", .ret_type = 1, .nargs = 3,
146 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
147 { .name = "chroot", .ret_type = 1, .nargs = 1,
148 .args = { { Name, 0 } } },
149 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
150 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
151 { .name = "close", .ret_type = 1, .nargs = 1,
152 .args = { { Int, 0 } } },
153 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
154 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
155 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
156 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
158 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
159 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
160 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
161 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
162 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
163 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
164 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
165 { .name = "connect", .ret_type = 1, .nargs = 3,
166 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
167 { .name = "connectat", .ret_type = 1, .nargs = 4,
168 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
170 { .name = "dup", .ret_type = 1, .nargs = 1,
171 .args = { { Int, 0 } } },
172 { .name = "dup2", .ret_type = 1, .nargs = 2,
173 .args = { { Int, 0 }, { Int, 1 } } },
174 { .name = "eaccess", .ret_type = 1, .nargs = 2,
175 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
176 { .name = "execve", .ret_type = 1, .nargs = 3,
177 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
178 { ExecEnv | IN, 2 } } },
179 { .name = "exit", .ret_type = 0, .nargs = 1,
180 .args = { { Hex, 0 } } },
181 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
182 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
183 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
184 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
185 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
186 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
187 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
188 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
189 { BinString | OUT, 3 }, { Sizet, 4 } } },
190 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
191 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
192 { BinString | OUT, 3 }, { Sizet, 4 } } },
193 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
194 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
195 { BinString | OUT, 3 }, { Sizet, 4 } } },
196 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
197 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
199 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
200 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
202 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
203 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
205 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
206 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
207 { BinString | IN, 3 }, { Sizet, 4 } } },
208 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
209 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
210 { BinString | IN, 3 }, { Sizet, 4 } } },
211 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
213 { BinString | IN, 3 }, { Sizet, 4 } } },
214 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
215 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
216 { Extattrnamespace, 3 }, { Name, 4 } } },
217 { .name = "faccessat", .ret_type = 1, .nargs = 4,
218 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
220 { .name = "fchflags", .ret_type = 1, .nargs = 2,
221 .args = { { Int, 0 }, { FileFlags, 1 } } },
222 { .name = "fchmod", .ret_type = 1, .nargs = 2,
223 .args = { { Int, 0 }, { Octal, 1 } } },
224 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
225 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
226 { .name = "fchown", .ret_type = 1, .nargs = 3,
227 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
228 { .name = "fchownat", .ret_type = 1, .nargs = 5,
229 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
231 { .name = "fcntl", .ret_type = 1, .nargs = 3,
232 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
233 { .name = "flock", .ret_type = 1, .nargs = 2,
234 .args = { { Int, 0 }, { Flockop, 1 } } },
235 { .name = "fstat", .ret_type = 1, .nargs = 2,
236 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
237 { .name = "fstatat", .ret_type = 1, .nargs = 4,
238 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
240 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
241 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
242 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
243 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
244 { .name = "futimens", .ret_type = 1, .nargs = 2,
245 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
246 { .name = "futimes", .ret_type = 1, .nargs = 2,
247 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
248 { .name = "futimesat", .ret_type = 1, .nargs = 3,
249 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
250 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
251 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
252 { PQuadHex | OUT, 3 } } },
253 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
254 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
255 { .name = "getitimer", .ret_type = 1, .nargs = 2,
256 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
257 { .name = "getpeername", .ret_type = 1, .nargs = 3,
258 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
259 { .name = "getpgid", .ret_type = 1, .nargs = 1,
260 .args = { { Int, 0 } } },
261 { .name = "getpriority", .ret_type = 1, .nargs = 2,
262 .args = { { Priowhich, 0 }, { Int, 1 } } },
263 { .name = "getrandom", .ret_type = 1, .nargs = 3,
264 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
265 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
266 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
267 { .name = "getrusage", .ret_type = 1, .nargs = 2,
268 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
269 { .name = "getsid", .ret_type = 1, .nargs = 1,
270 .args = { { Int, 0 } } },
271 { .name = "getsockname", .ret_type = 1, .nargs = 3,
272 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
273 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
274 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
275 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
276 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
277 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
278 { .name = "ioctl", .ret_type = 1, .nargs = 3,
279 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
280 { .name = "kevent", .ret_type = 1, .nargs = 6,
281 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
282 { Int, 4 }, { Timespec, 5 } } },
283 { .name = "kill", .ret_type = 1, .nargs = 2,
284 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
285 { .name = "kldfind", .ret_type = 1, .nargs = 1,
286 .args = { { Name | IN, 0 } } },
287 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
288 .args = { { Int, 0 } } },
289 { .name = "kldload", .ret_type = 1, .nargs = 1,
290 .args = { { Name | IN, 0 } } },
291 { .name = "kldnext", .ret_type = 1, .nargs = 1,
292 .args = { { Int, 0 } } },
293 { .name = "kldstat", .ret_type = 1, .nargs = 2,
294 .args = { { Int, 0 }, { Ptr, 1 } } },
295 { .name = "kldsym", .ret_type = 1, .nargs = 3,
296 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
297 { .name = "kldunload", .ret_type = 1, .nargs = 1,
298 .args = { { Int, 0 } } },
299 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
300 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
301 { .name = "kse_release", .ret_type = 0, .nargs = 1,
302 .args = { { Timespec, 0 } } },
303 { .name = "lchflags", .ret_type = 1, .nargs = 2,
304 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
305 { .name = "lchmod", .ret_type = 1, .nargs = 2,
306 .args = { { Name, 0 }, { Octal, 1 } } },
307 { .name = "lchown", .ret_type = 1, .nargs = 3,
308 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
309 { .name = "link", .ret_type = 1, .nargs = 2,
310 .args = { { Name, 0 }, { Name, 1 } } },
311 { .name = "linkat", .ret_type = 1, .nargs = 5,
312 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
314 { .name = "listen", .ret_type = 1, .nargs = 2,
315 .args = { { Int, 0 }, { Int, 1 } } },
316 { .name = "lseek", .ret_type = 2, .nargs = 3,
317 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
318 { .name = "lstat", .ret_type = 1, .nargs = 2,
319 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
320 { .name = "lutimes", .ret_type = 1, .nargs = 2,
321 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
322 { .name = "madvise", .ret_type = 1, .nargs = 3,
323 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
324 { .name = "minherit", .ret_type = 1, .nargs = 3,
325 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
326 { .name = "mkdir", .ret_type = 1, .nargs = 2,
327 .args = { { Name, 0 }, { Octal, 1 } } },
328 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
329 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
330 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
331 .args = { { Name, 0 }, { Octal, 1 } } },
332 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
333 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
334 { .name = "mknod", .ret_type = 1, .nargs = 3,
335 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
336 { .name = "mknodat", .ret_type = 1, .nargs = 4,
337 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
338 { .name = "mlock", .ret_type = 1, .nargs = 2,
339 .args = { { Ptr, 0 }, { Sizet, 1 } } },
340 { .name = "mlockall", .ret_type = 1, .nargs = 1,
341 .args = { { Mlockall, 0 } } },
342 { .name = "mmap", .ret_type = 1, .nargs = 6,
343 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
344 { Int, 4 }, { QuadHex, 5 } } },
345 { .name = "modfind", .ret_type = 1, .nargs = 1,
346 .args = { { Name | IN, 0 } } },
347 { .name = "mount", .ret_type = 1, .nargs = 4,
348 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
349 { .name = "mprotect", .ret_type = 1, .nargs = 3,
350 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
351 { .name = "msync", .ret_type = 1, .nargs = 3,
352 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
353 { .name = "munlock", .ret_type = 1, .nargs = 2,
354 .args = { { Ptr, 0 }, { Sizet, 1 } } },
355 { .name = "munmap", .ret_type = 1, .nargs = 2,
356 .args = { { Ptr, 0 }, { Sizet, 1 } } },
357 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
358 .args = { { Timespec, 0 } } },
359 { .name = "nmount", .ret_type = 1, .nargs = 3,
360 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
361 { .name = "open", .ret_type = 1, .nargs = 3,
362 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
363 { .name = "openat", .ret_type = 1, .nargs = 4,
364 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
366 { .name = "pathconf", .ret_type = 1, .nargs = 2,
367 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
368 { .name = "pipe", .ret_type = 1, .nargs = 1,
369 .args = { { PipeFds | OUT, 0 } } },
370 { .name = "pipe2", .ret_type = 1, .nargs = 2,
371 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
372 { .name = "poll", .ret_type = 1, .nargs = 3,
373 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
374 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
375 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
377 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
378 .args = { { Open, 0 } } },
379 { .name = "pread", .ret_type = 1, .nargs = 4,
380 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
382 { .name = "procctl", .ret_type = 1, .nargs = 4,
383 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
384 { .name = "ptrace", .ret_type = 1, .nargs = 4,
385 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
386 { .name = "pwrite", .ret_type = 1, .nargs = 4,
387 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
389 { .name = "quotactl", .ret_type = 1, .nargs = 4,
390 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
391 { .name = "read", .ret_type = 1, .nargs = 3,
392 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
393 { .name = "readlink", .ret_type = 1, .nargs = 3,
394 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
395 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
396 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
398 { .name = "readv", .ret_type = 1, .nargs = 3,
399 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
400 { .name = "reboot", .ret_type = 1, .nargs = 1,
401 .args = { { Reboothowto, 0 } } },
402 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
403 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
404 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
405 { Ptr | OUT, 5 } } },
406 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
407 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
408 { .name = "rename", .ret_type = 1, .nargs = 2,
409 .args = { { Name, 0 }, { Name, 1 } } },
410 { .name = "renameat", .ret_type = 1, .nargs = 4,
411 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
412 { .name = "rfork", .ret_type = 1, .nargs = 1,
413 .args = { { Rforkflags, 0 } } },
414 { .name = "rmdir", .ret_type = 1, .nargs = 1,
415 .args = { { Name, 0 } } },
416 { .name = "rtprio", .ret_type = 1, .nargs = 3,
417 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
418 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
419 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
420 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
421 .args = { { Schedpolicy, 0 } } },
422 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
423 .args = { { Schedpolicy, 0 } } },
424 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
425 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
426 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
427 .args = { { Int, 0 } } },
428 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
429 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
430 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
431 .args = { { Int, 0 }, { Schedparam, 1 } } },
432 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
433 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
434 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
435 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
436 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
437 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
438 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
439 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
440 { Sockaddr | IN, 3 }, { Socklent, 4 },
441 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
442 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
443 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
444 { Sockaddr | IN, 3 }, { Socklent, 4 },
445 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
446 { .name = "select", .ret_type = 1, .nargs = 5,
447 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
449 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
450 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
451 { .name = "sendto", .ret_type = 1, .nargs = 6,
452 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
453 { Msgflags, 3 }, { Sockaddr | IN, 4 },
454 { Socklent | IN, 5 } } },
455 { .name = "setitimer", .ret_type = 1, .nargs = 3,
456 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
457 { .name = "setpriority", .ret_type = 1, .nargs = 3,
458 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
459 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
460 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
461 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
462 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
463 { Ptr | IN, 3 }, { Socklent, 4 } } },
464 { .name = "shutdown", .ret_type = 1, .nargs = 2,
465 .args = { { Int, 0 }, { Shutdown, 1 } } },
466 { .name = "sigaction", .ret_type = 1, .nargs = 3,
467 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
468 { Sigaction | OUT, 2 } } },
469 { .name = "sigpending", .ret_type = 1, .nargs = 1,
470 .args = { { Sigset | OUT, 0 } } },
471 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
472 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
473 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
474 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
475 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
476 .args = { { Ptr, 0 } } },
477 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
478 .args = { { Sigset | IN, 0 } } },
479 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
480 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
481 { Timespec | IN, 2 } } },
482 { .name = "sigwait", .ret_type = 1, .nargs = 2,
483 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
484 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
485 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
486 { .name = "socket", .ret_type = 1, .nargs = 3,
487 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
488 { .name = "stat", .ret_type = 1, .nargs = 2,
489 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
490 { .name = "statfs", .ret_type = 1, .nargs = 2,
491 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
492 { .name = "symlink", .ret_type = 1, .nargs = 2,
493 .args = { { Name, 0 }, { Name, 1 } } },
494 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
495 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
496 { .name = "sysarch", .ret_type = 1, .nargs = 2,
497 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
498 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
499 .args = { { Long, 0 }, { Signal, 1 } } },
500 { .name = "thr_self", .ret_type = 1, .nargs = 1,
501 .args = { { Ptr, 0 } } },
502 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
503 .args = { { Long, 0 }, { Name, 1 } } },
504 { .name = "truncate", .ret_type = 1, .nargs = 2,
505 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
508 { .name = "umount", .ret_type = 1, .nargs = 2,
509 .args = { { Name, 0 }, { Int, 2 } } },
511 { .name = "unlink", .ret_type = 1, .nargs = 1,
512 .args = { { Name, 0 } } },
513 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
514 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
515 { .name = "unmount", .ret_type = 1, .nargs = 2,
516 .args = { { Name, 0 }, { Mountflags, 1 } } },
517 { .name = "utimensat", .ret_type = 1, .nargs = 4,
518 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
520 { .name = "utimes", .ret_type = 1, .nargs = 2,
521 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
522 { .name = "utrace", .ret_type = 1, .nargs = 1,
523 .args = { { Utrace, 0 } } },
524 { .name = "wait4", .ret_type = 1, .nargs = 4,
525 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
526 { Rusage | OUT, 3 } } },
527 { .name = "wait6", .ret_type = 1, .nargs = 6,
528 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
529 { Waitoptions, 3 }, { Rusage | OUT, 4 },
530 { Siginfo | OUT, 5 } } },
531 { .name = "write", .ret_type = 1, .nargs = 3,
532 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
533 { .name = "writev", .ret_type = 1, .nargs = 3,
534 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
537 { .name = "linux_access", .ret_type = 1, .nargs = 2,
538 .args = { { Name, 0 }, { Accessmode, 1 } } },
539 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
540 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
541 { ExecEnv | IN, 2 } } },
542 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
543 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
544 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
545 .args = { { Name | IN, 0 }, { Int, 1 } } },
546 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
547 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
548 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
549 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
550 { .name = "linux_open", .ret_type = 1, .nargs = 3,
551 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
552 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
553 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
554 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
555 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
556 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
557 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
559 /* CloudABI system calls. */
560 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
561 .args = { { CloudABIClockID, 0 } } },
562 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
563 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
564 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
565 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
566 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
567 .args = { { Int, 0 } } },
568 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
569 .args = { { CloudABIFileType, 0 } } },
570 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
571 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
572 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
573 .args = { { Int, 0 } } },
574 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
575 .args = { { Int, 0 } } },
576 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
577 .args = { { Int, 0 }, { Int, 1 } } },
578 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
579 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
580 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
581 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
582 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
583 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
584 { CloudABIFDSFlags, 2 } } },
585 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
586 .args = { { Int, 0 } } },
587 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
588 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
589 { CloudABIAdvice, 3 } } },
590 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
591 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
592 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
593 .args = { { Int, 0 }, { BinString | IN, 1 },
594 { CloudABIFileType, 3 } } },
595 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
596 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
597 { Int, 3 }, { BinString | IN, 4 } } },
598 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
599 .args = { { Int, 0 }, { BinString | IN, 1 },
600 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
601 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
602 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
604 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
605 .args = { { Int, 0 }, { BinString | IN, 1 },
606 { BinString | OUT, 3 }, { Int, 4 } } },
607 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
608 .args = { { Int, 0 }, { BinString | IN, 1 },
609 { Int, 3 }, { BinString | IN, 4 } } },
610 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
611 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
612 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
613 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
614 { CloudABIFSFlags, 2 } } },
615 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
616 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
617 { CloudABIFileStat | OUT, 3 } } },
618 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
619 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
620 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
621 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
622 .args = { { BinString | IN, 0 },
623 { Int, 2 }, { BinString | IN, 3 } } },
624 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
625 .args = { { Int, 0 }, { BinString | IN, 1 },
626 { CloudABIULFlags, 3 } } },
627 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
628 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
629 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
630 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
631 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
632 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
633 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
634 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
635 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
636 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
637 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
638 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
639 .args = { { Ptr, 0 }, { Int, 1 } } },
640 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
641 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
642 { IntArray, 3 }, { Int, 4 } } },
643 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
644 .args = { { Int, 0 } } },
645 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
646 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
647 .args = { { CloudABISignal, 0 } } },
648 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
649 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
650 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
651 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
652 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
653 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
654 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
658 static STAILQ_HEAD(, syscall) syscalls;
660 /* Xlat idea taken from strace */
666 #define X(a) { a, #a },
667 #define XEND { 0, NULL }
669 static struct xlat poll_flags[] = {
670 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
671 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
672 X(POLLWRBAND) X(POLLINIGNEOF) XEND
675 static struct xlat sigaction_flags[] = {
676 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
677 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
680 static struct xlat linux_socketcall_ops[] = {
681 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
682 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
683 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
684 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
685 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
690 #define X(a) { CLOUDABI_##a, #a },
692 static struct xlat cloudabi_advice[] = {
693 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
694 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
698 static struct xlat cloudabi_clockid[] = {
699 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
700 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
704 static struct xlat cloudabi_fdflags[] = {
705 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
706 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
710 static struct xlat cloudabi_fdsflags[] = {
711 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
715 static struct xlat cloudabi_filetype[] = {
716 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
717 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
718 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
719 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
720 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
724 static struct xlat cloudabi_fsflags[] = {
725 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
726 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
730 static struct xlat cloudabi_mflags[] = {
731 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
735 static struct xlat cloudabi_mprot[] = {
736 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
740 static struct xlat cloudabi_msflags[] = {
741 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
745 static struct xlat cloudabi_oflags[] = {
746 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
750 static struct xlat cloudabi_sdflags[] = {
751 X(SHUT_RD) X(SHUT_WR)
755 static struct xlat cloudabi_signal[] = {
756 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
757 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
758 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
759 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
760 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
764 static struct xlat cloudabi_ulflags[] = {
769 static struct xlat cloudabi_whence[] = {
770 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
778 * Searches an xlat array for a value, and returns it if found. Otherwise
779 * return a string representation.
782 lookup(struct xlat *xlat, int val, int base)
786 for (; xlat->str != NULL; xlat++)
787 if (xlat->val == val)
791 sprintf(tmp, "0%o", val);
794 sprintf(tmp, "0x%x", val);
797 sprintf(tmp, "%u", val);
800 errx(1,"Unknown lookup base");
807 xlookup(struct xlat *xlat, int val)
810 return (lookup(xlat, val, 16));
814 * Searches an xlat array containing bitfield values. Remaining bits
815 * set after removing the known ones are printed at the end:
819 xlookup_bits(struct xlat *xlat, int val)
822 static char str[512];
826 for (; xlat->str != NULL; xlat++) {
827 if ((xlat->val & rem) == xlat->val) {
829 * Don't print the "all-bits-zero" string unless all
830 * bits are really zero.
832 if (xlat->val == 0 && val != 0)
834 len += sprintf(str + len, "%s|", xlat->str);
840 * If we have leftover bits or didn't match anything, print
844 len += sprintf(str + len, "0x%x", rem);
845 if (len && str[len - 1] == '|')
852 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
856 str = decoder(value);
860 fprintf(fp, "%d", value);
864 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
868 if (!decoder(fp, value, &rem))
869 fprintf(fp, "0x%x", rem);
871 fprintf(fp, "|0x%x", rem);
875 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
880 if (!decoder(fp, value, &rem))
881 fprintf(fp, "0x%x", rem);
883 fprintf(fp, "|0x%x", rem);
888 * Add argument padding to subsequent system calls afater a Quad
889 * syscall arguments as needed. This used to be done by hand in the
890 * decoded_syscalls table which was ugly and error prone. It is
891 * simpler to do the fixup of offsets at initalization time than when
892 * decoding arguments.
895 quad_fixup(struct syscall *sc)
902 for (i = 0; i < sc->nargs; i++) {
903 /* This arg type is a dummy that doesn't use offset. */
904 if ((sc->args[i].type & ARG_MASK) == PipeFds)
907 assert(prev < sc->args[i].offset);
908 prev = sc->args[i].offset;
909 sc->args[i].offset += offset;
910 switch (sc->args[i].type & ARG_MASK) {
915 * 64-bit arguments on 32-bit powerpc must be
916 * 64-bit aligned. If the current offset is
917 * not aligned, the calling convention inserts
918 * a 32-bit pad argument that should be skipped.
920 if (sc->args[i].offset % 2 == 1) {
921 sc->args[i].offset++;
938 STAILQ_INIT(&syscalls);
939 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
943 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
947 static struct syscall *
948 find_syscall(struct procabi *abi, u_int number)
950 struct extra_syscall *es;
952 if (number < nitems(abi->syscalls))
953 return (abi->syscalls[number]);
954 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
955 if (es->number == number)
962 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
964 struct extra_syscall *es;
966 if (number < nitems(abi->syscalls)) {
967 assert(abi->syscalls[number] == NULL);
968 abi->syscalls[number] = sc;
970 es = malloc(sizeof(*es));
973 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
978 * If/when the list gets big, it might be desirable to do it
979 * as a hash table or binary search.
982 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
989 sc = find_syscall(t->proc->abi, number);
993 name = sysdecode_syscallname(t->proc->abi->abi, number);
995 asprintf(&new_name, "#%d", number);
999 STAILQ_FOREACH(sc, &syscalls, entries) {
1000 if (strcmp(name, sc->name) == 0) {
1001 add_syscall(t->proc->abi, number, sc);
1007 /* It is unknown. Add it into the list. */
1009 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1013 sc = calloc(1, sizeof(struct syscall));
1015 if (new_name != NULL)
1019 for (i = 0; i < nargs; i++) {
1020 sc->args[i].offset = i;
1021 /* Treat all unknown arguments as LongHex. */
1022 sc->args[i].type = LongHex;
1024 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1025 add_syscall(t->proc->abi, number, sc);
1031 * Copy a fixed amount of bytes from the process.
1034 get_struct(pid_t pid, void *offset, void *buf, int len)
1036 struct ptrace_io_desc iorequest;
1038 iorequest.piod_op = PIOD_READ_D;
1039 iorequest.piod_offs = offset;
1040 iorequest.piod_addr = buf;
1041 iorequest.piod_len = len;
1042 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1047 #define MAXSIZE 4096
1050 * Copy a string from the process. Note that it is
1051 * expected to be a C string, but if max is set, it will
1052 * only get that much.
1055 get_string(pid_t pid, void *addr, int max)
1057 struct ptrace_io_desc iorequest;
1059 size_t offset, size, totalsize;
1065 /* Read up to the end of the current page. */
1066 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1071 buf = malloc(totalsize);
1075 iorequest.piod_op = PIOD_READ_D;
1076 iorequest.piod_offs = (char *)addr + offset;
1077 iorequest.piod_addr = buf + offset;
1078 iorequest.piod_len = size;
1079 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1083 if (memchr(buf + offset, '\0', size) != NULL)
1086 if (totalsize < MAXSIZE && max == 0) {
1087 size = MAXSIZE - totalsize;
1088 if (size > PAGE_SIZE)
1090 nbuf = realloc(buf, totalsize + size);
1092 buf[totalsize - 1] = '\0';
1098 buf[totalsize - 1] = '\0';
1107 static char tmp[32];
1108 const char *signame;
1110 signame = sysdecode_signal(sig);
1111 if (signame == NULL) {
1112 snprintf(tmp, sizeof(tmp), "%d", sig);
1119 print_kevent(FILE *fp, struct kevent *ke)
1122 switch (ke->filter) {
1128 case EVFILT_PROCDESC:
1130 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1133 fputs(strsig2(ke->ident), fp);
1136 fprintf(fp, "%p", (void *)ke->ident);
1139 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1141 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1143 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1144 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1148 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1150 unsigned char *utrace_buffer;
1153 if (sysdecode_utrace(fp, utrace_addr, len)) {
1158 utrace_buffer = utrace_addr;
1159 fprintf(fp, "%zu:", len);
1161 fprintf(fp, " %02x", *utrace_buffer++);
1166 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1169 struct sockaddr_in *lsin;
1170 struct sockaddr_in6 *lsin6;
1171 struct sockaddr_un *sun;
1172 struct sockaddr *sa;
1174 pid_t pid = trussinfo->curthread->proc->pid;
1180 /* If the length is too small, just bail. */
1181 if (len < sizeof(*sa)) {
1182 fprintf(fp, "%p", arg);
1186 sa = calloc(1, len);
1187 if (get_struct(pid, arg, sa, len) == -1) {
1189 fprintf(fp, "%p", arg);
1193 switch (sa->sa_family) {
1195 if (len < sizeof(*lsin))
1196 goto sockaddr_short;
1197 lsin = (struct sockaddr_in *)(void *)sa;
1198 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1199 fprintf(fp, "{ AF_INET %s:%d }", addr,
1200 htons(lsin->sin_port));
1203 if (len < sizeof(*lsin6))
1204 goto sockaddr_short;
1205 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1206 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1208 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1209 htons(lsin6->sin6_port));
1212 sun = (struct sockaddr_un *)sa;
1213 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1214 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1220 "{ sa_len = %d, sa_family = %d, sa_data = {",
1221 (int)sa->sa_len, (int)sa->sa_family);
1222 for (q = (u_char *)sa->sa_data;
1223 q < (u_char *)sa + len; q++)
1224 fprintf(fp, "%s 0x%02x",
1225 q == (u_char *)sa->sa_data ? "" : ",",
1232 #define IOV_LIMIT 16
1235 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1237 struct iovec iov[IOV_LIMIT];
1238 size_t max_string = trussinfo->strsize;
1239 char tmp2[max_string + 1], *tmp3;
1241 pid_t pid = trussinfo->curthread->proc->pid;
1243 bool buf_truncated, iov_truncated;
1246 fprintf(fp, "%p", arg);
1249 if (iovcnt > IOV_LIMIT) {
1251 iov_truncated = true;
1253 iov_truncated = false;
1255 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1256 fprintf(fp, "%p", arg);
1261 for (i = 0; i < iovcnt; i++) {
1262 len = iov[i].iov_len;
1263 if (len > max_string) {
1265 buf_truncated = true;
1267 buf_truncated = false;
1269 fprintf(fp, "%s{", (i > 0) ? "," : "");
1270 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1271 tmp3 = malloc(len * 4 + 1);
1273 if (strvisx(tmp3, tmp2, len,
1274 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1278 buf_truncated = true;
1280 fprintf(fp, "\"%s\"%s", tmp3,
1281 buf_truncated ? "..." : "");
1284 fprintf(fp, "%p", iov[i].iov_base);
1286 fprintf(fp, ",%zu}", iov[i].iov_len);
1288 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1292 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1297 for (q = CMSG_DATA(cmsghdr);
1298 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1299 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1305 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1307 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1308 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1309 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1310 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1314 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1316 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1318 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1321 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1322 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1324 fprintf(fp, "ctx=%u,", info->sinfo_context);
1325 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1328 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1329 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1331 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1335 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1337 fprintf(fp, "{sid=%u,", info->snd_sid);
1339 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1340 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1341 fprintf(fp, "ctx=%u,", info->snd_context);
1342 fprintf(fp, "id=%u}", info->snd_assoc_id);
1346 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1348 fprintf(fp, "{sid=%u,", info->rcv_sid);
1349 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1351 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1352 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1353 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1354 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1355 fprintf(fp, "ctx=%u,", info->rcv_context);
1356 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1360 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1362 fprintf(fp, "{sid=%u,", info->nxt_sid);
1364 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1365 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1366 fprintf(fp, "len=%u,", info->nxt_length);
1367 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1371 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1374 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1375 fprintf(fp, ",val=%u}", info->pr_value);
1379 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1381 fprintf(fp, "{num=%u}", info->auth_keynumber);
1385 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1387 char buf[INET_ADDRSTRLEN];
1390 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1392 fprintf(fp, "{addr=%s}", s);
1394 fputs("{addr=???}", fp);
1398 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1400 char buf[INET6_ADDRSTRLEN];
1403 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1405 fprintf(fp, "{addr=%s}", s);
1407 fputs("{addr=???}", fp);
1411 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1416 len = cmsghdr->cmsg_len;
1417 data = CMSG_DATA(cmsghdr);
1418 switch (cmsghdr->cmsg_type) {
1420 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1421 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1423 print_gen_cmsg(fp, cmsghdr);
1426 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1427 print_sctp_sndrcvinfo(fp, receive,
1428 (struct sctp_sndrcvinfo *)data);
1430 print_gen_cmsg(fp, cmsghdr);
1434 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1435 print_sctp_extrcvinfo(fp,
1436 (struct sctp_extrcvinfo *)data);
1438 print_gen_cmsg(fp, cmsghdr);
1442 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1443 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1445 print_gen_cmsg(fp, cmsghdr);
1448 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1449 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1451 print_gen_cmsg(fp, cmsghdr);
1454 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1455 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1457 print_gen_cmsg(fp, cmsghdr);
1460 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1461 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1463 print_gen_cmsg(fp, cmsghdr);
1466 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1467 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1469 print_gen_cmsg(fp, cmsghdr);
1471 case SCTP_DSTADDRV4:
1472 if (len == CMSG_LEN(sizeof(struct in_addr)))
1473 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1475 print_gen_cmsg(fp, cmsghdr);
1477 case SCTP_DSTADDRV6:
1478 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1479 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1481 print_gen_cmsg(fp, cmsghdr);
1484 print_gen_cmsg(fp, cmsghdr);
1489 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1491 struct cmsghdr *cmsghdr;
1498 len = msghdr->msg_controllen;
1503 cmsgbuf = calloc(1, len);
1504 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1505 fprintf(fp, "%p", msghdr->msg_control);
1509 msghdr->msg_control = cmsgbuf;
1512 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1514 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1515 level = cmsghdr->cmsg_level;
1516 type = cmsghdr->cmsg_type;
1517 len = cmsghdr->cmsg_len;
1518 fprintf(fp, "%s{level=", first ? "" : ",");
1519 print_integer_arg(sysdecode_sockopt_level, fp, level);
1520 fputs(",type=", fp);
1521 temp = sysdecode_cmsg_type(level, type);
1525 fprintf(fp, "%d", type);
1527 fputs(",data=", fp);
1530 print_sctp_cmsg(fp, receive, cmsghdr);
1533 print_gen_cmsg(fp, cmsghdr);
1544 * Converts a syscall argument into a string. Said string is
1545 * allocated via malloc(), so needs to be free()'d. sc is
1546 * a pointer to the syscall description (see above); args is
1547 * an array of all of the system call arguments.
1550 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1551 struct trussinfo *trussinfo)
1558 fp = open_memstream(&tmp, &tmplen);
1559 pid = trussinfo->curthread->proc->pid;
1560 switch (sc->type & ARG_MASK) {
1562 fprintf(fp, "0x%x", (int)args[sc->offset]);
1565 fprintf(fp, "0%o", (int)args[sc->offset]);
1568 fprintf(fp, "%d", (int)args[sc->offset]);
1571 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1576 if (get_struct(pid, (void *)args[sc->offset], &val,
1578 fprintf(fp, "{ %u }", val);
1580 fprintf(fp, "0x%lx", args[sc->offset]);
1584 fprintf(fp, "0x%lx", args[sc->offset]);
1587 fprintf(fp, "%ld", args[sc->offset]);
1590 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1593 /* NULL-terminated string. */
1596 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1597 fprintf(fp, "\"%s\"", tmp2);
1603 * Binary block of data that might have printable characters.
1604 * XXX If type|OUT, assume that the length is the syscall's
1605 * return value. Otherwise, assume that the length of the block
1606 * is in the next syscall argument.
1608 int max_string = trussinfo->strsize;
1609 char tmp2[max_string + 1], *tmp3;
1616 len = args[sc->offset + 1];
1619 * Don't print more than max_string characters, to avoid word
1620 * wrap. If we have to truncate put some ... after the string.
1622 if (len > max_string) {
1626 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1628 tmp3 = malloc(len * 4 + 1);
1630 if (strvisx(tmp3, tmp2, len,
1631 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1636 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1640 fprintf(fp, "0x%lx", args[sc->offset]);
1650 char buf[PAGE_SIZE];
1657 * Only parse argv[] and environment arrays from exec calls
1660 if (((sc->type & ARG_MASK) == ExecArgs &&
1661 (trussinfo->flags & EXECVEARGS) == 0) ||
1662 ((sc->type & ARG_MASK) == ExecEnv &&
1663 (trussinfo->flags & EXECVEENVS) == 0)) {
1664 fprintf(fp, "0x%lx", args[sc->offset]);
1669 * Read a page of pointers at a time. Punt if the top-level
1670 * pointer is not aligned. Note that the first read is of
1673 addr = args[sc->offset];
1674 if (addr % sizeof(char *) != 0) {
1675 fprintf(fp, "0x%lx", args[sc->offset]);
1679 len = PAGE_SIZE - (addr & PAGE_MASK);
1680 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1681 fprintf(fp, "0x%lx", args[sc->offset]);
1688 while (u.strarray[i] != NULL) {
1689 string = get_string(pid, u.strarray[i], 0);
1690 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1695 if (i == len / sizeof(char *)) {
1698 if (get_struct(pid, (void *)addr, u.buf, len) ==
1700 fprintf(fp, ", <inval>");
1711 fprintf(fp, "%ld", args[sc->offset]);
1714 fprintf(fp, "0x%lx", args[sc->offset]);
1719 unsigned long long ll;
1721 #if _BYTE_ORDER == _LITTLE_ENDIAN
1722 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1725 ll = (unsigned long long)args[sc->offset] << 32 |
1726 args[sc->offset + 1];
1728 if ((sc->type & ARG_MASK) == Quad)
1729 fprintf(fp, "%lld", ll);
1731 fprintf(fp, "0x%llx", ll);
1738 if (get_struct(pid, (void *)args[sc->offset], &val,
1740 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1742 fprintf(fp, "0x%lx", args[sc->offset]);
1746 fprintf(fp, "0x%lx", args[sc->offset]);
1751 if (retval[0] == -1)
1753 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1754 fprintf(fp, "\"%s\"", tmp2);
1762 cmd = args[sc->offset];
1763 temp = sysdecode_ioctlname(cmd);
1767 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1768 cmd, cmd & IOC_OUT ? "R" : "",
1769 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1770 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1771 cmd & 0xFF, IOCPARM_LEN(cmd));
1778 if (get_struct(pid, (void *)args[sc->offset], &ts,
1780 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1783 fprintf(fp, "0x%lx", args[sc->offset]);
1787 struct timespec ts[2];
1791 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1795 for (i = 0; i < nitems(ts); i++) {
1798 switch (ts[i].tv_nsec) {
1800 fprintf(fp, "UTIME_NOW");
1803 fprintf(fp, "UTIME_OMIT");
1806 fprintf(fp, "%jd.%09ld",
1807 (intmax_t)ts[i].tv_sec,
1814 fprintf(fp, "0x%lx", args[sc->offset]);
1820 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1822 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1825 fprintf(fp, "0x%lx", args[sc->offset]);
1829 struct timeval tv[2];
1831 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1833 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1834 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1835 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1837 fprintf(fp, "0x%lx", args[sc->offset]);
1841 struct itimerval itv;
1843 if (get_struct(pid, (void *)args[sc->offset], &itv,
1845 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1846 (intmax_t)itv.it_interval.tv_sec,
1847 itv.it_interval.tv_usec,
1848 (intmax_t)itv.it_value.tv_sec,
1849 itv.it_value.tv_usec);
1851 fprintf(fp, "0x%lx", args[sc->offset]);
1856 struct linux_socketcall_args largs;
1858 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1859 sizeof(largs)) != -1)
1860 fprintf(fp, "{ %s, 0x%lx }",
1861 lookup(linux_socketcall_ops, largs.what, 10),
1862 (long unsigned int)largs.args);
1864 fprintf(fp, "0x%lx", args[sc->offset]);
1869 * XXX: A Pollfd argument expects the /next/ syscall argument
1870 * to be the number of fds in the array. This matches the poll
1874 int numfds = args[sc->offset + 1];
1875 size_t bytes = sizeof(struct pollfd) * numfds;
1878 if ((pfd = malloc(bytes)) == NULL)
1879 err(1, "Cannot malloc %zu bytes for pollfd array",
1881 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1884 for (i = 0; i < numfds; i++) {
1885 fprintf(fp, " %d/%s", pfd[i].fd,
1886 xlookup_bits(poll_flags, pfd[i].events));
1890 fprintf(fp, "0x%lx", args[sc->offset]);
1897 * XXX: A Fd_set argument expects the /first/ syscall argument
1898 * to be the number of fds in the array. This matches the
1902 int numfds = args[0];
1903 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1906 if ((fds = malloc(bytes)) == NULL)
1907 err(1, "Cannot malloc %zu bytes for fd_set array",
1909 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1912 for (i = 0; i < numfds; i++) {
1913 if (FD_ISSET(i, fds))
1914 fprintf(fp, " %d", i);
1918 fprintf(fp, "0x%lx", args[sc->offset]);
1923 fputs(strsig2(args[sc->offset]), fp);
1930 sig = args[sc->offset];
1931 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1932 sizeof(ss)) == -1) {
1933 fprintf(fp, "0x%lx", args[sc->offset]);
1938 for (i = 1; i < sys_nsig; i++) {
1939 if (sigismember(&ss, i)) {
1940 fprintf(fp, "%s%s", !first ? "|" : "",
1951 print_integer_arg(sysdecode_sigprocmask_how, fp,
1955 /* XXX: Output depends on the value of the previous argument. */
1956 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1957 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1958 args[sc->offset], 16);
1961 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1964 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1967 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1970 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1973 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1976 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1979 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1982 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1985 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
1988 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
1991 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
1994 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
1999 if (args[sc->offset] == 0) {
2005 * Extract the address length from the next argument. If
2006 * this is an output sockaddr (OUT is set), then the
2007 * next argument is a pointer to a socklen_t. Otherwise
2008 * the next argument contains a socklen_t by value.
2010 if (sc->type & OUT) {
2011 if (get_struct(pid, (void *)args[sc->offset + 1],
2012 &len, sizeof(len)) == -1) {
2013 fprintf(fp, "0x%lx", args[sc->offset]);
2017 len = args[sc->offset + 1];
2019 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2023 struct sigaction sa;
2025 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2028 if (sa.sa_handler == SIG_DFL)
2029 fputs("SIG_DFL", fp);
2030 else if (sa.sa_handler == SIG_IGN)
2031 fputs("SIG_IGN", fp);
2033 fprintf(fp, "%p", sa.sa_handler);
2034 fprintf(fp, " %s ss_t }",
2035 xlookup_bits(sigaction_flags, sa.sa_flags));
2037 fprintf(fp, "0x%lx", args[sc->offset]);
2042 * XXX XXX: The size of the array is determined by either the
2043 * next syscall argument, or by the syscall return value,
2044 * depending on which argument number we are. This matches the
2045 * kevent syscall, but luckily that's the only syscall that uses
2053 if (sc->offset == 1)
2054 numevents = args[sc->offset+1];
2055 else if (sc->offset == 3 && retval[0] != -1)
2056 numevents = retval[0];
2058 if (numevents >= 0) {
2059 bytes = sizeof(struct kevent) * numevents;
2060 if ((ke = malloc(bytes)) == NULL)
2062 "Cannot malloc %zu bytes for kevent array",
2066 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2069 for (i = 0; i < numevents; i++) {
2071 print_kevent(fp, &ke[i]);
2075 fprintf(fp, "0x%lx", args[sc->offset]);
2081 struct kevent_freebsd11 *ke11;
2087 if (sc->offset == 1)
2088 numevents = args[sc->offset+1];
2089 else if (sc->offset == 3 && retval[0] != -1)
2090 numevents = retval[0];
2092 if (numevents >= 0) {
2093 bytes = sizeof(struct kevent_freebsd11) * numevents;
2094 if ((ke11 = malloc(bytes)) == NULL)
2096 "Cannot malloc %zu bytes for kevent array",
2100 memset(&ke, 0, sizeof(ke));
2101 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2102 ke11, bytes) != -1) {
2104 for (i = 0; i < numevents; i++) {
2106 ke.ident = ke11[i].ident;
2107 ke.filter = ke11[i].filter;
2108 ke.flags = ke11[i].flags;
2109 ke.fflags = ke11[i].fflags;
2110 ke.data = ke11[i].data;
2111 ke.udata = ke11[i].udata;
2112 print_kevent(fp, &ke);
2116 fprintf(fp, "0x%lx", args[sc->offset]);
2124 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2128 strmode(st.st_mode, mode);
2130 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2131 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2132 (long)st.st_blksize);
2134 fprintf(fp, "0x%lx", args[sc->offset]);
2139 struct freebsd11_stat st;
2141 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2145 strmode(st.st_mode, mode);
2147 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2148 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2149 (long)st.st_blksize);
2151 fprintf(fp, "0x%lx", args[sc->offset]);
2159 if (get_struct(pid, (void *)args[sc->offset], &buf,
2160 sizeof(buf)) != -1) {
2163 bzero(fsid, sizeof(fsid));
2164 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2165 for (i = 0; i < sizeof(buf.f_fsid); i++)
2166 snprintf(&fsid[i*2],
2167 sizeof(fsid) - (i*2), "%02x",
2168 ((u_char *)&buf.f_fsid)[i]);
2171 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2172 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2173 buf.f_mntfromname, fsid);
2175 fprintf(fp, "0x%lx", args[sc->offset]);
2182 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2185 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2186 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2187 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2188 ru.ru_inblock, ru.ru_oublock);
2190 fprintf(fp, "0x%lx", args[sc->offset]);
2196 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2198 fprintf(fp, "{ cur=%ju,max=%ju }",
2199 rl.rlim_cur, rl.rlim_max);
2201 fprintf(fp, "0x%lx", args[sc->offset]);
2207 if (get_struct(pid, (void *)args[sc->offset], &status,
2208 sizeof(status)) != -1) {
2210 if (WIFCONTINUED(status))
2211 fputs("CONTINUED", fp);
2212 else if (WIFEXITED(status))
2213 fprintf(fp, "EXITED,val=%d",
2214 WEXITSTATUS(status));
2215 else if (WIFSIGNALED(status))
2216 fprintf(fp, "SIGNALED,sig=%s%s",
2217 strsig2(WTERMSIG(status)),
2218 WCOREDUMP(status) ? ",cored" : "");
2220 fprintf(fp, "STOPPED,sig=%s",
2221 strsig2(WTERMSIG(status)));
2224 fprintf(fp, "0x%lx", args[sc->offset]);
2228 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2231 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2234 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2237 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2240 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2243 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2246 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2249 print_integer_arg(sysdecode_sysarch_number, fp,
2254 * The pipe() system call in the kernel returns its
2255 * two file descriptors via return values. However,
2256 * the interface exposed by libc is that pipe()
2257 * accepts a pointer to an array of descriptors.
2258 * Format the output to match the libc API by printing
2259 * the returned file descriptors as a fake argument.
2261 * Overwrite the first retval to signal a successful
2264 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
2271 len = args[sc->offset + 1];
2272 utrace_addr = calloc(1, len);
2273 if (get_struct(pid, (void *)args[sc->offset],
2274 (void *)utrace_addr, len) != -1)
2275 print_utrace(fp, utrace_addr, len);
2277 fprintf(fp, "0x%lx", args[sc->offset]);
2282 int descriptors[16];
2283 unsigned long i, ndescriptors;
2286 ndescriptors = args[sc->offset + 1];
2288 if (ndescriptors > nitems(descriptors)) {
2289 ndescriptors = nitems(descriptors);
2292 if (get_struct(pid, (void *)args[sc->offset],
2293 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2295 for (i = 0; i < ndescriptors; i++)
2296 fprintf(fp, i == 0 ? " %d" : ", %d",
2298 fprintf(fp, truncated ? ", ... }" : " }");
2300 fprintf(fp, "0x%lx", args[sc->offset]);
2304 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2306 case CapFcntlRights: {
2309 if (sc->type & OUT) {
2310 if (get_struct(pid, (void *)args[sc->offset], &rights,
2311 sizeof(rights)) == -1) {
2312 fprintf(fp, "0x%lx", args[sc->offset]);
2316 rights = args[sc->offset];
2317 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2321 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2326 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2327 fprintf(fp, "0x%x", rem);
2329 fprintf(fp, "|0x%x", rem);
2333 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2336 print_integer_arg(sysdecode_getfsstat_mode, fp,
2340 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2342 case Kldunloadflags:
2343 print_integer_arg(sysdecode_kldunload_flags, fp,
2347 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2350 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2352 case Sockprotocol: {
2354 int domain, protocol;
2356 domain = args[sc->offset - 2];
2357 protocol = args[sc->offset];
2358 if (protocol == 0) {
2361 temp = sysdecode_socket_protocol(domain, protocol);
2365 fprintf(fp, "%d", protocol);
2371 print_integer_arg(sysdecode_sockopt_level, fp,
2378 level = args[sc->offset - 1];
2379 name = args[sc->offset];
2380 temp = sysdecode_sockopt_name(level, name);
2384 fprintf(fp, "%d", name);
2389 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2392 cap_rights_t rights;
2394 if (get_struct(pid, (void *)args[sc->offset], &rights,
2395 sizeof(rights)) != -1) {
2397 sysdecode_cap_rights(fp, &rights);
2400 fprintf(fp, "0x%lx", args[sc->offset]);
2404 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2406 case Extattrnamespace:
2407 print_integer_arg(sysdecode_extattrnamespace, fp,
2411 print_integer_arg(sysdecode_minherit_inherit, fp,
2415 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2418 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2421 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2424 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2427 print_integer_arg(sysdecode_ptrace_request, fp,
2431 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2432 fprintf(fp, "%#x", (int)args[sc->offset]);
2435 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2438 print_integer_arg(sysdecode_rtprio_function, fp,
2442 print_integer_arg(sysdecode_scheduler_policy, fp,
2446 struct sched_param sp;
2448 if (get_struct(pid, (void *)args[sc->offset], &sp,
2450 fprintf(fp, "{ %d }", sp.sched_priority);
2452 fprintf(fp, "0x%lx", args[sc->offset]);
2458 if (get_struct(pid, (void *)args[sc->offset], &sig,
2460 fprintf(fp, "{ %s }", strsig2(sig));
2462 fprintf(fp, "0x%lx", args[sc->offset]);
2468 if (get_struct(pid, (void *)args[sc->offset], &si,
2469 sizeof(si)) != -1) {
2470 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2471 decode_siginfo(fp, &si);
2474 fprintf(fp, "0x%lx", args[sc->offset]);
2479 * Print argument as an array of struct iovec, where the next
2480 * syscall argument is the number of elements of the array.
2483 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2484 (int)args[sc->offset + 1]);
2486 case Sctpsndrcvinfo: {
2487 struct sctp_sndrcvinfo info;
2489 if (get_struct(pid, (void *)args[sc->offset],
2490 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2491 fprintf(fp, "0x%lx", args[sc->offset]);
2494 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2498 struct msghdr msghdr;
2500 if (get_struct(pid, (void *)args[sc->offset],
2501 &msghdr, sizeof(struct msghdr)) == -1) {
2502 fprintf(fp, "0x%lx", args[sc->offset]);
2506 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2507 fprintf(fp, ",%d,", msghdr.msg_namelen);
2508 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2509 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2510 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2511 fprintf(fp, ",%u,", msghdr.msg_controllen);
2512 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2517 case CloudABIAdvice:
2518 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2520 case CloudABIClockID:
2521 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2523 case CloudABIFDSFlags:
2524 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2526 case CloudABIFDStat: {
2527 cloudabi_fdstat_t fds;
2528 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2530 fprintf(fp, "{ %s, ",
2531 xlookup(cloudabi_filetype, fds.fs_filetype));
2532 fprintf(fp, "%s, ... }",
2533 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2535 fprintf(fp, "0x%lx", args[sc->offset]);
2538 case CloudABIFileStat: {
2539 cloudabi_filestat_t fsb;
2540 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2542 fprintf(fp, "{ %s, %ju }",
2543 xlookup(cloudabi_filetype, fsb.st_filetype),
2544 (uintmax_t)fsb.st_size);
2546 fprintf(fp, "0x%lx", args[sc->offset]);
2549 case CloudABIFileType:
2550 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2552 case CloudABIFSFlags:
2553 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2555 case CloudABILookup:
2556 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2557 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2558 (int)args[sc->offset]);
2560 fprintf(fp, "%d", (int)args[sc->offset]);
2562 case CloudABIMFlags:
2563 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2566 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2568 case CloudABIMSFlags:
2569 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2571 case CloudABIOFlags:
2572 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2574 case CloudABISDFlags:
2575 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2577 case CloudABISignal:
2578 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2580 case CloudABITimestamp:
2581 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2582 args[sc->offset] % 1000000000);
2584 case CloudABIULFlags:
2585 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2587 case CloudABIWhence:
2588 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2592 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2599 * Print (to outfile) the system call and its arguments.
2602 print_syscall(struct trussinfo *trussinfo)
2604 struct threadinfo *t;
2609 t = trussinfo->curthread;
2611 name = t->cs.sc->name;
2612 nargs = t->cs.nargs;
2613 s_args = t->cs.s_args;
2615 len = print_line_prefix(trussinfo);
2616 len += fprintf(trussinfo->outfile, "%s(", name);
2618 for (i = 0; i < nargs; i++) {
2619 if (s_args[i] != NULL)
2620 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2622 len += fprintf(trussinfo->outfile,
2623 "<missing argument>");
2624 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2627 len += fprintf(trussinfo->outfile, ")");
2628 for (i = 0; i < 6 - (len / 8); i++)
2629 fprintf(trussinfo->outfile, "\t");
2633 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2635 struct timespec timediff;
2636 struct threadinfo *t;
2640 t = trussinfo->curthread;
2642 if (trussinfo->flags & COUNTONLY) {
2643 timespecsub(&t->after, &t->before, &timediff);
2644 timespecadd(&sc->time, &timediff, &sc->time);
2651 print_syscall(trussinfo);
2652 fflush(trussinfo->outfile);
2654 if (retval == NULL) {
2656 * This system call resulted in the current thread's exit,
2657 * so there is no return value or error to display.
2659 fprintf(trussinfo->outfile, "\n");
2664 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2666 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2667 error == INT_MAX ? "Unknown error" : strerror(error));
2670 else if (sc->ret_type == 2) {
2673 #if _BYTE_ORDER == _LITTLE_ENDIAN
2674 off = (off_t)retval[1] << 32 | retval[0];
2676 off = (off_t)retval[0] << 32 | retval[1];
2678 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2683 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2688 print_summary(struct trussinfo *trussinfo)
2690 struct timespec total = {0, 0};
2694 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2695 "syscall", "seconds", "calls", "errors");
2697 STAILQ_FOREACH(sc, &syscalls, entries)
2699 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2700 sc->name, (intmax_t)sc->time.tv_sec,
2701 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2702 timespecadd(&total, &sc->time, &total);
2703 ncall += sc->ncalls;
2704 nerror += sc->nerror;
2706 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2707 "", "-------------", "-------", "-------");
2708 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2709 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);