2 * Copyright 1997 Sean Eric Fagan
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Sean Eric Fagan
15 * 4. Neither the name of the author may be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
36 * This file has routines used to print out system calls and their
40 #include <sys/types.h>
41 #include <sys/event.h>
42 #include <sys/ioccom.h>
43 #include <sys/mount.h>
44 #include <sys/ptrace.h>
45 #include <sys/resource.h>
46 #include <sys/socket.h>
50 #include <machine/sysarch.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
63 #include <sysdecode.h>
67 #include <contrib/cloudabi/cloudabi_types_common.h>
73 /* 64-bit alignment on 32-bit platforms. */
74 #if !defined(__LP64__) && defined(__powerpc__)
80 /* Number of slots needed for a 64-bit argument. */
88 * This should probably be in its own file, sorted alphabetically.
90 static struct syscall decoded_syscalls[] = {
92 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
93 .args = { { Name | OUT, 0 }, { Int, 1 } } },
94 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
95 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
97 { .name = "accept", .ret_type = 1, .nargs = 3,
98 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
99 { .name = "access", .ret_type = 1, .nargs = 2,
100 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
101 { .name = "bind", .ret_type = 1, .nargs = 3,
102 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
103 { .name = "bindat", .ret_type = 1, .nargs = 4,
104 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
106 { .name = "break", .ret_type = 1, .nargs = 1,
107 .args = { { Ptr, 0 } } },
108 { .name = "chdir", .ret_type = 1, .nargs = 1,
109 .args = { { Name, 0 } } },
110 { .name = "chflags", .ret_type = 1, .nargs = 2,
111 .args = { { Name | IN, 0 }, { Hex, 1 } } },
112 { .name = "chmod", .ret_type = 1, .nargs = 2,
113 .args = { { Name, 0 }, { Octal, 1 } } },
114 { .name = "chown", .ret_type = 1, .nargs = 3,
115 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
116 { .name = "chroot", .ret_type = 1, .nargs = 1,
117 .args = { { Name, 0 } } },
118 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
119 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
120 { .name = "close", .ret_type = 1, .nargs = 1,
121 .args = { { Int, 0 } } },
122 { .name = "connect", .ret_type = 1, .nargs = 3,
123 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
124 { .name = "connectat", .ret_type = 1, .nargs = 4,
125 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
127 { .name = "eaccess", .ret_type = 1, .nargs = 2,
128 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
129 { .name = "execve", .ret_type = 1, .nargs = 3,
130 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
131 { ExecEnv | IN, 2 } } },
132 { .name = "exit", .ret_type = 0, .nargs = 1,
133 .args = { { Hex, 0 } } },
134 { .name = "faccessat", .ret_type = 1, .nargs = 4,
135 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
137 { .name = "fchmod", .ret_type = 1, .nargs = 2,
138 .args = { { Int, 0 }, { Octal, 1 } } },
139 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
140 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
141 { .name = "fchown", .ret_type = 1, .nargs = 3,
142 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
143 { .name = "fchownat", .ret_type = 1, .nargs = 5,
144 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
146 { .name = "fcntl", .ret_type = 1, .nargs = 3,
147 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
148 { .name = "fstat", .ret_type = 1, .nargs = 2,
149 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
150 { .name = "fstatat", .ret_type = 1, .nargs = 4,
151 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
153 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
154 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
155 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
156 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } },
157 { .name = "futimens", .ret_type = 1, .nargs = 2,
158 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
159 { .name = "futimes", .ret_type = 1, .nargs = 2,
160 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
161 { .name = "futimesat", .ret_type = 1, .nargs = 3,
162 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
163 { .name = "getitimer", .ret_type = 1, .nargs = 2,
164 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
165 { .name = "getpeername", .ret_type = 1, .nargs = 3,
166 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
167 { .name = "getpgid", .ret_type = 1, .nargs = 1,
168 .args = { { Int, 0 } } },
169 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
170 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
171 { .name = "getrusage", .ret_type = 1, .nargs = 2,
172 .args = { { Int, 0 }, { Rusage | OUT, 1 } } },
173 { .name = "getsid", .ret_type = 1, .nargs = 1,
174 .args = { { Int, 0 } } },
175 { .name = "getsockname", .ret_type = 1, .nargs = 3,
176 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
177 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
178 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
179 { .name = "ioctl", .ret_type = 1, .nargs = 3,
180 .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } },
181 { .name = "kevent", .ret_type = 1, .nargs = 6,
182 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
183 { Int, 4 }, { Timespec, 5 } } },
184 { .name = "kill", .ret_type = 1, .nargs = 2,
185 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
186 { .name = "kldfind", .ret_type = 1, .nargs = 1,
187 .args = { { Name | IN, 0 } } },
188 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
189 .args = { { Int, 0 } } },
190 { .name = "kldload", .ret_type = 1, .nargs = 1,
191 .args = { { Name | IN, 0 } } },
192 { .name = "kldnext", .ret_type = 1, .nargs = 1,
193 .args = { { Int, 0 } } },
194 { .name = "kldstat", .ret_type = 1, .nargs = 2,
195 .args = { { Int, 0 }, { Ptr, 1 } } },
196 { .name = "kldunload", .ret_type = 1, .nargs = 1,
197 .args = { { Int, 0 } } },
198 { .name = "kse_release", .ret_type = 0, .nargs = 1,
199 .args = { { Timespec, 0 } } },
200 { .name = "lchflags", .ret_type = 1, .nargs = 2,
201 .args = { { Name | IN, 0 }, { Hex, 1 } } },
202 { .name = "lchmod", .ret_type = 1, .nargs = 2,
203 .args = { { Name, 0 }, { Octal, 1 } } },
204 { .name = "lchown", .ret_type = 1, .nargs = 3,
205 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
206 { .name = "link", .ret_type = 1, .nargs = 2,
207 .args = { { Name, 0 }, { Name, 1 } } },
208 { .name = "linkat", .ret_type = 1, .nargs = 5,
209 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
211 { .name = "lseek", .ret_type = 2, .nargs = 3,
212 .args = { { Int, 0 }, { QuadHex, 1 + QUAD_ALIGN },
213 { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } },
214 { .name = "lstat", .ret_type = 1, .nargs = 2,
215 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
216 { .name = "lutimes", .ret_type = 1, .nargs = 2,
217 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
218 { .name = "mkdir", .ret_type = 1, .nargs = 2,
219 .args = { { Name, 0 }, { Octal, 1 } } },
220 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
221 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
222 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
223 .args = { { Name, 0 }, { Octal, 1 } } },
224 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
225 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
226 { .name = "mknod", .ret_type = 1, .nargs = 3,
227 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
228 { .name = "mknodat", .ret_type = 1, .nargs = 4,
229 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
230 { .name = "mmap", .ret_type = 1, .nargs = 6,
231 .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
232 { Int, 4 }, { QuadHex, 5 + QUAD_ALIGN } } },
233 { .name = "modfind", .ret_type = 1, .nargs = 1,
234 .args = { { Name | IN, 0 } } },
235 { .name = "mount", .ret_type = 1, .nargs = 4,
236 .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
237 { .name = "mprotect", .ret_type = 1, .nargs = 3,
238 .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
239 { .name = "munmap", .ret_type = 1, .nargs = 2,
240 .args = { { Ptr, 0 }, { Int, 1 } } },
241 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
242 .args = { { Timespec, 0 } } },
243 { .name = "open", .ret_type = 1, .nargs = 3,
244 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
245 { .name = "openat", .ret_type = 1, .nargs = 4,
246 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
248 { .name = "pathconf", .ret_type = 1, .nargs = 2,
249 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
250 { .name = "pipe", .ret_type = 1, .nargs = 1,
251 .args = { { PipeFds | OUT, 0 } } },
252 { .name = "pipe2", .ret_type = 1, .nargs = 2,
253 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
254 { .name = "poll", .ret_type = 1, .nargs = 3,
255 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
256 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
257 .args = { { Open, 0 } } },
258 { .name = "procctl", .ret_type = 1, .nargs = 4,
259 .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN },
260 { Procctl, 1 + QUAD_ALIGN + QUAD_SLOTS },
261 { Ptr, 2 + QUAD_ALIGN + QUAD_SLOTS } } },
262 { .name = "read", .ret_type = 1, .nargs = 3,
263 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
264 { .name = "readlink", .ret_type = 1, .nargs = 3,
265 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Int, 2 } } },
266 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
267 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
269 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
270 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 },
271 { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
272 { .name = "rename", .ret_type = 1, .nargs = 2,
273 .args = { { Name, 0 }, { Name, 1 } } },
274 { .name = "renameat", .ret_type = 1, .nargs = 4,
275 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
276 { .name = "rfork", .ret_type = 1, .nargs = 1,
277 .args = { { Rforkflags, 0 } } },
278 { .name = "rmdir", .ret_type = 1, .nargs = 1,
279 .args = { { Name, 0 } } },
280 { .name = "select", .ret_type = 1, .nargs = 5,
281 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
283 { .name = "sendto", .ret_type = 1, .nargs = 6,
284 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 },
285 { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
286 { .name = "setitimer", .ret_type = 1, .nargs = 3,
287 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
288 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
289 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
290 { .name = "shutdown", .ret_type = 1, .nargs = 2,
291 .args = { { Int, 0 }, { Shutdown, 1 } } },
292 { .name = "sigaction", .ret_type = 1, .nargs = 3,
293 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
294 { Sigaction | OUT, 2 } } },
295 { .name = "sigpending", .ret_type = 1, .nargs = 1,
296 .args = { { Sigset | OUT, 0 } } },
297 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
298 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
299 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
300 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
301 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
302 .args = { { Ptr, 0 } } },
303 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
304 .args = { { Sigset | IN, 0 } } },
305 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
306 .args = { { Sigset | IN, 0 }, { Ptr, 1 }, { Timespec | IN, 2 } } },
307 { .name = "sigwait", .ret_type = 1, .nargs = 2,
308 .args = { { Sigset | IN, 0 }, { Ptr, 1 } } },
309 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
310 .args = { { Sigset | IN, 0 }, { Ptr, 1 } } },
311 { .name = "socket", .ret_type = 1, .nargs = 3,
312 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } },
313 { .name = "stat", .ret_type = 1, .nargs = 2,
314 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
315 { .name = "statfs", .ret_type = 1, .nargs = 2,
316 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
317 { .name = "symlink", .ret_type = 1, .nargs = 2,
318 .args = { { Name, 0 }, { Name, 1 } } },
319 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
320 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
321 { .name = "sysarch", .ret_type = 1, .nargs = 2,
322 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
323 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
324 .args = { { Long, 0 }, { Signal, 1 } } },
325 { .name = "thr_self", .ret_type = 1, .nargs = 1,
326 .args = { { Ptr, 0 } } },
327 { .name = "truncate", .ret_type = 1, .nargs = 2,
328 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } },
331 { .name = "umount", .ret_type = 1, .nargs = 2,
332 .args = { { Name, 0 }, { Int, 2 } } },
334 { .name = "unlink", .ret_type = 1, .nargs = 1,
335 .args = { { Name, 0 } } },
336 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
337 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
338 { .name = "unmount", .ret_type = 1, .nargs = 2,
339 .args = { { Name, 0 }, { Int, 1 } } },
340 { .name = "utimensat", .ret_type = 1, .nargs = 4,
341 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
343 { .name = "utimes", .ret_type = 1, .nargs = 2,
344 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
345 { .name = "utrace", .ret_type = 1, .nargs = 1,
346 .args = { { Utrace, 0 } } },
347 { .name = "wait4", .ret_type = 1, .nargs = 4,
348 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
349 { Rusage | OUT, 3 } } },
350 { .name = "wait6", .ret_type = 1, .nargs = 6,
351 .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN },
352 { ExitStatus | OUT, 1 + QUAD_ALIGN + QUAD_SLOTS },
353 { Waitoptions, 2 + QUAD_ALIGN + QUAD_SLOTS },
354 { Rusage | OUT, 3 + QUAD_ALIGN + QUAD_SLOTS },
355 { Ptr, 4 + QUAD_ALIGN + QUAD_SLOTS } } },
356 { .name = "write", .ret_type = 1, .nargs = 3,
357 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } },
360 { .name = "linux_access", .ret_type = 1, .nargs = 2,
361 .args = { { Name, 0 }, { Accessmode, 1 } } },
362 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
363 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
364 { ExecEnv | IN, 2 } } },
365 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
366 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
367 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
368 .args = { { Name | IN, 0 }, { Int, 1 } } },
369 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
370 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
371 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
372 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
373 { .name = "linux_open", .ret_type = 1, .nargs = 3,
374 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
375 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
376 .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } },
377 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
378 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
379 { .name = "linux_stat64", .ret_type = 1, .nargs = 3,
380 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } },
382 /* CloudABI system calls. */
383 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
384 .args = { { CloudABIClockID, 0 } } },
385 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
386 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
387 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
388 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
389 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
390 .args = { { Int, 0 } } },
391 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
392 .args = { { CloudABIFileType, 0 } } },
393 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
394 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
395 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
396 .args = { { Int, 0 } } },
397 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
398 .args = { { Int, 0 } } },
399 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
400 .args = { { Int, 0 }, { Int, 1 } } },
401 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
402 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
403 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
404 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
405 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
406 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
407 { ClouduABIFDSFlags, 2 } } },
408 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
409 .args = { { Int, 0 } } },
410 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
411 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
412 { CloudABIAdvice, 3 } } },
413 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
414 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
415 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
416 .args = { { Int, 0 }, { BinString | IN, 1 },
417 { CloudABIFileType, 3 } } },
418 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
419 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
420 { Int, 3 }, { BinString | IN, 4 } } },
421 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
422 .args = { { Int, 0 }, { BinString | IN, 1 },
423 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
424 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
425 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
427 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
428 .args = { { Int, 0 }, { BinString | IN, 1 },
429 { BinString | OUT, 3 }, { Int, 4 } } },
430 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
431 .args = { { Int, 0 }, { BinString | IN, 1 },
432 { Int, 3 }, { BinString | IN, 4 } } },
433 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
434 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
435 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
436 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
437 { CloudABIFSFlags, 2 } } },
438 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
439 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
440 { CloudABIFileStat | OUT, 3 } } },
441 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
442 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
443 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
444 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
445 .args = { { BinString | IN, 0 },
446 { Int, 2 }, { BinString | IN, 3 } } },
447 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
448 .args = { { Int, 0 }, { BinString | IN, 1 },
449 { CloudABIULFlags, 3 } } },
450 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
451 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
452 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
453 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
454 { .name = "cloudabi_sys_mem_lock", .ret_type = 1, .nargs = 2,
455 .args = { { Ptr, 0 }, { Int, 1 } } },
456 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
457 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
458 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
459 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
460 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
461 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
462 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
463 { .name = "cloudabi_sys_mem_unlock", .ret_type = 1, .nargs = 2,
464 .args = { { Ptr, 0 }, { Int, 1 } } },
465 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
466 .args = { { Ptr, 0 }, { Int, 1 } } },
467 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
468 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
469 { IntArray, 3 }, { Int, 4 } } },
470 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
471 .args = { { Int, 0 } } },
472 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
473 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
474 .args = { { CloudABISignal, 0 } } },
475 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
476 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
477 { .name = "cloudabi_sys_sock_accept", .ret_type = 1, .nargs = 2,
478 .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 } } },
479 { .name = "cloudabi_sys_sock_bind", .ret_type = 1, .nargs = 3,
480 .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } },
481 { .name = "cloudabi_sys_sock_connect", .ret_type = 1, .nargs = 3,
482 .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } },
483 { .name = "cloudabi_sys_sock_listen", .ret_type = 1, .nargs = 2,
484 .args = { { Int, 0 }, { Int, 1 } } },
485 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
486 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
487 { .name = "cloudabi_sys_sock_stat_get", .ret_type = 1, .nargs = 3,
488 .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 },
489 { CloudABISSFlags, 2 } } },
490 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
491 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
492 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
496 static STAILQ_HEAD(, syscall) syscalls;
498 /* Xlat idea taken from strace */
504 #define X(a) { a, #a },
505 #define XEND { 0, NULL }
507 static struct xlat kevent_filters[] = {
508 X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
509 X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
510 X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
511 X(EVFILT_SENDFILE) XEND
514 static struct xlat kevent_flags[] = {
515 X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
516 X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
517 X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
520 static struct xlat kevent_user_ffctrl[] = {
521 X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY)
525 static struct xlat kevent_rdwr_fflags[] = {
526 X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND
529 static struct xlat kevent_vnode_fflags[] = {
530 X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB)
531 X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) XEND
534 static struct xlat kevent_proc_fflags[] = {
535 X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR)
539 static struct xlat kevent_timer_fflags[] = {
540 X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS)
544 static struct xlat poll_flags[] = {
545 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
546 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
547 X(POLLWRBAND) X(POLLINIGNEOF) XEND
550 static struct xlat sigaction_flags[] = {
551 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
552 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
555 static struct xlat pathconf_arg[] = {
556 X(_PC_LINK_MAX) X(_PC_MAX_CANON) X(_PC_MAX_INPUT)
557 X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF)
558 X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE)
559 X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO)
560 X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS)
561 X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE)
562 X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN)
563 X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX)
564 X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT)
565 X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND
568 static struct xlat at_flags[] = {
569 X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW)
573 static struct xlat sysarch_ops[] = {
574 #if defined(__i386__) || defined(__amd64__)
575 X(I386_GET_LDT) X(I386_SET_LDT) X(I386_GET_IOPERM) X(I386_SET_IOPERM)
576 X(I386_VM86) X(I386_GET_FSBASE) X(I386_SET_FSBASE) X(I386_GET_GSBASE)
577 X(I386_SET_GSBASE) X(I386_GET_XFPUSTATE) X(AMD64_GET_FSBASE)
578 X(AMD64_SET_FSBASE) X(AMD64_GET_GSBASE) X(AMD64_SET_GSBASE)
579 X(AMD64_GET_XFPUSTATE)
584 static struct xlat linux_socketcall_ops[] = {
585 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
586 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
587 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
588 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
589 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
594 #define X(a) { CLOUDABI_##a, #a },
596 static struct xlat cloudabi_advice[] = {
597 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
598 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
602 static struct xlat cloudabi_clockid[] = {
603 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
604 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
608 static struct xlat cloudabi_errno[] = {
609 X(E2BIG) X(EACCES) X(EADDRINUSE) X(EADDRNOTAVAIL)
610 X(EAFNOSUPPORT) X(EAGAIN) X(EALREADY) X(EBADF) X(EBADMSG)
611 X(EBUSY) X(ECANCELED) X(ECHILD) X(ECONNABORTED) X(ECONNREFUSED)
612 X(ECONNRESET) X(EDEADLK) X(EDESTADDRREQ) X(EDOM) X(EDQUOT)
613 X(EEXIST) X(EFAULT) X(EFBIG) X(EHOSTUNREACH) X(EIDRM) X(EILSEQ)
614 X(EINPROGRESS) X(EINTR) X(EINVAL) X(EIO) X(EISCONN) X(EISDIR)
615 X(ELOOP) X(EMFILE) X(EMLINK) X(EMSGSIZE) X(EMULTIHOP)
616 X(ENAMETOOLONG) X(ENETDOWN) X(ENETRESET) X(ENETUNREACH)
617 X(ENFILE) X(ENOBUFS) X(ENODEV) X(ENOENT) X(ENOEXEC) X(ENOLCK)
618 X(ENOLINK) X(ENOMEM) X(ENOMSG) X(ENOPROTOOPT) X(ENOSPC)
619 X(ENOSYS) X(ENOTCONN) X(ENOTDIR) X(ENOTEMPTY) X(ENOTRECOVERABLE)
620 X(ENOTSOCK) X(ENOTSUP) X(ENOTTY) X(ENXIO) X(EOVERFLOW)
621 X(EOWNERDEAD) X(EPERM) X(EPIPE) X(EPROTO) X(EPROTONOSUPPORT)
622 X(EPROTOTYPE) X(ERANGE) X(EROFS) X(ESPIPE) X(ESRCH) X(ESTALE)
623 X(ETIMEDOUT) X(ETXTBSY) X(EXDEV) X(ENOTCAPABLE)
627 static struct xlat cloudabi_fdflags[] = {
628 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
629 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
633 static struct xlat cloudabi_fdsflags[] = {
634 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
638 static struct xlat cloudabi_filetype[] = {
639 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
640 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
641 X(FILETYPE_FIFO) X(FILETYPE_POLL) X(FILETYPE_PROCESS)
642 X(FILETYPE_REGULAR_FILE) X(FILETYPE_SHARED_MEMORY)
643 X(FILETYPE_SOCKET_DGRAM) X(FILETYPE_SOCKET_SEQPACKET)
644 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
648 static struct xlat cloudabi_fsflags[] = {
649 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
650 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
654 static struct xlat cloudabi_mflags[] = {
655 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
659 static struct xlat cloudabi_mprot[] = {
660 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
664 static struct xlat cloudabi_msflags[] = {
665 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
669 static struct xlat cloudabi_oflags[] = {
670 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
674 static struct xlat cloudabi_sa_family[] = {
675 X(AF_UNSPEC) X(AF_INET) X(AF_INET6) X(AF_UNIX)
679 static struct xlat cloudabi_sdflags[] = {
680 X(SHUT_RD) X(SHUT_WR)
684 static struct xlat cloudabi_signal[] = {
685 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
686 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
687 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
688 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
689 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
693 static struct xlat cloudabi_ssflags[] = {
694 X(SOCKSTAT_CLEAR_ERROR)
698 static struct xlat cloudabi_ssstate[] = {
699 X(SOCKSTATE_ACCEPTCONN)
703 static struct xlat cloudabi_ulflags[] = {
708 static struct xlat cloudabi_whence[] = {
709 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
717 * Searches an xlat array for a value, and returns it if found. Otherwise
718 * return a string representation.
721 lookup(struct xlat *xlat, int val, int base)
725 for (; xlat->str != NULL; xlat++)
726 if (xlat->val == val)
730 sprintf(tmp, "0%o", val);
733 sprintf(tmp, "0x%x", val);
736 sprintf(tmp, "%u", val);
739 errx(1,"Unknown lookup base");
746 xlookup(struct xlat *xlat, int val)
749 return (lookup(xlat, val, 16));
753 * Searches an xlat array containing bitfield values. Remaining bits
754 * set after removing the known ones are printed at the end:
758 xlookup_bits(struct xlat *xlat, int val)
761 static char str[512];
765 for (; xlat->str != NULL; xlat++) {
766 if ((xlat->val & rem) == xlat->val) {
768 * Don't print the "all-bits-zero" string unless all
769 * bits are really zero.
771 if (xlat->val == 0 && val != 0)
773 len += sprintf(str + len, "%s|", xlat->str);
779 * If we have leftover bits or didn't match anything, print
783 len += sprintf(str + len, "0x%x", rem);
784 if (len && str[len - 1] == '|')
791 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
795 str = decoder(value);
799 fprintf(fp, "%d", value);
803 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
807 if (!decoder(fp, value, &rem))
808 fprintf(fp, "0x%x", rem);
810 fprintf(fp, "|0x%x", rem);
818 STAILQ_INIT(&syscalls);
819 for (sc = decoded_syscalls; sc->name != NULL; sc++)
820 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
823 * If/when the list gets big, it might be desirable to do it
824 * as a hash table or binary search.
827 get_syscall(const char *name, int nargs)
834 STAILQ_FOREACH(sc, &syscalls, entries)
835 if (strcmp(name, sc->name) == 0)
838 /* It is unknown. Add it into the list. */
840 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
844 sc = calloc(1, sizeof(struct syscall));
845 sc->name = strdup(name);
848 for (i = 0; i < nargs; i++) {
849 sc->args[i].offset = i;
850 /* Treat all unknown arguments as LongHex. */
851 sc->args[i].type = LongHex;
853 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
859 * Copy a fixed amount of bytes from the process.
862 get_struct(pid_t pid, void *offset, void *buf, int len)
864 struct ptrace_io_desc iorequest;
866 iorequest.piod_op = PIOD_READ_D;
867 iorequest.piod_offs = offset;
868 iorequest.piod_addr = buf;
869 iorequest.piod_len = len;
870 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
878 * Copy a string from the process. Note that it is
879 * expected to be a C string, but if max is set, it will
880 * only get that much.
883 get_string(pid_t pid, void *addr, int max)
885 struct ptrace_io_desc iorequest;
887 size_t offset, size, totalsize;
893 /* Read up to the end of the current page. */
894 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
899 buf = malloc(totalsize);
903 iorequest.piod_op = PIOD_READ_D;
904 iorequest.piod_offs = (char *)addr + offset;
905 iorequest.piod_addr = buf + offset;
906 iorequest.piod_len = size;
907 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
911 if (memchr(buf + offset, '\0', size) != NULL)
914 if (totalsize < MAXSIZE && max == 0) {
915 size = MAXSIZE - totalsize;
916 if (size > PAGE_SIZE)
918 nbuf = realloc(buf, totalsize + size);
920 buf[totalsize - 1] = '\0';
926 buf[totalsize - 1] = '\0';
938 signame = sysdecode_signal(sig);
939 if (signame == NULL) {
940 snprintf(tmp, sizeof(tmp), "%d", sig);
947 print_kevent(FILE *fp, struct kevent *ke, int input)
950 switch (ke->filter) {
956 case EVFILT_PROCDESC:
957 fprintf(fp, "%ju", (uintmax_t)ke->ident);
960 fputs(strsig2(ke->ident), fp);
963 fprintf(fp, "%p", (void *)ke->ident);
965 fprintf(fp, ",%s,%s,", xlookup(kevent_filters, ke->filter),
966 xlookup_bits(kevent_flags, ke->flags));
967 switch (ke->filter) {
970 fputs(xlookup_bits(kevent_rdwr_fflags, ke->fflags), fp);
973 fputs(xlookup_bits(kevent_vnode_fflags, ke->fflags), fp);
976 case EVFILT_PROCDESC:
977 fputs(xlookup_bits(kevent_proc_fflags, ke->fflags), fp);
980 fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp);
985 ctrl = ke->fflags & NOTE_FFCTRLMASK;
986 data = ke->fflags & NOTE_FFLAGSMASK;
988 fputs(xlookup(kevent_user_ffctrl, ctrl), fp);
989 if (ke->fflags & NOTE_TRIGGER)
990 fputs("|NOTE_TRIGGER", fp);
992 fprintf(fp, "|%#x", data);
994 fprintf(fp, "%#x", data);
999 fprintf(fp, "%#x", ke->fflags);
1001 fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
1005 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1007 unsigned char *utrace_buffer;
1010 if (sysdecode_utrace(fp, utrace_addr, len)) {
1015 utrace_buffer = utrace_addr;
1016 fprintf(fp, "%zu:", len);
1018 fprintf(fp, " %02x", *utrace_buffer++);
1023 * Converts a syscall argument into a string. Said string is
1024 * allocated via malloc(), so needs to be free()'d. sc is
1025 * a pointer to the syscall description (see above); args is
1026 * an array of all of the system call arguments.
1029 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1030 struct trussinfo *trussinfo)
1037 fp = open_memstream(&tmp, &tmplen);
1038 pid = trussinfo->curthread->proc->pid;
1039 switch (sc->type & ARG_MASK) {
1041 fprintf(fp, "0x%x", (int)args[sc->offset]);
1044 fprintf(fp, "0%o", (int)args[sc->offset]);
1047 fprintf(fp, "%d", (int)args[sc->offset]);
1050 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1053 fprintf(fp, "0x%lx", args[sc->offset]);
1056 fprintf(fp, "%ld", args[sc->offset]);
1059 /* NULL-terminated string. */
1062 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1063 fprintf(fp, "\"%s\"", tmp2);
1069 * Binary block of data that might have printable characters.
1070 * XXX If type|OUT, assume that the length is the syscall's
1071 * return value. Otherwise, assume that the length of the block
1072 * is in the next syscall argument.
1074 int max_string = trussinfo->strsize;
1075 char tmp2[max_string + 1], *tmp3;
1082 len = args[sc->offset + 1];
1085 * Don't print more than max_string characters, to avoid word
1086 * wrap. If we have to truncate put some ... after the string.
1088 if (len > max_string) {
1092 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1094 tmp3 = malloc(len * 4 + 1);
1096 if (strvisx(tmp3, tmp2, len,
1097 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1102 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1106 fprintf(fp, "0x%lx", args[sc->offset]);
1116 char buf[PAGE_SIZE];
1123 * Only parse argv[] and environment arrays from exec calls
1126 if (((sc->type & ARG_MASK) == ExecArgs &&
1127 (trussinfo->flags & EXECVEARGS) == 0) ||
1128 ((sc->type & ARG_MASK) == ExecEnv &&
1129 (trussinfo->flags & EXECVEENVS) == 0)) {
1130 fprintf(fp, "0x%lx", args[sc->offset]);
1135 * Read a page of pointers at a time. Punt if the top-level
1136 * pointer is not aligned. Note that the first read is of
1139 addr = args[sc->offset];
1140 if (addr % sizeof(char *) != 0) {
1141 fprintf(fp, "0x%lx", args[sc->offset]);
1145 len = PAGE_SIZE - (addr & PAGE_MASK);
1146 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1147 fprintf(fp, "0x%lx", args[sc->offset]);
1154 while (u.strarray[i] != NULL) {
1155 string = get_string(pid, u.strarray[i], 0);
1156 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1161 if (i == len / sizeof(char *)) {
1164 if (get_struct(pid, (void *)addr, u.buf, len) ==
1166 fprintf(fp, ", <inval>");
1177 fprintf(fp, "%ld", args[sc->offset]);
1180 fprintf(fp, "0x%lx", args[sc->offset]);
1185 unsigned long long ll;
1187 #if _BYTE_ORDER == _LITTLE_ENDIAN
1188 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1191 ll = (unsigned long long)args[sc->offset] << 32 |
1192 args[sc->offset + 1];
1194 if ((sc->type & ARG_MASK) == Quad)
1195 fprintf(fp, "%lld", ll);
1197 fprintf(fp, "0x%llx", ll);
1202 fprintf(fp, "0x%lx", args[sc->offset]);
1207 if (retval[0] == -1)
1209 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1210 fprintf(fp, "\"%s\"", tmp2);
1218 cmd = args[sc->offset];
1219 temp = sysdecode_ioctlname(cmd);
1223 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1224 cmd, cmd & IOC_OUT ? "R" : "",
1225 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1226 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1227 cmd & 0xFF, IOCPARM_LEN(cmd));
1234 if (get_struct(pid, (void *)args[sc->offset], &ts,
1236 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1239 fprintf(fp, "0x%lx", args[sc->offset]);
1243 struct timespec ts[2];
1247 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1251 for (i = 0; i < nitems(ts); i++) {
1254 switch (ts[i].tv_nsec) {
1256 fprintf(fp, "UTIME_NOW");
1259 fprintf(fp, "UTIME_OMIT");
1262 fprintf(fp, "%jd.%09ld",
1263 (intmax_t)ts[i].tv_sec,
1270 fprintf(fp, "0x%lx", args[sc->offset]);
1276 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1278 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1281 fprintf(fp, "0x%lx", args[sc->offset]);
1285 struct timeval tv[2];
1287 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1289 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1290 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1291 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1293 fprintf(fp, "0x%lx", args[sc->offset]);
1297 struct itimerval itv;
1299 if (get_struct(pid, (void *)args[sc->offset], &itv,
1301 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1302 (intmax_t)itv.it_interval.tv_sec,
1303 itv.it_interval.tv_usec,
1304 (intmax_t)itv.it_value.tv_sec,
1305 itv.it_value.tv_usec);
1307 fprintf(fp, "0x%lx", args[sc->offset]);
1312 struct linux_socketcall_args largs;
1314 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1315 sizeof(largs)) != -1)
1316 fprintf(fp, "{ %s, 0x%lx }",
1317 lookup(linux_socketcall_ops, largs.what, 10),
1318 (long unsigned int)largs.args);
1320 fprintf(fp, "0x%lx", args[sc->offset]);
1325 * XXX: A Pollfd argument expects the /next/ syscall argument
1326 * to be the number of fds in the array. This matches the poll
1330 int numfds = args[sc->offset + 1];
1331 size_t bytes = sizeof(struct pollfd) * numfds;
1334 if ((pfd = malloc(bytes)) == NULL)
1335 err(1, "Cannot malloc %zu bytes for pollfd array",
1337 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1340 for (i = 0; i < numfds; i++) {
1341 fprintf(fp, " %d/%s", pfd[i].fd,
1342 xlookup_bits(poll_flags, pfd[i].events));
1346 fprintf(fp, "0x%lx", args[sc->offset]);
1353 * XXX: A Fd_set argument expects the /first/ syscall argument
1354 * to be the number of fds in the array. This matches the
1358 int numfds = args[0];
1359 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1362 if ((fds = malloc(bytes)) == NULL)
1363 err(1, "Cannot malloc %zu bytes for fd_set array",
1365 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1368 for (i = 0; i < numfds; i++) {
1369 if (FD_ISSET(i, fds))
1370 fprintf(fp, " %d", i);
1374 fprintf(fp, "0x%lx", args[sc->offset]);
1379 fputs(strsig2(args[sc->offset]), fp);
1386 sig = args[sc->offset];
1387 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1388 sizeof(ss)) == -1) {
1389 fprintf(fp, "0x%lx", args[sc->offset]);
1394 for (i = 1; i < sys_nsig; i++) {
1395 if (sigismember(&ss, i)) {
1396 fprintf(fp, "%s%s", !first ? "|" : "",
1407 print_integer_arg(sysdecode_sigprocmask_how, fp,
1411 /* XXX: Output depends on the value of the previous argument. */
1412 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1413 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1414 args[sc->offset], 16);
1417 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1420 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1423 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1426 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1429 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1432 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1435 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1438 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1441 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
1444 fputs(xlookup(pathconf_arg, args[sc->offset]), fp);
1447 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
1451 struct sockaddr_in *lsin;
1452 struct sockaddr_in6 *lsin6;
1453 struct sockaddr_un *sun;
1454 struct sockaddr *sa;
1458 if (args[sc->offset] == 0) {
1464 * Extract the address length from the next argument. If
1465 * this is an output sockaddr (OUT is set), then the
1466 * next argument is a pointer to a socklen_t. Otherwise
1467 * the next argument contains a socklen_t by value.
1469 if (sc->type & OUT) {
1470 if (get_struct(pid, (void *)args[sc->offset + 1],
1471 &len, sizeof(len)) == -1) {
1472 fprintf(fp, "0x%lx", args[sc->offset]);
1476 len = args[sc->offset + 1];
1478 /* If the length is too small, just bail. */
1479 if (len < sizeof(*sa)) {
1480 fprintf(fp, "0x%lx", args[sc->offset]);
1484 sa = calloc(1, len);
1485 if (get_struct(pid, (void *)args[sc->offset], sa, len) == -1) {
1487 fprintf(fp, "0x%lx", args[sc->offset]);
1491 switch (sa->sa_family) {
1493 if (len < sizeof(*lsin))
1494 goto sockaddr_short;
1495 lsin = (struct sockaddr_in *)(void *)sa;
1496 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1497 fprintf(fp, "{ AF_INET %s:%d }", addr,
1498 htons(lsin->sin_port));
1501 if (len < sizeof(*lsin6))
1502 goto sockaddr_short;
1503 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1504 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1506 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1507 htons(lsin6->sin6_port));
1510 sun = (struct sockaddr_un *)sa;
1511 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1512 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1518 "{ sa_len = %d, sa_family = %d, sa_data = {",
1519 (int)sa->sa_len, (int)sa->sa_family);
1520 for (q = (u_char *)sa->sa_data;
1521 q < (u_char *)sa + len; q++)
1522 fprintf(fp, "%s 0x%02x",
1523 q == (u_char *)sa->sa_data ? "" : ",",
1531 struct sigaction sa;
1533 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
1536 if (sa.sa_handler == SIG_DFL)
1537 fputs("SIG_DFL", fp);
1538 else if (sa.sa_handler == SIG_IGN)
1539 fputs("SIG_IGN", fp);
1541 fprintf(fp, "%p", sa.sa_handler);
1542 fprintf(fp, " %s ss_t }",
1543 xlookup_bits(sigaction_flags, sa.sa_flags));
1545 fprintf(fp, "0x%lx", args[sc->offset]);
1550 * XXX XXX: The size of the array is determined by either the
1551 * next syscall argument, or by the syscall return value,
1552 * depending on which argument number we are. This matches the
1553 * kevent syscall, but luckily that's the only syscall that uses
1561 if (sc->offset == 1)
1562 numevents = args[sc->offset+1];
1563 else if (sc->offset == 3 && retval[0] != -1)
1564 numevents = retval[0];
1566 if (numevents >= 0) {
1567 bytes = sizeof(struct kevent) * numevents;
1568 if ((ke = malloc(bytes)) == NULL)
1570 "Cannot malloc %zu bytes for kevent array",
1574 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
1577 for (i = 0; i < numevents; i++) {
1579 print_kevent(fp, &ke[i], sc->offset == 1);
1583 fprintf(fp, "0x%lx", args[sc->offset]);
1591 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
1595 strmode(st.st_mode, mode);
1597 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
1598 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
1599 (long)st.st_blksize);
1601 fprintf(fp, "0x%lx", args[sc->offset]);
1609 if (get_struct(pid, (void *)args[sc->offset], &buf,
1610 sizeof(buf)) != -1) {
1613 bzero(fsid, sizeof(fsid));
1614 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
1615 for (i = 0; i < sizeof(buf.f_fsid); i++)
1616 snprintf(&fsid[i*2],
1617 sizeof(fsid) - (i*2), "%02x",
1618 ((u_char *)&buf.f_fsid)[i]);
1621 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
1622 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
1623 buf.f_mntfromname, fsid);
1625 fprintf(fp, "0x%lx", args[sc->offset]);
1632 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
1635 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
1636 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
1637 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
1638 ru.ru_inblock, ru.ru_oublock);
1640 fprintf(fp, "0x%lx", args[sc->offset]);
1646 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
1648 fprintf(fp, "{ cur=%ju,max=%ju }",
1649 rl.rlim_cur, rl.rlim_max);
1651 fprintf(fp, "0x%lx", args[sc->offset]);
1657 if (get_struct(pid, (void *)args[sc->offset], &status,
1658 sizeof(status)) != -1) {
1660 if (WIFCONTINUED(status))
1661 fputs("CONTINUED", fp);
1662 else if (WIFEXITED(status))
1663 fprintf(fp, "EXITED,val=%d",
1664 WEXITSTATUS(status));
1665 else if (WIFSIGNALED(status))
1666 fprintf(fp, "SIGNALED,sig=%s%s",
1667 strsig2(WTERMSIG(status)),
1668 WCOREDUMP(status) ? ",cored" : "");
1670 fprintf(fp, "STOPPED,sig=%s",
1671 strsig2(WTERMSIG(status)));
1674 fprintf(fp, "0x%lx", args[sc->offset]);
1678 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
1681 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
1684 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
1687 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
1690 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
1693 fputs(xlookup_bits(at_flags, args[sc->offset]), fp);
1696 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
1699 fputs(xlookup(sysarch_ops, args[sc->offset]), fp);
1703 * The pipe() system call in the kernel returns its
1704 * two file descriptors via return values. However,
1705 * the interface exposed by libc is that pipe()
1706 * accepts a pointer to an array of descriptors.
1707 * Format the output to match the libc API by printing
1708 * the returned file descriptors as a fake argument.
1710 * Overwrite the first retval to signal a successful
1713 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
1720 len = args[sc->offset + 1];
1721 utrace_addr = calloc(1, len);
1722 if (get_struct(pid, (void *)args[sc->offset],
1723 (void *)utrace_addr, len) != -1)
1724 print_utrace(fp, utrace_addr, len);
1726 fprintf(fp, "0x%lx", args[sc->offset]);
1731 int descriptors[16];
1732 unsigned long i, ndescriptors;
1735 ndescriptors = args[sc->offset + 1];
1737 if (ndescriptors > nitems(descriptors)) {
1738 ndescriptors = nitems(descriptors);
1741 if (get_struct(pid, (void *)args[sc->offset],
1742 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
1744 for (i = 0; i < ndescriptors; i++)
1745 fprintf(fp, i == 0 ? " %d" : ", %d",
1747 fprintf(fp, truncated ? ", ... }" : " }");
1749 fprintf(fp, "0x%lx", args[sc->offset]);
1753 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
1756 case CloudABIAdvice:
1757 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
1759 case CloudABIClockID:
1760 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
1762 case ClouduABIFDSFlags:
1763 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
1765 case CloudABIFDStat: {
1766 cloudabi_fdstat_t fds;
1767 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
1769 fprintf(fp, "{ %s, ",
1770 xlookup(cloudabi_filetype, fds.fs_filetype));
1771 fprintf(fp, "%s, ... }",
1772 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
1774 fprintf(fp, "0x%lx", args[sc->offset]);
1777 case CloudABIFileStat: {
1778 cloudabi_filestat_t fsb;
1779 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
1781 fprintf(fp, "{ %s, %ju }",
1782 xlookup(cloudabi_filetype, fsb.st_filetype),
1783 (uintmax_t)fsb.st_size);
1785 fprintf(fp, "0x%lx", args[sc->offset]);
1788 case CloudABIFileType:
1789 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
1791 case CloudABIFSFlags:
1792 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
1794 case CloudABILookup:
1795 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
1796 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
1797 (int)args[sc->offset]);
1799 fprintf(fp, "%d", (int)args[sc->offset]);
1801 case CloudABIMFlags:
1802 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
1805 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
1807 case CloudABIMSFlags:
1808 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
1810 case CloudABIOFlags:
1811 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
1813 case CloudABISDFlags:
1814 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
1816 case CloudABISignal:
1817 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
1819 case CloudABISockStat: {
1820 cloudabi_sockstat_t ss;
1821 if (get_struct(pid, (void *)args[sc->offset], &ss, sizeof(ss))
1823 fprintf(fp, "{ %s, ", xlookup(
1824 cloudabi_sa_family, ss.ss_sockname.sa_family));
1825 fprintf(fp, "%s, ", xlookup(
1826 cloudabi_sa_family, ss.ss_peername.sa_family));
1827 fprintf(fp, "%s, ", xlookup(
1828 cloudabi_errno, ss.ss_error));
1829 fprintf(fp, "%s }", xlookup_bits(
1830 cloudabi_ssstate, ss.ss_state));
1832 fprintf(fp, "0x%lx", args[sc->offset]);
1835 case CloudABISSFlags:
1836 fputs(xlookup_bits(cloudabi_ssflags, args[sc->offset]), fp);
1838 case CloudABITimestamp:
1839 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
1840 args[sc->offset] % 1000000000);
1842 case CloudABIULFlags:
1843 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
1845 case CloudABIWhence:
1846 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
1850 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
1857 * Print (to outfile) the system call and its arguments.
1860 print_syscall(struct trussinfo *trussinfo)
1862 struct threadinfo *t;
1867 t = trussinfo->curthread;
1870 nargs = t->cs.nargs;
1871 s_args = t->cs.s_args;
1873 len = print_line_prefix(trussinfo);
1874 len += fprintf(trussinfo->outfile, "%s(", name);
1876 for (i = 0; i < nargs; i++) {
1877 if (s_args[i] != NULL)
1878 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
1880 len += fprintf(trussinfo->outfile,
1881 "<missing argument>");
1882 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
1885 len += fprintf(trussinfo->outfile, ")");
1886 for (i = 0; i < 6 - (len / 8); i++)
1887 fprintf(trussinfo->outfile, "\t");
1891 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
1893 struct timespec timediff;
1894 struct threadinfo *t;
1898 t = trussinfo->curthread;
1900 if (trussinfo->flags & COUNTONLY) {
1901 timespecsubt(&t->after, &t->before, &timediff);
1902 timespecadd(&sc->time, &timediff, &sc->time);
1909 print_syscall(trussinfo);
1910 fflush(trussinfo->outfile);
1912 if (retval == NULL) {
1914 * This system call resulted in the current thread's exit,
1915 * so there is no return value or error to display.
1917 fprintf(trussinfo->outfile, "\n");
1922 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
1924 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
1925 error == INT_MAX ? "Unknown error" : strerror(error));
1928 else if (sc->ret_type == 2) {
1931 #if _BYTE_ORDER == _LITTLE_ENDIAN
1932 off = (off_t)retval[1] << 32 | retval[0];
1934 off = (off_t)retval[0] << 32 | retval[1];
1936 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
1941 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
1946 print_summary(struct trussinfo *trussinfo)
1948 struct timespec total = {0, 0};
1952 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
1953 "syscall", "seconds", "calls", "errors");
1955 STAILQ_FOREACH(sc, &syscalls, entries)
1957 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
1958 sc->name, (intmax_t)sc->time.tv_sec,
1959 sc->time.tv_nsec, sc->ncalls, sc->nerror);
1960 timespecadd(&total, &sc->time, &total);
1961 ncall += sc->ncalls;
1962 nerror += sc->nerror;
1964 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
1965 "", "-------------", "-------", "-------");
1966 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
1967 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);