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
55 #include <netinet/in.h>
56 #include <netinet/sctp.h>
57 #include <arpa/inet.h>
70 #include <sysdecode.h>
74 #include <contrib/cloudabi/cloudabi_types_common.h>
81 * This should probably be in its own file, sorted alphabetically.
83 static struct syscall decoded_syscalls[] = {
85 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
86 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
87 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
88 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
89 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
90 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
91 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
92 .args = { { Int, 0 }, { Acltype, 1 } } },
93 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
94 .args = { { Name, 0 }, { Acltype, 1 } } },
95 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
96 .args = { { Name, 0 }, { Acltype, 1 } } },
97 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
98 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
99 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
100 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
101 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
102 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
103 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
104 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
106 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
108 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
110 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
111 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
112 .args = { { Name | OUT, 0 }, { Int, 1 } } },
113 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
114 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
116 { .name = "accept", .ret_type = 1, .nargs = 3,
117 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
118 { .name = "access", .ret_type = 1, .nargs = 2,
119 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
120 { .name = "bind", .ret_type = 1, .nargs = 3,
121 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
122 { .name = "bindat", .ret_type = 1, .nargs = 4,
123 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
125 { .name = "break", .ret_type = 1, .nargs = 1,
126 .args = { { Ptr, 0 } } },
127 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
128 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
129 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
130 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
131 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
132 .args = { { PUInt | OUT, 0 } } },
133 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
134 .args = { { Int, 0 }, { CapRights, 1 } } },
135 { .name = "chdir", .ret_type = 1, .nargs = 1,
136 .args = { { Name, 0 } } },
137 { .name = "chflags", .ret_type = 1, .nargs = 2,
138 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
139 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
140 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
142 { .name = "chmod", .ret_type = 1, .nargs = 2,
143 .args = { { Name, 0 }, { Octal, 1 } } },
144 { .name = "chown", .ret_type = 1, .nargs = 3,
145 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
146 { .name = "chroot", .ret_type = 1, .nargs = 1,
147 .args = { { Name, 0 } } },
148 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
149 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
150 { .name = "close", .ret_type = 1, .nargs = 1,
151 .args = { { Int, 0 } } },
152 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
153 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
154 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
155 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
157 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
158 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
159 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
160 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
161 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
162 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
163 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
164 { .name = "connect", .ret_type = 1, .nargs = 3,
165 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
166 { .name = "connectat", .ret_type = 1, .nargs = 4,
167 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
169 { .name = "dup", .ret_type = 1, .nargs = 1,
170 .args = { { Int, 0 } } },
171 { .name = "dup2", .ret_type = 1, .nargs = 2,
172 .args = { { Int, 0 }, { Int, 1 } } },
173 { .name = "eaccess", .ret_type = 1, .nargs = 2,
174 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
175 { .name = "execve", .ret_type = 1, .nargs = 3,
176 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
177 { ExecEnv | IN, 2 } } },
178 { .name = "exit", .ret_type = 0, .nargs = 1,
179 .args = { { Hex, 0 } } },
180 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
181 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
182 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
183 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
184 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
185 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
186 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
187 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
188 { BinString | OUT, 3 }, { Sizet, 4 } } },
189 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
190 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
191 { BinString | OUT, 3 }, { Sizet, 4 } } },
192 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
193 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
194 { BinString | OUT, 3 }, { Sizet, 4 } } },
195 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
196 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
198 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
199 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
201 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
202 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
204 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
205 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
206 { BinString | IN, 3 }, { Sizet, 4 } } },
207 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
208 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
209 { BinString | IN, 3 }, { Sizet, 4 } } },
210 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
211 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
212 { BinString | IN, 3 }, { Sizet, 4 } } },
213 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
214 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
215 { Extattrnamespace, 3 }, { Name, 4 } } },
216 { .name = "faccessat", .ret_type = 1, .nargs = 4,
217 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
219 { .name = "fchflags", .ret_type = 1, .nargs = 2,
220 .args = { { Int, 0 }, { FileFlags, 1 } } },
221 { .name = "fchmod", .ret_type = 1, .nargs = 2,
222 .args = { { Int, 0 }, { Octal, 1 } } },
223 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
224 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
225 { .name = "fchown", .ret_type = 1, .nargs = 3,
226 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
227 { .name = "fchownat", .ret_type = 1, .nargs = 5,
228 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
230 { .name = "fcntl", .ret_type = 1, .nargs = 3,
231 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
232 { .name = "flock", .ret_type = 1, .nargs = 2,
233 .args = { { Int, 0 }, { Flockop, 1 } } },
234 { .name = "fstat", .ret_type = 1, .nargs = 2,
235 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
236 { .name = "fstatat", .ret_type = 1, .nargs = 4,
237 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
239 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
240 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
241 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
242 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
243 { .name = "futimens", .ret_type = 1, .nargs = 2,
244 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
245 { .name = "futimes", .ret_type = 1, .nargs = 2,
246 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
247 { .name = "futimesat", .ret_type = 1, .nargs = 3,
248 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
249 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
250 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
251 { PQuadHex | OUT, 3 } } },
252 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
253 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
254 { .name = "getitimer", .ret_type = 1, .nargs = 2,
255 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
256 { .name = "getpeername", .ret_type = 1, .nargs = 3,
257 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
258 { .name = "getpgid", .ret_type = 1, .nargs = 1,
259 .args = { { Int, 0 } } },
260 { .name = "getpriority", .ret_type = 1, .nargs = 2,
261 .args = { { Priowhich, 0 }, { Int, 1 } } },
262 { .name = "getrandom", .ret_type = 1, .nargs = 3,
263 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
264 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
265 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
266 { .name = "getrusage", .ret_type = 1, .nargs = 2,
267 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
268 { .name = "getsid", .ret_type = 1, .nargs = 1,
269 .args = { { Int, 0 } } },
270 { .name = "getsockname", .ret_type = 1, .nargs = 3,
271 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
272 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
273 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
274 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
275 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
276 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
277 { .name = "ioctl", .ret_type = 1, .nargs = 3,
278 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
279 { .name = "kevent", .ret_type = 1, .nargs = 6,
280 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
281 { Int, 4 }, { Timespec, 5 } } },
282 { .name = "kill", .ret_type = 1, .nargs = 2,
283 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
284 { .name = "kldfind", .ret_type = 1, .nargs = 1,
285 .args = { { Name | IN, 0 } } },
286 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
287 .args = { { Int, 0 } } },
288 { .name = "kldload", .ret_type = 1, .nargs = 1,
289 .args = { { Name | IN, 0 } } },
290 { .name = "kldnext", .ret_type = 1, .nargs = 1,
291 .args = { { Int, 0 } } },
292 { .name = "kldstat", .ret_type = 1, .nargs = 2,
293 .args = { { Int, 0 }, { Ptr, 1 } } },
294 { .name = "kldsym", .ret_type = 1, .nargs = 3,
295 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
296 { .name = "kldunload", .ret_type = 1, .nargs = 1,
297 .args = { { Int, 0 } } },
298 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
299 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
300 { .name = "kse_release", .ret_type = 0, .nargs = 1,
301 .args = { { Timespec, 0 } } },
302 { .name = "lchflags", .ret_type = 1, .nargs = 2,
303 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
304 { .name = "lchmod", .ret_type = 1, .nargs = 2,
305 .args = { { Name, 0 }, { Octal, 1 } } },
306 { .name = "lchown", .ret_type = 1, .nargs = 3,
307 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
308 { .name = "link", .ret_type = 1, .nargs = 2,
309 .args = { { Name, 0 }, { Name, 1 } } },
310 { .name = "linkat", .ret_type = 1, .nargs = 5,
311 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
313 { .name = "listen", .ret_type = 1, .nargs = 2,
314 .args = { { Int, 0 }, { Int, 1 } } },
315 { .name = "lseek", .ret_type = 2, .nargs = 3,
316 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
317 { .name = "lstat", .ret_type = 1, .nargs = 2,
318 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
319 { .name = "lutimes", .ret_type = 1, .nargs = 2,
320 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
321 { .name = "madvise", .ret_type = 1, .nargs = 3,
322 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
323 { .name = "minherit", .ret_type = 1, .nargs = 3,
324 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
325 { .name = "mkdir", .ret_type = 1, .nargs = 2,
326 .args = { { Name, 0 }, { Octal, 1 } } },
327 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
328 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
329 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
330 .args = { { Name, 0 }, { Octal, 1 } } },
331 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
332 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
333 { .name = "mknod", .ret_type = 1, .nargs = 3,
334 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
335 { .name = "mknodat", .ret_type = 1, .nargs = 4,
336 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
337 { .name = "mlock", .ret_type = 1, .nargs = 2,
338 .args = { { Ptr, 0 }, { Sizet, 1 } } },
339 { .name = "mlockall", .ret_type = 1, .nargs = 1,
340 .args = { { Mlockall, 0 } } },
341 { .name = "mmap", .ret_type = 1, .nargs = 6,
342 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
343 { Int, 4 }, { QuadHex, 5 } } },
344 { .name = "modfind", .ret_type = 1, .nargs = 1,
345 .args = { { Name | IN, 0 } } },
346 { .name = "mount", .ret_type = 1, .nargs = 4,
347 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
348 { .name = "mprotect", .ret_type = 1, .nargs = 3,
349 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
350 { .name = "msync", .ret_type = 1, .nargs = 3,
351 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
352 { .name = "munlock", .ret_type = 1, .nargs = 2,
353 .args = { { Ptr, 0 }, { Sizet, 1 } } },
354 { .name = "munmap", .ret_type = 1, .nargs = 2,
355 .args = { { Ptr, 0 }, { Sizet, 1 } } },
356 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
357 .args = { { Timespec, 0 } } },
358 { .name = "nmount", .ret_type = 1, .nargs = 3,
359 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
360 { .name = "open", .ret_type = 1, .nargs = 3,
361 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
362 { .name = "openat", .ret_type = 1, .nargs = 4,
363 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
365 { .name = "pathconf", .ret_type = 1, .nargs = 2,
366 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
367 { .name = "pipe", .ret_type = 1, .nargs = 1,
368 .args = { { PipeFds | OUT, 0 } } },
369 { .name = "pipe2", .ret_type = 1, .nargs = 2,
370 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
371 { .name = "poll", .ret_type = 1, .nargs = 3,
372 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
373 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
374 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
376 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
377 .args = { { Open, 0 } } },
378 { .name = "pread", .ret_type = 1, .nargs = 4,
379 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
381 { .name = "procctl", .ret_type = 1, .nargs = 4,
382 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
383 { .name = "ptrace", .ret_type = 1, .nargs = 4,
384 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
385 { .name = "pwrite", .ret_type = 1, .nargs = 4,
386 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
388 { .name = "quotactl", .ret_type = 1, .nargs = 4,
389 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
390 { .name = "read", .ret_type = 1, .nargs = 3,
391 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
392 { .name = "readlink", .ret_type = 1, .nargs = 3,
393 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
394 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
395 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
397 { .name = "readv", .ret_type = 1, .nargs = 3,
398 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
399 { .name = "reboot", .ret_type = 1, .nargs = 1,
400 .args = { { Reboothowto, 0 } } },
401 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
402 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
403 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
404 { Ptr | OUT, 5 } } },
405 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
406 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
407 { .name = "rename", .ret_type = 1, .nargs = 2,
408 .args = { { Name, 0 }, { Name, 1 } } },
409 { .name = "renameat", .ret_type = 1, .nargs = 4,
410 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
411 { .name = "rfork", .ret_type = 1, .nargs = 1,
412 .args = { { Rforkflags, 0 } } },
413 { .name = "rmdir", .ret_type = 1, .nargs = 1,
414 .args = { { Name, 0 } } },
415 { .name = "rtprio", .ret_type = 1, .nargs = 3,
416 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
417 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
418 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
419 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
420 .args = { { Schedpolicy, 0 } } },
421 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
422 .args = { { Schedpolicy, 0 } } },
423 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
424 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
425 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
426 .args = { { Int, 0 } } },
427 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
428 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
429 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
430 .args = { { Int, 0 }, { Schedparam, 1 } } },
431 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
432 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
433 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
434 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
435 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
436 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
437 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
438 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
439 { Sockaddr | IN, 3 }, { Socklent, 4 },
440 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
441 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
442 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
443 { Sockaddr | IN, 3 }, { Socklent, 4 },
444 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
445 { .name = "select", .ret_type = 1, .nargs = 5,
446 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
448 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
449 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
450 { .name = "sendto", .ret_type = 1, .nargs = 6,
451 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
452 { Msgflags, 3 }, { Sockaddr | IN, 4 },
453 { Socklent | IN, 5 } } },
454 { .name = "setitimer", .ret_type = 1, .nargs = 3,
455 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
456 { .name = "setpriority", .ret_type = 1, .nargs = 3,
457 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
458 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
459 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
460 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
461 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
462 { Ptr | IN, 3 }, { Socklent, 4 } } },
463 { .name = "shutdown", .ret_type = 1, .nargs = 2,
464 .args = { { Int, 0 }, { Shutdown, 1 } } },
465 { .name = "sigaction", .ret_type = 1, .nargs = 3,
466 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
467 { Sigaction | OUT, 2 } } },
468 { .name = "sigpending", .ret_type = 1, .nargs = 1,
469 .args = { { Sigset | OUT, 0 } } },
470 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
471 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
472 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
473 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
474 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
475 .args = { { Ptr, 0 } } },
476 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
477 .args = { { Sigset | IN, 0 } } },
478 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
479 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
480 { Timespec | IN, 2 } } },
481 { .name = "sigwait", .ret_type = 1, .nargs = 2,
482 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
483 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
484 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
485 { .name = "socket", .ret_type = 1, .nargs = 3,
486 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
487 { .name = "stat", .ret_type = 1, .nargs = 2,
488 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
489 { .name = "statfs", .ret_type = 1, .nargs = 2,
490 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
491 { .name = "symlink", .ret_type = 1, .nargs = 2,
492 .args = { { Name, 0 }, { Name, 1 } } },
493 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
494 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
495 { .name = "sysarch", .ret_type = 1, .nargs = 2,
496 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
497 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
498 .args = { { Long, 0 }, { Signal, 1 } } },
499 { .name = "thr_self", .ret_type = 1, .nargs = 1,
500 .args = { { Ptr, 0 } } },
501 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
502 .args = { { Long, 0 }, { Name, 1 } } },
503 { .name = "truncate", .ret_type = 1, .nargs = 2,
504 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
507 { .name = "umount", .ret_type = 1, .nargs = 2,
508 .args = { { Name, 0 }, { Int, 2 } } },
510 { .name = "unlink", .ret_type = 1, .nargs = 1,
511 .args = { { Name, 0 } } },
512 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
513 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
514 { .name = "unmount", .ret_type = 1, .nargs = 2,
515 .args = { { Name, 0 }, { Mountflags, 1 } } },
516 { .name = "utimensat", .ret_type = 1, .nargs = 4,
517 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
519 { .name = "utimes", .ret_type = 1, .nargs = 2,
520 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
521 { .name = "utrace", .ret_type = 1, .nargs = 1,
522 .args = { { Utrace, 0 } } },
523 { .name = "wait4", .ret_type = 1, .nargs = 4,
524 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
525 { Rusage | OUT, 3 } } },
526 { .name = "wait6", .ret_type = 1, .nargs = 6,
527 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
528 { Waitoptions, 3 }, { Rusage | OUT, 4 },
529 { Siginfo | OUT, 5 } } },
530 { .name = "write", .ret_type = 1, .nargs = 3,
531 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
532 { .name = "writev", .ret_type = 1, .nargs = 3,
533 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
536 { .name = "linux_access", .ret_type = 1, .nargs = 2,
537 .args = { { Name, 0 }, { Accessmode, 1 } } },
538 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
539 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
540 { ExecEnv | IN, 2 } } },
541 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
542 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
543 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
544 .args = { { Name | IN, 0 }, { Int, 1 } } },
545 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
546 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
547 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
548 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
549 { .name = "linux_open", .ret_type = 1, .nargs = 3,
550 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
551 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
552 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
553 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
554 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
555 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
556 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
558 /* CloudABI system calls. */
559 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
560 .args = { { CloudABIClockID, 0 } } },
561 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
562 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
563 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
564 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
565 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
566 .args = { { Int, 0 } } },
567 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
568 .args = { { CloudABIFileType, 0 } } },
569 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
570 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
571 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
572 .args = { { Int, 0 } } },
573 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
574 .args = { { Int, 0 } } },
575 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
576 .args = { { Int, 0 }, { Int, 1 } } },
577 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
578 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
579 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
580 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
581 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
582 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
583 { CloudABIFDSFlags, 2 } } },
584 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
585 .args = { { Int, 0 } } },
586 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
587 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
588 { CloudABIAdvice, 3 } } },
589 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
590 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
591 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
592 .args = { { Int, 0 }, { BinString | IN, 1 },
593 { CloudABIFileType, 3 } } },
594 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
595 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
596 { Int, 3 }, { BinString | IN, 4 } } },
597 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
598 .args = { { Int, 0 }, { BinString | IN, 1 },
599 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
600 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
601 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
603 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
604 .args = { { Int, 0 }, { BinString | IN, 1 },
605 { BinString | OUT, 3 }, { Int, 4 } } },
606 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
607 .args = { { Int, 0 }, { BinString | IN, 1 },
608 { Int, 3 }, { BinString | IN, 4 } } },
609 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
610 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
611 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
612 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
613 { CloudABIFSFlags, 2 } } },
614 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
615 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
616 { CloudABIFileStat | OUT, 3 } } },
617 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
618 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
619 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
620 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
621 .args = { { BinString | IN, 0 },
622 { Int, 2 }, { BinString | IN, 3 } } },
623 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
624 .args = { { Int, 0 }, { BinString | IN, 1 },
625 { CloudABIULFlags, 3 } } },
626 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
627 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
628 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
629 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
630 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
631 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
632 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
633 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
634 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
635 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
636 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
637 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
638 .args = { { Ptr, 0 }, { Int, 1 } } },
639 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
640 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
641 { IntArray, 3 }, { Int, 4 } } },
642 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
643 .args = { { Int, 0 } } },
644 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
645 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
646 .args = { { CloudABISignal, 0 } } },
647 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
648 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
649 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
650 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
651 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
652 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
653 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
657 static STAILQ_HEAD(, syscall) syscalls;
659 /* Xlat idea taken from strace */
665 #define X(a) { a, #a },
666 #define XEND { 0, NULL }
668 static struct xlat poll_flags[] = {
669 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
670 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
671 X(POLLWRBAND) X(POLLINIGNEOF) XEND
674 static struct xlat sigaction_flags[] = {
675 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
676 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
679 static struct xlat linux_socketcall_ops[] = {
680 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
681 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
682 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
683 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
684 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
689 #define X(a) { CLOUDABI_##a, #a },
691 static struct xlat cloudabi_advice[] = {
692 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
693 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
697 static struct xlat cloudabi_clockid[] = {
698 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
699 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
703 static struct xlat cloudabi_fdflags[] = {
704 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
705 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
709 static struct xlat cloudabi_fdsflags[] = {
710 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
714 static struct xlat cloudabi_filetype[] = {
715 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
716 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
717 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
718 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
719 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
723 static struct xlat cloudabi_fsflags[] = {
724 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
725 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
729 static struct xlat cloudabi_mflags[] = {
730 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
734 static struct xlat cloudabi_mprot[] = {
735 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
739 static struct xlat cloudabi_msflags[] = {
740 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
744 static struct xlat cloudabi_oflags[] = {
745 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
749 static struct xlat cloudabi_sdflags[] = {
750 X(SHUT_RD) X(SHUT_WR)
754 static struct xlat cloudabi_signal[] = {
755 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
756 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
757 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
758 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
759 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
763 static struct xlat cloudabi_ulflags[] = {
768 static struct xlat cloudabi_whence[] = {
769 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
777 * Searches an xlat array for a value, and returns it if found. Otherwise
778 * return a string representation.
781 lookup(struct xlat *xlat, int val, int base)
785 for (; xlat->str != NULL; xlat++)
786 if (xlat->val == val)
790 sprintf(tmp, "0%o", val);
793 sprintf(tmp, "0x%x", val);
796 sprintf(tmp, "%u", val);
799 errx(1,"Unknown lookup base");
806 xlookup(struct xlat *xlat, int val)
809 return (lookup(xlat, val, 16));
813 * Searches an xlat array containing bitfield values. Remaining bits
814 * set after removing the known ones are printed at the end:
818 xlookup_bits(struct xlat *xlat, int val)
821 static char str[512];
825 for (; xlat->str != NULL; xlat++) {
826 if ((xlat->val & rem) == xlat->val) {
828 * Don't print the "all-bits-zero" string unless all
829 * bits are really zero.
831 if (xlat->val == 0 && val != 0)
833 len += sprintf(str + len, "%s|", xlat->str);
839 * If we have leftover bits or didn't match anything, print
843 len += sprintf(str + len, "0x%x", rem);
844 if (len && str[len - 1] == '|')
851 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
855 str = decoder(value);
859 fprintf(fp, "%d", value);
863 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
867 if (!decoder(fp, value, &rem))
868 fprintf(fp, "0x%x", rem);
870 fprintf(fp, "|0x%x", rem);
874 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
879 if (!decoder(fp, value, &rem))
880 fprintf(fp, "0x%x", rem);
882 fprintf(fp, "|0x%x", rem);
887 * Add argument padding to subsequent system calls afater a Quad
888 * syscall arguments as needed. This used to be done by hand in the
889 * decoded_syscalls table which was ugly and error prone. It is
890 * simpler to do the fixup of offsets at initalization time than when
891 * decoding arguments.
894 quad_fixup(struct syscall *sc)
901 for (i = 0; i < sc->nargs; i++) {
902 /* This arg type is a dummy that doesn't use offset. */
903 if ((sc->args[i].type & ARG_MASK) == PipeFds)
906 assert(prev < sc->args[i].offset);
907 prev = sc->args[i].offset;
908 sc->args[i].offset += offset;
909 switch (sc->args[i].type & ARG_MASK) {
914 * 64-bit arguments on 32-bit powerpc must be
915 * 64-bit aligned. If the current offset is
916 * not aligned, the calling convention inserts
917 * a 32-bit pad argument that should be skipped.
919 if (sc->args[i].offset % 2 == 1) {
920 sc->args[i].offset++;
937 STAILQ_INIT(&syscalls);
938 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
942 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
946 static struct syscall *
947 find_syscall(struct procabi *abi, u_int number)
949 struct extra_syscall *es;
951 if (number < nitems(abi->syscalls))
952 return (abi->syscalls[number]);
953 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
954 if (es->number == number)
961 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
963 struct extra_syscall *es;
965 if (number < nitems(abi->syscalls)) {
966 assert(abi->syscalls[number] == NULL);
967 abi->syscalls[number] = sc;
969 es = malloc(sizeof(*es));
972 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
977 * If/when the list gets big, it might be desirable to do it
978 * as a hash table or binary search.
981 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
988 sc = find_syscall(t->proc->abi, number);
992 name = sysdecode_syscallname(t->proc->abi->abi, number);
994 asprintf(&new_name, "#%d", number);
998 STAILQ_FOREACH(sc, &syscalls, entries) {
999 if (strcmp(name, sc->name) == 0) {
1000 add_syscall(t->proc->abi, number, sc);
1006 /* It is unknown. Add it into the list. */
1008 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1012 sc = calloc(1, sizeof(struct syscall));
1014 if (new_name != NULL)
1018 for (i = 0; i < nargs; i++) {
1019 sc->args[i].offset = i;
1020 /* Treat all unknown arguments as LongHex. */
1021 sc->args[i].type = LongHex;
1023 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1024 add_syscall(t->proc->abi, number, sc);
1030 * Copy a fixed amount of bytes from the process.
1033 get_struct(pid_t pid, void *offset, void *buf, int len)
1035 struct ptrace_io_desc iorequest;
1037 iorequest.piod_op = PIOD_READ_D;
1038 iorequest.piod_offs = offset;
1039 iorequest.piod_addr = buf;
1040 iorequest.piod_len = len;
1041 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1046 #define MAXSIZE 4096
1049 * Copy a string from the process. Note that it is
1050 * expected to be a C string, but if max is set, it will
1051 * only get that much.
1054 get_string(pid_t pid, void *addr, int max)
1056 struct ptrace_io_desc iorequest;
1058 size_t offset, size, totalsize;
1064 /* Read up to the end of the current page. */
1065 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1070 buf = malloc(totalsize);
1074 iorequest.piod_op = PIOD_READ_D;
1075 iorequest.piod_offs = (char *)addr + offset;
1076 iorequest.piod_addr = buf + offset;
1077 iorequest.piod_len = size;
1078 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1082 if (memchr(buf + offset, '\0', size) != NULL)
1085 if (totalsize < MAXSIZE && max == 0) {
1086 size = MAXSIZE - totalsize;
1087 if (size > PAGE_SIZE)
1089 nbuf = realloc(buf, totalsize + size);
1091 buf[totalsize - 1] = '\0';
1097 buf[totalsize - 1] = '\0';
1106 static char tmp[32];
1107 const char *signame;
1109 signame = sysdecode_signal(sig);
1110 if (signame == NULL) {
1111 snprintf(tmp, sizeof(tmp), "%d", sig);
1118 print_kevent(FILE *fp, struct kevent *ke)
1121 switch (ke->filter) {
1127 case EVFILT_PROCDESC:
1129 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1132 fputs(strsig2(ke->ident), fp);
1135 fprintf(fp, "%p", (void *)ke->ident);
1138 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1140 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1142 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1143 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1147 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1149 unsigned char *utrace_buffer;
1152 if (sysdecode_utrace(fp, utrace_addr, len)) {
1157 utrace_buffer = utrace_addr;
1158 fprintf(fp, "%zu:", len);
1160 fprintf(fp, " %02x", *utrace_buffer++);
1165 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1168 struct sockaddr_in *lsin;
1169 struct sockaddr_in6 *lsin6;
1170 struct sockaddr_un *sun;
1171 struct sockaddr *sa;
1173 pid_t pid = trussinfo->curthread->proc->pid;
1179 /* If the length is too small, just bail. */
1180 if (len < sizeof(*sa)) {
1181 fprintf(fp, "%p", arg);
1185 sa = calloc(1, len);
1186 if (get_struct(pid, arg, sa, len) == -1) {
1188 fprintf(fp, "%p", arg);
1192 switch (sa->sa_family) {
1194 if (len < sizeof(*lsin))
1195 goto sockaddr_short;
1196 lsin = (struct sockaddr_in *)(void *)sa;
1197 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1198 fprintf(fp, "{ AF_INET %s:%d }", addr,
1199 htons(lsin->sin_port));
1202 if (len < sizeof(*lsin6))
1203 goto sockaddr_short;
1204 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1205 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1207 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1208 htons(lsin6->sin6_port));
1211 sun = (struct sockaddr_un *)sa;
1212 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1213 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1219 "{ sa_len = %d, sa_family = %d, sa_data = {",
1220 (int)sa->sa_len, (int)sa->sa_family);
1221 for (q = (u_char *)sa->sa_data;
1222 q < (u_char *)sa + len; q++)
1223 fprintf(fp, "%s 0x%02x",
1224 q == (u_char *)sa->sa_data ? "" : ",",
1231 #define IOV_LIMIT 16
1234 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1236 struct iovec iov[IOV_LIMIT];
1237 size_t max_string = trussinfo->strsize;
1238 char tmp2[max_string + 1], *tmp3;
1240 pid_t pid = trussinfo->curthread->proc->pid;
1242 bool buf_truncated, iov_truncated;
1245 fprintf(fp, "%p", arg);
1248 if (iovcnt > IOV_LIMIT) {
1250 iov_truncated = true;
1252 iov_truncated = false;
1254 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1255 fprintf(fp, "%p", arg);
1260 for (i = 0; i < iovcnt; i++) {
1261 len = iov[i].iov_len;
1262 if (len > max_string) {
1264 buf_truncated = true;
1266 buf_truncated = false;
1268 fprintf(fp, "%s{", (i > 0) ? "," : "");
1269 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1270 tmp3 = malloc(len * 4 + 1);
1272 if (strvisx(tmp3, tmp2, len,
1273 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1277 buf_truncated = true;
1279 fprintf(fp, "\"%s\"%s", tmp3,
1280 buf_truncated ? "..." : "");
1283 fprintf(fp, "%p", iov[i].iov_base);
1285 fprintf(fp, ",%zu}", iov[i].iov_len);
1287 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1291 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1296 for (q = CMSG_DATA(cmsghdr);
1297 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1298 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1304 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1306 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1307 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1308 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1309 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1313 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1315 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1317 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1320 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1321 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1323 fprintf(fp, "ctx=%u,", info->sinfo_context);
1324 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1327 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1328 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1330 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1334 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1336 fprintf(fp, "{sid=%u,", info->snd_sid);
1338 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1339 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1340 fprintf(fp, "ctx=%u,", info->snd_context);
1341 fprintf(fp, "id=%u}", info->snd_assoc_id);
1345 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1347 fprintf(fp, "{sid=%u,", info->rcv_sid);
1348 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1350 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1351 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1352 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1353 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1354 fprintf(fp, "ctx=%u,", info->rcv_context);
1355 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1359 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1361 fprintf(fp, "{sid=%u,", info->nxt_sid);
1363 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1364 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1365 fprintf(fp, "len=%u,", info->nxt_length);
1366 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1370 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1373 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1374 fprintf(fp, ",val=%u}", info->pr_value);
1378 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1380 fprintf(fp, "{num=%u}", info->auth_keynumber);
1384 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1386 char buf[INET_ADDRSTRLEN];
1389 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1391 fprintf(fp, "{addr=%s}", s);
1393 fputs("{addr=???}", fp);
1397 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1399 char buf[INET6_ADDRSTRLEN];
1402 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1404 fprintf(fp, "{addr=%s}", s);
1406 fputs("{addr=???}", fp);
1410 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1415 len = cmsghdr->cmsg_len;
1416 data = CMSG_DATA(cmsghdr);
1417 switch (cmsghdr->cmsg_type) {
1419 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1420 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1422 print_gen_cmsg(fp, cmsghdr);
1425 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1426 print_sctp_sndrcvinfo(fp, receive,
1427 (struct sctp_sndrcvinfo *)data);
1429 print_gen_cmsg(fp, cmsghdr);
1433 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1434 print_sctp_extrcvinfo(fp,
1435 (struct sctp_extrcvinfo *)data);
1437 print_gen_cmsg(fp, cmsghdr);
1441 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1442 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1444 print_gen_cmsg(fp, cmsghdr);
1447 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1448 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1450 print_gen_cmsg(fp, cmsghdr);
1453 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1454 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1456 print_gen_cmsg(fp, cmsghdr);
1459 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1460 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1462 print_gen_cmsg(fp, cmsghdr);
1465 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1466 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1468 print_gen_cmsg(fp, cmsghdr);
1470 case SCTP_DSTADDRV4:
1471 if (len == CMSG_LEN(sizeof(struct in_addr)))
1472 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1474 print_gen_cmsg(fp, cmsghdr);
1476 case SCTP_DSTADDRV6:
1477 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1478 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1480 print_gen_cmsg(fp, cmsghdr);
1483 print_gen_cmsg(fp, cmsghdr);
1488 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1490 struct cmsghdr *cmsghdr;
1497 len = msghdr->msg_controllen;
1502 cmsgbuf = calloc(1, len);
1503 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1504 fprintf(fp, "%p", msghdr->msg_control);
1508 msghdr->msg_control = cmsgbuf;
1511 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1513 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1514 level = cmsghdr->cmsg_level;
1515 type = cmsghdr->cmsg_type;
1516 len = cmsghdr->cmsg_len;
1517 fprintf(fp, "%s{level=", first ? "" : ",");
1518 print_integer_arg(sysdecode_sockopt_level, fp, level);
1519 fputs(",type=", fp);
1520 temp = sysdecode_cmsg_type(level, type);
1524 fprintf(fp, "%d", type);
1526 fputs(",data=", fp);
1529 print_sctp_cmsg(fp, receive, cmsghdr);
1532 print_gen_cmsg(fp, cmsghdr);
1543 * Converts a syscall argument into a string. Said string is
1544 * allocated via malloc(), so needs to be free()'d. sc is
1545 * a pointer to the syscall description (see above); args is
1546 * an array of all of the system call arguments.
1549 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1550 struct trussinfo *trussinfo)
1557 fp = open_memstream(&tmp, &tmplen);
1558 pid = trussinfo->curthread->proc->pid;
1559 switch (sc->type & ARG_MASK) {
1561 fprintf(fp, "0x%x", (int)args[sc->offset]);
1564 fprintf(fp, "0%o", (int)args[sc->offset]);
1567 fprintf(fp, "%d", (int)args[sc->offset]);
1570 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1575 if (get_struct(pid, (void *)args[sc->offset], &val,
1577 fprintf(fp, "{ %u }", val);
1579 fprintf(fp, "0x%lx", args[sc->offset]);
1583 fprintf(fp, "0x%lx", args[sc->offset]);
1586 fprintf(fp, "%ld", args[sc->offset]);
1589 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1592 /* NULL-terminated string. */
1595 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1596 fprintf(fp, "\"%s\"", tmp2);
1602 * Binary block of data that might have printable characters.
1603 * XXX If type|OUT, assume that the length is the syscall's
1604 * return value. Otherwise, assume that the length of the block
1605 * is in the next syscall argument.
1607 int max_string = trussinfo->strsize;
1608 char tmp2[max_string + 1], *tmp3;
1615 len = args[sc->offset + 1];
1618 * Don't print more than max_string characters, to avoid word
1619 * wrap. If we have to truncate put some ... after the string.
1621 if (len > max_string) {
1625 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1627 tmp3 = malloc(len * 4 + 1);
1629 if (strvisx(tmp3, tmp2, len,
1630 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1635 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1639 fprintf(fp, "0x%lx", args[sc->offset]);
1649 char buf[PAGE_SIZE];
1656 * Only parse argv[] and environment arrays from exec calls
1659 if (((sc->type & ARG_MASK) == ExecArgs &&
1660 (trussinfo->flags & EXECVEARGS) == 0) ||
1661 ((sc->type & ARG_MASK) == ExecEnv &&
1662 (trussinfo->flags & EXECVEENVS) == 0)) {
1663 fprintf(fp, "0x%lx", args[sc->offset]);
1668 * Read a page of pointers at a time. Punt if the top-level
1669 * pointer is not aligned. Note that the first read is of
1672 addr = args[sc->offset];
1673 if (addr % sizeof(char *) != 0) {
1674 fprintf(fp, "0x%lx", args[sc->offset]);
1678 len = PAGE_SIZE - (addr & PAGE_MASK);
1679 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1680 fprintf(fp, "0x%lx", args[sc->offset]);
1687 while (u.strarray[i] != NULL) {
1688 string = get_string(pid, u.strarray[i], 0);
1689 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1694 if (i == len / sizeof(char *)) {
1697 if (get_struct(pid, (void *)addr, u.buf, len) ==
1699 fprintf(fp, ", <inval>");
1710 fprintf(fp, "%ld", args[sc->offset]);
1713 fprintf(fp, "0x%lx", args[sc->offset]);
1718 unsigned long long ll;
1720 #if _BYTE_ORDER == _LITTLE_ENDIAN
1721 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1724 ll = (unsigned long long)args[sc->offset] << 32 |
1725 args[sc->offset + 1];
1727 if ((sc->type & ARG_MASK) == Quad)
1728 fprintf(fp, "%lld", ll);
1730 fprintf(fp, "0x%llx", ll);
1737 if (get_struct(pid, (void *)args[sc->offset], &val,
1739 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1741 fprintf(fp, "0x%lx", args[sc->offset]);
1745 fprintf(fp, "0x%lx", args[sc->offset]);
1750 if (retval[0] == -1)
1752 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1753 fprintf(fp, "\"%s\"", tmp2);
1761 cmd = args[sc->offset];
1762 temp = sysdecode_ioctlname(cmd);
1766 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1767 cmd, cmd & IOC_OUT ? "R" : "",
1768 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1769 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1770 cmd & 0xFF, IOCPARM_LEN(cmd));
1777 if (get_struct(pid, (void *)args[sc->offset], &ts,
1779 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1782 fprintf(fp, "0x%lx", args[sc->offset]);
1786 struct timespec ts[2];
1790 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1794 for (i = 0; i < nitems(ts); i++) {
1797 switch (ts[i].tv_nsec) {
1799 fprintf(fp, "UTIME_NOW");
1802 fprintf(fp, "UTIME_OMIT");
1805 fprintf(fp, "%jd.%09ld",
1806 (intmax_t)ts[i].tv_sec,
1813 fprintf(fp, "0x%lx", args[sc->offset]);
1819 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1821 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1824 fprintf(fp, "0x%lx", args[sc->offset]);
1828 struct timeval tv[2];
1830 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1832 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1833 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1834 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1836 fprintf(fp, "0x%lx", args[sc->offset]);
1840 struct itimerval itv;
1842 if (get_struct(pid, (void *)args[sc->offset], &itv,
1844 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1845 (intmax_t)itv.it_interval.tv_sec,
1846 itv.it_interval.tv_usec,
1847 (intmax_t)itv.it_value.tv_sec,
1848 itv.it_value.tv_usec);
1850 fprintf(fp, "0x%lx", args[sc->offset]);
1855 struct linux_socketcall_args largs;
1857 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1858 sizeof(largs)) != -1)
1859 fprintf(fp, "{ %s, 0x%lx }",
1860 lookup(linux_socketcall_ops, largs.what, 10),
1861 (long unsigned int)largs.args);
1863 fprintf(fp, "0x%lx", args[sc->offset]);
1868 * XXX: A Pollfd argument expects the /next/ syscall argument
1869 * to be the number of fds in the array. This matches the poll
1873 int numfds = args[sc->offset + 1];
1874 size_t bytes = sizeof(struct pollfd) * numfds;
1877 if ((pfd = malloc(bytes)) == NULL)
1878 err(1, "Cannot malloc %zu bytes for pollfd array",
1880 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1883 for (i = 0; i < numfds; i++) {
1884 fprintf(fp, " %d/%s", pfd[i].fd,
1885 xlookup_bits(poll_flags, pfd[i].events));
1889 fprintf(fp, "0x%lx", args[sc->offset]);
1896 * XXX: A Fd_set argument expects the /first/ syscall argument
1897 * to be the number of fds in the array. This matches the
1901 int numfds = args[0];
1902 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1905 if ((fds = malloc(bytes)) == NULL)
1906 err(1, "Cannot malloc %zu bytes for fd_set array",
1908 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1911 for (i = 0; i < numfds; i++) {
1912 if (FD_ISSET(i, fds))
1913 fprintf(fp, " %d", i);
1917 fprintf(fp, "0x%lx", args[sc->offset]);
1922 fputs(strsig2(args[sc->offset]), fp);
1929 sig = args[sc->offset];
1930 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1931 sizeof(ss)) == -1) {
1932 fprintf(fp, "0x%lx", args[sc->offset]);
1937 for (i = 1; i < sys_nsig; i++) {
1938 if (sigismember(&ss, i)) {
1939 fprintf(fp, "%s%s", !first ? "|" : "",
1950 print_integer_arg(sysdecode_sigprocmask_how, fp,
1954 /* XXX: Output depends on the value of the previous argument. */
1955 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1956 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1957 args[sc->offset], 16);
1960 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1963 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1966 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1969 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1972 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1975 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1978 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1981 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1984 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
1987 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
1990 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
1993 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
1998 if (args[sc->offset] == 0) {
2004 * Extract the address length from the next argument. If
2005 * this is an output sockaddr (OUT is set), then the
2006 * next argument is a pointer to a socklen_t. Otherwise
2007 * the next argument contains a socklen_t by value.
2009 if (sc->type & OUT) {
2010 if (get_struct(pid, (void *)args[sc->offset + 1],
2011 &len, sizeof(len)) == -1) {
2012 fprintf(fp, "0x%lx", args[sc->offset]);
2016 len = args[sc->offset + 1];
2018 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2022 struct sigaction sa;
2024 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2027 if (sa.sa_handler == SIG_DFL)
2028 fputs("SIG_DFL", fp);
2029 else if (sa.sa_handler == SIG_IGN)
2030 fputs("SIG_IGN", fp);
2032 fprintf(fp, "%p", sa.sa_handler);
2033 fprintf(fp, " %s ss_t }",
2034 xlookup_bits(sigaction_flags, sa.sa_flags));
2036 fprintf(fp, "0x%lx", args[sc->offset]);
2041 * XXX XXX: The size of the array is determined by either the
2042 * next syscall argument, or by the syscall return value,
2043 * depending on which argument number we are. This matches the
2044 * kevent syscall, but luckily that's the only syscall that uses
2052 if (sc->offset == 1)
2053 numevents = args[sc->offset+1];
2054 else if (sc->offset == 3 && retval[0] != -1)
2055 numevents = retval[0];
2057 if (numevents >= 0) {
2058 bytes = sizeof(struct kevent) * numevents;
2059 if ((ke = malloc(bytes)) == NULL)
2061 "Cannot malloc %zu bytes for kevent array",
2065 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2068 for (i = 0; i < numevents; i++) {
2070 print_kevent(fp, &ke[i]);
2074 fprintf(fp, "0x%lx", args[sc->offset]);
2080 struct kevent_freebsd11 *ke11;
2086 if (sc->offset == 1)
2087 numevents = args[sc->offset+1];
2088 else if (sc->offset == 3 && retval[0] != -1)
2089 numevents = retval[0];
2091 if (numevents >= 0) {
2092 bytes = sizeof(struct kevent_freebsd11) * numevents;
2093 if ((ke11 = malloc(bytes)) == NULL)
2095 "Cannot malloc %zu bytes for kevent array",
2099 memset(&ke, 0, sizeof(ke));
2100 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2101 ke11, bytes) != -1) {
2103 for (i = 0; i < numevents; i++) {
2105 ke.ident = ke11[i].ident;
2106 ke.filter = ke11[i].filter;
2107 ke.flags = ke11[i].flags;
2108 ke.fflags = ke11[i].fflags;
2109 ke.data = ke11[i].data;
2110 ke.udata = ke11[i].udata;
2111 print_kevent(fp, &ke);
2115 fprintf(fp, "0x%lx", args[sc->offset]);
2123 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2127 strmode(st.st_mode, mode);
2129 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2130 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2131 (long)st.st_blksize);
2133 fprintf(fp, "0x%lx", args[sc->offset]);
2138 struct freebsd11_stat st;
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]);
2158 if (get_struct(pid, (void *)args[sc->offset], &buf,
2159 sizeof(buf)) != -1) {
2162 bzero(fsid, sizeof(fsid));
2163 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2164 for (i = 0; i < sizeof(buf.f_fsid); i++)
2165 snprintf(&fsid[i*2],
2166 sizeof(fsid) - (i*2), "%02x",
2167 ((u_char *)&buf.f_fsid)[i]);
2170 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2171 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2172 buf.f_mntfromname, fsid);
2174 fprintf(fp, "0x%lx", args[sc->offset]);
2181 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2184 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2185 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2186 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2187 ru.ru_inblock, ru.ru_oublock);
2189 fprintf(fp, "0x%lx", args[sc->offset]);
2195 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2197 fprintf(fp, "{ cur=%ju,max=%ju }",
2198 rl.rlim_cur, rl.rlim_max);
2200 fprintf(fp, "0x%lx", args[sc->offset]);
2206 if (get_struct(pid, (void *)args[sc->offset], &status,
2207 sizeof(status)) != -1) {
2209 if (WIFCONTINUED(status))
2210 fputs("CONTINUED", fp);
2211 else if (WIFEXITED(status))
2212 fprintf(fp, "EXITED,val=%d",
2213 WEXITSTATUS(status));
2214 else if (WIFSIGNALED(status))
2215 fprintf(fp, "SIGNALED,sig=%s%s",
2216 strsig2(WTERMSIG(status)),
2217 WCOREDUMP(status) ? ",cored" : "");
2219 fprintf(fp, "STOPPED,sig=%s",
2220 strsig2(WTERMSIG(status)));
2223 fprintf(fp, "0x%lx", args[sc->offset]);
2227 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2230 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2233 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2236 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2239 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2242 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2245 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2248 print_integer_arg(sysdecode_sysarch_number, fp,
2253 * The pipe() system call in the kernel returns its
2254 * two file descriptors via return values. However,
2255 * the interface exposed by libc is that pipe()
2256 * accepts a pointer to an array of descriptors.
2257 * Format the output to match the libc API by printing
2258 * the returned file descriptors as a fake argument.
2260 * Overwrite the first retval to signal a successful
2263 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
2270 len = args[sc->offset + 1];
2271 utrace_addr = calloc(1, len);
2272 if (get_struct(pid, (void *)args[sc->offset],
2273 (void *)utrace_addr, len) != -1)
2274 print_utrace(fp, utrace_addr, len);
2276 fprintf(fp, "0x%lx", args[sc->offset]);
2281 int descriptors[16];
2282 unsigned long i, ndescriptors;
2285 ndescriptors = args[sc->offset + 1];
2287 if (ndescriptors > nitems(descriptors)) {
2288 ndescriptors = nitems(descriptors);
2291 if (get_struct(pid, (void *)args[sc->offset],
2292 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2294 for (i = 0; i < ndescriptors; i++)
2295 fprintf(fp, i == 0 ? " %d" : ", %d",
2297 fprintf(fp, truncated ? ", ... }" : " }");
2299 fprintf(fp, "0x%lx", args[sc->offset]);
2303 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2305 case CapFcntlRights: {
2308 if (sc->type & OUT) {
2309 if (get_struct(pid, (void *)args[sc->offset], &rights,
2310 sizeof(rights)) == -1) {
2311 fprintf(fp, "0x%lx", args[sc->offset]);
2315 rights = args[sc->offset];
2316 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2320 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2325 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2326 fprintf(fp, "0x%x", rem);
2328 fprintf(fp, "|0x%x", rem);
2332 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2335 print_integer_arg(sysdecode_getfsstat_mode, fp,
2339 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2341 case Kldunloadflags:
2342 print_integer_arg(sysdecode_kldunload_flags, fp,
2346 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2349 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2351 case Sockprotocol: {
2353 int domain, protocol;
2355 domain = args[sc->offset - 2];
2356 protocol = args[sc->offset];
2357 if (protocol == 0) {
2360 temp = sysdecode_socket_protocol(domain, protocol);
2364 fprintf(fp, "%d", protocol);
2370 print_integer_arg(sysdecode_sockopt_level, fp,
2377 level = args[sc->offset - 1];
2378 name = args[sc->offset];
2379 temp = sysdecode_sockopt_name(level, name);
2383 fprintf(fp, "%d", name);
2388 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2391 cap_rights_t rights;
2393 if (get_struct(pid, (void *)args[sc->offset], &rights,
2394 sizeof(rights)) != -1) {
2396 sysdecode_cap_rights(fp, &rights);
2399 fprintf(fp, "0x%lx", args[sc->offset]);
2403 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2405 case Extattrnamespace:
2406 print_integer_arg(sysdecode_extattrnamespace, fp,
2410 print_integer_arg(sysdecode_minherit_inherit, fp,
2414 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2417 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2420 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2423 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2426 print_integer_arg(sysdecode_ptrace_request, fp,
2430 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2431 fprintf(fp, "%#x", (int)args[sc->offset]);
2434 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2437 print_integer_arg(sysdecode_rtprio_function, fp,
2441 print_integer_arg(sysdecode_scheduler_policy, fp,
2445 struct sched_param sp;
2447 if (get_struct(pid, (void *)args[sc->offset], &sp,
2449 fprintf(fp, "{ %d }", sp.sched_priority);
2451 fprintf(fp, "0x%lx", args[sc->offset]);
2457 if (get_struct(pid, (void *)args[sc->offset], &sig,
2459 fprintf(fp, "{ %s }", strsig2(sig));
2461 fprintf(fp, "0x%lx", args[sc->offset]);
2467 if (get_struct(pid, (void *)args[sc->offset], &si,
2468 sizeof(si)) != -1) {
2469 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2470 decode_siginfo(fp, &si);
2473 fprintf(fp, "0x%lx", args[sc->offset]);
2478 * Print argument as an array of struct iovec, where the next
2479 * syscall argument is the number of elements of the array.
2482 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2483 (int)args[sc->offset + 1]);
2485 case Sctpsndrcvinfo: {
2486 struct sctp_sndrcvinfo info;
2488 if (get_struct(pid, (void *)args[sc->offset],
2489 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2490 fprintf(fp, "0x%lx", args[sc->offset]);
2493 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2497 struct msghdr msghdr;
2499 if (get_struct(pid, (void *)args[sc->offset],
2500 &msghdr, sizeof(struct msghdr)) == -1) {
2501 fprintf(fp, "0x%lx", args[sc->offset]);
2505 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2506 fprintf(fp, ",%d,", msghdr.msg_namelen);
2507 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2508 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2509 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2510 fprintf(fp, ",%u,", msghdr.msg_controllen);
2511 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2516 case CloudABIAdvice:
2517 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2519 case CloudABIClockID:
2520 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2522 case CloudABIFDSFlags:
2523 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2525 case CloudABIFDStat: {
2526 cloudabi_fdstat_t fds;
2527 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2529 fprintf(fp, "{ %s, ",
2530 xlookup(cloudabi_filetype, fds.fs_filetype));
2531 fprintf(fp, "%s, ... }",
2532 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2534 fprintf(fp, "0x%lx", args[sc->offset]);
2537 case CloudABIFileStat: {
2538 cloudabi_filestat_t fsb;
2539 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2541 fprintf(fp, "{ %s, %ju }",
2542 xlookup(cloudabi_filetype, fsb.st_filetype),
2543 (uintmax_t)fsb.st_size);
2545 fprintf(fp, "0x%lx", args[sc->offset]);
2548 case CloudABIFileType:
2549 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2551 case CloudABIFSFlags:
2552 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2554 case CloudABILookup:
2555 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2556 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2557 (int)args[sc->offset]);
2559 fprintf(fp, "%d", (int)args[sc->offset]);
2561 case CloudABIMFlags:
2562 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2565 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2567 case CloudABIMSFlags:
2568 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2570 case CloudABIOFlags:
2571 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2573 case CloudABISDFlags:
2574 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2576 case CloudABISignal:
2577 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2579 case CloudABITimestamp:
2580 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2581 args[sc->offset] % 1000000000);
2583 case CloudABIULFlags:
2584 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2586 case CloudABIWhence:
2587 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2591 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2598 * Print (to outfile) the system call and its arguments.
2601 print_syscall(struct trussinfo *trussinfo)
2603 struct threadinfo *t;
2608 t = trussinfo->curthread;
2610 name = t->cs.sc->name;
2611 nargs = t->cs.nargs;
2612 s_args = t->cs.s_args;
2614 len = print_line_prefix(trussinfo);
2615 len += fprintf(trussinfo->outfile, "%s(", name);
2617 for (i = 0; i < nargs; i++) {
2618 if (s_args[i] != NULL)
2619 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2621 len += fprintf(trussinfo->outfile,
2622 "<missing argument>");
2623 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2626 len += fprintf(trussinfo->outfile, ")");
2627 for (i = 0; i < 6 - (len / 8); i++)
2628 fprintf(trussinfo->outfile, "\t");
2632 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2634 struct timespec timediff;
2635 struct threadinfo *t;
2639 t = trussinfo->curthread;
2641 if (trussinfo->flags & COUNTONLY) {
2642 timespecsubt(&t->after, &t->before, &timediff);
2643 timespecadd(&sc->time, &timediff, &sc->time);
2650 print_syscall(trussinfo);
2651 fflush(trussinfo->outfile);
2653 if (retval == NULL) {
2655 * This system call resulted in the current thread's exit,
2656 * so there is no return value or error to display.
2658 fprintf(trussinfo->outfile, "\n");
2663 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2665 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2666 error == INT_MAX ? "Unknown error" : strerror(error));
2669 else if (sc->ret_type == 2) {
2672 #if _BYTE_ORDER == _LITTLE_ENDIAN
2673 off = (off_t)retval[1] << 32 | retval[0];
2675 off = (off_t)retval[0] << 32 | retval[1];
2677 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2682 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2687 print_summary(struct trussinfo *trussinfo)
2689 struct timespec total = {0, 0};
2693 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2694 "syscall", "seconds", "calls", "errors");
2696 STAILQ_FOREACH(sc, &syscalls, entries)
2698 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2699 sc->name, (intmax_t)sc->time.tv_sec,
2700 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2701 timespecadd(&total, &sc->time, &total);
2702 ncall += sc->ncalls;
2703 nerror += sc->nerror;
2705 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2706 "", "-------------", "-------", "-------");
2707 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2708 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);