2 * SPDX-License-Identifier: BSD-4-Clause
4 * Copyright 1997 Sean Eric Fagan
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Sean Eric Fagan
17 * 4. Neither the name of the author may be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * This file has routines used to print out system calls and their
42 #include <sys/capsicum.h>
43 #include <sys/types.h>
44 #define _WANT_FREEBSD11_KEVENT
45 #include <sys/event.h>
46 #include <sys/ioccom.h>
47 #include <sys/mount.h>
48 #include <sys/ptrace.h>
49 #include <sys/resource.h>
50 #include <sys/socket.h>
51 #define _WANT_FREEBSD11_STAT
56 #include <netinet/in.h>
57 #include <netinet/sctp.h>
58 #include <arpa/inet.h>
71 #include <sysdecode.h>
75 #include <contrib/cloudabi/cloudabi_types_common.h>
82 * This should probably be in its own file, sorted alphabetically.
84 static struct syscall decoded_syscalls[] = {
86 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
87 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
88 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
89 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
90 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
91 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
92 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
93 .args = { { Int, 0 }, { Acltype, 1 } } },
94 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
95 .args = { { Name, 0 }, { Acltype, 1 } } },
96 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
97 .args = { { Name, 0 }, { Acltype, 1 } } },
98 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
99 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
100 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
101 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
102 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
103 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
104 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
105 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
106 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
107 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
108 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
109 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
110 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
111 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
112 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
113 .args = { { Name | OUT, 0 }, { Int, 1 } } },
114 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
115 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
117 { .name = "accept", .ret_type = 1, .nargs = 3,
118 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
119 { .name = "access", .ret_type = 1, .nargs = 2,
120 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
121 { .name = "bind", .ret_type = 1, .nargs = 3,
122 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
123 { .name = "bindat", .ret_type = 1, .nargs = 4,
124 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
126 { .name = "break", .ret_type = 1, .nargs = 1,
127 .args = { { Ptr, 0 } } },
128 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
129 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
130 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
131 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
132 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
133 .args = { { PUInt | OUT, 0 } } },
134 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
135 .args = { { Int, 0 }, { CapRights, 1 } } },
136 { .name = "chdir", .ret_type = 1, .nargs = 1,
137 .args = { { Name, 0 } } },
138 { .name = "chflags", .ret_type = 1, .nargs = 2,
139 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
140 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
141 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
143 { .name = "chmod", .ret_type = 1, .nargs = 2,
144 .args = { { Name, 0 }, { Octal, 1 } } },
145 { .name = "chown", .ret_type = 1, .nargs = 3,
146 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
147 { .name = "chroot", .ret_type = 1, .nargs = 1,
148 .args = { { Name, 0 } } },
149 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
150 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
151 { .name = "close", .ret_type = 1, .nargs = 1,
152 .args = { { Int, 0 } } },
153 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
154 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
155 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
156 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
158 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
159 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
160 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
161 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
162 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
163 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
164 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
165 { .name = "connect", .ret_type = 1, .nargs = 3,
166 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
167 { .name = "connectat", .ret_type = 1, .nargs = 4,
168 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
170 { .name = "dup", .ret_type = 1, .nargs = 1,
171 .args = { { Int, 0 } } },
172 { .name = "dup2", .ret_type = 1, .nargs = 2,
173 .args = { { Int, 0 }, { Int, 1 } } },
174 { .name = "eaccess", .ret_type = 1, .nargs = 2,
175 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
176 { .name = "execve", .ret_type = 1, .nargs = 3,
177 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
178 { ExecEnv | IN, 2 } } },
179 { .name = "exit", .ret_type = 0, .nargs = 1,
180 .args = { { Hex, 0 } } },
181 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
182 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
183 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
184 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
185 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
186 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
187 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
188 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
189 { BinString | OUT, 3 }, { Sizet, 4 } } },
190 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
191 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
192 { BinString | OUT, 3 }, { Sizet, 4 } } },
193 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
194 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
195 { BinString | OUT, 3 }, { Sizet, 4 } } },
196 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
197 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
199 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
200 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
202 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
203 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
205 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
206 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
207 { BinString | IN, 3 }, { Sizet, 4 } } },
208 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
209 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
210 { BinString | IN, 3 }, { Sizet, 4 } } },
211 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
212 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
213 { BinString | IN, 3 }, { Sizet, 4 } } },
214 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
215 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
216 { Extattrnamespace, 3 }, { Name, 4 } } },
217 { .name = "faccessat", .ret_type = 1, .nargs = 4,
218 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
220 { .name = "fchflags", .ret_type = 1, .nargs = 2,
221 .args = { { Int, 0 }, { FileFlags, 1 } } },
222 { .name = "fchmod", .ret_type = 1, .nargs = 2,
223 .args = { { Int, 0 }, { Octal, 1 } } },
224 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
225 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
226 { .name = "fchown", .ret_type = 1, .nargs = 3,
227 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
228 { .name = "fchownat", .ret_type = 1, .nargs = 5,
229 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
231 { .name = "fcntl", .ret_type = 1, .nargs = 3,
232 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
233 { .name = "flock", .ret_type = 1, .nargs = 2,
234 .args = { { Int, 0 }, { Flockop, 1 } } },
235 { .name = "fstat", .ret_type = 1, .nargs = 2,
236 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
237 { .name = "fstatat", .ret_type = 1, .nargs = 4,
238 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
240 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
241 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
242 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
243 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
244 { .name = "futimens", .ret_type = 1, .nargs = 2,
245 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
246 { .name = "futimes", .ret_type = 1, .nargs = 2,
247 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
248 { .name = "futimesat", .ret_type = 1, .nargs = 3,
249 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
250 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
251 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
252 { PQuadHex | OUT, 3 } } },
253 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
254 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
255 { .name = "getitimer", .ret_type = 1, .nargs = 2,
256 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
257 { .name = "getpeername", .ret_type = 1, .nargs = 3,
258 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
259 { .name = "getpgid", .ret_type = 1, .nargs = 1,
260 .args = { { Int, 0 } } },
261 { .name = "getpriority", .ret_type = 1, .nargs = 2,
262 .args = { { Priowhich, 0 }, { Int, 1 } } },
263 { .name = "getrandom", .ret_type = 1, .nargs = 3,
264 .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
265 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
266 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
267 { .name = "getrusage", .ret_type = 1, .nargs = 2,
268 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
269 { .name = "getsid", .ret_type = 1, .nargs = 1,
270 .args = { { Int, 0 } } },
271 { .name = "getsockname", .ret_type = 1, .nargs = 3,
272 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
273 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
274 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
275 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
276 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
277 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
278 { .name = "ioctl", .ret_type = 1, .nargs = 3,
279 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
280 { .name = "kevent", .ret_type = 1, .nargs = 6,
281 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
282 { Int, 4 }, { Timespec, 5 } } },
283 { .name = "kill", .ret_type = 1, .nargs = 2,
284 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
285 { .name = "kldfind", .ret_type = 1, .nargs = 1,
286 .args = { { Name | IN, 0 } } },
287 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
288 .args = { { Int, 0 } } },
289 { .name = "kldload", .ret_type = 1, .nargs = 1,
290 .args = { { Name | IN, 0 } } },
291 { .name = "kldnext", .ret_type = 1, .nargs = 1,
292 .args = { { Int, 0 } } },
293 { .name = "kldstat", .ret_type = 1, .nargs = 2,
294 .args = { { Int, 0 }, { Ptr, 1 } } },
295 { .name = "kldsym", .ret_type = 1, .nargs = 3,
296 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
297 { .name = "kldunload", .ret_type = 1, .nargs = 1,
298 .args = { { Int, 0 } } },
299 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
300 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
301 { .name = "kse_release", .ret_type = 0, .nargs = 1,
302 .args = { { Timespec, 0 } } },
303 { .name = "lchflags", .ret_type = 1, .nargs = 2,
304 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
305 { .name = "lchmod", .ret_type = 1, .nargs = 2,
306 .args = { { Name, 0 }, { Octal, 1 } } },
307 { .name = "lchown", .ret_type = 1, .nargs = 3,
308 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
309 { .name = "link", .ret_type = 1, .nargs = 2,
310 .args = { { Name, 0 }, { Name, 1 } } },
311 { .name = "linkat", .ret_type = 1, .nargs = 5,
312 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
314 { .name = "listen", .ret_type = 1, .nargs = 2,
315 .args = { { Int, 0 }, { Int, 1 } } },
316 { .name = "lseek", .ret_type = 2, .nargs = 3,
317 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
318 { .name = "lstat", .ret_type = 1, .nargs = 2,
319 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
320 { .name = "lutimes", .ret_type = 1, .nargs = 2,
321 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
322 { .name = "madvise", .ret_type = 1, .nargs = 3,
323 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
324 { .name = "minherit", .ret_type = 1, .nargs = 3,
325 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
326 { .name = "mkdir", .ret_type = 1, .nargs = 2,
327 .args = { { Name, 0 }, { Octal, 1 } } },
328 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
329 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
330 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
331 .args = { { Name, 0 }, { Octal, 1 } } },
332 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
333 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
334 { .name = "mknod", .ret_type = 1, .nargs = 3,
335 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
336 { .name = "mknodat", .ret_type = 1, .nargs = 4,
337 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
338 { .name = "mlock", .ret_type = 1, .nargs = 2,
339 .args = { { Ptr, 0 }, { Sizet, 1 } } },
340 { .name = "mlockall", .ret_type = 1, .nargs = 1,
341 .args = { { Mlockall, 0 } } },
342 { .name = "mmap", .ret_type = 1, .nargs = 6,
343 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
344 { Int, 4 }, { QuadHex, 5 } } },
345 { .name = "modfind", .ret_type = 1, .nargs = 1,
346 .args = { { Name | IN, 0 } } },
347 { .name = "mount", .ret_type = 1, .nargs = 4,
348 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
349 { .name = "mprotect", .ret_type = 1, .nargs = 3,
350 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
351 { .name = "msync", .ret_type = 1, .nargs = 3,
352 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
353 { .name = "munlock", .ret_type = 1, .nargs = 2,
354 .args = { { Ptr, 0 }, { Sizet, 1 } } },
355 { .name = "munmap", .ret_type = 1, .nargs = 2,
356 .args = { { Ptr, 0 }, { Sizet, 1 } } },
357 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
358 .args = { { Timespec, 0 } } },
359 { .name = "nmount", .ret_type = 1, .nargs = 3,
360 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
361 { .name = "open", .ret_type = 1, .nargs = 3,
362 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
363 { .name = "openat", .ret_type = 1, .nargs = 4,
364 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
366 { .name = "pathconf", .ret_type = 1, .nargs = 2,
367 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
368 { .name = "pipe", .ret_type = 1, .nargs = 1,
369 .args = { { PipeFds | OUT, 0 } } },
370 { .name = "pipe2", .ret_type = 1, .nargs = 2,
371 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
372 { .name = "poll", .ret_type = 1, .nargs = 3,
373 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
374 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
375 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
377 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
378 .args = { { Open, 0 } } },
379 { .name = "pread", .ret_type = 1, .nargs = 4,
380 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
382 { .name = "procctl", .ret_type = 1, .nargs = 4,
383 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
384 { .name = "ptrace", .ret_type = 1, .nargs = 4,
385 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
386 { .name = "pwrite", .ret_type = 1, .nargs = 4,
387 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
389 { .name = "quotactl", .ret_type = 1, .nargs = 4,
390 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
391 { .name = "read", .ret_type = 1, .nargs = 3,
392 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
393 { .name = "readlink", .ret_type = 1, .nargs = 3,
394 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
395 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
396 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
398 { .name = "readv", .ret_type = 1, .nargs = 3,
399 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
400 { .name = "reboot", .ret_type = 1, .nargs = 1,
401 .args = { { Reboothowto, 0 } } },
402 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
403 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
404 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
405 { Ptr | OUT, 5 } } },
406 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
407 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
408 { .name = "rename", .ret_type = 1, .nargs = 2,
409 .args = { { Name, 0 }, { Name, 1 } } },
410 { .name = "renameat", .ret_type = 1, .nargs = 4,
411 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
412 { .name = "rfork", .ret_type = 1, .nargs = 1,
413 .args = { { Rforkflags, 0 } } },
414 { .name = "rmdir", .ret_type = 1, .nargs = 1,
415 .args = { { Name, 0 } } },
416 { .name = "rtprio", .ret_type = 1, .nargs = 3,
417 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
418 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
419 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
420 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
421 .args = { { Schedpolicy, 0 } } },
422 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
423 .args = { { Schedpolicy, 0 } } },
424 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
425 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
426 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
427 .args = { { Int, 0 } } },
428 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
429 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
430 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
431 .args = { { Int, 0 }, { Schedparam, 1 } } },
432 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
433 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
434 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
435 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
436 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
437 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
438 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
439 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
440 { Sockaddr | IN, 3 }, { Socklent, 4 },
441 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
442 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
443 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
444 { Sockaddr | IN, 3 }, { Socklent, 4 },
445 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
446 { .name = "select", .ret_type = 1, .nargs = 5,
447 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
449 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
450 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
451 { .name = "sendto", .ret_type = 1, .nargs = 6,
452 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
453 { Msgflags, 3 }, { Sockaddr | IN, 4 },
454 { Socklent | IN, 5 } } },
455 { .name = "setitimer", .ret_type = 1, .nargs = 3,
456 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
457 { .name = "setpriority", .ret_type = 1, .nargs = 3,
458 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
459 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
460 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
461 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
462 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
463 { Ptr | IN, 3 }, { Socklent, 4 } } },
464 { .name = "shm_open", .ret_type = 1, .nargs = 3,
465 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
466 { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
467 .args = { { Name | IN, 0 } } },
468 { .name = "shutdown", .ret_type = 1, .nargs = 2,
469 .args = { { Int, 0 }, { Shutdown, 1 } } },
470 { .name = "sigaction", .ret_type = 1, .nargs = 3,
471 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
472 { Sigaction | OUT, 2 } } },
473 { .name = "sigpending", .ret_type = 1, .nargs = 1,
474 .args = { { Sigset | OUT, 0 } } },
475 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
476 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
477 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
478 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
479 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
480 .args = { { Ptr, 0 } } },
481 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
482 .args = { { Sigset | IN, 0 } } },
483 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
484 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
485 { Timespec | IN, 2 } } },
486 { .name = "sigwait", .ret_type = 1, .nargs = 2,
487 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
488 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
489 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
490 { .name = "socket", .ret_type = 1, .nargs = 3,
491 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
492 { .name = "stat", .ret_type = 1, .nargs = 2,
493 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
494 { .name = "statfs", .ret_type = 1, .nargs = 2,
495 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
496 { .name = "symlink", .ret_type = 1, .nargs = 2,
497 .args = { { Name, 0 }, { Name, 1 } } },
498 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
499 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
500 { .name = "sysarch", .ret_type = 1, .nargs = 2,
501 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
502 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
503 .args = { { Long, 0 }, { Signal, 1 } } },
504 { .name = "thr_self", .ret_type = 1, .nargs = 1,
505 .args = { { Ptr, 0 } } },
506 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
507 .args = { { Long, 0 }, { Name, 1 } } },
508 { .name = "truncate", .ret_type = 1, .nargs = 2,
509 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
512 { .name = "umount", .ret_type = 1, .nargs = 2,
513 .args = { { Name, 0 }, { Int, 2 } } },
515 { .name = "unlink", .ret_type = 1, .nargs = 1,
516 .args = { { Name, 0 } } },
517 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
518 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
519 { .name = "unmount", .ret_type = 1, .nargs = 2,
520 .args = { { Name, 0 }, { Mountflags, 1 } } },
521 { .name = "utimensat", .ret_type = 1, .nargs = 4,
522 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
524 { .name = "utimes", .ret_type = 1, .nargs = 2,
525 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
526 { .name = "utrace", .ret_type = 1, .nargs = 1,
527 .args = { { Utrace, 0 } } },
528 { .name = "wait4", .ret_type = 1, .nargs = 4,
529 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
530 { Rusage | OUT, 3 } } },
531 { .name = "wait6", .ret_type = 1, .nargs = 6,
532 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
533 { Waitoptions, 3 }, { Rusage | OUT, 4 },
534 { Siginfo | OUT, 5 } } },
535 { .name = "write", .ret_type = 1, .nargs = 3,
536 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
537 { .name = "writev", .ret_type = 1, .nargs = 3,
538 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
541 { .name = "linux_access", .ret_type = 1, .nargs = 2,
542 .args = { { Name, 0 }, { Accessmode, 1 } } },
543 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
544 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
545 { ExecEnv | IN, 2 } } },
546 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
547 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
548 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
549 .args = { { Name | IN, 0 }, { Int, 1 } } },
550 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
551 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
552 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
553 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
554 { .name = "linux_open", .ret_type = 1, .nargs = 3,
555 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
556 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
557 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
558 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
559 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
560 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
561 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
563 /* CloudABI system calls. */
564 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
565 .args = { { CloudABIClockID, 0 } } },
566 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
567 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
568 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
569 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
570 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
571 .args = { { Int, 0 } } },
572 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
573 .args = { { CloudABIFileType, 0 } } },
574 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
575 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
576 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
577 .args = { { Int, 0 } } },
578 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
579 .args = { { Int, 0 } } },
580 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
581 .args = { { Int, 0 }, { Int, 1 } } },
582 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
583 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
584 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
585 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
586 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
587 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
588 { CloudABIFDSFlags, 2 } } },
589 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
590 .args = { { Int, 0 } } },
591 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
592 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
593 { CloudABIAdvice, 3 } } },
594 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
595 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
596 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
597 .args = { { Int, 0 }, { BinString | IN, 1 },
598 { CloudABIFileType, 3 } } },
599 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
600 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
601 { Int, 3 }, { BinString | IN, 4 } } },
602 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
603 .args = { { Int, 0 }, { BinString | IN, 1 },
604 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
605 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
606 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
608 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
609 .args = { { Int, 0 }, { BinString | IN, 1 },
610 { BinString | OUT, 3 }, { Int, 4 } } },
611 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
612 .args = { { Int, 0 }, { BinString | IN, 1 },
613 { Int, 3 }, { BinString | IN, 4 } } },
614 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
615 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
616 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
617 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
618 { CloudABIFSFlags, 2 } } },
619 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
620 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
621 { CloudABIFileStat | OUT, 3 } } },
622 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
623 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
624 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
625 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
626 .args = { { BinString | IN, 0 },
627 { Int, 2 }, { BinString | IN, 3 } } },
628 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
629 .args = { { Int, 0 }, { BinString | IN, 1 },
630 { CloudABIULFlags, 3 } } },
631 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
632 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
633 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
634 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
635 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
636 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
637 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
638 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
639 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
640 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
641 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
642 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
643 .args = { { Ptr, 0 }, { Int, 1 } } },
644 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
645 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
646 { IntArray, 3 }, { Int, 4 } } },
647 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
648 .args = { { Int, 0 } } },
649 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
650 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
651 .args = { { CloudABISignal, 0 } } },
652 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
653 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
654 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
655 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
656 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
657 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
658 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
662 static STAILQ_HEAD(, syscall) syscalls;
664 /* Xlat idea taken from strace */
670 #define X(a) { a, #a },
671 #define XEND { 0, NULL }
673 static struct xlat poll_flags[] = {
674 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
675 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
676 X(POLLWRBAND) X(POLLINIGNEOF) XEND
679 static struct xlat sigaction_flags[] = {
680 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
681 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
684 static struct xlat linux_socketcall_ops[] = {
685 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
686 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
687 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
688 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
689 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
694 #define X(a) { CLOUDABI_##a, #a },
696 static struct xlat cloudabi_advice[] = {
697 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
698 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
702 static struct xlat cloudabi_clockid[] = {
703 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
704 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
708 static struct xlat cloudabi_fdflags[] = {
709 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
710 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
714 static struct xlat cloudabi_fdsflags[] = {
715 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
719 static struct xlat cloudabi_filetype[] = {
720 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
721 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
722 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
723 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
724 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
728 static struct xlat cloudabi_fsflags[] = {
729 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
730 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
734 static struct xlat cloudabi_mflags[] = {
735 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
739 static struct xlat cloudabi_mprot[] = {
740 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
744 static struct xlat cloudabi_msflags[] = {
745 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
749 static struct xlat cloudabi_oflags[] = {
750 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
754 static struct xlat cloudabi_sdflags[] = {
755 X(SHUT_RD) X(SHUT_WR)
759 static struct xlat cloudabi_signal[] = {
760 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
761 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
762 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
763 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
764 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
768 static struct xlat cloudabi_ulflags[] = {
773 static struct xlat cloudabi_whence[] = {
774 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
782 * Searches an xlat array for a value, and returns it if found. Otherwise
783 * return a string representation.
786 lookup(struct xlat *xlat, int val, int base)
790 for (; xlat->str != NULL; xlat++)
791 if (xlat->val == val)
795 sprintf(tmp, "0%o", val);
798 sprintf(tmp, "0x%x", val);
801 sprintf(tmp, "%u", val);
804 errx(1,"Unknown lookup base");
811 xlookup(struct xlat *xlat, int val)
814 return (lookup(xlat, val, 16));
818 * Searches an xlat array containing bitfield values. Remaining bits
819 * set after removing the known ones are printed at the end:
823 xlookup_bits(struct xlat *xlat, int val)
826 static char str[512];
830 for (; xlat->str != NULL; xlat++) {
831 if ((xlat->val & rem) == xlat->val) {
833 * Don't print the "all-bits-zero" string unless all
834 * bits are really zero.
836 if (xlat->val == 0 && val != 0)
838 len += sprintf(str + len, "%s|", xlat->str);
844 * If we have leftover bits or didn't match anything, print
848 len += sprintf(str + len, "0x%x", rem);
849 if (len && str[len - 1] == '|')
856 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
860 str = decoder(value);
864 fprintf(fp, "%d", value);
868 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
872 if (!decoder(fp, value, &rem))
873 fprintf(fp, "0x%x", rem);
875 fprintf(fp, "|0x%x", rem);
879 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
884 if (!decoder(fp, value, &rem))
885 fprintf(fp, "0x%x", rem);
887 fprintf(fp, "|0x%x", rem);
892 * Add argument padding to subsequent system calls afater a Quad
893 * syscall arguments as needed. This used to be done by hand in the
894 * decoded_syscalls table which was ugly and error prone. It is
895 * simpler to do the fixup of offsets at initalization time than when
896 * decoding arguments.
899 quad_fixup(struct syscall *sc)
906 for (i = 0; i < sc->nargs; i++) {
907 /* This arg type is a dummy that doesn't use offset. */
908 if ((sc->args[i].type & ARG_MASK) == PipeFds)
911 assert(prev < sc->args[i].offset);
912 prev = sc->args[i].offset;
913 sc->args[i].offset += offset;
914 switch (sc->args[i].type & ARG_MASK) {
919 * 64-bit arguments on 32-bit powerpc must be
920 * 64-bit aligned. If the current offset is
921 * not aligned, the calling convention inserts
922 * a 32-bit pad argument that should be skipped.
924 if (sc->args[i].offset % 2 == 1) {
925 sc->args[i].offset++;
942 STAILQ_INIT(&syscalls);
943 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
947 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
951 static struct syscall *
952 find_syscall(struct procabi *abi, u_int number)
954 struct extra_syscall *es;
956 if (number < nitems(abi->syscalls))
957 return (abi->syscalls[number]);
958 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
959 if (es->number == number)
966 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
968 struct extra_syscall *es;
970 if (number < nitems(abi->syscalls)) {
971 assert(abi->syscalls[number] == NULL);
972 abi->syscalls[number] = sc;
974 es = malloc(sizeof(*es));
977 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
982 * If/when the list gets big, it might be desirable to do it
983 * as a hash table or binary search.
986 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
993 sc = find_syscall(t->proc->abi, number);
997 name = sysdecode_syscallname(t->proc->abi->abi, number);
999 asprintf(&new_name, "#%d", number);
1003 STAILQ_FOREACH(sc, &syscalls, entries) {
1004 if (strcmp(name, sc->name) == 0) {
1005 add_syscall(t->proc->abi, number, sc);
1011 /* It is unknown. Add it into the list. */
1013 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1017 sc = calloc(1, sizeof(struct syscall));
1019 if (new_name != NULL)
1023 for (i = 0; i < nargs; i++) {
1024 sc->args[i].offset = i;
1025 /* Treat all unknown arguments as LongHex. */
1026 sc->args[i].type = LongHex;
1028 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1029 add_syscall(t->proc->abi, number, sc);
1035 * Copy a fixed amount of bytes from the process.
1038 get_struct(pid_t pid, void *offset, void *buf, int len)
1040 struct ptrace_io_desc iorequest;
1042 iorequest.piod_op = PIOD_READ_D;
1043 iorequest.piod_offs = offset;
1044 iorequest.piod_addr = buf;
1045 iorequest.piod_len = len;
1046 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1051 #define MAXSIZE 4096
1054 * Copy a string from the process. Note that it is
1055 * expected to be a C string, but if max is set, it will
1056 * only get that much.
1059 get_string(pid_t pid, void *addr, int max)
1061 struct ptrace_io_desc iorequest;
1063 size_t offset, size, totalsize;
1069 /* Read up to the end of the current page. */
1070 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1075 buf = malloc(totalsize);
1079 iorequest.piod_op = PIOD_READ_D;
1080 iorequest.piod_offs = (char *)addr + offset;
1081 iorequest.piod_addr = buf + offset;
1082 iorequest.piod_len = size;
1083 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1087 if (memchr(buf + offset, '\0', size) != NULL)
1090 if (totalsize < MAXSIZE && max == 0) {
1091 size = MAXSIZE - totalsize;
1092 if (size > PAGE_SIZE)
1094 nbuf = realloc(buf, totalsize + size);
1096 buf[totalsize - 1] = '\0';
1102 buf[totalsize - 1] = '\0';
1111 static char tmp[32];
1112 const char *signame;
1114 signame = sysdecode_signal(sig);
1115 if (signame == NULL) {
1116 snprintf(tmp, sizeof(tmp), "%d", sig);
1123 print_kevent(FILE *fp, struct kevent *ke)
1126 switch (ke->filter) {
1132 case EVFILT_PROCDESC:
1134 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1137 fputs(strsig2(ke->ident), fp);
1140 fprintf(fp, "%p", (void *)ke->ident);
1143 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1145 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1147 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1148 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1152 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1154 unsigned char *utrace_buffer;
1157 if (sysdecode_utrace(fp, utrace_addr, len)) {
1162 utrace_buffer = utrace_addr;
1163 fprintf(fp, "%zu:", len);
1165 fprintf(fp, " %02x", *utrace_buffer++);
1170 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1173 struct sockaddr_in *lsin;
1174 struct sockaddr_in6 *lsin6;
1175 struct sockaddr_un *sun;
1176 struct sockaddr *sa;
1178 pid_t pid = trussinfo->curthread->proc->pid;
1184 /* If the length is too small, just bail. */
1185 if (len < sizeof(*sa)) {
1186 fprintf(fp, "%p", arg);
1190 sa = calloc(1, len);
1191 if (get_struct(pid, arg, sa, len) == -1) {
1193 fprintf(fp, "%p", arg);
1197 switch (sa->sa_family) {
1199 if (len < sizeof(*lsin))
1200 goto sockaddr_short;
1201 lsin = (struct sockaddr_in *)(void *)sa;
1202 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1203 fprintf(fp, "{ AF_INET %s:%d }", addr,
1204 htons(lsin->sin_port));
1207 if (len < sizeof(*lsin6))
1208 goto sockaddr_short;
1209 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1210 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1212 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1213 htons(lsin6->sin6_port));
1216 sun = (struct sockaddr_un *)sa;
1217 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1218 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1224 "{ sa_len = %d, sa_family = %d, sa_data = {",
1225 (int)sa->sa_len, (int)sa->sa_family);
1226 for (q = (u_char *)sa->sa_data;
1227 q < (u_char *)sa + len; q++)
1228 fprintf(fp, "%s 0x%02x",
1229 q == (u_char *)sa->sa_data ? "" : ",",
1236 #define IOV_LIMIT 16
1239 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1241 struct iovec iov[IOV_LIMIT];
1242 size_t max_string = trussinfo->strsize;
1243 char tmp2[max_string + 1], *tmp3;
1245 pid_t pid = trussinfo->curthread->proc->pid;
1247 bool buf_truncated, iov_truncated;
1250 fprintf(fp, "%p", arg);
1253 if (iovcnt > IOV_LIMIT) {
1255 iov_truncated = true;
1257 iov_truncated = false;
1259 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1260 fprintf(fp, "%p", arg);
1265 for (i = 0; i < iovcnt; i++) {
1266 len = iov[i].iov_len;
1267 if (len > max_string) {
1269 buf_truncated = true;
1271 buf_truncated = false;
1273 fprintf(fp, "%s{", (i > 0) ? "," : "");
1274 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1275 tmp3 = malloc(len * 4 + 1);
1277 if (strvisx(tmp3, tmp2, len,
1278 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1282 buf_truncated = true;
1284 fprintf(fp, "\"%s\"%s", tmp3,
1285 buf_truncated ? "..." : "");
1288 fprintf(fp, "%p", iov[i].iov_base);
1290 fprintf(fp, ",%zu}", iov[i].iov_len);
1292 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1296 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1301 for (q = CMSG_DATA(cmsghdr);
1302 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1303 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1309 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1311 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1312 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1313 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1314 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1318 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1320 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1322 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1325 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1326 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1328 fprintf(fp, "ctx=%u,", info->sinfo_context);
1329 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1332 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1333 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1335 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1339 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1341 fprintf(fp, "{sid=%u,", info->snd_sid);
1343 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1344 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1345 fprintf(fp, "ctx=%u,", info->snd_context);
1346 fprintf(fp, "id=%u}", info->snd_assoc_id);
1350 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1352 fprintf(fp, "{sid=%u,", info->rcv_sid);
1353 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1355 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1356 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1357 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1358 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1359 fprintf(fp, "ctx=%u,", info->rcv_context);
1360 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1364 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1366 fprintf(fp, "{sid=%u,", info->nxt_sid);
1368 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1369 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1370 fprintf(fp, "len=%u,", info->nxt_length);
1371 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1375 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1378 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1379 fprintf(fp, ",val=%u}", info->pr_value);
1383 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1385 fprintf(fp, "{num=%u}", info->auth_keynumber);
1389 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1391 char buf[INET_ADDRSTRLEN];
1394 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1396 fprintf(fp, "{addr=%s}", s);
1398 fputs("{addr=???}", fp);
1402 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1404 char buf[INET6_ADDRSTRLEN];
1407 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1409 fprintf(fp, "{addr=%s}", s);
1411 fputs("{addr=???}", fp);
1415 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1420 len = cmsghdr->cmsg_len;
1421 data = CMSG_DATA(cmsghdr);
1422 switch (cmsghdr->cmsg_type) {
1424 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1425 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1427 print_gen_cmsg(fp, cmsghdr);
1430 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1431 print_sctp_sndrcvinfo(fp, receive,
1432 (struct sctp_sndrcvinfo *)data);
1434 print_gen_cmsg(fp, cmsghdr);
1438 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1439 print_sctp_extrcvinfo(fp,
1440 (struct sctp_extrcvinfo *)data);
1442 print_gen_cmsg(fp, cmsghdr);
1446 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1447 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1449 print_gen_cmsg(fp, cmsghdr);
1452 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1453 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1455 print_gen_cmsg(fp, cmsghdr);
1458 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1459 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1461 print_gen_cmsg(fp, cmsghdr);
1464 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1465 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1467 print_gen_cmsg(fp, cmsghdr);
1470 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1471 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1473 print_gen_cmsg(fp, cmsghdr);
1475 case SCTP_DSTADDRV4:
1476 if (len == CMSG_LEN(sizeof(struct in_addr)))
1477 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1479 print_gen_cmsg(fp, cmsghdr);
1481 case SCTP_DSTADDRV6:
1482 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1483 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1485 print_gen_cmsg(fp, cmsghdr);
1488 print_gen_cmsg(fp, cmsghdr);
1493 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1495 struct cmsghdr *cmsghdr;
1502 len = msghdr->msg_controllen;
1507 cmsgbuf = calloc(1, len);
1508 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1509 fprintf(fp, "%p", msghdr->msg_control);
1513 msghdr->msg_control = cmsgbuf;
1516 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1518 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1519 level = cmsghdr->cmsg_level;
1520 type = cmsghdr->cmsg_type;
1521 len = cmsghdr->cmsg_len;
1522 fprintf(fp, "%s{level=", first ? "" : ",");
1523 print_integer_arg(sysdecode_sockopt_level, fp, level);
1524 fputs(",type=", fp);
1525 temp = sysdecode_cmsg_type(level, type);
1529 fprintf(fp, "%d", type);
1531 fputs(",data=", fp);
1534 print_sctp_cmsg(fp, receive, cmsghdr);
1537 print_gen_cmsg(fp, cmsghdr);
1548 * Converts a syscall argument into a string. Said string is
1549 * allocated via malloc(), so needs to be free()'d. sc is
1550 * a pointer to the syscall description (see above); args is
1551 * an array of all of the system call arguments.
1554 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1555 struct trussinfo *trussinfo)
1562 fp = open_memstream(&tmp, &tmplen);
1563 pid = trussinfo->curthread->proc->pid;
1564 switch (sc->type & ARG_MASK) {
1566 fprintf(fp, "0x%x", (int)args[sc->offset]);
1569 fprintf(fp, "0%o", (int)args[sc->offset]);
1572 fprintf(fp, "%d", (int)args[sc->offset]);
1575 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1580 if (get_struct(pid, (void *)args[sc->offset], &val,
1582 fprintf(fp, "{ %u }", val);
1584 fprintf(fp, "0x%lx", args[sc->offset]);
1588 fprintf(fp, "0x%lx", args[sc->offset]);
1591 fprintf(fp, "%ld", args[sc->offset]);
1594 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1597 /* NULL-terminated string. */
1600 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1601 fprintf(fp, "\"%s\"", tmp2);
1607 * Binary block of data that might have printable characters.
1608 * XXX If type|OUT, assume that the length is the syscall's
1609 * return value. Otherwise, assume that the length of the block
1610 * is in the next syscall argument.
1612 int max_string = trussinfo->strsize;
1613 char tmp2[max_string + 1], *tmp3;
1620 len = args[sc->offset + 1];
1623 * Don't print more than max_string characters, to avoid word
1624 * wrap. If we have to truncate put some ... after the string.
1626 if (len > max_string) {
1630 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1632 tmp3 = malloc(len * 4 + 1);
1634 if (strvisx(tmp3, tmp2, len,
1635 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1640 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1644 fprintf(fp, "0x%lx", args[sc->offset]);
1654 char buf[PAGE_SIZE];
1661 * Only parse argv[] and environment arrays from exec calls
1664 if (((sc->type & ARG_MASK) == ExecArgs &&
1665 (trussinfo->flags & EXECVEARGS) == 0) ||
1666 ((sc->type & ARG_MASK) == ExecEnv &&
1667 (trussinfo->flags & EXECVEENVS) == 0)) {
1668 fprintf(fp, "0x%lx", args[sc->offset]);
1673 * Read a page of pointers at a time. Punt if the top-level
1674 * pointer is not aligned. Note that the first read is of
1677 addr = args[sc->offset];
1678 if (addr % sizeof(char *) != 0) {
1679 fprintf(fp, "0x%lx", args[sc->offset]);
1683 len = PAGE_SIZE - (addr & PAGE_MASK);
1684 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1685 fprintf(fp, "0x%lx", args[sc->offset]);
1692 while (u.strarray[i] != NULL) {
1693 string = get_string(pid, u.strarray[i], 0);
1694 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1699 if (i == len / sizeof(char *)) {
1702 if (get_struct(pid, (void *)addr, u.buf, len) ==
1704 fprintf(fp, ", <inval>");
1715 fprintf(fp, "%ld", args[sc->offset]);
1718 fprintf(fp, "0x%lx", args[sc->offset]);
1723 unsigned long long ll;
1725 #if _BYTE_ORDER == _LITTLE_ENDIAN
1726 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1729 ll = (unsigned long long)args[sc->offset] << 32 |
1730 args[sc->offset + 1];
1732 if ((sc->type & ARG_MASK) == Quad)
1733 fprintf(fp, "%lld", ll);
1735 fprintf(fp, "0x%llx", ll);
1742 if (get_struct(pid, (void *)args[sc->offset], &val,
1744 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1746 fprintf(fp, "0x%lx", args[sc->offset]);
1750 fprintf(fp, "0x%lx", args[sc->offset]);
1755 if (retval[0] == -1)
1757 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1758 fprintf(fp, "\"%s\"", tmp2);
1766 cmd = args[sc->offset];
1767 temp = sysdecode_ioctlname(cmd);
1771 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1772 cmd, cmd & IOC_OUT ? "R" : "",
1773 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1774 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1775 cmd & 0xFF, IOCPARM_LEN(cmd));
1782 if (get_struct(pid, (void *)args[sc->offset], &ts,
1784 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1787 fprintf(fp, "0x%lx", args[sc->offset]);
1791 struct timespec ts[2];
1795 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1799 for (i = 0; i < nitems(ts); i++) {
1802 switch (ts[i].tv_nsec) {
1804 fprintf(fp, "UTIME_NOW");
1807 fprintf(fp, "UTIME_OMIT");
1810 fprintf(fp, "%jd.%09ld",
1811 (intmax_t)ts[i].tv_sec,
1818 fprintf(fp, "0x%lx", args[sc->offset]);
1824 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1826 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1829 fprintf(fp, "0x%lx", args[sc->offset]);
1833 struct timeval tv[2];
1835 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1837 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1838 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1839 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1841 fprintf(fp, "0x%lx", args[sc->offset]);
1845 struct itimerval itv;
1847 if (get_struct(pid, (void *)args[sc->offset], &itv,
1849 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1850 (intmax_t)itv.it_interval.tv_sec,
1851 itv.it_interval.tv_usec,
1852 (intmax_t)itv.it_value.tv_sec,
1853 itv.it_value.tv_usec);
1855 fprintf(fp, "0x%lx", args[sc->offset]);
1860 struct linux_socketcall_args largs;
1862 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1863 sizeof(largs)) != -1)
1864 fprintf(fp, "{ %s, 0x%lx }",
1865 lookup(linux_socketcall_ops, largs.what, 10),
1866 (long unsigned int)largs.args);
1868 fprintf(fp, "0x%lx", args[sc->offset]);
1873 * XXX: A Pollfd argument expects the /next/ syscall argument
1874 * to be the number of fds in the array. This matches the poll
1878 int numfds = args[sc->offset + 1];
1879 size_t bytes = sizeof(struct pollfd) * numfds;
1882 if ((pfd = malloc(bytes)) == NULL)
1883 err(1, "Cannot malloc %zu bytes for pollfd array",
1885 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1888 for (i = 0; i < numfds; i++) {
1889 fprintf(fp, " %d/%s", pfd[i].fd,
1890 xlookup_bits(poll_flags, pfd[i].events));
1894 fprintf(fp, "0x%lx", args[sc->offset]);
1901 * XXX: A Fd_set argument expects the /first/ syscall argument
1902 * to be the number of fds in the array. This matches the
1906 int numfds = args[0];
1907 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1910 if ((fds = malloc(bytes)) == NULL)
1911 err(1, "Cannot malloc %zu bytes for fd_set array",
1913 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1916 for (i = 0; i < numfds; i++) {
1917 if (FD_ISSET(i, fds))
1918 fprintf(fp, " %d", i);
1922 fprintf(fp, "0x%lx", args[sc->offset]);
1927 fputs(strsig2(args[sc->offset]), fp);
1934 sig = args[sc->offset];
1935 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1936 sizeof(ss)) == -1) {
1937 fprintf(fp, "0x%lx", args[sc->offset]);
1942 for (i = 1; i < sys_nsig; i++) {
1943 if (sigismember(&ss, i)) {
1944 fprintf(fp, "%s%s", !first ? "|" : "",
1955 print_integer_arg(sysdecode_sigprocmask_how, fp,
1959 /* XXX: Output depends on the value of the previous argument. */
1960 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1961 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1962 args[sc->offset], 16);
1965 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1968 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1971 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1974 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1977 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1980 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1983 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1986 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1989 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
1992 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
1995 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
1998 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
2003 if (args[sc->offset] == 0) {
2009 * Extract the address length from the next argument. If
2010 * this is an output sockaddr (OUT is set), then the
2011 * next argument is a pointer to a socklen_t. Otherwise
2012 * the next argument contains a socklen_t by value.
2014 if (sc->type & OUT) {
2015 if (get_struct(pid, (void *)args[sc->offset + 1],
2016 &len, sizeof(len)) == -1) {
2017 fprintf(fp, "0x%lx", args[sc->offset]);
2021 len = args[sc->offset + 1];
2023 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2027 struct sigaction sa;
2029 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2032 if (sa.sa_handler == SIG_DFL)
2033 fputs("SIG_DFL", fp);
2034 else if (sa.sa_handler == SIG_IGN)
2035 fputs("SIG_IGN", fp);
2037 fprintf(fp, "%p", sa.sa_handler);
2038 fprintf(fp, " %s ss_t }",
2039 xlookup_bits(sigaction_flags, sa.sa_flags));
2041 fprintf(fp, "0x%lx", args[sc->offset]);
2046 * XXX XXX: The size of the array is determined by either the
2047 * next syscall argument, or by the syscall return value,
2048 * depending on which argument number we are. This matches the
2049 * kevent syscall, but luckily that's the only syscall that uses
2057 if (sc->offset == 1)
2058 numevents = args[sc->offset+1];
2059 else if (sc->offset == 3 && retval[0] != -1)
2060 numevents = retval[0];
2062 if (numevents >= 0) {
2063 bytes = sizeof(struct kevent) * numevents;
2064 if ((ke = malloc(bytes)) == NULL)
2066 "Cannot malloc %zu bytes for kevent array",
2070 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2073 for (i = 0; i < numevents; i++) {
2075 print_kevent(fp, &ke[i]);
2079 fprintf(fp, "0x%lx", args[sc->offset]);
2085 struct kevent_freebsd11 *ke11;
2091 if (sc->offset == 1)
2092 numevents = args[sc->offset+1];
2093 else if (sc->offset == 3 && retval[0] != -1)
2094 numevents = retval[0];
2096 if (numevents >= 0) {
2097 bytes = sizeof(struct kevent_freebsd11) * numevents;
2098 if ((ke11 = malloc(bytes)) == NULL)
2100 "Cannot malloc %zu bytes for kevent array",
2104 memset(&ke, 0, sizeof(ke));
2105 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2106 ke11, bytes) != -1) {
2108 for (i = 0; i < numevents; i++) {
2110 ke.ident = ke11[i].ident;
2111 ke.filter = ke11[i].filter;
2112 ke.flags = ke11[i].flags;
2113 ke.fflags = ke11[i].fflags;
2114 ke.data = ke11[i].data;
2115 ke.udata = ke11[i].udata;
2116 print_kevent(fp, &ke);
2120 fprintf(fp, "0x%lx", args[sc->offset]);
2128 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2132 strmode(st.st_mode, mode);
2134 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2135 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2136 (long)st.st_blksize);
2138 fprintf(fp, "0x%lx", args[sc->offset]);
2143 struct freebsd11_stat st;
2145 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2149 strmode(st.st_mode, mode);
2151 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2152 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2153 (long)st.st_blksize);
2155 fprintf(fp, "0x%lx", args[sc->offset]);
2163 if (get_struct(pid, (void *)args[sc->offset], &buf,
2164 sizeof(buf)) != -1) {
2167 bzero(fsid, sizeof(fsid));
2168 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2169 for (i = 0; i < sizeof(buf.f_fsid); i++)
2170 snprintf(&fsid[i*2],
2171 sizeof(fsid) - (i*2), "%02x",
2172 ((u_char *)&buf.f_fsid)[i]);
2175 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2176 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2177 buf.f_mntfromname, fsid);
2179 fprintf(fp, "0x%lx", args[sc->offset]);
2186 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2189 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2190 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2191 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2192 ru.ru_inblock, ru.ru_oublock);
2194 fprintf(fp, "0x%lx", args[sc->offset]);
2200 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2202 fprintf(fp, "{ cur=%ju,max=%ju }",
2203 rl.rlim_cur, rl.rlim_max);
2205 fprintf(fp, "0x%lx", args[sc->offset]);
2211 if (get_struct(pid, (void *)args[sc->offset], &status,
2212 sizeof(status)) != -1) {
2214 if (WIFCONTINUED(status))
2215 fputs("CONTINUED", fp);
2216 else if (WIFEXITED(status))
2217 fprintf(fp, "EXITED,val=%d",
2218 WEXITSTATUS(status));
2219 else if (WIFSIGNALED(status))
2220 fprintf(fp, "SIGNALED,sig=%s%s",
2221 strsig2(WTERMSIG(status)),
2222 WCOREDUMP(status) ? ",cored" : "");
2224 fprintf(fp, "STOPPED,sig=%s",
2225 strsig2(WTERMSIG(status)));
2228 fprintf(fp, "0x%lx", args[sc->offset]);
2232 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2235 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2238 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2241 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2244 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2247 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2250 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2253 print_integer_arg(sysdecode_sysarch_number, fp,
2258 * The pipe() system call in the kernel returns its
2259 * two file descriptors via return values. However,
2260 * the interface exposed by libc is that pipe()
2261 * accepts a pointer to an array of descriptors.
2262 * Format the output to match the libc API by printing
2263 * the returned file descriptors as a fake argument.
2265 * Overwrite the first retval to signal a successful
2268 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
2275 len = args[sc->offset + 1];
2276 utrace_addr = calloc(1, len);
2277 if (get_struct(pid, (void *)args[sc->offset],
2278 (void *)utrace_addr, len) != -1)
2279 print_utrace(fp, utrace_addr, len);
2281 fprintf(fp, "0x%lx", args[sc->offset]);
2286 int descriptors[16];
2287 unsigned long i, ndescriptors;
2290 ndescriptors = args[sc->offset + 1];
2292 if (ndescriptors > nitems(descriptors)) {
2293 ndescriptors = nitems(descriptors);
2296 if (get_struct(pid, (void *)args[sc->offset],
2297 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2299 for (i = 0; i < ndescriptors; i++)
2300 fprintf(fp, i == 0 ? " %d" : ", %d",
2302 fprintf(fp, truncated ? ", ... }" : " }");
2304 fprintf(fp, "0x%lx", args[sc->offset]);
2308 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2310 case CapFcntlRights: {
2313 if (sc->type & OUT) {
2314 if (get_struct(pid, (void *)args[sc->offset], &rights,
2315 sizeof(rights)) == -1) {
2316 fprintf(fp, "0x%lx", args[sc->offset]);
2320 rights = args[sc->offset];
2321 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2325 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2330 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2331 fprintf(fp, "0x%x", rem);
2333 fprintf(fp, "|0x%x", rem);
2337 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2340 print_integer_arg(sysdecode_getfsstat_mode, fp,
2344 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2346 case Kldunloadflags:
2347 print_integer_arg(sysdecode_kldunload_flags, fp,
2351 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2354 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2356 case Sockprotocol: {
2358 int domain, protocol;
2360 domain = args[sc->offset - 2];
2361 protocol = args[sc->offset];
2362 if (protocol == 0) {
2365 temp = sysdecode_socket_protocol(domain, protocol);
2369 fprintf(fp, "%d", protocol);
2375 print_integer_arg(sysdecode_sockopt_level, fp,
2382 level = args[sc->offset - 1];
2383 name = args[sc->offset];
2384 temp = sysdecode_sockopt_name(level, name);
2388 fprintf(fp, "%d", name);
2393 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2396 cap_rights_t rights;
2398 if (get_struct(pid, (void *)args[sc->offset], &rights,
2399 sizeof(rights)) != -1) {
2401 sysdecode_cap_rights(fp, &rights);
2404 fprintf(fp, "0x%lx", args[sc->offset]);
2408 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2410 case Extattrnamespace:
2411 print_integer_arg(sysdecode_extattrnamespace, fp,
2415 print_integer_arg(sysdecode_minherit_inherit, fp,
2419 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2422 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2425 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2428 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2431 print_integer_arg(sysdecode_ptrace_request, fp,
2435 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2436 fprintf(fp, "%#x", (int)args[sc->offset]);
2439 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2442 print_integer_arg(sysdecode_rtprio_function, fp,
2446 print_integer_arg(sysdecode_scheduler_policy, fp,
2450 struct sched_param sp;
2452 if (get_struct(pid, (void *)args[sc->offset], &sp,
2454 fprintf(fp, "{ %d }", sp.sched_priority);
2456 fprintf(fp, "0x%lx", args[sc->offset]);
2462 if (get_struct(pid, (void *)args[sc->offset], &sig,
2464 fprintf(fp, "{ %s }", strsig2(sig));
2466 fprintf(fp, "0x%lx", args[sc->offset]);
2472 if (get_struct(pid, (void *)args[sc->offset], &si,
2473 sizeof(si)) != -1) {
2474 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2475 decode_siginfo(fp, &si);
2478 fprintf(fp, "0x%lx", args[sc->offset]);
2483 * Print argument as an array of struct iovec, where the next
2484 * syscall argument is the number of elements of the array.
2487 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2488 (int)args[sc->offset + 1]);
2490 case Sctpsndrcvinfo: {
2491 struct sctp_sndrcvinfo info;
2493 if (get_struct(pid, (void *)args[sc->offset],
2494 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2495 fprintf(fp, "0x%lx", args[sc->offset]);
2498 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2502 struct msghdr msghdr;
2504 if (get_struct(pid, (void *)args[sc->offset],
2505 &msghdr, sizeof(struct msghdr)) == -1) {
2506 fprintf(fp, "0x%lx", args[sc->offset]);
2510 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2511 fprintf(fp, ",%d,", msghdr.msg_namelen);
2512 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2513 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2514 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2515 fprintf(fp, ",%u,", msghdr.msg_controllen);
2516 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2521 case CloudABIAdvice:
2522 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2524 case CloudABIClockID:
2525 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2527 case CloudABIFDSFlags:
2528 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2530 case CloudABIFDStat: {
2531 cloudabi_fdstat_t fds;
2532 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2534 fprintf(fp, "{ %s, ",
2535 xlookup(cloudabi_filetype, fds.fs_filetype));
2536 fprintf(fp, "%s, ... }",
2537 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2539 fprintf(fp, "0x%lx", args[sc->offset]);
2542 case CloudABIFileStat: {
2543 cloudabi_filestat_t fsb;
2544 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2546 fprintf(fp, "{ %s, %ju }",
2547 xlookup(cloudabi_filetype, fsb.st_filetype),
2548 (uintmax_t)fsb.st_size);
2550 fprintf(fp, "0x%lx", args[sc->offset]);
2553 case CloudABIFileType:
2554 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2556 case CloudABIFSFlags:
2557 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2559 case CloudABILookup:
2560 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2561 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2562 (int)args[sc->offset]);
2564 fprintf(fp, "%d", (int)args[sc->offset]);
2566 case CloudABIMFlags:
2567 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2570 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2572 case CloudABIMSFlags:
2573 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2575 case CloudABIOFlags:
2576 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2578 case CloudABISDFlags:
2579 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2581 case CloudABISignal:
2582 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2584 case CloudABITimestamp:
2585 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2586 args[sc->offset] % 1000000000);
2588 case CloudABIULFlags:
2589 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2591 case CloudABIWhence:
2592 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2596 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2603 * Print (to outfile) the system call and its arguments.
2606 print_syscall(struct trussinfo *trussinfo)
2608 struct threadinfo *t;
2613 t = trussinfo->curthread;
2615 name = t->cs.sc->name;
2616 nargs = t->cs.nargs;
2617 s_args = t->cs.s_args;
2619 len = print_line_prefix(trussinfo);
2620 len += fprintf(trussinfo->outfile, "%s(", name);
2622 for (i = 0; i < nargs; i++) {
2623 if (s_args[i] != NULL)
2624 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2626 len += fprintf(trussinfo->outfile,
2627 "<missing argument>");
2628 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2631 len += fprintf(trussinfo->outfile, ")");
2632 for (i = 0; i < 6 - (len / 8); i++)
2633 fprintf(trussinfo->outfile, "\t");
2637 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2639 struct timespec timediff;
2640 struct threadinfo *t;
2644 t = trussinfo->curthread;
2646 if (trussinfo->flags & COUNTONLY) {
2647 timespecsub(&t->after, &t->before, &timediff);
2648 timespecadd(&sc->time, &timediff, &sc->time);
2655 print_syscall(trussinfo);
2656 fflush(trussinfo->outfile);
2658 if (retval == NULL) {
2660 * This system call resulted in the current thread's exit,
2661 * so there is no return value or error to display.
2663 fprintf(trussinfo->outfile, "\n");
2668 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2670 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2671 error == INT_MAX ? "Unknown error" : strerror(error));
2674 else if (sc->ret_type == 2) {
2677 #if _BYTE_ORDER == _LITTLE_ENDIAN
2678 off = (off_t)retval[1] << 32 | retval[0];
2680 off = (off_t)retval[0] << 32 | retval[1];
2682 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2687 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2692 print_summary(struct trussinfo *trussinfo)
2694 struct timespec total = {0, 0};
2698 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2699 "syscall", "seconds", "calls", "errors");
2701 STAILQ_FOREACH(sc, &syscalls, entries)
2703 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2704 sc->name, (intmax_t)sc->time.tv_sec,
2705 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2706 timespecadd(&total, &sc->time, &total);
2707 ncall += sc->ncalls;
2708 nerror += sc->nerror;
2710 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2711 "", "-------------", "-------", "-------");
2712 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2713 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);