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>
72 #include <sysdecode.h>
76 #include <contrib/cloudabi/cloudabi_types_common.h>
83 * This should probably be in its own file, sorted alphabetically.
85 static struct syscall decoded_syscalls[] = {
87 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
88 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
89 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
90 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
91 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
92 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
93 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
94 .args = { { Int, 0 }, { Acltype, 1 } } },
95 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
96 .args = { { Name, 0 }, { Acltype, 1 } } },
97 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
98 .args = { { Name, 0 }, { Acltype, 1 } } },
99 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
100 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
101 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
102 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
103 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
104 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
106 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
108 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
110 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
111 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
112 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
113 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
114 .args = { { Name | OUT, 0 }, { Int, 1 } } },
115 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
116 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
118 { .name = "accept", .ret_type = 1, .nargs = 3,
119 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
120 { .name = "access", .ret_type = 1, .nargs = 2,
121 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
122 { .name = "bind", .ret_type = 1, .nargs = 3,
123 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
124 { .name = "bindat", .ret_type = 1, .nargs = 4,
125 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
127 { .name = "break", .ret_type = 1, .nargs = 1,
128 .args = { { Ptr, 0 } } },
129 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
130 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
131 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
132 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
133 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
134 .args = { { PUInt | OUT, 0 } } },
135 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
136 .args = { { Int, 0 }, { CapRights, 1 } } },
137 { .name = "chdir", .ret_type = 1, .nargs = 1,
138 .args = { { Name, 0 } } },
139 { .name = "chflags", .ret_type = 1, .nargs = 2,
140 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
141 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
142 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
144 { .name = "chmod", .ret_type = 1, .nargs = 2,
145 .args = { { Name, 0 }, { Octal, 1 } } },
146 { .name = "chown", .ret_type = 1, .nargs = 3,
147 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
148 { .name = "chroot", .ret_type = 1, .nargs = 1,
149 .args = { { Name, 0 } } },
150 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
151 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
152 { .name = "close", .ret_type = 1, .nargs = 1,
153 .args = { { Int, 0 } } },
154 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
155 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
156 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
157 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
159 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
160 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
161 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
162 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
163 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
164 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
165 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
166 { .name = "connect", .ret_type = 1, .nargs = 3,
167 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
168 { .name = "connectat", .ret_type = 1, .nargs = 4,
169 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
171 { .name = "dup", .ret_type = 1, .nargs = 1,
172 .args = { { Int, 0 } } },
173 { .name = "dup2", .ret_type = 1, .nargs = 2,
174 .args = { { Int, 0 }, { Int, 1 } } },
175 { .name = "eaccess", .ret_type = 1, .nargs = 2,
176 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
177 { .name = "execve", .ret_type = 1, .nargs = 3,
178 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
179 { ExecEnv | IN, 2 } } },
180 { .name = "exit", .ret_type = 0, .nargs = 1,
181 .args = { { Hex, 0 } } },
182 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
183 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
184 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
185 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
186 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
187 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
188 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
189 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
190 { BinString | OUT, 3 }, { Sizet, 4 } } },
191 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
192 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
193 { BinString | OUT, 3 }, { Sizet, 4 } } },
194 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
195 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
196 { BinString | OUT, 3 }, { Sizet, 4 } } },
197 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
198 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
200 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
201 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
203 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
204 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
206 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
207 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
208 { BinString | IN, 3 }, { Sizet, 4 } } },
209 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
210 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
211 { BinString | IN, 3 }, { Sizet, 4 } } },
212 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
213 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
214 { BinString | IN, 3 }, { Sizet, 4 } } },
215 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
216 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
217 { Extattrnamespace, 3 }, { Name, 4 } } },
218 { .name = "faccessat", .ret_type = 1, .nargs = 4,
219 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
221 { .name = "fchflags", .ret_type = 1, .nargs = 2,
222 .args = { { Int, 0 }, { FileFlags, 1 } } },
223 { .name = "fchmod", .ret_type = 1, .nargs = 2,
224 .args = { { Int, 0 }, { Octal, 1 } } },
225 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
226 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
227 { .name = "fchown", .ret_type = 1, .nargs = 3,
228 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
229 { .name = "fchownat", .ret_type = 1, .nargs = 5,
230 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
232 { .name = "fcntl", .ret_type = 1, .nargs = 3,
233 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
234 { .name = "flock", .ret_type = 1, .nargs = 2,
235 .args = { { Int, 0 }, { Flockop, 1 } } },
236 { .name = "fstat", .ret_type = 1, .nargs = 2,
237 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
238 { .name = "fstatat", .ret_type = 1, .nargs = 4,
239 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
241 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
242 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
243 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
244 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
245 { .name = "futimens", .ret_type = 1, .nargs = 2,
246 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
247 { .name = "futimes", .ret_type = 1, .nargs = 2,
248 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
249 { .name = "futimesat", .ret_type = 1, .nargs = 3,
250 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
251 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
252 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
253 { PQuadHex | OUT, 3 } } },
254 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
255 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
256 { .name = "getitimer", .ret_type = 1, .nargs = 2,
257 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
258 { .name = "getpeername", .ret_type = 1, .nargs = 3,
259 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
260 { .name = "getpgid", .ret_type = 1, .nargs = 1,
261 .args = { { Int, 0 } } },
262 { .name = "getpriority", .ret_type = 1, .nargs = 2,
263 .args = { { Priowhich, 0 }, { Int, 1 } } },
264 { .name = "getrandom", .ret_type = 1, .nargs = 3,
265 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
266 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
267 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
268 { .name = "getrusage", .ret_type = 1, .nargs = 2,
269 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
270 { .name = "getsid", .ret_type = 1, .nargs = 1,
271 .args = { { Int, 0 } } },
272 { .name = "getsockname", .ret_type = 1, .nargs = 3,
273 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
274 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
275 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
276 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
277 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
278 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
279 { .name = "ioctl", .ret_type = 1, .nargs = 3,
280 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
281 { .name = "kevent", .ret_type = 1, .nargs = 6,
282 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
283 { Int, 4 }, { Timespec, 5 } } },
284 { .name = "kill", .ret_type = 1, .nargs = 2,
285 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
286 { .name = "kldfind", .ret_type = 1, .nargs = 1,
287 .args = { { Name | IN, 0 } } },
288 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
289 .args = { { Int, 0 } } },
290 { .name = "kldload", .ret_type = 1, .nargs = 1,
291 .args = { { Name | IN, 0 } } },
292 { .name = "kldnext", .ret_type = 1, .nargs = 1,
293 .args = { { Int, 0 } } },
294 { .name = "kldstat", .ret_type = 1, .nargs = 2,
295 .args = { { Int, 0 }, { Ptr, 1 } } },
296 { .name = "kldsym", .ret_type = 1, .nargs = 3,
297 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
298 { .name = "kldunload", .ret_type = 1, .nargs = 1,
299 .args = { { Int, 0 } } },
300 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
301 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
302 { .name = "kse_release", .ret_type = 0, .nargs = 1,
303 .args = { { Timespec, 0 } } },
304 { .name = "lchflags", .ret_type = 1, .nargs = 2,
305 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
306 { .name = "lchmod", .ret_type = 1, .nargs = 2,
307 .args = { { Name, 0 }, { Octal, 1 } } },
308 { .name = "lchown", .ret_type = 1, .nargs = 3,
309 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
310 { .name = "link", .ret_type = 1, .nargs = 2,
311 .args = { { Name, 0 }, { Name, 1 } } },
312 { .name = "linkat", .ret_type = 1, .nargs = 5,
313 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
315 { .name = "listen", .ret_type = 1, .nargs = 2,
316 .args = { { Int, 0 }, { Int, 1 } } },
317 { .name = "lseek", .ret_type = 2, .nargs = 3,
318 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
319 { .name = "lstat", .ret_type = 1, .nargs = 2,
320 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
321 { .name = "lutimes", .ret_type = 1, .nargs = 2,
322 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
323 { .name = "madvise", .ret_type = 1, .nargs = 3,
324 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
325 { .name = "minherit", .ret_type = 1, .nargs = 3,
326 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
327 { .name = "mkdir", .ret_type = 1, .nargs = 2,
328 .args = { { Name, 0 }, { Octal, 1 } } },
329 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
330 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
331 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
332 .args = { { Name, 0 }, { Octal, 1 } } },
333 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
334 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
335 { .name = "mknod", .ret_type = 1, .nargs = 3,
336 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
337 { .name = "mknodat", .ret_type = 1, .nargs = 4,
338 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
339 { .name = "mlock", .ret_type = 1, .nargs = 2,
340 .args = { { Ptr, 0 }, { Sizet, 1 } } },
341 { .name = "mlockall", .ret_type = 1, .nargs = 1,
342 .args = { { Mlockall, 0 } } },
343 { .name = "mmap", .ret_type = 1, .nargs = 6,
344 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
345 { Int, 4 }, { QuadHex, 5 } } },
346 { .name = "modfind", .ret_type = 1, .nargs = 1,
347 .args = { { Name | IN, 0 } } },
348 { .name = "mount", .ret_type = 1, .nargs = 4,
349 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
350 { .name = "mprotect", .ret_type = 1, .nargs = 3,
351 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
352 { .name = "msync", .ret_type = 1, .nargs = 3,
353 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
354 { .name = "munlock", .ret_type = 1, .nargs = 2,
355 .args = { { Ptr, 0 }, { Sizet, 1 } } },
356 { .name = "munmap", .ret_type = 1, .nargs = 2,
357 .args = { { Ptr, 0 }, { Sizet, 1 } } },
358 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
359 .args = { { Timespec, 0 } } },
360 { .name = "nmount", .ret_type = 1, .nargs = 3,
361 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
362 { .name = "open", .ret_type = 1, .nargs = 3,
363 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
364 { .name = "openat", .ret_type = 1, .nargs = 4,
365 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
367 { .name = "pathconf", .ret_type = 1, .nargs = 2,
368 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
369 { .name = "pipe", .ret_type = 1, .nargs = 1,
370 .args = { { PipeFds | OUT, 0 } } },
371 { .name = "pipe2", .ret_type = 1, .nargs = 2,
372 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
373 { .name = "poll", .ret_type = 1, .nargs = 3,
374 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
375 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
376 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
378 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
379 .args = { { Open, 0 } } },
380 { .name = "pread", .ret_type = 1, .nargs = 4,
381 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
383 { .name = "procctl", .ret_type = 1, .nargs = 4,
384 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
385 { .name = "ptrace", .ret_type = 1, .nargs = 4,
386 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
387 { .name = "pwrite", .ret_type = 1, .nargs = 4,
388 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
390 { .name = "quotactl", .ret_type = 1, .nargs = 4,
391 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
392 { .name = "read", .ret_type = 1, .nargs = 3,
393 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
394 { .name = "readlink", .ret_type = 1, .nargs = 3,
395 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
396 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
397 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
399 { .name = "readv", .ret_type = 1, .nargs = 3,
400 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
401 { .name = "reboot", .ret_type = 1, .nargs = 1,
402 .args = { { Reboothowto, 0 } } },
403 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
404 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
405 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
406 { Ptr | OUT, 5 } } },
407 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
408 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
409 { .name = "rename", .ret_type = 1, .nargs = 2,
410 .args = { { Name, 0 }, { Name, 1 } } },
411 { .name = "renameat", .ret_type = 1, .nargs = 4,
412 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
413 { .name = "rfork", .ret_type = 1, .nargs = 1,
414 .args = { { Rforkflags, 0 } } },
415 { .name = "rmdir", .ret_type = 1, .nargs = 1,
416 .args = { { Name, 0 } } },
417 { .name = "rtprio", .ret_type = 1, .nargs = 3,
418 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
419 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
420 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
421 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
422 .args = { { Schedpolicy, 0 } } },
423 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
424 .args = { { Schedpolicy, 0 } } },
425 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
426 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
427 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
428 .args = { { Int, 0 } } },
429 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
430 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
431 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
432 .args = { { Int, 0 }, { Schedparam, 1 } } },
433 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
434 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
435 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
436 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
437 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
438 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
439 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
440 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
441 { Sockaddr | IN, 3 }, { Socklent, 4 },
442 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
443 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
444 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
445 { Sockaddr | IN, 3 }, { Socklent, 4 },
446 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
447 { .name = "select", .ret_type = 1, .nargs = 5,
448 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
450 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
451 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
452 { .name = "sendto", .ret_type = 1, .nargs = 6,
453 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
454 { Msgflags, 3 }, { Sockaddr | IN, 4 },
455 { Socklent | IN, 5 } } },
456 { .name = "setitimer", .ret_type = 1, .nargs = 3,
457 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
458 { .name = "setpriority", .ret_type = 1, .nargs = 3,
459 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
460 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
461 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
462 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
463 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
464 { Ptr | IN, 3 }, { Socklent, 4 } } },
465 { .name = "shm_open", .ret_type = 1, .nargs = 3,
466 .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
467 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
468 .args = { { Name | IN, 0 } } },
469 { .name = "shutdown", .ret_type = 1, .nargs = 2,
470 .args = { { Int, 0 }, { Shutdown, 1 } } },
471 { .name = "sigaction", .ret_type = 1, .nargs = 3,
472 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
473 { Sigaction | OUT, 2 } } },
474 { .name = "sigpending", .ret_type = 1, .nargs = 1,
475 .args = { { Sigset | OUT, 0 } } },
476 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
477 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
478 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
479 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
480 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
481 .args = { { Ptr, 0 } } },
482 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
483 .args = { { Sigset | IN, 0 } } },
484 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
485 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
486 { Timespec | IN, 2 } } },
487 { .name = "sigwait", .ret_type = 1, .nargs = 2,
488 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
489 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
490 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
491 { .name = "socket", .ret_type = 1, .nargs = 3,
492 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
493 { .name = "stat", .ret_type = 1, .nargs = 2,
494 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
495 { .name = "statfs", .ret_type = 1, .nargs = 2,
496 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
497 { .name = "symlink", .ret_type = 1, .nargs = 2,
498 .args = { { Name, 0 }, { Name, 1 } } },
499 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
500 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
501 { .name = "sysarch", .ret_type = 1, .nargs = 2,
502 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
503 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
504 .args = { { Long, 0 }, { Signal, 1 } } },
505 { .name = "thr_self", .ret_type = 1, .nargs = 1,
506 .args = { { Ptr, 0 } } },
507 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
508 .args = { { Long, 0 }, { Name, 1 } } },
509 { .name = "truncate", .ret_type = 1, .nargs = 2,
510 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
513 { .name = "umount", .ret_type = 1, .nargs = 2,
514 .args = { { Name, 0 }, { Int, 2 } } },
516 { .name = "unlink", .ret_type = 1, .nargs = 1,
517 .args = { { Name, 0 } } },
518 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
519 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
520 { .name = "unmount", .ret_type = 1, .nargs = 2,
521 .args = { { Name, 0 }, { Mountflags, 1 } } },
522 { .name = "utimensat", .ret_type = 1, .nargs = 4,
523 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
525 { .name = "utimes", .ret_type = 1, .nargs = 2,
526 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
527 { .name = "utrace", .ret_type = 1, .nargs = 1,
528 .args = { { Utrace, 0 } } },
529 { .name = "wait4", .ret_type = 1, .nargs = 4,
530 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
531 { Rusage | OUT, 3 } } },
532 { .name = "wait6", .ret_type = 1, .nargs = 6,
533 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
534 { Waitoptions, 3 }, { Rusage | OUT, 4 },
535 { Siginfo | OUT, 5 } } },
536 { .name = "write", .ret_type = 1, .nargs = 3,
537 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
538 { .name = "writev", .ret_type = 1, .nargs = 3,
539 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
542 { .name = "linux_access", .ret_type = 1, .nargs = 2,
543 .args = { { Name, 0 }, { Accessmode, 1 } } },
544 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
545 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
546 { ExecEnv | IN, 2 } } },
547 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
548 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
549 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
550 .args = { { Name | IN, 0 }, { Int, 1 } } },
551 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
552 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
553 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
554 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
555 { .name = "linux_open", .ret_type = 1, .nargs = 3,
556 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
557 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
558 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
559 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
560 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
561 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
562 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
564 /* CloudABI system calls. */
565 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
566 .args = { { CloudABIClockID, 0 } } },
567 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
568 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
569 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
570 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
571 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
572 .args = { { Int, 0 } } },
573 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
574 .args = { { CloudABIFileType, 0 } } },
575 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
576 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
577 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
578 .args = { { Int, 0 } } },
579 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
580 .args = { { Int, 0 } } },
581 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
582 .args = { { Int, 0 }, { Int, 1 } } },
583 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
584 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
585 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
586 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
587 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
588 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
589 { CloudABIFDSFlags, 2 } } },
590 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
591 .args = { { Int, 0 } } },
592 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
593 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
594 { CloudABIAdvice, 3 } } },
595 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
596 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
597 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
598 .args = { { Int, 0 }, { BinString | IN, 1 },
599 { CloudABIFileType, 3 } } },
600 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
601 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
602 { Int, 3 }, { BinString | IN, 4 } } },
603 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
604 .args = { { Int, 0 }, { BinString | IN, 1 },
605 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
606 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
607 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
609 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
610 .args = { { Int, 0 }, { BinString | IN, 1 },
611 { BinString | OUT, 3 }, { Int, 4 } } },
612 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
613 .args = { { Int, 0 }, { BinString | IN, 1 },
614 { Int, 3 }, { BinString | IN, 4 } } },
615 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
616 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
617 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
618 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
619 { CloudABIFSFlags, 2 } } },
620 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
621 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
622 { CloudABIFileStat | OUT, 3 } } },
623 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
624 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
625 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
626 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
627 .args = { { BinString | IN, 0 },
628 { Int, 2 }, { BinString | IN, 3 } } },
629 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
630 .args = { { Int, 0 }, { BinString | IN, 1 },
631 { CloudABIULFlags, 3 } } },
632 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
633 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
634 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
635 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
636 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
637 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
638 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
639 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
640 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
641 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
642 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
643 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
644 .args = { { Ptr, 0 }, { Int, 1 } } },
645 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
646 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
647 { IntArray, 3 }, { Int, 4 } } },
648 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
649 .args = { { Int, 0 } } },
650 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
651 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
652 .args = { { CloudABISignal, 0 } } },
653 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
654 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
655 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
656 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
657 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
658 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
659 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
663 static STAILQ_HEAD(, syscall) syscalls;
665 /* Xlat idea taken from strace */
671 #define X(a) { a, #a },
672 #define XEND { 0, NULL }
674 static struct xlat poll_flags[] = {
675 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
676 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
677 X(POLLWRBAND) X(POLLINIGNEOF) XEND
680 static struct xlat sigaction_flags[] = {
681 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
682 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
685 static struct xlat linux_socketcall_ops[] = {
686 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
687 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
688 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
689 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
690 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
695 #define X(a) { CLOUDABI_##a, #a },
697 static struct xlat cloudabi_advice[] = {
698 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
699 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
703 static struct xlat cloudabi_clockid[] = {
704 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
705 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
709 static struct xlat cloudabi_fdflags[] = {
710 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
711 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
715 static struct xlat cloudabi_fdsflags[] = {
716 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
720 static struct xlat cloudabi_filetype[] = {
721 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
722 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
723 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
724 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
725 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
729 static struct xlat cloudabi_fsflags[] = {
730 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
731 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
735 static struct xlat cloudabi_mflags[] = {
736 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
740 static struct xlat cloudabi_mprot[] = {
741 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
745 static struct xlat cloudabi_msflags[] = {
746 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
750 static struct xlat cloudabi_oflags[] = {
751 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
755 static struct xlat cloudabi_sdflags[] = {
756 X(SHUT_RD) X(SHUT_WR)
760 static struct xlat cloudabi_signal[] = {
761 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
762 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
763 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
764 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
765 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
769 static struct xlat cloudabi_ulflags[] = {
774 static struct xlat cloudabi_whence[] = {
775 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
783 * Searches an xlat array for a value, and returns it if found. Otherwise
784 * return a string representation.
787 lookup(struct xlat *xlat, int val, int base)
791 for (; xlat->str != NULL; xlat++)
792 if (xlat->val == val)
796 sprintf(tmp, "0%o", val);
799 sprintf(tmp, "0x%x", val);
802 sprintf(tmp, "%u", val);
805 errx(1,"Unknown lookup base");
812 xlookup(struct xlat *xlat, int val)
815 return (lookup(xlat, val, 16));
819 * Searches an xlat array containing bitfield values. Remaining bits
820 * set after removing the known ones are printed at the end:
824 xlookup_bits(struct xlat *xlat, int val)
827 static char str[512];
831 for (; xlat->str != NULL; xlat++) {
832 if ((xlat->val & rem) == xlat->val) {
834 * Don't print the "all-bits-zero" string unless all
835 * bits are really zero.
837 if (xlat->val == 0 && val != 0)
839 len += sprintf(str + len, "%s|", xlat->str);
845 * If we have leftover bits or didn't match anything, print
849 len += sprintf(str + len, "0x%x", rem);
850 if (len && str[len - 1] == '|')
857 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
861 str = decoder(value);
865 fprintf(fp, "%d", value);
869 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
873 if (!decoder(fp, value, &rem))
874 fprintf(fp, "0x%x", rem);
876 fprintf(fp, "|0x%x", rem);
880 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
885 if (!decoder(fp, value, &rem))
886 fprintf(fp, "0x%x", rem);
888 fprintf(fp, "|0x%x", rem);
893 * Add argument padding to subsequent system calls afater a Quad
894 * syscall arguments as needed. This used to be done by hand in the
895 * decoded_syscalls table which was ugly and error prone. It is
896 * simpler to do the fixup of offsets at initalization time than when
897 * decoding arguments.
900 quad_fixup(struct syscall *sc)
907 for (i = 0; i < sc->nargs; i++) {
908 /* This arg type is a dummy that doesn't use offset. */
909 if ((sc->args[i].type & ARG_MASK) == PipeFds)
912 assert(prev < sc->args[i].offset);
913 prev = sc->args[i].offset;
914 sc->args[i].offset += offset;
915 switch (sc->args[i].type & ARG_MASK) {
920 * 64-bit arguments on 32-bit powerpc must be
921 * 64-bit aligned. If the current offset is
922 * not aligned, the calling convention inserts
923 * a 32-bit pad argument that should be skipped.
925 if (sc->args[i].offset % 2 == 1) {
926 sc->args[i].offset++;
943 STAILQ_INIT(&syscalls);
944 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
948 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
952 static struct syscall *
953 find_syscall(struct procabi *abi, u_int number)
955 struct extra_syscall *es;
957 if (number < nitems(abi->syscalls))
958 return (abi->syscalls[number]);
959 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
960 if (es->number == number)
967 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
969 struct extra_syscall *es;
971 if (number < nitems(abi->syscalls)) {
972 assert(abi->syscalls[number] == NULL);
973 abi->syscalls[number] = sc;
975 es = malloc(sizeof(*es));
978 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
983 * If/when the list gets big, it might be desirable to do it
984 * as a hash table or binary search.
987 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
994 sc = find_syscall(t->proc->abi, number);
998 name = sysdecode_syscallname(t->proc->abi->abi, number);
1000 asprintf(&new_name, "#%d", number);
1004 STAILQ_FOREACH(sc, &syscalls, entries) {
1005 if (strcmp(name, sc->name) == 0) {
1006 add_syscall(t->proc->abi, number, sc);
1012 /* It is unknown. Add it into the list. */
1014 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1018 sc = calloc(1, sizeof(struct syscall));
1020 if (new_name != NULL)
1024 for (i = 0; i < nargs; i++) {
1025 sc->args[i].offset = i;
1026 /* Treat all unknown arguments as LongHex. */
1027 sc->args[i].type = LongHex;
1029 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1030 add_syscall(t->proc->abi, number, sc);
1036 * Copy a fixed amount of bytes from the process.
1039 get_struct(pid_t pid, void *offset, void *buf, int len)
1041 struct ptrace_io_desc iorequest;
1043 iorequest.piod_op = PIOD_READ_D;
1044 iorequest.piod_offs = offset;
1045 iorequest.piod_addr = buf;
1046 iorequest.piod_len = len;
1047 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1052 #define MAXSIZE 4096
1055 * Copy a string from the process. Note that it is
1056 * expected to be a C string, but if max is set, it will
1057 * only get that much.
1060 get_string(pid_t pid, void *addr, int max)
1062 struct ptrace_io_desc iorequest;
1064 size_t offset, size, totalsize;
1070 /* Read up to the end of the current page. */
1071 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1076 buf = malloc(totalsize);
1080 iorequest.piod_op = PIOD_READ_D;
1081 iorequest.piod_offs = (char *)addr + offset;
1082 iorequest.piod_addr = buf + offset;
1083 iorequest.piod_len = size;
1084 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1088 if (memchr(buf + offset, '\0', size) != NULL)
1091 if (totalsize < MAXSIZE && max == 0) {
1092 size = MAXSIZE - totalsize;
1093 if (size > PAGE_SIZE)
1095 nbuf = realloc(buf, totalsize + size);
1097 buf[totalsize - 1] = '\0';
1103 buf[totalsize - 1] = '\0';
1112 static char tmp[32];
1113 const char *signame;
1115 signame = sysdecode_signal(sig);
1116 if (signame == NULL) {
1117 snprintf(tmp, sizeof(tmp), "%d", sig);
1124 print_kevent(FILE *fp, struct kevent *ke)
1127 switch (ke->filter) {
1133 case EVFILT_PROCDESC:
1135 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1138 fputs(strsig2(ke->ident), fp);
1141 fprintf(fp, "%p", (void *)ke->ident);
1144 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1146 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1148 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1149 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1153 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1155 unsigned char *utrace_buffer;
1158 if (sysdecode_utrace(fp, utrace_addr, len)) {
1163 utrace_buffer = utrace_addr;
1164 fprintf(fp, "%zu:", len);
1166 fprintf(fp, " %02x", *utrace_buffer++);
1171 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1174 struct sockaddr_in *lsin;
1175 struct sockaddr_in6 *lsin6;
1176 struct sockaddr_un *sun;
1177 struct sockaddr *sa;
1179 pid_t pid = trussinfo->curthread->proc->pid;
1185 /* If the length is too small, just bail. */
1186 if (len < sizeof(*sa)) {
1187 fprintf(fp, "%p", arg);
1191 sa = calloc(1, len);
1192 if (get_struct(pid, arg, sa, len) == -1) {
1194 fprintf(fp, "%p", arg);
1198 switch (sa->sa_family) {
1200 if (len < sizeof(*lsin))
1201 goto sockaddr_short;
1202 lsin = (struct sockaddr_in *)(void *)sa;
1203 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1204 fprintf(fp, "{ AF_INET %s:%d }", addr,
1205 htons(lsin->sin_port));
1208 if (len < sizeof(*lsin6))
1209 goto sockaddr_short;
1210 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1211 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1213 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1214 htons(lsin6->sin6_port));
1217 sun = (struct sockaddr_un *)sa;
1218 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1219 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1225 "{ sa_len = %d, sa_family = %d, sa_data = {",
1226 (int)sa->sa_len, (int)sa->sa_family);
1227 for (q = (u_char *)sa->sa_data;
1228 q < (u_char *)sa + len; q++)
1229 fprintf(fp, "%s 0x%02x",
1230 q == (u_char *)sa->sa_data ? "" : ",",
1237 #define IOV_LIMIT 16
1240 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1242 struct iovec iov[IOV_LIMIT];
1243 size_t max_string = trussinfo->strsize;
1244 char tmp2[max_string + 1], *tmp3;
1246 pid_t pid = trussinfo->curthread->proc->pid;
1248 bool buf_truncated, iov_truncated;
1251 fprintf(fp, "%p", arg);
1254 if (iovcnt > IOV_LIMIT) {
1256 iov_truncated = true;
1258 iov_truncated = false;
1260 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1261 fprintf(fp, "%p", arg);
1266 for (i = 0; i < iovcnt; i++) {
1267 len = iov[i].iov_len;
1268 if (len > max_string) {
1270 buf_truncated = true;
1272 buf_truncated = false;
1274 fprintf(fp, "%s{", (i > 0) ? "," : "");
1275 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1276 tmp3 = malloc(len * 4 + 1);
1278 if (strvisx(tmp3, tmp2, len,
1279 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1283 buf_truncated = true;
1285 fprintf(fp, "\"%s\"%s", tmp3,
1286 buf_truncated ? "..." : "");
1289 fprintf(fp, "%p", iov[i].iov_base);
1291 fprintf(fp, ",%zu}", iov[i].iov_len);
1293 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1297 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1302 for (q = CMSG_DATA(cmsghdr);
1303 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1304 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1310 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1312 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1313 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1314 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1315 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1319 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1321 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1323 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1326 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1327 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1329 fprintf(fp, "ctx=%u,", info->sinfo_context);
1330 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1333 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1334 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1336 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1340 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1342 fprintf(fp, "{sid=%u,", info->snd_sid);
1344 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1345 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1346 fprintf(fp, "ctx=%u,", info->snd_context);
1347 fprintf(fp, "id=%u}", info->snd_assoc_id);
1351 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1353 fprintf(fp, "{sid=%u,", info->rcv_sid);
1354 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1356 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1357 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1358 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1359 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1360 fprintf(fp, "ctx=%u,", info->rcv_context);
1361 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1365 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1367 fprintf(fp, "{sid=%u,", info->nxt_sid);
1369 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1370 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1371 fprintf(fp, "len=%u,", info->nxt_length);
1372 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1376 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1379 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1380 fprintf(fp, ",val=%u}", info->pr_value);
1384 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1386 fprintf(fp, "{num=%u}", info->auth_keynumber);
1390 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1392 char buf[INET_ADDRSTRLEN];
1395 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1397 fprintf(fp, "{addr=%s}", s);
1399 fputs("{addr=???}", fp);
1403 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1405 char buf[INET6_ADDRSTRLEN];
1408 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1410 fprintf(fp, "{addr=%s}", s);
1412 fputs("{addr=???}", fp);
1416 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1421 len = cmsghdr->cmsg_len;
1422 data = CMSG_DATA(cmsghdr);
1423 switch (cmsghdr->cmsg_type) {
1425 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1426 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1428 print_gen_cmsg(fp, cmsghdr);
1431 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1432 print_sctp_sndrcvinfo(fp, receive,
1433 (struct sctp_sndrcvinfo *)data);
1435 print_gen_cmsg(fp, cmsghdr);
1439 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1440 print_sctp_extrcvinfo(fp,
1441 (struct sctp_extrcvinfo *)data);
1443 print_gen_cmsg(fp, cmsghdr);
1447 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1448 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1450 print_gen_cmsg(fp, cmsghdr);
1453 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1454 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1456 print_gen_cmsg(fp, cmsghdr);
1459 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1460 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1462 print_gen_cmsg(fp, cmsghdr);
1465 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1466 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1468 print_gen_cmsg(fp, cmsghdr);
1471 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1472 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1474 print_gen_cmsg(fp, cmsghdr);
1476 case SCTP_DSTADDRV4:
1477 if (len == CMSG_LEN(sizeof(struct in_addr)))
1478 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1480 print_gen_cmsg(fp, cmsghdr);
1482 case SCTP_DSTADDRV6:
1483 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1484 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1486 print_gen_cmsg(fp, cmsghdr);
1489 print_gen_cmsg(fp, cmsghdr);
1494 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1496 struct cmsghdr *cmsghdr;
1503 len = msghdr->msg_controllen;
1508 cmsgbuf = calloc(1, len);
1509 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1510 fprintf(fp, "%p", msghdr->msg_control);
1514 msghdr->msg_control = cmsgbuf;
1517 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1519 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1520 level = cmsghdr->cmsg_level;
1521 type = cmsghdr->cmsg_type;
1522 len = cmsghdr->cmsg_len;
1523 fprintf(fp, "%s{level=", first ? "" : ",");
1524 print_integer_arg(sysdecode_sockopt_level, fp, level);
1525 fputs(",type=", fp);
1526 temp = sysdecode_cmsg_type(level, type);
1530 fprintf(fp, "%d", type);
1532 fputs(",data=", fp);
1535 print_sctp_cmsg(fp, receive, cmsghdr);
1538 print_gen_cmsg(fp, cmsghdr);
1549 * Converts a syscall argument into a string. Said string is
1550 * allocated via malloc(), so needs to be free()'d. sc is
1551 * a pointer to the syscall description (see above); args is
1552 * an array of all of the system call arguments.
1555 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1556 struct trussinfo *trussinfo)
1563 fp = open_memstream(&tmp, &tmplen);
1564 pid = trussinfo->curthread->proc->pid;
1565 switch (sc->type & ARG_MASK) {
1567 fprintf(fp, "0x%x", (int)args[sc->offset]);
1570 fprintf(fp, "0%o", (int)args[sc->offset]);
1573 fprintf(fp, "%d", (int)args[sc->offset]);
1576 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1581 if (get_struct(pid, (void *)args[sc->offset], &val,
1583 fprintf(fp, "{ %u }", val);
1585 fprintf(fp, "0x%lx", args[sc->offset]);
1589 fprintf(fp, "0x%lx", args[sc->offset]);
1592 fprintf(fp, "%ld", args[sc->offset]);
1595 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1598 /* Handle special SHM_ANON value. */
1599 if ((char *)args[sc->offset] == SHM_ANON) {
1600 fprintf(fp, "SHM_ANON");
1605 /* NULL-terminated string. */
1608 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1609 fprintf(fp, "\"%s\"", tmp2);
1615 * Binary block of data that might have printable characters.
1616 * XXX If type|OUT, assume that the length is the syscall's
1617 * return value. Otherwise, assume that the length of the block
1618 * is in the next syscall argument.
1620 int max_string = trussinfo->strsize;
1621 char tmp2[max_string + 1], *tmp3;
1628 len = args[sc->offset + 1];
1631 * Don't print more than max_string characters, to avoid word
1632 * wrap. If we have to truncate put some ... after the string.
1634 if (len > max_string) {
1638 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1640 tmp3 = malloc(len * 4 + 1);
1642 if (strvisx(tmp3, tmp2, len,
1643 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1648 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1652 fprintf(fp, "0x%lx", args[sc->offset]);
1662 char buf[PAGE_SIZE];
1669 * Only parse argv[] and environment arrays from exec calls
1672 if (((sc->type & ARG_MASK) == ExecArgs &&
1673 (trussinfo->flags & EXECVEARGS) == 0) ||
1674 ((sc->type & ARG_MASK) == ExecEnv &&
1675 (trussinfo->flags & EXECVEENVS) == 0)) {
1676 fprintf(fp, "0x%lx", args[sc->offset]);
1681 * Read a page of pointers at a time. Punt if the top-level
1682 * pointer is not aligned. Note that the first read is of
1685 addr = args[sc->offset];
1686 if (addr % sizeof(char *) != 0) {
1687 fprintf(fp, "0x%lx", args[sc->offset]);
1691 len = PAGE_SIZE - (addr & PAGE_MASK);
1692 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1693 fprintf(fp, "0x%lx", args[sc->offset]);
1700 while (u.strarray[i] != NULL) {
1701 string = get_string(pid, u.strarray[i], 0);
1702 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1707 if (i == len / sizeof(char *)) {
1710 if (get_struct(pid, (void *)addr, u.buf, len) ==
1712 fprintf(fp, ", <inval>");
1723 fprintf(fp, "%ld", args[sc->offset]);
1726 fprintf(fp, "0x%lx", args[sc->offset]);
1731 unsigned long long ll;
1733 #if _BYTE_ORDER == _LITTLE_ENDIAN
1734 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1737 ll = (unsigned long long)args[sc->offset] << 32 |
1738 args[sc->offset + 1];
1740 if ((sc->type & ARG_MASK) == Quad)
1741 fprintf(fp, "%lld", ll);
1743 fprintf(fp, "0x%llx", ll);
1750 if (get_struct(pid, (void *)args[sc->offset], &val,
1752 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1754 fprintf(fp, "0x%lx", args[sc->offset]);
1758 fprintf(fp, "0x%lx", args[sc->offset]);
1763 if (retval[0] == -1)
1765 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1766 fprintf(fp, "\"%s\"", tmp2);
1774 cmd = args[sc->offset];
1775 temp = sysdecode_ioctlname(cmd);
1779 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1780 cmd, cmd & IOC_OUT ? "R" : "",
1781 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1782 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1783 cmd & 0xFF, IOCPARM_LEN(cmd));
1790 if (get_struct(pid, (void *)args[sc->offset], &ts,
1792 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1795 fprintf(fp, "0x%lx", args[sc->offset]);
1799 struct timespec ts[2];
1803 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1807 for (i = 0; i < nitems(ts); i++) {
1810 switch (ts[i].tv_nsec) {
1812 fprintf(fp, "UTIME_NOW");
1815 fprintf(fp, "UTIME_OMIT");
1818 fprintf(fp, "%jd.%09ld",
1819 (intmax_t)ts[i].tv_sec,
1826 fprintf(fp, "0x%lx", args[sc->offset]);
1832 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1834 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1837 fprintf(fp, "0x%lx", args[sc->offset]);
1841 struct timeval tv[2];
1843 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1845 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1846 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1847 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1849 fprintf(fp, "0x%lx", args[sc->offset]);
1853 struct itimerval itv;
1855 if (get_struct(pid, (void *)args[sc->offset], &itv,
1857 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1858 (intmax_t)itv.it_interval.tv_sec,
1859 itv.it_interval.tv_usec,
1860 (intmax_t)itv.it_value.tv_sec,
1861 itv.it_value.tv_usec);
1863 fprintf(fp, "0x%lx", args[sc->offset]);
1868 struct linux_socketcall_args largs;
1870 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1871 sizeof(largs)) != -1)
1872 fprintf(fp, "{ %s, 0x%lx }",
1873 lookup(linux_socketcall_ops, largs.what, 10),
1874 (long unsigned int)largs.args);
1876 fprintf(fp, "0x%lx", args[sc->offset]);
1881 * XXX: A Pollfd argument expects the /next/ syscall argument
1882 * to be the number of fds in the array. This matches the poll
1886 int numfds = args[sc->offset + 1];
1887 size_t bytes = sizeof(struct pollfd) * numfds;
1890 if ((pfd = malloc(bytes)) == NULL)
1891 err(1, "Cannot malloc %zu bytes for pollfd array",
1893 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1896 for (i = 0; i < numfds; i++) {
1897 fprintf(fp, " %d/%s", pfd[i].fd,
1898 xlookup_bits(poll_flags, pfd[i].events));
1902 fprintf(fp, "0x%lx", args[sc->offset]);
1909 * XXX: A Fd_set argument expects the /first/ syscall argument
1910 * to be the number of fds in the array. This matches the
1914 int numfds = args[0];
1915 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1918 if ((fds = malloc(bytes)) == NULL)
1919 err(1, "Cannot malloc %zu bytes for fd_set array",
1921 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1924 for (i = 0; i < numfds; i++) {
1925 if (FD_ISSET(i, fds))
1926 fprintf(fp, " %d", i);
1930 fprintf(fp, "0x%lx", args[sc->offset]);
1935 fputs(strsig2(args[sc->offset]), fp);
1942 sig = args[sc->offset];
1943 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1944 sizeof(ss)) == -1) {
1945 fprintf(fp, "0x%lx", args[sc->offset]);
1950 for (i = 1; i < sys_nsig; i++) {
1951 if (sigismember(&ss, i)) {
1952 fprintf(fp, "%s%s", !first ? "|" : "",
1963 print_integer_arg(sysdecode_sigprocmask_how, fp,
1967 /* XXX: Output depends on the value of the previous argument. */
1968 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1969 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1970 args[sc->offset], 16);
1973 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1976 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1979 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1982 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1985 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1988 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1991 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1994 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1997 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
2000 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
2003 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
2006 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2011 if (args[sc->offset] == 0) {
2017 * Extract the address length from the next argument. If
2018 * this is an output sockaddr (OUT is set), then the
2019 * next argument is a pointer to a socklen_t. Otherwise
2020 * the next argument contains a socklen_t by value.
2022 if (sc->type & OUT) {
2023 if (get_struct(pid, (void *)args[sc->offset + 1],
2024 &len, sizeof(len)) == -1) {
2025 fprintf(fp, "0x%lx", args[sc->offset]);
2029 len = args[sc->offset + 1];
2031 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2035 struct sigaction sa;
2037 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2040 if (sa.sa_handler == SIG_DFL)
2041 fputs("SIG_DFL", fp);
2042 else if (sa.sa_handler == SIG_IGN)
2043 fputs("SIG_IGN", fp);
2045 fprintf(fp, "%p", sa.sa_handler);
2046 fprintf(fp, " %s ss_t }",
2047 xlookup_bits(sigaction_flags, sa.sa_flags));
2049 fprintf(fp, "0x%lx", args[sc->offset]);
2054 * XXX XXX: The size of the array is determined by either the
2055 * next syscall argument, or by the syscall return value,
2056 * depending on which argument number we are. This matches the
2057 * kevent syscall, but luckily that's the only syscall that uses
2065 if (sc->offset == 1)
2066 numevents = args[sc->offset+1];
2067 else if (sc->offset == 3 && retval[0] != -1)
2068 numevents = retval[0];
2070 if (numevents >= 0) {
2071 bytes = sizeof(struct kevent) * numevents;
2072 if ((ke = malloc(bytes)) == NULL)
2074 "Cannot malloc %zu bytes for kevent array",
2078 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2081 for (i = 0; i < numevents; i++) {
2083 print_kevent(fp, &ke[i]);
2087 fprintf(fp, "0x%lx", args[sc->offset]);
2093 struct kevent_freebsd11 *ke11;
2099 if (sc->offset == 1)
2100 numevents = args[sc->offset+1];
2101 else if (sc->offset == 3 && retval[0] != -1)
2102 numevents = retval[0];
2104 if (numevents >= 0) {
2105 bytes = sizeof(struct kevent_freebsd11) * numevents;
2106 if ((ke11 = malloc(bytes)) == NULL)
2108 "Cannot malloc %zu bytes for kevent array",
2112 memset(&ke, 0, sizeof(ke));
2113 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2114 ke11, bytes) != -1) {
2116 for (i = 0; i < numevents; i++) {
2118 ke.ident = ke11[i].ident;
2119 ke.filter = ke11[i].filter;
2120 ke.flags = ke11[i].flags;
2121 ke.fflags = ke11[i].fflags;
2122 ke.data = ke11[i].data;
2123 ke.udata = ke11[i].udata;
2124 print_kevent(fp, &ke);
2128 fprintf(fp, "0x%lx", args[sc->offset]);
2136 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2140 strmode(st.st_mode, mode);
2142 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2143 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2144 (long)st.st_blksize);
2146 fprintf(fp, "0x%lx", args[sc->offset]);
2151 struct freebsd11_stat st;
2153 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2157 strmode(st.st_mode, mode);
2159 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2160 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2161 (long)st.st_blksize);
2163 fprintf(fp, "0x%lx", args[sc->offset]);
2171 if (get_struct(pid, (void *)args[sc->offset], &buf,
2172 sizeof(buf)) != -1) {
2175 bzero(fsid, sizeof(fsid));
2176 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2177 for (i = 0; i < sizeof(buf.f_fsid); i++)
2178 snprintf(&fsid[i*2],
2179 sizeof(fsid) - (i*2), "%02x",
2180 ((u_char *)&buf.f_fsid)[i]);
2183 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2184 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2185 buf.f_mntfromname, fsid);
2187 fprintf(fp, "0x%lx", args[sc->offset]);
2194 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2197 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2198 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2199 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2200 ru.ru_inblock, ru.ru_oublock);
2202 fprintf(fp, "0x%lx", args[sc->offset]);
2208 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2210 fprintf(fp, "{ cur=%ju,max=%ju }",
2211 rl.rlim_cur, rl.rlim_max);
2213 fprintf(fp, "0x%lx", args[sc->offset]);
2219 if (get_struct(pid, (void *)args[sc->offset], &status,
2220 sizeof(status)) != -1) {
2222 if (WIFCONTINUED(status))
2223 fputs("CONTINUED", fp);
2224 else if (WIFEXITED(status))
2225 fprintf(fp, "EXITED,val=%d",
2226 WEXITSTATUS(status));
2227 else if (WIFSIGNALED(status))
2228 fprintf(fp, "SIGNALED,sig=%s%s",
2229 strsig2(WTERMSIG(status)),
2230 WCOREDUMP(status) ? ",cored" : "");
2232 fprintf(fp, "STOPPED,sig=%s",
2233 strsig2(WTERMSIG(status)));
2236 fprintf(fp, "0x%lx", args[sc->offset]);
2240 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2243 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2246 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2249 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2252 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2255 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2258 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2261 print_integer_arg(sysdecode_sysarch_number, fp,
2266 * The pipe() system call in the kernel returns its
2267 * two file descriptors via return values. However,
2268 * the interface exposed by libc is that pipe()
2269 * accepts a pointer to an array of descriptors.
2270 * Format the output to match the libc API by printing
2271 * the returned file descriptors as a fake argument.
2273 * Overwrite the first retval to signal a successful
2276 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
2283 len = args[sc->offset + 1];
2284 utrace_addr = calloc(1, len);
2285 if (get_struct(pid, (void *)args[sc->offset],
2286 (void *)utrace_addr, len) != -1)
2287 print_utrace(fp, utrace_addr, len);
2289 fprintf(fp, "0x%lx", args[sc->offset]);
2294 int descriptors[16];
2295 unsigned long i, ndescriptors;
2298 ndescriptors = args[sc->offset + 1];
2300 if (ndescriptors > nitems(descriptors)) {
2301 ndescriptors = nitems(descriptors);
2304 if (get_struct(pid, (void *)args[sc->offset],
2305 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2307 for (i = 0; i < ndescriptors; i++)
2308 fprintf(fp, i == 0 ? " %d" : ", %d",
2310 fprintf(fp, truncated ? ", ... }" : " }");
2312 fprintf(fp, "0x%lx", args[sc->offset]);
2316 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2318 case CapFcntlRights: {
2321 if (sc->type & OUT) {
2322 if (get_struct(pid, (void *)args[sc->offset], &rights,
2323 sizeof(rights)) == -1) {
2324 fprintf(fp, "0x%lx", args[sc->offset]);
2328 rights = args[sc->offset];
2329 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2333 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2338 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2339 fprintf(fp, "0x%x", rem);
2341 fprintf(fp, "|0x%x", rem);
2345 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2348 print_integer_arg(sysdecode_getfsstat_mode, fp,
2352 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2354 case Kldunloadflags:
2355 print_integer_arg(sysdecode_kldunload_flags, fp,
2359 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2362 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2364 case Sockprotocol: {
2366 int domain, protocol;
2368 domain = args[sc->offset - 2];
2369 protocol = args[sc->offset];
2370 if (protocol == 0) {
2373 temp = sysdecode_socket_protocol(domain, protocol);
2377 fprintf(fp, "%d", protocol);
2383 print_integer_arg(sysdecode_sockopt_level, fp,
2390 level = args[sc->offset - 1];
2391 name = args[sc->offset];
2392 temp = sysdecode_sockopt_name(level, name);
2396 fprintf(fp, "%d", name);
2401 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2404 cap_rights_t rights;
2406 if (get_struct(pid, (void *)args[sc->offset], &rights,
2407 sizeof(rights)) != -1) {
2409 sysdecode_cap_rights(fp, &rights);
2412 fprintf(fp, "0x%lx", args[sc->offset]);
2416 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2418 case Extattrnamespace:
2419 print_integer_arg(sysdecode_extattrnamespace, fp,
2423 print_integer_arg(sysdecode_minherit_inherit, fp,
2427 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2430 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2433 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2436 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2439 print_integer_arg(sysdecode_ptrace_request, fp,
2443 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2444 fprintf(fp, "%#x", (int)args[sc->offset]);
2447 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2450 print_integer_arg(sysdecode_rtprio_function, fp,
2454 print_integer_arg(sysdecode_scheduler_policy, fp,
2458 struct sched_param sp;
2460 if (get_struct(pid, (void *)args[sc->offset], &sp,
2462 fprintf(fp, "{ %d }", sp.sched_priority);
2464 fprintf(fp, "0x%lx", args[sc->offset]);
2470 if (get_struct(pid, (void *)args[sc->offset], &sig,
2472 fprintf(fp, "{ %s }", strsig2(sig));
2474 fprintf(fp, "0x%lx", args[sc->offset]);
2480 if (get_struct(pid, (void *)args[sc->offset], &si,
2481 sizeof(si)) != -1) {
2482 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2483 decode_siginfo(fp, &si);
2486 fprintf(fp, "0x%lx", args[sc->offset]);
2491 * Print argument as an array of struct iovec, where the next
2492 * syscall argument is the number of elements of the array.
2495 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2496 (int)args[sc->offset + 1]);
2498 case Sctpsndrcvinfo: {
2499 struct sctp_sndrcvinfo info;
2501 if (get_struct(pid, (void *)args[sc->offset],
2502 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2503 fprintf(fp, "0x%lx", args[sc->offset]);
2506 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2510 struct msghdr msghdr;
2512 if (get_struct(pid, (void *)args[sc->offset],
2513 &msghdr, sizeof(struct msghdr)) == -1) {
2514 fprintf(fp, "0x%lx", args[sc->offset]);
2518 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2519 fprintf(fp, ",%d,", msghdr.msg_namelen);
2520 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2521 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2522 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2523 fprintf(fp, ",%u,", msghdr.msg_controllen);
2524 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2529 case CloudABIAdvice:
2530 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2532 case CloudABIClockID:
2533 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2535 case CloudABIFDSFlags:
2536 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2538 case CloudABIFDStat: {
2539 cloudabi_fdstat_t fds;
2540 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2542 fprintf(fp, "{ %s, ",
2543 xlookup(cloudabi_filetype, fds.fs_filetype));
2544 fprintf(fp, "%s, ... }",
2545 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2547 fprintf(fp, "0x%lx", args[sc->offset]);
2550 case CloudABIFileStat: {
2551 cloudabi_filestat_t fsb;
2552 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2554 fprintf(fp, "{ %s, %ju }",
2555 xlookup(cloudabi_filetype, fsb.st_filetype),
2556 (uintmax_t)fsb.st_size);
2558 fprintf(fp, "0x%lx", args[sc->offset]);
2561 case CloudABIFileType:
2562 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2564 case CloudABIFSFlags:
2565 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2567 case CloudABILookup:
2568 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2569 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2570 (int)args[sc->offset]);
2572 fprintf(fp, "%d", (int)args[sc->offset]);
2574 case CloudABIMFlags:
2575 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2578 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2580 case CloudABIMSFlags:
2581 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2583 case CloudABIOFlags:
2584 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2586 case CloudABISDFlags:
2587 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2589 case CloudABISignal:
2590 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2592 case CloudABITimestamp:
2593 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2594 args[sc->offset] % 1000000000);
2596 case CloudABIULFlags:
2597 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2599 case CloudABIWhence:
2600 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2604 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2611 * Print (to outfile) the system call and its arguments.
2614 print_syscall(struct trussinfo *trussinfo)
2616 struct threadinfo *t;
2621 t = trussinfo->curthread;
2623 name = t->cs.sc->name;
2624 nargs = t->cs.nargs;
2625 s_args = t->cs.s_args;
2627 len = print_line_prefix(trussinfo);
2628 len += fprintf(trussinfo->outfile, "%s(", name);
2630 for (i = 0; i < nargs; i++) {
2631 if (s_args[i] != NULL)
2632 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2634 len += fprintf(trussinfo->outfile,
2635 "<missing argument>");
2636 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2639 len += fprintf(trussinfo->outfile, ")");
2640 for (i = 0; i < 6 - (len / 8); i++)
2641 fprintf(trussinfo->outfile, "\t");
2645 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2647 struct timespec timediff;
2648 struct threadinfo *t;
2652 t = trussinfo->curthread;
2654 if (trussinfo->flags & COUNTONLY) {
2655 timespecsub(&t->after, &t->before, &timediff);
2656 timespecadd(&sc->time, &timediff, &sc->time);
2663 print_syscall(trussinfo);
2664 fflush(trussinfo->outfile);
2666 if (retval == NULL) {
2668 * This system call resulted in the current thread's exit,
2669 * so there is no return value or error to display.
2671 fprintf(trussinfo->outfile, "\n");
2676 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2678 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2679 error == INT_MAX ? "Unknown error" : strerror(error));
2682 else if (sc->ret_type == 2) {
2685 #if _BYTE_ORDER == _LITTLE_ENDIAN
2686 off = (off_t)retval[1] << 32 | retval[0];
2688 off = (off_t)retval[0] << 32 | retval[1];
2690 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2695 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2700 print_summary(struct trussinfo *trussinfo)
2702 struct timespec total = {0, 0};
2706 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2707 "syscall", "seconds", "calls", "errors");
2709 STAILQ_FOREACH(sc, &syscalls, entries)
2711 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2712 sc->name, (intmax_t)sc->time.tv_sec,
2713 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2714 timespecadd(&total, &sc->time, &total);
2715 ncall += sc->ncalls;
2716 nerror += sc->nerror;
2718 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2719 "", "-------------", "-------", "-------");
2720 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2721 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);