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>
64 #include <sysdecode.h>
68 #include <contrib/cloudabi/cloudabi_types_common.h>
74 /* 64-bit alignment on 32-bit platforms. */
75 #if !defined(__LP64__) && defined(__powerpc__)
81 /* Number of slots needed for a 64-bit argument. */
89 * This should probably be in its own file, sorted alphabetically.
91 static struct syscall decoded_syscalls[] = {
93 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
94 .args = { { Name | OUT, 0 }, { Int, 1 } } },
95 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
96 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
98 { .name = "accept", .ret_type = 1, .nargs = 3,
99 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
100 { .name = "access", .ret_type = 1, .nargs = 2,
101 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
102 { .name = "bind", .ret_type = 1, .nargs = 3,
103 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
104 { .name = "bindat", .ret_type = 1, .nargs = 4,
105 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
107 { .name = "break", .ret_type = 1, .nargs = 1,
108 .args = { { Ptr, 0 } } },
109 { .name = "chdir", .ret_type = 1, .nargs = 1,
110 .args = { { Name, 0 } } },
111 { .name = "chflags", .ret_type = 1, .nargs = 2,
112 .args = { { Name | IN, 0 }, { Hex, 1 } } },
113 { .name = "chmod", .ret_type = 1, .nargs = 2,
114 .args = { { Name, 0 }, { Octal, 1 } } },
115 { .name = "chown", .ret_type = 1, .nargs = 3,
116 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
117 { .name = "chroot", .ret_type = 1, .nargs = 1,
118 .args = { { Name, 0 } } },
119 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
120 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
121 { .name = "close", .ret_type = 1, .nargs = 1,
122 .args = { { Int, 0 } } },
123 { .name = "connect", .ret_type = 1, .nargs = 3,
124 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
125 { .name = "connectat", .ret_type = 1, .nargs = 4,
126 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
128 { .name = "eaccess", .ret_type = 1, .nargs = 2,
129 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
130 { .name = "execve", .ret_type = 1, .nargs = 3,
131 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
132 { ExecEnv | IN, 2 } } },
133 { .name = "exit", .ret_type = 0, .nargs = 1,
134 .args = { { Hex, 0 } } },
135 { .name = "faccessat", .ret_type = 1, .nargs = 4,
136 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
138 { .name = "fchmod", .ret_type = 1, .nargs = 2,
139 .args = { { Int, 0 }, { Octal, 1 } } },
140 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
141 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
142 { .name = "fchown", .ret_type = 1, .nargs = 3,
143 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
144 { .name = "fchownat", .ret_type = 1, .nargs = 5,
145 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
147 { .name = "fcntl", .ret_type = 1, .nargs = 3,
148 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
149 { .name = "fstat", .ret_type = 1, .nargs = 2,
150 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
151 { .name = "fstatat", .ret_type = 1, .nargs = 4,
152 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
154 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
155 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
156 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
157 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } },
158 { .name = "futimens", .ret_type = 1, .nargs = 2,
159 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
160 { .name = "futimes", .ret_type = 1, .nargs = 2,
161 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
162 { .name = "futimesat", .ret_type = 1, .nargs = 3,
163 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
164 { .name = "getitimer", .ret_type = 1, .nargs = 2,
165 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
166 { .name = "getpeername", .ret_type = 1, .nargs = 3,
167 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
168 { .name = "getpgid", .ret_type = 1, .nargs = 1,
169 .args = { { Int, 0 } } },
170 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
171 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
172 { .name = "getrusage", .ret_type = 1, .nargs = 2,
173 .args = { { Int, 0 }, { Rusage | OUT, 1 } } },
174 { .name = "getsid", .ret_type = 1, .nargs = 1,
175 .args = { { Int, 0 } } },
176 { .name = "getsockname", .ret_type = 1, .nargs = 3,
177 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
178 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
179 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
180 { .name = "ioctl", .ret_type = 1, .nargs = 3,
181 .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } },
182 { .name = "kevent", .ret_type = 1, .nargs = 6,
183 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
184 { Int, 4 }, { Timespec, 5 } } },
185 { .name = "kill", .ret_type = 1, .nargs = 2,
186 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
187 { .name = "kldfind", .ret_type = 1, .nargs = 1,
188 .args = { { Name | IN, 0 } } },
189 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
190 .args = { { Int, 0 } } },
191 { .name = "kldload", .ret_type = 1, .nargs = 1,
192 .args = { { Name | IN, 0 } } },
193 { .name = "kldnext", .ret_type = 1, .nargs = 1,
194 .args = { { Int, 0 } } },
195 { .name = "kldstat", .ret_type = 1, .nargs = 2,
196 .args = { { Int, 0 }, { Ptr, 1 } } },
197 { .name = "kldunload", .ret_type = 1, .nargs = 1,
198 .args = { { Int, 0 } } },
199 { .name = "kse_release", .ret_type = 0, .nargs = 1,
200 .args = { { Timespec, 0 } } },
201 { .name = "lchflags", .ret_type = 1, .nargs = 2,
202 .args = { { Name | IN, 0 }, { Hex, 1 } } },
203 { .name = "lchmod", .ret_type = 1, .nargs = 2,
204 .args = { { Name, 0 }, { Octal, 1 } } },
205 { .name = "lchown", .ret_type = 1, .nargs = 3,
206 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
207 { .name = "link", .ret_type = 1, .nargs = 2,
208 .args = { { Name, 0 }, { Name, 1 } } },
209 { .name = "linkat", .ret_type = 1, .nargs = 5,
210 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
212 { .name = "lseek", .ret_type = 2, .nargs = 3,
213 .args = { { Int, 0 }, { QuadHex, 1 + QUAD_ALIGN },
214 { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } },
215 { .name = "lstat", .ret_type = 1, .nargs = 2,
216 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
217 { .name = "lutimes", .ret_type = 1, .nargs = 2,
218 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
219 { .name = "mkdir", .ret_type = 1, .nargs = 2,
220 .args = { { Name, 0 }, { Octal, 1 } } },
221 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
222 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
223 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
224 .args = { { Name, 0 }, { Octal, 1 } } },
225 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
226 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
227 { .name = "mknod", .ret_type = 1, .nargs = 3,
228 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
229 { .name = "mknodat", .ret_type = 1, .nargs = 4,
230 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
231 { .name = "mmap", .ret_type = 1, .nargs = 6,
232 .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
233 { Int, 4 }, { QuadHex, 5 + QUAD_ALIGN } } },
234 { .name = "modfind", .ret_type = 1, .nargs = 1,
235 .args = { { Name | IN, 0 } } },
236 { .name = "mount", .ret_type = 1, .nargs = 4,
237 .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
238 { .name = "mprotect", .ret_type = 1, .nargs = 3,
239 .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
240 { .name = "munmap", .ret_type = 1, .nargs = 2,
241 .args = { { Ptr, 0 }, { Int, 1 } } },
242 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
243 .args = { { Timespec, 0 } } },
244 { .name = "open", .ret_type = 1, .nargs = 3,
245 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
246 { .name = "openat", .ret_type = 1, .nargs = 4,
247 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
249 { .name = "pathconf", .ret_type = 1, .nargs = 2,
250 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
251 { .name = "pipe", .ret_type = 1, .nargs = 1,
252 .args = { { PipeFds | OUT, 0 } } },
253 { .name = "pipe2", .ret_type = 1, .nargs = 2,
254 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
255 { .name = "poll", .ret_type = 1, .nargs = 3,
256 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
257 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
258 .args = { { Open, 0 } } },
259 { .name = "procctl", .ret_type = 1, .nargs = 4,
260 .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN },
261 { Procctl, 1 + QUAD_ALIGN + QUAD_SLOTS },
262 { Ptr, 2 + QUAD_ALIGN + QUAD_SLOTS } } },
263 { .name = "read", .ret_type = 1, .nargs = 3,
264 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
265 { .name = "readlink", .ret_type = 1, .nargs = 3,
266 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Int, 2 } } },
267 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
268 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
270 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
271 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 },
272 { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
273 { .name = "rename", .ret_type = 1, .nargs = 2,
274 .args = { { Name, 0 }, { Name, 1 } } },
275 { .name = "renameat", .ret_type = 1, .nargs = 4,
276 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
277 { .name = "rfork", .ret_type = 1, .nargs = 1,
278 .args = { { Rforkflags, 0 } } },
279 { .name = "rmdir", .ret_type = 1, .nargs = 1,
280 .args = { { Name, 0 } } },
281 { .name = "select", .ret_type = 1, .nargs = 5,
282 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
284 { .name = "sendto", .ret_type = 1, .nargs = 6,
285 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 },
286 { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
287 { .name = "setitimer", .ret_type = 1, .nargs = 3,
288 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
289 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
290 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
291 { .name = "shutdown", .ret_type = 1, .nargs = 2,
292 .args = { { Int, 0 }, { Shutdown, 1 } } },
293 { .name = "sigaction", .ret_type = 1, .nargs = 3,
294 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
295 { Sigaction | OUT, 2 } } },
296 { .name = "sigpending", .ret_type = 1, .nargs = 1,
297 .args = { { Sigset | OUT, 0 } } },
298 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
299 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
300 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
301 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
302 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
303 .args = { { Ptr, 0 } } },
304 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
305 .args = { { Sigset | IN, 0 } } },
306 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
307 .args = { { Sigset | IN, 0 }, { Ptr, 1 }, { Timespec | IN, 2 } } },
308 { .name = "sigwait", .ret_type = 1, .nargs = 2,
309 .args = { { Sigset | IN, 0 }, { Ptr, 1 } } },
310 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
311 .args = { { Sigset | IN, 0 }, { Ptr, 1 } } },
312 { .name = "socket", .ret_type = 1, .nargs = 3,
313 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } },
314 { .name = "stat", .ret_type = 1, .nargs = 2,
315 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
316 { .name = "statfs", .ret_type = 1, .nargs = 2,
317 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
318 { .name = "symlink", .ret_type = 1, .nargs = 2,
319 .args = { { Name, 0 }, { Name, 1 } } },
320 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
321 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
322 { .name = "sysarch", .ret_type = 1, .nargs = 2,
323 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
324 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
325 .args = { { Long, 0 }, { Signal, 1 } } },
326 { .name = "thr_self", .ret_type = 1, .nargs = 1,
327 .args = { { Ptr, 0 } } },
328 { .name = "truncate", .ret_type = 1, .nargs = 2,
329 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } },
332 { .name = "umount", .ret_type = 1, .nargs = 2,
333 .args = { { Name, 0 }, { Int, 2 } } },
335 { .name = "unlink", .ret_type = 1, .nargs = 1,
336 .args = { { Name, 0 } } },
337 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
338 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
339 { .name = "unmount", .ret_type = 1, .nargs = 2,
340 .args = { { Name, 0 }, { Int, 1 } } },
341 { .name = "utimensat", .ret_type = 1, .nargs = 4,
342 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
344 { .name = "utimes", .ret_type = 1, .nargs = 2,
345 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
346 { .name = "utrace", .ret_type = 1, .nargs = 1,
347 .args = { { Utrace, 0 } } },
348 { .name = "wait4", .ret_type = 1, .nargs = 4,
349 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
350 { Rusage | OUT, 3 } } },
351 { .name = "wait6", .ret_type = 1, .nargs = 6,
352 .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN },
353 { ExitStatus | OUT, 1 + QUAD_ALIGN + QUAD_SLOTS },
354 { Waitoptions, 2 + QUAD_ALIGN + QUAD_SLOTS },
355 { Rusage | OUT, 3 + QUAD_ALIGN + QUAD_SLOTS },
356 { Ptr, 4 + QUAD_ALIGN + QUAD_SLOTS } } },
357 { .name = "write", .ret_type = 1, .nargs = 3,
358 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } },
361 { .name = "linux_access", .ret_type = 1, .nargs = 2,
362 .args = { { Name, 0 }, { Accessmode, 1 } } },
363 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
364 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
365 { ExecEnv | IN, 2 } } },
366 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
367 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
368 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
369 .args = { { Name | IN, 0 }, { Int, 1 } } },
370 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
371 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
372 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
373 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
374 { .name = "linux_open", .ret_type = 1, .nargs = 3,
375 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
376 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
377 .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } },
378 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
379 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
380 { .name = "linux_stat64", .ret_type = 1, .nargs = 3,
381 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } },
383 /* CloudABI system calls. */
384 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
385 .args = { { CloudABIClockID, 0 } } },
386 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
387 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
388 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
389 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
390 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
391 .args = { { Int, 0 } } },
392 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
393 .args = { { CloudABIFileType, 0 } } },
394 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
395 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
396 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
397 .args = { { Int, 0 } } },
398 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
399 .args = { { Int, 0 } } },
400 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
401 .args = { { Int, 0 }, { Int, 1 } } },
402 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
403 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
404 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
405 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
406 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
407 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
408 { ClouduABIFDSFlags, 2 } } },
409 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
410 .args = { { Int, 0 } } },
411 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
412 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
413 { CloudABIAdvice, 3 } } },
414 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
415 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
416 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
417 .args = { { Int, 0 }, { BinString | IN, 1 },
418 { CloudABIFileType, 3 } } },
419 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
420 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
421 { Int, 3 }, { BinString | IN, 4 } } },
422 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
423 .args = { { Int, 0 }, { BinString | IN, 1 },
424 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
425 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
426 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
428 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
429 .args = { { Int, 0 }, { BinString | IN, 1 },
430 { BinString | OUT, 3 }, { Int, 4 } } },
431 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
432 .args = { { Int, 0 }, { BinString | IN, 1 },
433 { Int, 3 }, { BinString | IN, 4 } } },
434 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
435 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
436 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
437 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
438 { CloudABIFSFlags, 2 } } },
439 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
440 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
441 { CloudABIFileStat | OUT, 3 } } },
442 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
443 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
444 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
445 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
446 .args = { { BinString | IN, 0 },
447 { Int, 2 }, { BinString | IN, 3 } } },
448 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
449 .args = { { Int, 0 }, { BinString | IN, 1 },
450 { CloudABIULFlags, 3 } } },
451 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
452 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
453 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
454 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
455 { .name = "cloudabi_sys_mem_lock", .ret_type = 1, .nargs = 2,
456 .args = { { Ptr, 0 }, { Int, 1 } } },
457 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
458 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
459 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
460 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
461 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
462 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
463 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
464 { .name = "cloudabi_sys_mem_unlock", .ret_type = 1, .nargs = 2,
465 .args = { { Ptr, 0 }, { Int, 1 } } },
466 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
467 .args = { { Ptr, 0 }, { Int, 1 } } },
468 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
469 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
470 { IntArray, 3 }, { Int, 4 } } },
471 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
472 .args = { { Int, 0 } } },
473 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
474 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
475 .args = { { CloudABISignal, 0 } } },
476 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
477 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
478 { .name = "cloudabi_sys_sock_accept", .ret_type = 1, .nargs = 2,
479 .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 } } },
480 { .name = "cloudabi_sys_sock_bind", .ret_type = 1, .nargs = 3,
481 .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } },
482 { .name = "cloudabi_sys_sock_connect", .ret_type = 1, .nargs = 3,
483 .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } },
484 { .name = "cloudabi_sys_sock_listen", .ret_type = 1, .nargs = 2,
485 .args = { { Int, 0 }, { Int, 1 } } },
486 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
487 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
488 { .name = "cloudabi_sys_sock_stat_get", .ret_type = 1, .nargs = 3,
489 .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 },
490 { CloudABISSFlags, 2 } } },
491 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
492 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
493 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
497 static STAILQ_HEAD(, syscall) syscalls;
499 /* Xlat idea taken from strace */
505 #define X(a) { a, #a },
506 #define XEND { 0, NULL }
508 static struct xlat kevent_filters[] = {
509 X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
510 X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
511 X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
512 X(EVFILT_SENDFILE) XEND
515 static struct xlat kevent_flags[] = {
516 X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
517 X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
518 X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
521 static struct xlat kevent_user_ffctrl[] = {
522 X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY)
526 static struct xlat kevent_rdwr_fflags[] = {
527 X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND
530 static struct xlat kevent_vnode_fflags[] = {
531 X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB)
532 X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) XEND
535 static struct xlat kevent_proc_fflags[] = {
536 X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR)
540 static struct xlat kevent_timer_fflags[] = {
541 X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS)
545 static struct xlat poll_flags[] = {
546 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
547 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
548 X(POLLWRBAND) X(POLLINIGNEOF) XEND
551 static struct xlat sigaction_flags[] = {
552 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
553 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
556 static struct xlat pathconf_arg[] = {
557 X(_PC_LINK_MAX) X(_PC_MAX_CANON) X(_PC_MAX_INPUT)
558 X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF)
559 X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE)
560 X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO)
561 X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS)
562 X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE)
563 X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN)
564 X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX)
565 X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT)
566 X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND
569 static struct xlat at_flags[] = {
570 X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW)
574 static struct xlat sysarch_ops[] = {
575 #if defined(__i386__) || defined(__amd64__)
576 X(I386_GET_LDT) X(I386_SET_LDT) X(I386_GET_IOPERM) X(I386_SET_IOPERM)
577 X(I386_VM86) X(I386_GET_FSBASE) X(I386_SET_FSBASE) X(I386_GET_GSBASE)
578 X(I386_SET_GSBASE) X(I386_GET_XFPUSTATE) X(AMD64_GET_FSBASE)
579 X(AMD64_SET_FSBASE) X(AMD64_GET_GSBASE) X(AMD64_SET_GSBASE)
580 X(AMD64_GET_XFPUSTATE)
585 static struct xlat linux_socketcall_ops[] = {
586 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
587 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
588 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
589 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
590 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
595 #define X(a) { CLOUDABI_##a, #a },
597 static struct xlat cloudabi_advice[] = {
598 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
599 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
603 static struct xlat cloudabi_clockid[] = {
604 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
605 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
609 static struct xlat cloudabi_errno[] = {
610 X(E2BIG) X(EACCES) X(EADDRINUSE) X(EADDRNOTAVAIL)
611 X(EAFNOSUPPORT) X(EAGAIN) X(EALREADY) X(EBADF) X(EBADMSG)
612 X(EBUSY) X(ECANCELED) X(ECHILD) X(ECONNABORTED) X(ECONNREFUSED)
613 X(ECONNRESET) X(EDEADLK) X(EDESTADDRREQ) X(EDOM) X(EDQUOT)
614 X(EEXIST) X(EFAULT) X(EFBIG) X(EHOSTUNREACH) X(EIDRM) X(EILSEQ)
615 X(EINPROGRESS) X(EINTR) X(EINVAL) X(EIO) X(EISCONN) X(EISDIR)
616 X(ELOOP) X(EMFILE) X(EMLINK) X(EMSGSIZE) X(EMULTIHOP)
617 X(ENAMETOOLONG) X(ENETDOWN) X(ENETRESET) X(ENETUNREACH)
618 X(ENFILE) X(ENOBUFS) X(ENODEV) X(ENOENT) X(ENOEXEC) X(ENOLCK)
619 X(ENOLINK) X(ENOMEM) X(ENOMSG) X(ENOPROTOOPT) X(ENOSPC)
620 X(ENOSYS) X(ENOTCONN) X(ENOTDIR) X(ENOTEMPTY) X(ENOTRECOVERABLE)
621 X(ENOTSOCK) X(ENOTSUP) X(ENOTTY) X(ENXIO) X(EOVERFLOW)
622 X(EOWNERDEAD) X(EPERM) X(EPIPE) X(EPROTO) X(EPROTONOSUPPORT)
623 X(EPROTOTYPE) X(ERANGE) X(EROFS) X(ESPIPE) X(ESRCH) X(ESTALE)
624 X(ETIMEDOUT) X(ETXTBSY) X(EXDEV) X(ENOTCAPABLE)
628 static struct xlat cloudabi_fdflags[] = {
629 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
630 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
634 static struct xlat cloudabi_fdsflags[] = {
635 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
639 static struct xlat cloudabi_filetype[] = {
640 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
641 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
642 X(FILETYPE_FIFO) X(FILETYPE_POLL) X(FILETYPE_PROCESS)
643 X(FILETYPE_REGULAR_FILE) X(FILETYPE_SHARED_MEMORY)
644 X(FILETYPE_SOCKET_DGRAM) X(FILETYPE_SOCKET_SEQPACKET)
645 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
649 static struct xlat cloudabi_fsflags[] = {
650 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
651 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
655 static struct xlat cloudabi_mflags[] = {
656 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
660 static struct xlat cloudabi_mprot[] = {
661 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
665 static struct xlat cloudabi_msflags[] = {
666 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
670 static struct xlat cloudabi_oflags[] = {
671 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
675 static struct xlat cloudabi_sa_family[] = {
676 X(AF_UNSPEC) X(AF_INET) X(AF_INET6) X(AF_UNIX)
680 static struct xlat cloudabi_sdflags[] = {
681 X(SHUT_RD) X(SHUT_WR)
685 static struct xlat cloudabi_signal[] = {
686 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
687 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
688 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
689 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
690 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
694 static struct xlat cloudabi_ssflags[] = {
695 X(SOCKSTAT_CLEAR_ERROR)
699 static struct xlat cloudabi_ssstate[] = {
700 X(SOCKSTATE_ACCEPTCONN)
704 static struct xlat cloudabi_ulflags[] = {
709 static struct xlat cloudabi_whence[] = {
710 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
718 * Searches an xlat array for a value, and returns it if found. Otherwise
719 * return a string representation.
722 lookup(struct xlat *xlat, int val, int base)
726 for (; xlat->str != NULL; xlat++)
727 if (xlat->val == val)
731 sprintf(tmp, "0%o", val);
734 sprintf(tmp, "0x%x", val);
737 sprintf(tmp, "%u", val);
740 errx(1,"Unknown lookup base");
747 xlookup(struct xlat *xlat, int val)
750 return (lookup(xlat, val, 16));
754 * Searches an xlat array containing bitfield values. Remaining bits
755 * set after removing the known ones are printed at the end:
759 xlookup_bits(struct xlat *xlat, int val)
762 static char str[512];
766 for (; xlat->str != NULL; xlat++) {
767 if ((xlat->val & rem) == xlat->val) {
769 * Don't print the "all-bits-zero" string unless all
770 * bits are really zero.
772 if (xlat->val == 0 && val != 0)
774 len += sprintf(str + len, "%s|", xlat->str);
780 * If we have leftover bits or didn't match anything, print
784 len += sprintf(str + len, "0x%x", rem);
785 if (len && str[len - 1] == '|')
792 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
796 str = decoder(value);
800 fprintf(fp, "%d", value);
804 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
808 if (!decoder(fp, value, &rem))
809 fprintf(fp, "0x%x", rem);
811 fprintf(fp, "|0x%x", rem);
819 STAILQ_INIT(&syscalls);
820 for (sc = decoded_syscalls; sc->name != NULL; sc++)
821 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
824 static struct syscall *
825 find_syscall(struct procabi *abi, u_int number)
827 struct extra_syscall *es;
829 if (number < nitems(abi->syscalls))
830 return (abi->syscalls[number]);
831 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
832 if (es->number == number)
839 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
841 struct extra_syscall *es;
843 if (number < nitems(abi->syscalls)) {
844 assert(abi->syscalls[number] == NULL);
845 abi->syscalls[number] = sc;
847 es = malloc(sizeof(*es));
850 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
855 * If/when the list gets big, it might be desirable to do it
856 * as a hash table or binary search.
859 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
866 sc = find_syscall(t->proc->abi, number);
870 name = sysdecode_syscallname(t->proc->abi->abi, number);
872 asprintf(&new_name, "#%d", number);
876 STAILQ_FOREACH(sc, &syscalls, entries) {
877 if (strcmp(name, sc->name) == 0) {
878 add_syscall(t->proc->abi, number, sc);
884 /* It is unknown. Add it into the list. */
886 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
890 sc = calloc(1, sizeof(struct syscall));
892 if (new_name != NULL)
896 for (i = 0; i < nargs; i++) {
897 sc->args[i].offset = i;
898 /* Treat all unknown arguments as LongHex. */
899 sc->args[i].type = LongHex;
901 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
902 add_syscall(t->proc->abi, number, sc);
908 * Copy a fixed amount of bytes from the process.
911 get_struct(pid_t pid, void *offset, void *buf, int len)
913 struct ptrace_io_desc iorequest;
915 iorequest.piod_op = PIOD_READ_D;
916 iorequest.piod_offs = offset;
917 iorequest.piod_addr = buf;
918 iorequest.piod_len = len;
919 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
927 * Copy a string from the process. Note that it is
928 * expected to be a C string, but if max is set, it will
929 * only get that much.
932 get_string(pid_t pid, void *addr, int max)
934 struct ptrace_io_desc iorequest;
936 size_t offset, size, totalsize;
942 /* Read up to the end of the current page. */
943 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
948 buf = malloc(totalsize);
952 iorequest.piod_op = PIOD_READ_D;
953 iorequest.piod_offs = (char *)addr + offset;
954 iorequest.piod_addr = buf + offset;
955 iorequest.piod_len = size;
956 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
960 if (memchr(buf + offset, '\0', size) != NULL)
963 if (totalsize < MAXSIZE && max == 0) {
964 size = MAXSIZE - totalsize;
965 if (size > PAGE_SIZE)
967 nbuf = realloc(buf, totalsize + size);
969 buf[totalsize - 1] = '\0';
975 buf[totalsize - 1] = '\0';
987 signame = sysdecode_signal(sig);
988 if (signame == NULL) {
989 snprintf(tmp, sizeof(tmp), "%d", sig);
996 print_kevent(FILE *fp, struct kevent *ke, int input)
999 switch (ke->filter) {
1005 case EVFILT_PROCDESC:
1006 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1009 fputs(strsig2(ke->ident), fp);
1012 fprintf(fp, "%p", (void *)ke->ident);
1014 fprintf(fp, ",%s,%s,", xlookup(kevent_filters, ke->filter),
1015 xlookup_bits(kevent_flags, ke->flags));
1016 switch (ke->filter) {
1019 fputs(xlookup_bits(kevent_rdwr_fflags, ke->fflags), fp);
1022 fputs(xlookup_bits(kevent_vnode_fflags, ke->fflags), fp);
1025 case EVFILT_PROCDESC:
1026 fputs(xlookup_bits(kevent_proc_fflags, ke->fflags), fp);
1029 fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp);
1034 ctrl = ke->fflags & NOTE_FFCTRLMASK;
1035 data = ke->fflags & NOTE_FFLAGSMASK;
1037 fputs(xlookup(kevent_user_ffctrl, ctrl), fp);
1038 if (ke->fflags & NOTE_TRIGGER)
1039 fputs("|NOTE_TRIGGER", fp);
1041 fprintf(fp, "|%#x", data);
1043 fprintf(fp, "%#x", data);
1048 fprintf(fp, "%#x", ke->fflags);
1050 fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
1054 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1056 unsigned char *utrace_buffer;
1059 if (sysdecode_utrace(fp, utrace_addr, len)) {
1064 utrace_buffer = utrace_addr;
1065 fprintf(fp, "%zu:", len);
1067 fprintf(fp, " %02x", *utrace_buffer++);
1072 * Converts a syscall argument into a string. Said string is
1073 * allocated via malloc(), so needs to be free()'d. sc is
1074 * a pointer to the syscall description (see above); args is
1075 * an array of all of the system call arguments.
1078 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1079 struct trussinfo *trussinfo)
1086 fp = open_memstream(&tmp, &tmplen);
1087 pid = trussinfo->curthread->proc->pid;
1088 switch (sc->type & ARG_MASK) {
1090 fprintf(fp, "0x%x", (int)args[sc->offset]);
1093 fprintf(fp, "0%o", (int)args[sc->offset]);
1096 fprintf(fp, "%d", (int)args[sc->offset]);
1099 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1102 fprintf(fp, "0x%lx", args[sc->offset]);
1105 fprintf(fp, "%ld", args[sc->offset]);
1108 /* NULL-terminated string. */
1111 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1112 fprintf(fp, "\"%s\"", tmp2);
1118 * Binary block of data that might have printable characters.
1119 * XXX If type|OUT, assume that the length is the syscall's
1120 * return value. Otherwise, assume that the length of the block
1121 * is in the next syscall argument.
1123 int max_string = trussinfo->strsize;
1124 char tmp2[max_string + 1], *tmp3;
1131 len = args[sc->offset + 1];
1134 * Don't print more than max_string characters, to avoid word
1135 * wrap. If we have to truncate put some ... after the string.
1137 if (len > max_string) {
1141 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1143 tmp3 = malloc(len * 4 + 1);
1145 if (strvisx(tmp3, tmp2, len,
1146 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1151 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1155 fprintf(fp, "0x%lx", args[sc->offset]);
1165 char buf[PAGE_SIZE];
1172 * Only parse argv[] and environment arrays from exec calls
1175 if (((sc->type & ARG_MASK) == ExecArgs &&
1176 (trussinfo->flags & EXECVEARGS) == 0) ||
1177 ((sc->type & ARG_MASK) == ExecEnv &&
1178 (trussinfo->flags & EXECVEENVS) == 0)) {
1179 fprintf(fp, "0x%lx", args[sc->offset]);
1184 * Read a page of pointers at a time. Punt if the top-level
1185 * pointer is not aligned. Note that the first read is of
1188 addr = args[sc->offset];
1189 if (addr % sizeof(char *) != 0) {
1190 fprintf(fp, "0x%lx", args[sc->offset]);
1194 len = PAGE_SIZE - (addr & PAGE_MASK);
1195 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1196 fprintf(fp, "0x%lx", args[sc->offset]);
1203 while (u.strarray[i] != NULL) {
1204 string = get_string(pid, u.strarray[i], 0);
1205 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1210 if (i == len / sizeof(char *)) {
1213 if (get_struct(pid, (void *)addr, u.buf, len) ==
1215 fprintf(fp, ", <inval>");
1226 fprintf(fp, "%ld", args[sc->offset]);
1229 fprintf(fp, "0x%lx", args[sc->offset]);
1234 unsigned long long ll;
1236 #if _BYTE_ORDER == _LITTLE_ENDIAN
1237 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1240 ll = (unsigned long long)args[sc->offset] << 32 |
1241 args[sc->offset + 1];
1243 if ((sc->type & ARG_MASK) == Quad)
1244 fprintf(fp, "%lld", ll);
1246 fprintf(fp, "0x%llx", ll);
1251 fprintf(fp, "0x%lx", args[sc->offset]);
1256 if (retval[0] == -1)
1258 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1259 fprintf(fp, "\"%s\"", tmp2);
1267 cmd = args[sc->offset];
1268 temp = sysdecode_ioctlname(cmd);
1272 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1273 cmd, cmd & IOC_OUT ? "R" : "",
1274 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1275 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1276 cmd & 0xFF, IOCPARM_LEN(cmd));
1283 if (get_struct(pid, (void *)args[sc->offset], &ts,
1285 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1288 fprintf(fp, "0x%lx", args[sc->offset]);
1292 struct timespec ts[2];
1296 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1300 for (i = 0; i < nitems(ts); i++) {
1303 switch (ts[i].tv_nsec) {
1305 fprintf(fp, "UTIME_NOW");
1308 fprintf(fp, "UTIME_OMIT");
1311 fprintf(fp, "%jd.%09ld",
1312 (intmax_t)ts[i].tv_sec,
1319 fprintf(fp, "0x%lx", args[sc->offset]);
1325 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1327 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1330 fprintf(fp, "0x%lx", args[sc->offset]);
1334 struct timeval tv[2];
1336 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1338 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1339 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1340 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1342 fprintf(fp, "0x%lx", args[sc->offset]);
1346 struct itimerval itv;
1348 if (get_struct(pid, (void *)args[sc->offset], &itv,
1350 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1351 (intmax_t)itv.it_interval.tv_sec,
1352 itv.it_interval.tv_usec,
1353 (intmax_t)itv.it_value.tv_sec,
1354 itv.it_value.tv_usec);
1356 fprintf(fp, "0x%lx", args[sc->offset]);
1361 struct linux_socketcall_args largs;
1363 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1364 sizeof(largs)) != -1)
1365 fprintf(fp, "{ %s, 0x%lx }",
1366 lookup(linux_socketcall_ops, largs.what, 10),
1367 (long unsigned int)largs.args);
1369 fprintf(fp, "0x%lx", args[sc->offset]);
1374 * XXX: A Pollfd argument expects the /next/ syscall argument
1375 * to be the number of fds in the array. This matches the poll
1379 int numfds = args[sc->offset + 1];
1380 size_t bytes = sizeof(struct pollfd) * numfds;
1383 if ((pfd = malloc(bytes)) == NULL)
1384 err(1, "Cannot malloc %zu bytes for pollfd array",
1386 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1389 for (i = 0; i < numfds; i++) {
1390 fprintf(fp, " %d/%s", pfd[i].fd,
1391 xlookup_bits(poll_flags, pfd[i].events));
1395 fprintf(fp, "0x%lx", args[sc->offset]);
1402 * XXX: A Fd_set argument expects the /first/ syscall argument
1403 * to be the number of fds in the array. This matches the
1407 int numfds = args[0];
1408 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1411 if ((fds = malloc(bytes)) == NULL)
1412 err(1, "Cannot malloc %zu bytes for fd_set array",
1414 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1417 for (i = 0; i < numfds; i++) {
1418 if (FD_ISSET(i, fds))
1419 fprintf(fp, " %d", i);
1423 fprintf(fp, "0x%lx", args[sc->offset]);
1428 fputs(strsig2(args[sc->offset]), fp);
1435 sig = args[sc->offset];
1436 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1437 sizeof(ss)) == -1) {
1438 fprintf(fp, "0x%lx", args[sc->offset]);
1443 for (i = 1; i < sys_nsig; i++) {
1444 if (sigismember(&ss, i)) {
1445 fprintf(fp, "%s%s", !first ? "|" : "",
1456 print_integer_arg(sysdecode_sigprocmask_how, fp,
1460 /* XXX: Output depends on the value of the previous argument. */
1461 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1462 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1463 args[sc->offset], 16);
1466 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1469 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1472 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1475 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1478 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1481 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1484 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1487 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1490 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
1493 fputs(xlookup(pathconf_arg, args[sc->offset]), fp);
1496 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
1500 struct sockaddr_in *lsin;
1501 struct sockaddr_in6 *lsin6;
1502 struct sockaddr_un *sun;
1503 struct sockaddr *sa;
1507 if (args[sc->offset] == 0) {
1513 * Extract the address length from the next argument. If
1514 * this is an output sockaddr (OUT is set), then the
1515 * next argument is a pointer to a socklen_t. Otherwise
1516 * the next argument contains a socklen_t by value.
1518 if (sc->type & OUT) {
1519 if (get_struct(pid, (void *)args[sc->offset + 1],
1520 &len, sizeof(len)) == -1) {
1521 fprintf(fp, "0x%lx", args[sc->offset]);
1525 len = args[sc->offset + 1];
1527 /* If the length is too small, just bail. */
1528 if (len < sizeof(*sa)) {
1529 fprintf(fp, "0x%lx", args[sc->offset]);
1533 sa = calloc(1, len);
1534 if (get_struct(pid, (void *)args[sc->offset], sa, len) == -1) {
1536 fprintf(fp, "0x%lx", args[sc->offset]);
1540 switch (sa->sa_family) {
1542 if (len < sizeof(*lsin))
1543 goto sockaddr_short;
1544 lsin = (struct sockaddr_in *)(void *)sa;
1545 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1546 fprintf(fp, "{ AF_INET %s:%d }", addr,
1547 htons(lsin->sin_port));
1550 if (len < sizeof(*lsin6))
1551 goto sockaddr_short;
1552 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1553 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1555 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1556 htons(lsin6->sin6_port));
1559 sun = (struct sockaddr_un *)sa;
1560 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1561 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1567 "{ sa_len = %d, sa_family = %d, sa_data = {",
1568 (int)sa->sa_len, (int)sa->sa_family);
1569 for (q = (u_char *)sa->sa_data;
1570 q < (u_char *)sa + len; q++)
1571 fprintf(fp, "%s 0x%02x",
1572 q == (u_char *)sa->sa_data ? "" : ",",
1580 struct sigaction sa;
1582 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
1585 if (sa.sa_handler == SIG_DFL)
1586 fputs("SIG_DFL", fp);
1587 else if (sa.sa_handler == SIG_IGN)
1588 fputs("SIG_IGN", fp);
1590 fprintf(fp, "%p", sa.sa_handler);
1591 fprintf(fp, " %s ss_t }",
1592 xlookup_bits(sigaction_flags, sa.sa_flags));
1594 fprintf(fp, "0x%lx", args[sc->offset]);
1599 * XXX XXX: The size of the array is determined by either the
1600 * next syscall argument, or by the syscall return value,
1601 * depending on which argument number we are. This matches the
1602 * kevent syscall, but luckily that's the only syscall that uses
1610 if (sc->offset == 1)
1611 numevents = args[sc->offset+1];
1612 else if (sc->offset == 3 && retval[0] != -1)
1613 numevents = retval[0];
1615 if (numevents >= 0) {
1616 bytes = sizeof(struct kevent) * numevents;
1617 if ((ke = malloc(bytes)) == NULL)
1619 "Cannot malloc %zu bytes for kevent array",
1623 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
1626 for (i = 0; i < numevents; i++) {
1628 print_kevent(fp, &ke[i], sc->offset == 1);
1632 fprintf(fp, "0x%lx", args[sc->offset]);
1640 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
1644 strmode(st.st_mode, mode);
1646 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
1647 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
1648 (long)st.st_blksize);
1650 fprintf(fp, "0x%lx", args[sc->offset]);
1658 if (get_struct(pid, (void *)args[sc->offset], &buf,
1659 sizeof(buf)) != -1) {
1662 bzero(fsid, sizeof(fsid));
1663 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
1664 for (i = 0; i < sizeof(buf.f_fsid); i++)
1665 snprintf(&fsid[i*2],
1666 sizeof(fsid) - (i*2), "%02x",
1667 ((u_char *)&buf.f_fsid)[i]);
1670 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
1671 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
1672 buf.f_mntfromname, fsid);
1674 fprintf(fp, "0x%lx", args[sc->offset]);
1681 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
1684 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
1685 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
1686 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
1687 ru.ru_inblock, ru.ru_oublock);
1689 fprintf(fp, "0x%lx", args[sc->offset]);
1695 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
1697 fprintf(fp, "{ cur=%ju,max=%ju }",
1698 rl.rlim_cur, rl.rlim_max);
1700 fprintf(fp, "0x%lx", args[sc->offset]);
1706 if (get_struct(pid, (void *)args[sc->offset], &status,
1707 sizeof(status)) != -1) {
1709 if (WIFCONTINUED(status))
1710 fputs("CONTINUED", fp);
1711 else if (WIFEXITED(status))
1712 fprintf(fp, "EXITED,val=%d",
1713 WEXITSTATUS(status));
1714 else if (WIFSIGNALED(status))
1715 fprintf(fp, "SIGNALED,sig=%s%s",
1716 strsig2(WTERMSIG(status)),
1717 WCOREDUMP(status) ? ",cored" : "");
1719 fprintf(fp, "STOPPED,sig=%s",
1720 strsig2(WTERMSIG(status)));
1723 fprintf(fp, "0x%lx", args[sc->offset]);
1727 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
1730 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
1733 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
1736 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
1739 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
1742 fputs(xlookup_bits(at_flags, args[sc->offset]), fp);
1745 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
1748 fputs(xlookup(sysarch_ops, args[sc->offset]), fp);
1752 * The pipe() system call in the kernel returns its
1753 * two file descriptors via return values. However,
1754 * the interface exposed by libc is that pipe()
1755 * accepts a pointer to an array of descriptors.
1756 * Format the output to match the libc API by printing
1757 * the returned file descriptors as a fake argument.
1759 * Overwrite the first retval to signal a successful
1762 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
1769 len = args[sc->offset + 1];
1770 utrace_addr = calloc(1, len);
1771 if (get_struct(pid, (void *)args[sc->offset],
1772 (void *)utrace_addr, len) != -1)
1773 print_utrace(fp, utrace_addr, len);
1775 fprintf(fp, "0x%lx", args[sc->offset]);
1780 int descriptors[16];
1781 unsigned long i, ndescriptors;
1784 ndescriptors = args[sc->offset + 1];
1786 if (ndescriptors > nitems(descriptors)) {
1787 ndescriptors = nitems(descriptors);
1790 if (get_struct(pid, (void *)args[sc->offset],
1791 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
1793 for (i = 0; i < ndescriptors; i++)
1794 fprintf(fp, i == 0 ? " %d" : ", %d",
1796 fprintf(fp, truncated ? ", ... }" : " }");
1798 fprintf(fp, "0x%lx", args[sc->offset]);
1802 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
1805 case CloudABIAdvice:
1806 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
1808 case CloudABIClockID:
1809 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
1811 case ClouduABIFDSFlags:
1812 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
1814 case CloudABIFDStat: {
1815 cloudabi_fdstat_t fds;
1816 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
1818 fprintf(fp, "{ %s, ",
1819 xlookup(cloudabi_filetype, fds.fs_filetype));
1820 fprintf(fp, "%s, ... }",
1821 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
1823 fprintf(fp, "0x%lx", args[sc->offset]);
1826 case CloudABIFileStat: {
1827 cloudabi_filestat_t fsb;
1828 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
1830 fprintf(fp, "{ %s, %ju }",
1831 xlookup(cloudabi_filetype, fsb.st_filetype),
1832 (uintmax_t)fsb.st_size);
1834 fprintf(fp, "0x%lx", args[sc->offset]);
1837 case CloudABIFileType:
1838 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
1840 case CloudABIFSFlags:
1841 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
1843 case CloudABILookup:
1844 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
1845 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
1846 (int)args[sc->offset]);
1848 fprintf(fp, "%d", (int)args[sc->offset]);
1850 case CloudABIMFlags:
1851 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
1854 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
1856 case CloudABIMSFlags:
1857 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
1859 case CloudABIOFlags:
1860 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
1862 case CloudABISDFlags:
1863 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
1865 case CloudABISignal:
1866 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
1868 case CloudABISockStat: {
1869 cloudabi_sockstat_t ss;
1870 if (get_struct(pid, (void *)args[sc->offset], &ss, sizeof(ss))
1872 fprintf(fp, "{ %s, ", xlookup(
1873 cloudabi_sa_family, ss.ss_sockname.sa_family));
1874 fprintf(fp, "%s, ", xlookup(
1875 cloudabi_sa_family, ss.ss_peername.sa_family));
1876 fprintf(fp, "%s, ", xlookup(
1877 cloudabi_errno, ss.ss_error));
1878 fprintf(fp, "%s }", xlookup_bits(
1879 cloudabi_ssstate, ss.ss_state));
1881 fprintf(fp, "0x%lx", args[sc->offset]);
1884 case CloudABISSFlags:
1885 fputs(xlookup_bits(cloudabi_ssflags, args[sc->offset]), fp);
1887 case CloudABITimestamp:
1888 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
1889 args[sc->offset] % 1000000000);
1891 case CloudABIULFlags:
1892 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
1894 case CloudABIWhence:
1895 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
1899 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
1906 * Print (to outfile) the system call and its arguments.
1909 print_syscall(struct trussinfo *trussinfo)
1911 struct threadinfo *t;
1916 t = trussinfo->curthread;
1918 name = t->cs.sc->name;
1919 nargs = t->cs.nargs;
1920 s_args = t->cs.s_args;
1922 len = print_line_prefix(trussinfo);
1923 len += fprintf(trussinfo->outfile, "%s(", name);
1925 for (i = 0; i < nargs; i++) {
1926 if (s_args[i] != NULL)
1927 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
1929 len += fprintf(trussinfo->outfile,
1930 "<missing argument>");
1931 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
1934 len += fprintf(trussinfo->outfile, ")");
1935 for (i = 0; i < 6 - (len / 8); i++)
1936 fprintf(trussinfo->outfile, "\t");
1940 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
1942 struct timespec timediff;
1943 struct threadinfo *t;
1947 t = trussinfo->curthread;
1949 if (trussinfo->flags & COUNTONLY) {
1950 timespecsubt(&t->after, &t->before, &timediff);
1951 timespecadd(&sc->time, &timediff, &sc->time);
1958 print_syscall(trussinfo);
1959 fflush(trussinfo->outfile);
1961 if (retval == NULL) {
1963 * This system call resulted in the current thread's exit,
1964 * so there is no return value or error to display.
1966 fprintf(trussinfo->outfile, "\n");
1971 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
1973 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
1974 error == INT_MAX ? "Unknown error" : strerror(error));
1977 else if (sc->ret_type == 2) {
1980 #if _BYTE_ORDER == _LITTLE_ENDIAN
1981 off = (off_t)retval[1] << 32 | retval[0];
1983 off = (off_t)retval[0] << 32 | retval[1];
1985 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
1990 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
1995 print_summary(struct trussinfo *trussinfo)
1997 struct timespec total = {0, 0};
2001 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2002 "syscall", "seconds", "calls", "errors");
2004 STAILQ_FOREACH(sc, &syscalls, entries)
2006 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2007 sc->name, (intmax_t)sc->time.tv_sec,
2008 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2009 timespecadd(&total, &sc->time, &total);
2010 ncall += sc->ncalls;
2011 nerror += sc->nerror;
2013 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2014 "", "-------------", "-------", "-------");
2015 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2016 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);