2 * SPDX-License-Identifier: BSD-4-Clause
4 * Copyright 1997 Sean Eric Fagan
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Sean Eric Fagan
17 * 4. Neither the name of the author may be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * This file has routines used to print out system calls and their
42 #include <sys/capsicum.h>
43 #include <sys/types.h>
44 #define _WANT_FREEBSD11_KEVENT
45 #include <sys/event.h>
46 #include <sys/ioccom.h>
48 #include <sys/mount.h>
49 #include <sys/ptrace.h>
50 #include <sys/resource.h>
51 #include <sys/socket.h>
52 #define _WANT_FREEBSD11_STAT
57 #include <netinet/in.h>
58 #include <netinet/sctp.h>
59 #include <arpa/inet.h>
64 #define _WANT_KERNEL_ERRNO
74 #include <sysdecode.h>
78 #include <contrib/cloudabi/cloudabi_types_common.h>
85 * This should probably be in its own file, sorted alphabetically.
87 static struct syscall decoded_syscalls[] = {
89 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
90 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
91 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
92 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
93 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
94 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
95 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
96 .args = { { Int, 0 }, { Acltype, 1 } } },
97 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
98 .args = { { Name, 0 }, { Acltype, 1 } } },
99 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
100 .args = { { Name, 0 }, { Acltype, 1 } } },
101 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
102 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
103 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
104 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
106 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
108 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
110 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
111 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
112 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
113 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
114 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
115 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
116 .args = { { Name | OUT, 0 }, { Int, 1 } } },
117 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
118 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
120 { .name = "accept", .ret_type = 1, .nargs = 3,
121 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
122 { .name = "access", .ret_type = 1, .nargs = 2,
123 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
124 { .name = "bind", .ret_type = 1, .nargs = 3,
125 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
126 { .name = "bindat", .ret_type = 1, .nargs = 4,
127 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
129 { .name = "break", .ret_type = 1, .nargs = 1,
130 .args = { { Ptr, 0 } } },
131 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
132 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
133 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
134 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
135 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
136 .args = { { PUInt | OUT, 0 } } },
137 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
138 .args = { { Int, 0 }, { CapRights, 1 } } },
139 { .name = "chdir", .ret_type = 1, .nargs = 1,
140 .args = { { Name, 0 } } },
141 { .name = "chflags", .ret_type = 1, .nargs = 2,
142 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
143 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
144 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
146 { .name = "chmod", .ret_type = 1, .nargs = 2,
147 .args = { { Name, 0 }, { Octal, 1 } } },
148 { .name = "chown", .ret_type = 1, .nargs = 3,
149 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
150 { .name = "chroot", .ret_type = 1, .nargs = 1,
151 .args = { { Name, 0 } } },
152 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
153 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
154 { .name = "close", .ret_type = 1, .nargs = 1,
155 .args = { { Int, 0 } } },
156 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
157 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
158 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
159 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
161 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
162 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
163 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
164 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
165 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
166 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
167 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
168 { .name = "connect", .ret_type = 1, .nargs = 3,
169 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
170 { .name = "connectat", .ret_type = 1, .nargs = 4,
171 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
173 { .name = "dup", .ret_type = 1, .nargs = 1,
174 .args = { { Int, 0 } } },
175 { .name = "dup2", .ret_type = 1, .nargs = 2,
176 .args = { { Int, 0 }, { Int, 1 } } },
177 { .name = "eaccess", .ret_type = 1, .nargs = 2,
178 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
179 { .name = "execve", .ret_type = 1, .nargs = 3,
180 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
181 { ExecEnv | IN, 2 } } },
182 { .name = "exit", .ret_type = 0, .nargs = 1,
183 .args = { { Hex, 0 } } },
184 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
185 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
186 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
187 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
188 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
189 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
190 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
191 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
192 { BinString | OUT, 3 }, { Sizet, 4 } } },
193 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
194 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
195 { BinString | OUT, 3 }, { Sizet, 4 } } },
196 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
197 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
198 { BinString | OUT, 3 }, { Sizet, 4 } } },
199 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
200 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
202 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
203 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
205 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
206 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
208 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
209 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
210 { BinString | IN, 3 }, { Sizet, 4 } } },
211 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
213 { BinString | IN, 3 }, { Sizet, 4 } } },
214 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
215 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
216 { BinString | IN, 3 }, { Sizet, 4 } } },
217 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
218 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
219 { Extattrnamespace, 3 }, { Name, 4 } } },
220 { .name = "faccessat", .ret_type = 1, .nargs = 4,
221 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
223 { .name = "fchflags", .ret_type = 1, .nargs = 2,
224 .args = { { Int, 0 }, { FileFlags, 1 } } },
225 { .name = "fchmod", .ret_type = 1, .nargs = 2,
226 .args = { { Int, 0 }, { Octal, 1 } } },
227 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
228 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
229 { .name = "fchown", .ret_type = 1, .nargs = 3,
230 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
231 { .name = "fchownat", .ret_type = 1, .nargs = 5,
232 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
234 { .name = "fcntl", .ret_type = 1, .nargs = 3,
235 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
236 { .name = "fdatasync", .ret_type = 1, .nargs = 1,
237 .args = { { Int, 0 } } },
238 { .name = "flock", .ret_type = 1, .nargs = 2,
239 .args = { { Int, 0 }, { Flockop, 1 } } },
240 { .name = "fstat", .ret_type = 1, .nargs = 2,
241 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
242 { .name = "fstatat", .ret_type = 1, .nargs = 4,
243 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
245 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
246 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
247 { .name = "fsync", .ret_type = 1, .nargs = 1,
248 .args = { { Int, 0 } } },
249 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
250 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
251 { .name = "futimens", .ret_type = 1, .nargs = 2,
252 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
253 { .name = "futimes", .ret_type = 1, .nargs = 2,
254 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
255 { .name = "futimesat", .ret_type = 1, .nargs = 3,
256 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
257 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
258 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
259 { PQuadHex | OUT, 3 } } },
260 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
261 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
262 { .name = "getitimer", .ret_type = 1, .nargs = 2,
263 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
264 { .name = "getpeername", .ret_type = 1, .nargs = 3,
265 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
266 { .name = "getpgid", .ret_type = 1, .nargs = 1,
267 .args = { { Int, 0 } } },
268 { .name = "getpriority", .ret_type = 1, .nargs = 2,
269 .args = { { Priowhich, 0 }, { Int, 1 } } },
270 { .name = "getrandom", .ret_type = 1, .nargs = 3,
271 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
272 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
273 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
274 { .name = "getrusage", .ret_type = 1, .nargs = 2,
275 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
276 { .name = "getsid", .ret_type = 1, .nargs = 1,
277 .args = { { Int, 0 } } },
278 { .name = "getsockname", .ret_type = 1, .nargs = 3,
279 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
280 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
281 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
282 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
283 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
284 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
285 { .name = "ioctl", .ret_type = 1, .nargs = 3,
286 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
287 { .name = "kevent", .ret_type = 1, .nargs = 6,
288 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
289 { Int, 4 }, { Timespec, 5 } } },
290 { .name = "kill", .ret_type = 1, .nargs = 2,
291 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
292 { .name = "kldfind", .ret_type = 1, .nargs = 1,
293 .args = { { Name | IN, 0 } } },
294 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
295 .args = { { Int, 0 } } },
296 { .name = "kldload", .ret_type = 1, .nargs = 1,
297 .args = { { Name | IN, 0 } } },
298 { .name = "kldnext", .ret_type = 1, .nargs = 1,
299 .args = { { Int, 0 } } },
300 { .name = "kldstat", .ret_type = 1, .nargs = 2,
301 .args = { { Int, 0 }, { Ptr, 1 } } },
302 { .name = "kldsym", .ret_type = 1, .nargs = 3,
303 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
304 { .name = "kldunload", .ret_type = 1, .nargs = 1,
305 .args = { { Int, 0 } } },
306 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
307 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
308 { .name = "kse_release", .ret_type = 0, .nargs = 1,
309 .args = { { Timespec, 0 } } },
310 { .name = "lchflags", .ret_type = 1, .nargs = 2,
311 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
312 { .name = "lchmod", .ret_type = 1, .nargs = 2,
313 .args = { { Name, 0 }, { Octal, 1 } } },
314 { .name = "lchown", .ret_type = 1, .nargs = 3,
315 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
316 { .name = "link", .ret_type = 1, .nargs = 2,
317 .args = { { Name, 0 }, { Name, 1 } } },
318 { .name = "linkat", .ret_type = 1, .nargs = 5,
319 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
321 { .name = "listen", .ret_type = 1, .nargs = 2,
322 .args = { { Int, 0 }, { Int, 1 } } },
323 { .name = "lseek", .ret_type = 2, .nargs = 3,
324 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
325 { .name = "lstat", .ret_type = 1, .nargs = 2,
326 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
327 { .name = "lutimes", .ret_type = 1, .nargs = 2,
328 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
329 { .name = "madvise", .ret_type = 1, .nargs = 3,
330 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
331 { .name = "minherit", .ret_type = 1, .nargs = 3,
332 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
333 { .name = "mkdir", .ret_type = 1, .nargs = 2,
334 .args = { { Name, 0 }, { Octal, 1 } } },
335 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
336 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
337 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
338 .args = { { Name, 0 }, { Octal, 1 } } },
339 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
340 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
341 { .name = "mknod", .ret_type = 1, .nargs = 3,
342 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
343 { .name = "mknodat", .ret_type = 1, .nargs = 4,
344 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
345 { .name = "mlock", .ret_type = 1, .nargs = 2,
346 .args = { { Ptr, 0 }, { Sizet, 1 } } },
347 { .name = "mlockall", .ret_type = 1, .nargs = 1,
348 .args = { { Mlockall, 0 } } },
349 { .name = "mmap", .ret_type = 1, .nargs = 6,
350 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
351 { Int, 4 }, { QuadHex, 5 } } },
352 { .name = "modfind", .ret_type = 1, .nargs = 1,
353 .args = { { Name | IN, 0 } } },
354 { .name = "mount", .ret_type = 1, .nargs = 4,
355 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
356 { .name = "mprotect", .ret_type = 1, .nargs = 3,
357 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
358 { .name = "msync", .ret_type = 1, .nargs = 3,
359 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
360 { .name = "munlock", .ret_type = 1, .nargs = 2,
361 .args = { { Ptr, 0 }, { Sizet, 1 } } },
362 { .name = "munmap", .ret_type = 1, .nargs = 2,
363 .args = { { Ptr, 0 }, { Sizet, 1 } } },
364 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
365 .args = { { Timespec, 0 } } },
366 { .name = "nmount", .ret_type = 1, .nargs = 3,
367 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
368 { .name = "open", .ret_type = 1, .nargs = 3,
369 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
370 { .name = "openat", .ret_type = 1, .nargs = 4,
371 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
373 { .name = "pathconf", .ret_type = 1, .nargs = 2,
374 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
375 { .name = "pipe", .ret_type = 1, .nargs = 1,
376 .args = { { PipeFds | OUT, 0 } } },
377 { .name = "pipe2", .ret_type = 1, .nargs = 2,
378 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
379 { .name = "poll", .ret_type = 1, .nargs = 3,
380 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
381 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
382 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
384 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
385 .args = { { Open, 0 } } },
386 { .name = "pread", .ret_type = 1, .nargs = 4,
387 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
389 { .name = "procctl", .ret_type = 1, .nargs = 4,
390 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
391 { .name = "ptrace", .ret_type = 1, .nargs = 4,
392 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
393 { .name = "pwrite", .ret_type = 1, .nargs = 4,
394 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
396 { .name = "quotactl", .ret_type = 1, .nargs = 4,
397 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
398 { .name = "read", .ret_type = 1, .nargs = 3,
399 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
400 { .name = "readlink", .ret_type = 1, .nargs = 3,
401 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
402 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
403 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
405 { .name = "readv", .ret_type = 1, .nargs = 3,
406 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
407 { .name = "reboot", .ret_type = 1, .nargs = 1,
408 .args = { { Reboothowto, 0 } } },
409 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
410 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
411 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
412 { Ptr | OUT, 5 } } },
413 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
414 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
415 { .name = "rename", .ret_type = 1, .nargs = 2,
416 .args = { { Name, 0 }, { Name, 1 } } },
417 { .name = "renameat", .ret_type = 1, .nargs = 4,
418 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
419 { .name = "rfork", .ret_type = 1, .nargs = 1,
420 .args = { { Rforkflags, 0 } } },
421 { .name = "rmdir", .ret_type = 1, .nargs = 1,
422 .args = { { Name, 0 } } },
423 { .name = "rtprio", .ret_type = 1, .nargs = 3,
424 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
425 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
426 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
427 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
428 .args = { { Schedpolicy, 0 } } },
429 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
430 .args = { { Schedpolicy, 0 } } },
431 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
432 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
433 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
434 .args = { { Int, 0 } } },
435 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
436 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
437 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
438 .args = { { Int, 0 }, { Schedparam, 1 } } },
439 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
440 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
441 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
442 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
443 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
444 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
445 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
446 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
447 { Sockaddr | IN, 3 }, { Socklent, 4 },
448 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
449 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
450 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
451 { Sockaddr | IN, 3 }, { Socklent, 4 },
452 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
453 { .name = "select", .ret_type = 1, .nargs = 5,
454 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
456 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
457 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
458 { .name = "sendto", .ret_type = 1, .nargs = 6,
459 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
460 { Msgflags, 3 }, { Sockaddr | IN, 4 },
461 { Socklent | IN, 5 } } },
462 { .name = "setitimer", .ret_type = 1, .nargs = 3,
463 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
464 { .name = "setpriority", .ret_type = 1, .nargs = 3,
465 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
466 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
467 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
468 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
469 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
470 { Ptr | IN, 3 }, { Socklent, 4 } } },
471 { .name = "shm_open", .ret_type = 1, .nargs = 3,
472 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
473 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
474 .args = { { Name | IN, 0 } } },
475 { .name = "shutdown", .ret_type = 1, .nargs = 2,
476 .args = { { Int, 0 }, { Shutdown, 1 } } },
477 { .name = "sigaction", .ret_type = 1, .nargs = 3,
478 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
479 { Sigaction | OUT, 2 } } },
480 { .name = "sigpending", .ret_type = 1, .nargs = 1,
481 .args = { { Sigset | OUT, 0 } } },
482 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
483 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
484 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
485 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
486 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
487 .args = { { Ptr, 0 } } },
488 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
489 .args = { { Sigset | IN, 0 } } },
490 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
491 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
492 { Timespec | IN, 2 } } },
493 { .name = "sigwait", .ret_type = 1, .nargs = 2,
494 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
495 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
496 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
497 { .name = "socket", .ret_type = 1, .nargs = 3,
498 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
499 { .name = "stat", .ret_type = 1, .nargs = 2,
500 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
501 { .name = "statfs", .ret_type = 1, .nargs = 2,
502 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
503 { .name = "symlink", .ret_type = 1, .nargs = 2,
504 .args = { { Name, 0 }, { Name, 1 } } },
505 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
506 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
507 { .name = "sysarch", .ret_type = 1, .nargs = 2,
508 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
509 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
510 .args = { { Long, 0 }, { Signal, 1 } } },
511 { .name = "thr_self", .ret_type = 1, .nargs = 1,
512 .args = { { Ptr, 0 } } },
513 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
514 .args = { { Long, 0 }, { Name, 1 } } },
515 { .name = "truncate", .ret_type = 1, .nargs = 2,
516 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
519 { .name = "umount", .ret_type = 1, .nargs = 2,
520 .args = { { Name, 0 }, { Int, 2 } } },
522 { .name = "unlink", .ret_type = 1, .nargs = 1,
523 .args = { { Name, 0 } } },
524 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
525 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
526 { .name = "unmount", .ret_type = 1, .nargs = 2,
527 .args = { { Name, 0 }, { Mountflags, 1 } } },
528 { .name = "utimensat", .ret_type = 1, .nargs = 4,
529 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
531 { .name = "utimes", .ret_type = 1, .nargs = 2,
532 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
533 { .name = "utrace", .ret_type = 1, .nargs = 1,
534 .args = { { Utrace, 0 } } },
535 { .name = "wait4", .ret_type = 1, .nargs = 4,
536 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
537 { Rusage | OUT, 3 } } },
538 { .name = "wait6", .ret_type = 1, .nargs = 6,
539 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
540 { Waitoptions, 3 }, { Rusage | OUT, 4 },
541 { Siginfo | OUT, 5 } } },
542 { .name = "write", .ret_type = 1, .nargs = 3,
543 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
544 { .name = "writev", .ret_type = 1, .nargs = 3,
545 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
548 { .name = "linux_access", .ret_type = 1, .nargs = 2,
549 .args = { { Name, 0 }, { Accessmode, 1 } } },
550 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
551 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
552 { ExecEnv | IN, 2 } } },
553 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
554 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
555 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
556 .args = { { Name | IN, 0 }, { Int, 1 } } },
557 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
558 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
559 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
560 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
561 { .name = "linux_open", .ret_type = 1, .nargs = 3,
562 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
563 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
564 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
565 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
566 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
567 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
568 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
570 /* CloudABI system calls. */
571 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
572 .args = { { CloudABIClockID, 0 } } },
573 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
574 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
575 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
576 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
577 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
578 .args = { { Int, 0 } } },
579 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
580 .args = { { CloudABIFileType, 0 } } },
581 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
582 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
583 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
584 .args = { { Int, 0 } } },
585 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
586 .args = { { Int, 0 } } },
587 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
588 .args = { { Int, 0 }, { Int, 1 } } },
589 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
590 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
591 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
592 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
593 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
594 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
595 { CloudABIFDSFlags, 2 } } },
596 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
597 .args = { { Int, 0 } } },
598 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
599 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
600 { CloudABIAdvice, 3 } } },
601 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
602 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
603 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
604 .args = { { Int, 0 }, { BinString | IN, 1 },
605 { CloudABIFileType, 3 } } },
606 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
607 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
608 { Int, 3 }, { BinString | IN, 4 } } },
609 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
610 .args = { { Int, 0 }, { BinString | IN, 1 },
611 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
612 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
613 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
615 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
616 .args = { { Int, 0 }, { BinString | IN, 1 },
617 { BinString | OUT, 3 }, { Int, 4 } } },
618 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
619 .args = { { Int, 0 }, { BinString | IN, 1 },
620 { Int, 3 }, { BinString | IN, 4 } } },
621 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
622 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
623 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
624 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
625 { CloudABIFSFlags, 2 } } },
626 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
627 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
628 { CloudABIFileStat | OUT, 3 } } },
629 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
630 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
631 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
632 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
633 .args = { { BinString | IN, 0 },
634 { Int, 2 }, { BinString | IN, 3 } } },
635 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
636 .args = { { Int, 0 }, { BinString | IN, 1 },
637 { CloudABIULFlags, 3 } } },
638 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
639 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
640 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
641 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
642 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
643 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
644 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
645 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
646 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
647 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
648 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
649 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
650 .args = { { Ptr, 0 }, { Int, 1 } } },
651 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
652 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
653 { IntArray, 3 }, { Int, 4 } } },
654 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
655 .args = { { Int, 0 } } },
656 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
657 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
658 .args = { { CloudABISignal, 0 } } },
659 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
660 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
661 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
662 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
663 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
664 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
665 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
669 static STAILQ_HEAD(, syscall) syscalls;
671 /* Xlat idea taken from strace */
677 #define X(a) { a, #a },
678 #define XEND { 0, NULL }
680 static struct xlat poll_flags[] = {
681 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
682 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
683 X(POLLWRBAND) X(POLLINIGNEOF) XEND
686 static struct xlat sigaction_flags[] = {
687 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
688 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
691 static struct xlat linux_socketcall_ops[] = {
692 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
693 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
694 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
695 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
696 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
701 #define X(a) { CLOUDABI_##a, #a },
703 static struct xlat cloudabi_advice[] = {
704 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
705 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
709 static struct xlat cloudabi_clockid[] = {
710 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
711 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
715 static struct xlat cloudabi_fdflags[] = {
716 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
717 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
721 static struct xlat cloudabi_fdsflags[] = {
722 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
726 static struct xlat cloudabi_filetype[] = {
727 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
728 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
729 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
730 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
731 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
735 static struct xlat cloudabi_fsflags[] = {
736 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
737 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
741 static struct xlat cloudabi_mflags[] = {
742 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
746 static struct xlat cloudabi_mprot[] = {
747 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
751 static struct xlat cloudabi_msflags[] = {
752 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
756 static struct xlat cloudabi_oflags[] = {
757 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
761 static struct xlat cloudabi_sdflags[] = {
762 X(SHUT_RD) X(SHUT_WR)
766 static struct xlat cloudabi_signal[] = {
767 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
768 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
769 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
770 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
771 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
775 static struct xlat cloudabi_ulflags[] = {
780 static struct xlat cloudabi_whence[] = {
781 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
789 * Searches an xlat array for a value, and returns it if found. Otherwise
790 * return a string representation.
793 lookup(struct xlat *xlat, int val, int base)
797 for (; xlat->str != NULL; xlat++)
798 if (xlat->val == val)
802 sprintf(tmp, "0%o", val);
805 sprintf(tmp, "0x%x", val);
808 sprintf(tmp, "%u", val);
811 errx(1,"Unknown lookup base");
818 xlookup(struct xlat *xlat, int val)
821 return (lookup(xlat, val, 16));
825 * Searches an xlat array containing bitfield values. Remaining bits
826 * set after removing the known ones are printed at the end:
830 xlookup_bits(struct xlat *xlat, int val)
833 static char str[512];
837 for (; xlat->str != NULL; xlat++) {
838 if ((xlat->val & rem) == xlat->val) {
840 * Don't print the "all-bits-zero" string unless all
841 * bits are really zero.
843 if (xlat->val == 0 && val != 0)
845 len += sprintf(str + len, "%s|", xlat->str);
851 * If we have leftover bits or didn't match anything, print
855 len += sprintf(str + len, "0x%x", rem);
856 if (len && str[len - 1] == '|')
863 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
867 str = decoder(value);
871 fprintf(fp, "%d", value);
875 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
879 if (!decoder(fp, value, &rem))
880 fprintf(fp, "0x%x", rem);
882 fprintf(fp, "|0x%x", rem);
886 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
891 if (!decoder(fp, value, &rem))
892 fprintf(fp, "0x%x", rem);
894 fprintf(fp, "|0x%x", rem);
899 * Add argument padding to subsequent system calls afater a Quad
900 * syscall arguments as needed. This used to be done by hand in the
901 * decoded_syscalls table which was ugly and error prone. It is
902 * simpler to do the fixup of offsets at initalization time than when
903 * decoding arguments.
906 quad_fixup(struct syscall *sc)
913 for (i = 0; i < sc->nargs; i++) {
914 /* This arg type is a dummy that doesn't use offset. */
915 if ((sc->args[i].type & ARG_MASK) == PipeFds)
918 assert(prev < sc->args[i].offset);
919 prev = sc->args[i].offset;
920 sc->args[i].offset += offset;
921 switch (sc->args[i].type & ARG_MASK) {
926 * 64-bit arguments on 32-bit powerpc must be
927 * 64-bit aligned. If the current offset is
928 * not aligned, the calling convention inserts
929 * a 32-bit pad argument that should be skipped.
931 if (sc->args[i].offset % 2 == 1) {
932 sc->args[i].offset++;
949 STAILQ_INIT(&syscalls);
950 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
954 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
958 static struct syscall *
959 find_syscall(struct procabi *abi, u_int number)
961 struct extra_syscall *es;
963 if (number < nitems(abi->syscalls))
964 return (abi->syscalls[number]);
965 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
966 if (es->number == number)
973 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
975 struct extra_syscall *es;
977 if (number < nitems(abi->syscalls)) {
978 assert(abi->syscalls[number] == NULL);
979 abi->syscalls[number] = sc;
981 es = malloc(sizeof(*es));
984 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
989 * If/when the list gets big, it might be desirable to do it
990 * as a hash table or binary search.
993 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
1000 sc = find_syscall(t->proc->abi, number);
1004 name = sysdecode_syscallname(t->proc->abi->abi, number);
1006 asprintf(&new_name, "#%d", number);
1010 STAILQ_FOREACH(sc, &syscalls, entries) {
1011 if (strcmp(name, sc->name) == 0) {
1012 add_syscall(t->proc->abi, number, sc);
1018 /* It is unknown. Add it into the list. */
1020 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1024 sc = calloc(1, sizeof(struct syscall));
1026 if (new_name != NULL)
1030 for (i = 0; i < nargs; i++) {
1031 sc->args[i].offset = i;
1032 /* Treat all unknown arguments as LongHex. */
1033 sc->args[i].type = LongHex;
1035 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1036 add_syscall(t->proc->abi, number, sc);
1042 * Copy a fixed amount of bytes from the process.
1045 get_struct(pid_t pid, void *offset, void *buf, int len)
1047 struct ptrace_io_desc iorequest;
1049 iorequest.piod_op = PIOD_READ_D;
1050 iorequest.piod_offs = offset;
1051 iorequest.piod_addr = buf;
1052 iorequest.piod_len = len;
1053 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1058 #define MAXSIZE 4096
1061 * Copy a string from the process. Note that it is
1062 * expected to be a C string, but if max is set, it will
1063 * only get that much.
1066 get_string(pid_t pid, void *addr, int max)
1068 struct ptrace_io_desc iorequest;
1070 size_t offset, size, totalsize;
1076 /* Read up to the end of the current page. */
1077 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1082 buf = malloc(totalsize);
1086 iorequest.piod_op = PIOD_READ_D;
1087 iorequest.piod_offs = (char *)addr + offset;
1088 iorequest.piod_addr = buf + offset;
1089 iorequest.piod_len = size;
1090 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1094 if (memchr(buf + offset, '\0', size) != NULL)
1097 if (totalsize < MAXSIZE && max == 0) {
1098 size = MAXSIZE - totalsize;
1099 if (size > PAGE_SIZE)
1101 nbuf = realloc(buf, totalsize + size);
1103 buf[totalsize - 1] = '\0';
1109 buf[totalsize - 1] = '\0';
1118 static char tmp[32];
1119 const char *signame;
1121 signame = sysdecode_signal(sig);
1122 if (signame == NULL) {
1123 snprintf(tmp, sizeof(tmp), "%d", sig);
1130 print_kevent(FILE *fp, struct kevent *ke)
1133 switch (ke->filter) {
1139 case EVFILT_PROCDESC:
1141 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1144 fputs(strsig2(ke->ident), fp);
1147 fprintf(fp, "%p", (void *)ke->ident);
1150 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1152 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1154 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1155 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1159 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1161 unsigned char *utrace_buffer;
1164 if (sysdecode_utrace(fp, utrace_addr, len)) {
1169 utrace_buffer = utrace_addr;
1170 fprintf(fp, "%zu:", len);
1172 fprintf(fp, " %02x", *utrace_buffer++);
1177 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1180 struct sockaddr_in *lsin;
1181 struct sockaddr_in6 *lsin6;
1182 struct sockaddr_un *sun;
1183 struct sockaddr *sa;
1185 pid_t pid = trussinfo->curthread->proc->pid;
1191 /* If the length is too small, just bail. */
1192 if (len < sizeof(*sa)) {
1193 fprintf(fp, "%p", arg);
1197 sa = calloc(1, len);
1198 if (get_struct(pid, arg, sa, len) == -1) {
1200 fprintf(fp, "%p", arg);
1204 switch (sa->sa_family) {
1206 if (len < sizeof(*lsin))
1207 goto sockaddr_short;
1208 lsin = (struct sockaddr_in *)(void *)sa;
1209 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1210 fprintf(fp, "{ AF_INET %s:%d }", addr,
1211 htons(lsin->sin_port));
1214 if (len < sizeof(*lsin6))
1215 goto sockaddr_short;
1216 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1217 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1219 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1220 htons(lsin6->sin6_port));
1223 sun = (struct sockaddr_un *)sa;
1224 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1225 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1231 "{ sa_len = %d, sa_family = %d, sa_data = {",
1232 (int)sa->sa_len, (int)sa->sa_family);
1233 for (q = (u_char *)sa->sa_data;
1234 q < (u_char *)sa + len; q++)
1235 fprintf(fp, "%s 0x%02x",
1236 q == (u_char *)sa->sa_data ? "" : ",",
1243 #define IOV_LIMIT 16
1246 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1248 struct iovec iov[IOV_LIMIT];
1249 size_t max_string = trussinfo->strsize;
1250 char tmp2[max_string + 1], *tmp3;
1252 pid_t pid = trussinfo->curthread->proc->pid;
1254 bool buf_truncated, iov_truncated;
1257 fprintf(fp, "%p", arg);
1260 if (iovcnt > IOV_LIMIT) {
1262 iov_truncated = true;
1264 iov_truncated = false;
1266 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1267 fprintf(fp, "%p", arg);
1272 for (i = 0; i < iovcnt; i++) {
1273 len = iov[i].iov_len;
1274 if (len > max_string) {
1276 buf_truncated = true;
1278 buf_truncated = false;
1280 fprintf(fp, "%s{", (i > 0) ? "," : "");
1281 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1282 tmp3 = malloc(len * 4 + 1);
1284 if (strvisx(tmp3, tmp2, len,
1285 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1289 buf_truncated = true;
1291 fprintf(fp, "\"%s\"%s", tmp3,
1292 buf_truncated ? "..." : "");
1295 fprintf(fp, "%p", iov[i].iov_base);
1297 fprintf(fp, ",%zu}", iov[i].iov_len);
1299 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1303 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1308 for (q = CMSG_DATA(cmsghdr);
1309 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1310 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1316 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1318 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1319 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1320 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1321 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1325 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1327 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1329 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1332 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1333 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1335 fprintf(fp, "ctx=%u,", info->sinfo_context);
1336 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1339 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1340 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1342 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1346 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1348 fprintf(fp, "{sid=%u,", info->snd_sid);
1350 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1351 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1352 fprintf(fp, "ctx=%u,", info->snd_context);
1353 fprintf(fp, "id=%u}", info->snd_assoc_id);
1357 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1359 fprintf(fp, "{sid=%u,", info->rcv_sid);
1360 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1362 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1363 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1364 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1365 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1366 fprintf(fp, "ctx=%u,", info->rcv_context);
1367 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1371 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1373 fprintf(fp, "{sid=%u,", info->nxt_sid);
1375 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1376 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1377 fprintf(fp, "len=%u,", info->nxt_length);
1378 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1382 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1385 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1386 fprintf(fp, ",val=%u}", info->pr_value);
1390 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1392 fprintf(fp, "{num=%u}", info->auth_keynumber);
1396 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1398 char buf[INET_ADDRSTRLEN];
1401 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1403 fprintf(fp, "{addr=%s}", s);
1405 fputs("{addr=???}", fp);
1409 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1411 char buf[INET6_ADDRSTRLEN];
1414 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1416 fprintf(fp, "{addr=%s}", s);
1418 fputs("{addr=???}", fp);
1422 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1427 len = cmsghdr->cmsg_len;
1428 data = CMSG_DATA(cmsghdr);
1429 switch (cmsghdr->cmsg_type) {
1431 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1432 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1434 print_gen_cmsg(fp, cmsghdr);
1437 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1438 print_sctp_sndrcvinfo(fp, receive,
1439 (struct sctp_sndrcvinfo *)data);
1441 print_gen_cmsg(fp, cmsghdr);
1445 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1446 print_sctp_extrcvinfo(fp,
1447 (struct sctp_extrcvinfo *)data);
1449 print_gen_cmsg(fp, cmsghdr);
1453 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1454 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1456 print_gen_cmsg(fp, cmsghdr);
1459 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1460 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1462 print_gen_cmsg(fp, cmsghdr);
1465 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1466 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1468 print_gen_cmsg(fp, cmsghdr);
1471 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1472 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1474 print_gen_cmsg(fp, cmsghdr);
1477 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1478 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1480 print_gen_cmsg(fp, cmsghdr);
1482 case SCTP_DSTADDRV4:
1483 if (len == CMSG_LEN(sizeof(struct in_addr)))
1484 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1486 print_gen_cmsg(fp, cmsghdr);
1488 case SCTP_DSTADDRV6:
1489 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1490 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1492 print_gen_cmsg(fp, cmsghdr);
1495 print_gen_cmsg(fp, cmsghdr);
1500 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1502 struct cmsghdr *cmsghdr;
1509 len = msghdr->msg_controllen;
1514 cmsgbuf = calloc(1, len);
1515 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1516 fprintf(fp, "%p", msghdr->msg_control);
1520 msghdr->msg_control = cmsgbuf;
1523 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1525 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1526 level = cmsghdr->cmsg_level;
1527 type = cmsghdr->cmsg_type;
1528 len = cmsghdr->cmsg_len;
1529 fprintf(fp, "%s{level=", first ? "" : ",");
1530 print_integer_arg(sysdecode_sockopt_level, fp, level);
1531 fputs(",type=", fp);
1532 temp = sysdecode_cmsg_type(level, type);
1536 fprintf(fp, "%d", type);
1538 fputs(",data=", fp);
1541 print_sctp_cmsg(fp, receive, cmsghdr);
1544 print_gen_cmsg(fp, cmsghdr);
1555 * Converts a syscall argument into a string. Said string is
1556 * allocated via malloc(), so needs to be free()'d. sc is
1557 * a pointer to the syscall description (see above); args is
1558 * an array of all of the system call arguments.
1561 print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
1562 struct trussinfo *trussinfo)
1569 fp = open_memstream(&tmp, &tmplen);
1570 pid = trussinfo->curthread->proc->pid;
1571 switch (sc->type & ARG_MASK) {
1573 fprintf(fp, "0x%x", (int)args[sc->offset]);
1576 fprintf(fp, "0%o", (int)args[sc->offset]);
1579 fprintf(fp, "%d", (int)args[sc->offset]);
1582 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1587 if (get_struct(pid, (void *)args[sc->offset], &val,
1589 fprintf(fp, "{ %u }", val);
1591 fprintf(fp, "0x%lx", args[sc->offset]);
1595 fprintf(fp, "0x%lx", args[sc->offset]);
1598 fprintf(fp, "%ld", args[sc->offset]);
1601 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1604 /* Handle special SHM_ANON value. */
1605 if ((char *)args[sc->offset] == SHM_ANON) {
1606 fprintf(fp, "SHM_ANON");
1611 /* NULL-terminated string. */
1614 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1615 fprintf(fp, "\"%s\"", tmp2);
1621 * Binary block of data that might have printable characters.
1622 * XXX If type|OUT, assume that the length is the syscall's
1623 * return value. Otherwise, assume that the length of the block
1624 * is in the next syscall argument.
1626 int max_string = trussinfo->strsize;
1627 char tmp2[max_string + 1], *tmp3;
1634 len = args[sc->offset + 1];
1637 * Don't print more than max_string characters, to avoid word
1638 * wrap. If we have to truncate put some ... after the string.
1640 if (len > max_string) {
1644 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1646 tmp3 = malloc(len * 4 + 1);
1648 if (strvisx(tmp3, tmp2, len,
1649 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1654 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1658 fprintf(fp, "0x%lx", args[sc->offset]);
1668 char buf[PAGE_SIZE];
1675 * Only parse argv[] and environment arrays from exec calls
1678 if (((sc->type & ARG_MASK) == ExecArgs &&
1679 (trussinfo->flags & EXECVEARGS) == 0) ||
1680 ((sc->type & ARG_MASK) == ExecEnv &&
1681 (trussinfo->flags & EXECVEENVS) == 0)) {
1682 fprintf(fp, "0x%lx", args[sc->offset]);
1687 * Read a page of pointers at a time. Punt if the top-level
1688 * pointer is not aligned. Note that the first read is of
1691 addr = args[sc->offset];
1692 if (addr % sizeof(char *) != 0) {
1693 fprintf(fp, "0x%lx", args[sc->offset]);
1697 len = PAGE_SIZE - (addr & PAGE_MASK);
1698 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1699 fprintf(fp, "0x%lx", args[sc->offset]);
1706 while (u.strarray[i] != NULL) {
1707 string = get_string(pid, u.strarray[i], 0);
1708 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1713 if (i == len / sizeof(char *)) {
1716 if (get_struct(pid, (void *)addr, u.buf, len) ==
1718 fprintf(fp, ", <inval>");
1729 fprintf(fp, "%ld", args[sc->offset]);
1732 fprintf(fp, "0x%lx", args[sc->offset]);
1737 unsigned long long ll;
1739 #if _BYTE_ORDER == _LITTLE_ENDIAN
1740 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1743 ll = (unsigned long long)args[sc->offset] << 32 |
1744 args[sc->offset + 1];
1746 if ((sc->type & ARG_MASK) == Quad)
1747 fprintf(fp, "%lld", ll);
1749 fprintf(fp, "0x%llx", ll);
1756 if (get_struct(pid, (void *)args[sc->offset], &val,
1758 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1760 fprintf(fp, "0x%lx", args[sc->offset]);
1764 fprintf(fp, "0x%lx", args[sc->offset]);
1769 if (retval[0] == -1)
1771 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1772 fprintf(fp, "\"%s\"", tmp2);
1780 cmd = args[sc->offset];
1781 temp = sysdecode_ioctlname(cmd);
1785 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1786 cmd, cmd & IOC_OUT ? "R" : "",
1787 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1788 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1789 cmd & 0xFF, IOCPARM_LEN(cmd));
1796 if (get_struct(pid, (void *)args[sc->offset], &ts,
1798 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1801 fprintf(fp, "0x%lx", args[sc->offset]);
1805 struct timespec ts[2];
1809 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1813 for (i = 0; i < nitems(ts); i++) {
1816 switch (ts[i].tv_nsec) {
1818 fprintf(fp, "UTIME_NOW");
1821 fprintf(fp, "UTIME_OMIT");
1824 fprintf(fp, "%jd.%09ld",
1825 (intmax_t)ts[i].tv_sec,
1832 fprintf(fp, "0x%lx", args[sc->offset]);
1838 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1840 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1843 fprintf(fp, "0x%lx", args[sc->offset]);
1847 struct timeval tv[2];
1849 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1851 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1852 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1853 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1855 fprintf(fp, "0x%lx", args[sc->offset]);
1859 struct itimerval itv;
1861 if (get_struct(pid, (void *)args[sc->offset], &itv,
1863 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1864 (intmax_t)itv.it_interval.tv_sec,
1865 itv.it_interval.tv_usec,
1866 (intmax_t)itv.it_value.tv_sec,
1867 itv.it_value.tv_usec);
1869 fprintf(fp, "0x%lx", args[sc->offset]);
1874 struct linux_socketcall_args largs;
1876 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1877 sizeof(largs)) != -1)
1878 fprintf(fp, "{ %s, 0x%lx }",
1879 lookup(linux_socketcall_ops, largs.what, 10),
1880 (long unsigned int)largs.args);
1882 fprintf(fp, "0x%lx", args[sc->offset]);
1887 * XXX: A Pollfd argument expects the /next/ syscall argument
1888 * to be the number of fds in the array. This matches the poll
1892 int numfds = args[sc->offset + 1];
1893 size_t bytes = sizeof(struct pollfd) * numfds;
1896 if ((pfd = malloc(bytes)) == NULL)
1897 err(1, "Cannot malloc %zu bytes for pollfd array",
1899 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1902 for (i = 0; i < numfds; i++) {
1903 fprintf(fp, " %d/%s", pfd[i].fd,
1904 xlookup_bits(poll_flags, pfd[i].events));
1908 fprintf(fp, "0x%lx", args[sc->offset]);
1915 * XXX: A Fd_set argument expects the /first/ syscall argument
1916 * to be the number of fds in the array. This matches the
1920 int numfds = args[0];
1921 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1924 if ((fds = malloc(bytes)) == NULL)
1925 err(1, "Cannot malloc %zu bytes for fd_set array",
1927 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1930 for (i = 0; i < numfds; i++) {
1931 if (FD_ISSET(i, fds))
1932 fprintf(fp, " %d", i);
1936 fprintf(fp, "0x%lx", args[sc->offset]);
1941 fputs(strsig2(args[sc->offset]), fp);
1948 sig = args[sc->offset];
1949 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1950 sizeof(ss)) == -1) {
1951 fprintf(fp, "0x%lx", args[sc->offset]);
1956 for (i = 1; i < sys_nsig; i++) {
1957 if (sigismember(&ss, i)) {
1958 fprintf(fp, "%s%s", !first ? "|" : "",
1969 print_integer_arg(sysdecode_sigprocmask_how, fp,
1973 /* XXX: Output depends on the value of the previous argument. */
1974 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1975 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1976 args[sc->offset], 16);
1979 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1982 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1985 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1988 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1991 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1994 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1997 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
2000 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
2003 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2006 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2009 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2012 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2017 if (args[sc->offset] == 0) {
2023 * Extract the address length from the next argument. If
2024 * this is an output sockaddr (OUT is set), then the
2025 * next argument is a pointer to a socklen_t. Otherwise
2026 * the next argument contains a socklen_t by value.
2028 if (sc->type & OUT) {
2029 if (get_struct(pid, (void *)args[sc->offset + 1],
2030 &len, sizeof(len)) == -1) {
2031 fprintf(fp, "0x%lx", args[sc->offset]);
2035 len = args[sc->offset + 1];
2037 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2041 struct sigaction sa;
2043 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2046 if (sa.sa_handler == SIG_DFL)
2047 fputs("SIG_DFL", fp);
2048 else if (sa.sa_handler == SIG_IGN)
2049 fputs("SIG_IGN", fp);
2051 fprintf(fp, "%p", sa.sa_handler);
2052 fprintf(fp, " %s ss_t }",
2053 xlookup_bits(sigaction_flags, sa.sa_flags));
2055 fprintf(fp, "0x%lx", args[sc->offset]);
2060 * XXX XXX: The size of the array is determined by either the
2061 * next syscall argument, or by the syscall return value,
2062 * depending on which argument number we are. This matches the
2063 * kevent syscall, but luckily that's the only syscall that uses
2071 if (sc->offset == 1)
2072 numevents = args[sc->offset+1];
2073 else if (sc->offset == 3 && retval[0] != -1)
2074 numevents = retval[0];
2076 if (numevents >= 0) {
2077 bytes = sizeof(struct kevent) * numevents;
2078 if ((ke = malloc(bytes)) == NULL)
2080 "Cannot malloc %zu bytes for kevent array",
2084 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2087 for (i = 0; i < numevents; i++) {
2089 print_kevent(fp, &ke[i]);
2093 fprintf(fp, "0x%lx", args[sc->offset]);
2099 struct kevent_freebsd11 *ke11;
2105 if (sc->offset == 1)
2106 numevents = args[sc->offset+1];
2107 else if (sc->offset == 3 && retval[0] != -1)
2108 numevents = retval[0];
2110 if (numevents >= 0) {
2111 bytes = sizeof(struct kevent_freebsd11) * numevents;
2112 if ((ke11 = malloc(bytes)) == NULL)
2114 "Cannot malloc %zu bytes for kevent array",
2118 memset(&ke, 0, sizeof(ke));
2119 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2120 ke11, bytes) != -1) {
2122 for (i = 0; i < numevents; i++) {
2124 ke.ident = ke11[i].ident;
2125 ke.filter = ke11[i].filter;
2126 ke.flags = ke11[i].flags;
2127 ke.fflags = ke11[i].fflags;
2128 ke.data = ke11[i].data;
2129 ke.udata = ke11[i].udata;
2130 print_kevent(fp, &ke);
2134 fprintf(fp, "0x%lx", args[sc->offset]);
2142 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2146 strmode(st.st_mode, mode);
2148 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2149 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2150 (long)st.st_blksize);
2152 fprintf(fp, "0x%lx", args[sc->offset]);
2157 struct freebsd11_stat st;
2159 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2163 strmode(st.st_mode, mode);
2165 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2166 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2167 (long)st.st_blksize);
2169 fprintf(fp, "0x%lx", args[sc->offset]);
2177 if (get_struct(pid, (void *)args[sc->offset], &buf,
2178 sizeof(buf)) != -1) {
2181 bzero(fsid, sizeof(fsid));
2182 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2183 for (i = 0; i < sizeof(buf.f_fsid); i++)
2184 snprintf(&fsid[i*2],
2185 sizeof(fsid) - (i*2), "%02x",
2186 ((u_char *)&buf.f_fsid)[i]);
2189 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2190 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2191 buf.f_mntfromname, fsid);
2193 fprintf(fp, "0x%lx", args[sc->offset]);
2200 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2203 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2204 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2205 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2206 ru.ru_inblock, ru.ru_oublock);
2208 fprintf(fp, "0x%lx", args[sc->offset]);
2214 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2216 fprintf(fp, "{ cur=%ju,max=%ju }",
2217 rl.rlim_cur, rl.rlim_max);
2219 fprintf(fp, "0x%lx", args[sc->offset]);
2225 if (get_struct(pid, (void *)args[sc->offset], &status,
2226 sizeof(status)) != -1) {
2228 if (WIFCONTINUED(status))
2229 fputs("CONTINUED", fp);
2230 else if (WIFEXITED(status))
2231 fprintf(fp, "EXITED,val=%d",
2232 WEXITSTATUS(status));
2233 else if (WIFSIGNALED(status))
2234 fprintf(fp, "SIGNALED,sig=%s%s",
2235 strsig2(WTERMSIG(status)),
2236 WCOREDUMP(status) ? ",cored" : "");
2238 fprintf(fp, "STOPPED,sig=%s",
2239 strsig2(WTERMSIG(status)));
2242 fprintf(fp, "0x%lx", args[sc->offset]);
2246 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2249 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2252 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2255 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2258 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2261 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2264 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2267 print_integer_arg(sysdecode_sysarch_number, fp,
2272 * The pipe() system call in the kernel returns its
2273 * two file descriptors via return values. However,
2274 * the interface exposed by libc is that pipe()
2275 * accepts a pointer to an array of descriptors.
2276 * Format the output to match the libc API by printing
2277 * the returned file descriptors as a fake argument.
2279 * Overwrite the first retval to signal a successful
2282 fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
2289 len = args[sc->offset + 1];
2290 utrace_addr = calloc(1, len);
2291 if (get_struct(pid, (void *)args[sc->offset],
2292 (void *)utrace_addr, len) != -1)
2293 print_utrace(fp, utrace_addr, len);
2295 fprintf(fp, "0x%lx", args[sc->offset]);
2300 int descriptors[16];
2301 unsigned long i, ndescriptors;
2304 ndescriptors = args[sc->offset + 1];
2306 if (ndescriptors > nitems(descriptors)) {
2307 ndescriptors = nitems(descriptors);
2310 if (get_struct(pid, (void *)args[sc->offset],
2311 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2313 for (i = 0; i < ndescriptors; i++)
2314 fprintf(fp, i == 0 ? " %d" : ", %d",
2316 fprintf(fp, truncated ? ", ... }" : " }");
2318 fprintf(fp, "0x%lx", args[sc->offset]);
2322 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2324 case CapFcntlRights: {
2327 if (sc->type & OUT) {
2328 if (get_struct(pid, (void *)args[sc->offset], &rights,
2329 sizeof(rights)) == -1) {
2330 fprintf(fp, "0x%lx", args[sc->offset]);
2334 rights = args[sc->offset];
2335 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2339 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2344 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2345 fprintf(fp, "0x%x", rem);
2347 fprintf(fp, "|0x%x", rem);
2351 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2354 print_integer_arg(sysdecode_getfsstat_mode, fp,
2358 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2360 case Kldunloadflags:
2361 print_integer_arg(sysdecode_kldunload_flags, fp,
2365 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2368 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2370 case Sockprotocol: {
2372 int domain, protocol;
2374 domain = args[sc->offset - 2];
2375 protocol = args[sc->offset];
2376 if (protocol == 0) {
2379 temp = sysdecode_socket_protocol(domain, protocol);
2383 fprintf(fp, "%d", protocol);
2389 print_integer_arg(sysdecode_sockopt_level, fp,
2396 level = args[sc->offset - 1];
2397 name = args[sc->offset];
2398 temp = sysdecode_sockopt_name(level, name);
2402 fprintf(fp, "%d", name);
2407 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2410 cap_rights_t rights;
2412 if (get_struct(pid, (void *)args[sc->offset], &rights,
2413 sizeof(rights)) != -1) {
2415 sysdecode_cap_rights(fp, &rights);
2418 fprintf(fp, "0x%lx", args[sc->offset]);
2422 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2424 case Extattrnamespace:
2425 print_integer_arg(sysdecode_extattrnamespace, fp,
2429 print_integer_arg(sysdecode_minherit_inherit, fp,
2433 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2436 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2439 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2442 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2445 print_integer_arg(sysdecode_ptrace_request, fp,
2449 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2450 fprintf(fp, "%#x", (int)args[sc->offset]);
2453 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2456 print_integer_arg(sysdecode_rtprio_function, fp,
2460 print_integer_arg(sysdecode_scheduler_policy, fp,
2464 struct sched_param sp;
2466 if (get_struct(pid, (void *)args[sc->offset], &sp,
2468 fprintf(fp, "{ %d }", sp.sched_priority);
2470 fprintf(fp, "0x%lx", args[sc->offset]);
2476 if (get_struct(pid, (void *)args[sc->offset], &sig,
2478 fprintf(fp, "{ %s }", strsig2(sig));
2480 fprintf(fp, "0x%lx", args[sc->offset]);
2486 if (get_struct(pid, (void *)args[sc->offset], &si,
2487 sizeof(si)) != -1) {
2488 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2489 decode_siginfo(fp, &si);
2492 fprintf(fp, "0x%lx", args[sc->offset]);
2497 * Print argument as an array of struct iovec, where the next
2498 * syscall argument is the number of elements of the array.
2501 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2502 (int)args[sc->offset + 1]);
2504 case Sctpsndrcvinfo: {
2505 struct sctp_sndrcvinfo info;
2507 if (get_struct(pid, (void *)args[sc->offset],
2508 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2509 fprintf(fp, "0x%lx", args[sc->offset]);
2512 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2516 struct msghdr msghdr;
2518 if (get_struct(pid, (void *)args[sc->offset],
2519 &msghdr, sizeof(struct msghdr)) == -1) {
2520 fprintf(fp, "0x%lx", args[sc->offset]);
2524 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2525 fprintf(fp, ",%d,", msghdr.msg_namelen);
2526 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2527 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2528 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2529 fprintf(fp, ",%u,", msghdr.msg_controllen);
2530 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2535 case CloudABIAdvice:
2536 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2538 case CloudABIClockID:
2539 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2541 case CloudABIFDSFlags:
2542 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2544 case CloudABIFDStat: {
2545 cloudabi_fdstat_t fds;
2546 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2548 fprintf(fp, "{ %s, ",
2549 xlookup(cloudabi_filetype, fds.fs_filetype));
2550 fprintf(fp, "%s, ... }",
2551 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2553 fprintf(fp, "0x%lx", args[sc->offset]);
2556 case CloudABIFileStat: {
2557 cloudabi_filestat_t fsb;
2558 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2560 fprintf(fp, "{ %s, %ju }",
2561 xlookup(cloudabi_filetype, fsb.st_filetype),
2562 (uintmax_t)fsb.st_size);
2564 fprintf(fp, "0x%lx", args[sc->offset]);
2567 case CloudABIFileType:
2568 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2570 case CloudABIFSFlags:
2571 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2573 case CloudABILookup:
2574 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2575 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2576 (int)args[sc->offset]);
2578 fprintf(fp, "%d", (int)args[sc->offset]);
2580 case CloudABIMFlags:
2581 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2584 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2586 case CloudABIMSFlags:
2587 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2589 case CloudABIOFlags:
2590 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2592 case CloudABISDFlags:
2593 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2595 case CloudABISignal:
2596 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2598 case CloudABITimestamp:
2599 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2600 args[sc->offset] % 1000000000);
2602 case CloudABIULFlags:
2603 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2605 case CloudABIWhence:
2606 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2610 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2617 * Print (to outfile) the system call and its arguments.
2620 print_syscall(struct trussinfo *trussinfo)
2622 struct threadinfo *t;
2627 t = trussinfo->curthread;
2629 name = t->cs.sc->name;
2630 nargs = t->cs.nargs;
2631 s_args = t->cs.s_args;
2633 len = print_line_prefix(trussinfo);
2634 len += fprintf(trussinfo->outfile, "%s(", name);
2636 for (i = 0; i < nargs; i++) {
2637 if (s_args[i] != NULL)
2638 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2640 len += fprintf(trussinfo->outfile,
2641 "<missing argument>");
2642 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2645 len += fprintf(trussinfo->outfile, ")");
2646 for (i = 0; i < 6 - (len / 8); i++)
2647 fprintf(trussinfo->outfile, "\t");
2651 print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval)
2653 struct timespec timediff;
2654 struct threadinfo *t;
2657 t = trussinfo->curthread;
2659 if (trussinfo->flags & COUNTONLY) {
2660 timespecsub(&t->after, &t->before, &timediff);
2661 timespecadd(&sc->time, &timediff, &sc->time);
2668 print_syscall(trussinfo);
2669 fflush(trussinfo->outfile);
2671 if (retval == NULL) {
2673 * This system call resulted in the current thread's exit,
2674 * so there is no return value or error to display.
2676 fprintf(trussinfo->outfile, "\n");
2680 if (error == ERESTART)
2681 fprintf(trussinfo->outfile, " ERESTART\n");
2682 else if (error == EJUSTRETURN)
2683 fprintf(trussinfo->outfile, " EJUSTRETURN\n");
2684 else if (error != 0) {
2685 fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
2686 sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
2690 else if (sc->ret_type == 2) {
2693 #if _BYTE_ORDER == _LITTLE_ENDIAN
2694 off = (off_t)retval[1] << 32 | retval[0];
2696 off = (off_t)retval[0] << 32 | retval[1];
2698 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2703 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
2704 (intmax_t)retval[0], (intmax_t)retval[0]);
2708 print_summary(struct trussinfo *trussinfo)
2710 struct timespec total = {0, 0};
2714 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2715 "syscall", "seconds", "calls", "errors");
2717 STAILQ_FOREACH(sc, &syscalls, entries)
2719 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2720 sc->name, (intmax_t)sc->time.tv_sec,
2721 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2722 timespecadd(&total, &sc->time, &total);
2723 ncall += sc->ncalls;
2724 nerror += sc->nerror;
2726 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2727 "", "-------------", "-------", "-------");
2728 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2729 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);