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
55 #include <netinet/in.h>
56 #include <netinet/sctp.h>
57 #include <arpa/inet.h>
70 #include <sysdecode.h>
74 #include <contrib/cloudabi/cloudabi_types_common.h>
81 * This should probably be in its own file, sorted alphabetically.
83 static struct syscall decoded_syscalls[] = {
85 { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
86 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
87 { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
88 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
89 { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
90 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
91 { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
92 .args = { { Int, 0 }, { Acltype, 1 } } },
93 { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
94 .args = { { Name, 0 }, { Acltype, 1 } } },
95 { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
96 .args = { { Name, 0 }, { Acltype, 1 } } },
97 { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
98 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
99 { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
100 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
101 { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
102 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
103 { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
104 .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
105 { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
106 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
107 { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
108 .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
109 { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
110 .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
111 { .name = "__getcwd", .ret_type = 1, .nargs = 2,
112 .args = { { Name | OUT, 0 }, { Int, 1 } } },
113 { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
114 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
116 { .name = "accept", .ret_type = 1, .nargs = 3,
117 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
118 { .name = "access", .ret_type = 1, .nargs = 2,
119 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
120 { .name = "bind", .ret_type = 1, .nargs = 3,
121 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
122 { .name = "bindat", .ret_type = 1, .nargs = 4,
123 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
125 { .name = "break", .ret_type = 1, .nargs = 1,
126 .args = { { Ptr, 0 } } },
127 { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
128 .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
129 { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
130 .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
131 { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
132 .args = { { PUInt | OUT, 0 } } },
133 { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
134 .args = { { Int, 0 }, { CapRights, 1 } } },
135 { .name = "chdir", .ret_type = 1, .nargs = 1,
136 .args = { { Name, 0 } } },
137 { .name = "chflags", .ret_type = 1, .nargs = 2,
138 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
139 { .name = "chflagsat", .ret_type = 1, .nargs = 4,
140 .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
142 { .name = "chmod", .ret_type = 1, .nargs = 2,
143 .args = { { Name, 0 }, { Octal, 1 } } },
144 { .name = "chown", .ret_type = 1, .nargs = 3,
145 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
146 { .name = "chroot", .ret_type = 1, .nargs = 1,
147 .args = { { Name, 0 } } },
148 { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
149 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
150 { .name = "close", .ret_type = 1, .nargs = 1,
151 .args = { { Int, 0 } } },
152 { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
153 .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
154 { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
155 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
157 { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
158 .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
159 { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
160 { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
161 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
162 { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
163 .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
164 { .name = "connect", .ret_type = 1, .nargs = 3,
165 .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
166 { .name = "connectat", .ret_type = 1, .nargs = 4,
167 .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
169 { .name = "dup", .ret_type = 1, .nargs = 1,
170 .args = { { Int, 0 } } },
171 { .name = "dup2", .ret_type = 1, .nargs = 2,
172 .args = { { Int, 0 }, { Int, 1 } } },
173 { .name = "eaccess", .ret_type = 1, .nargs = 2,
174 .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
175 { .name = "execve", .ret_type = 1, .nargs = 3,
176 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
177 { ExecEnv | IN, 2 } } },
178 { .name = "exit", .ret_type = 0, .nargs = 1,
179 .args = { { Hex, 0 } } },
180 { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
181 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
182 { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
183 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
184 { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
185 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
186 { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
187 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
188 { BinString | OUT, 3 }, { Sizet, 4 } } },
189 { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
190 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
191 { BinString | OUT, 3 }, { Sizet, 4 } } },
192 { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
193 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
194 { BinString | OUT, 3 }, { Sizet, 4 } } },
195 { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
196 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
198 { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
199 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
201 { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
202 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
204 { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
205 .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
206 { BinString | IN, 3 }, { Sizet, 4 } } },
207 { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
208 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
209 { BinString | IN, 3 }, { Sizet, 4 } } },
210 { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
211 .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
212 { BinString | IN, 3 }, { Sizet, 4 } } },
213 { .name = "extattrctl", .ret_type = 1, .nargs = 5,
214 .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
215 { Extattrnamespace, 3 }, { Name, 4 } } },
216 { .name = "faccessat", .ret_type = 1, .nargs = 4,
217 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
219 { .name = "fchflags", .ret_type = 1, .nargs = 2,
220 .args = { { Int, 0 }, { FileFlags, 1 } } },
221 { .name = "fchmod", .ret_type = 1, .nargs = 2,
222 .args = { { Int, 0 }, { Octal, 1 } } },
223 { .name = "fchmodat", .ret_type = 1, .nargs = 4,
224 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
225 { .name = "fchown", .ret_type = 1, .nargs = 3,
226 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
227 { .name = "fchownat", .ret_type = 1, .nargs = 5,
228 .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
230 { .name = "fcntl", .ret_type = 1, .nargs = 3,
231 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
232 { .name = "flock", .ret_type = 1, .nargs = 2,
233 .args = { { Int, 0 }, { Flockop, 1 } } },
234 { .name = "fstat", .ret_type = 1, .nargs = 2,
235 .args = { { Int, 0 }, { Stat | OUT, 1 } } },
236 { .name = "fstatat", .ret_type = 1, .nargs = 4,
237 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
239 { .name = "fstatfs", .ret_type = 1, .nargs = 2,
240 .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
241 { .name = "ftruncate", .ret_type = 1, .nargs = 2,
242 .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
243 { .name = "futimens", .ret_type = 1, .nargs = 2,
244 .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
245 { .name = "futimes", .ret_type = 1, .nargs = 2,
246 .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
247 { .name = "futimesat", .ret_type = 1, .nargs = 3,
248 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
249 { .name = "getdirentries", .ret_type = 1, .nargs = 4,
250 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
251 { PQuadHex | OUT, 3 } } },
252 { .name = "getfsstat", .ret_type = 1, .nargs = 3,
253 .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
254 { .name = "getitimer", .ret_type = 1, .nargs = 2,
255 .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
256 { .name = "getpeername", .ret_type = 1, .nargs = 3,
257 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
258 { .name = "getpgid", .ret_type = 1, .nargs = 1,
259 .args = { { Int, 0 } } },
260 { .name = "getpriority", .ret_type = 1, .nargs = 2,
261 .args = { { Priowhich, 0 }, { Int, 1 } } },
262 { .name = "getrlimit", .ret_type = 1, .nargs = 2,
263 .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
264 { .name = "getrusage", .ret_type = 1, .nargs = 2,
265 .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
266 { .name = "getsid", .ret_type = 1, .nargs = 1,
267 .args = { { Int, 0 } } },
268 { .name = "getsockname", .ret_type = 1, .nargs = 3,
269 .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
270 { .name = "getsockopt", .ret_type = 1, .nargs = 5,
271 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
272 { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
273 { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
274 .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
275 { .name = "ioctl", .ret_type = 1, .nargs = 3,
276 .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
277 { .name = "kevent", .ret_type = 1, .nargs = 6,
278 .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
279 { Int, 4 }, { Timespec, 5 } } },
280 { .name = "kill", .ret_type = 1, .nargs = 2,
281 .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
282 { .name = "kldfind", .ret_type = 1, .nargs = 1,
283 .args = { { Name | IN, 0 } } },
284 { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
285 .args = { { Int, 0 } } },
286 { .name = "kldload", .ret_type = 1, .nargs = 1,
287 .args = { { Name | IN, 0 } } },
288 { .name = "kldnext", .ret_type = 1, .nargs = 1,
289 .args = { { Int, 0 } } },
290 { .name = "kldstat", .ret_type = 1, .nargs = 2,
291 .args = { { Int, 0 }, { Ptr, 1 } } },
292 { .name = "kldsym", .ret_type = 1, .nargs = 3,
293 .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
294 { .name = "kldunload", .ret_type = 1, .nargs = 1,
295 .args = { { Int, 0 } } },
296 { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
297 .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
298 { .name = "kse_release", .ret_type = 0, .nargs = 1,
299 .args = { { Timespec, 0 } } },
300 { .name = "lchflags", .ret_type = 1, .nargs = 2,
301 .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
302 { .name = "lchmod", .ret_type = 1, .nargs = 2,
303 .args = { { Name, 0 }, { Octal, 1 } } },
304 { .name = "lchown", .ret_type = 1, .nargs = 3,
305 .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
306 { .name = "link", .ret_type = 1, .nargs = 2,
307 .args = { { Name, 0 }, { Name, 1 } } },
308 { .name = "linkat", .ret_type = 1, .nargs = 5,
309 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
311 { .name = "listen", .ret_type = 1, .nargs = 2,
312 .args = { { Int, 0 }, { Int, 1 } } },
313 { .name = "lseek", .ret_type = 2, .nargs = 3,
314 .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
315 { .name = "lstat", .ret_type = 1, .nargs = 2,
316 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
317 { .name = "lutimes", .ret_type = 1, .nargs = 2,
318 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
319 { .name = "madvise", .ret_type = 1, .nargs = 3,
320 .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
321 { .name = "minherit", .ret_type = 1, .nargs = 3,
322 .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
323 { .name = "mkdir", .ret_type = 1, .nargs = 2,
324 .args = { { Name, 0 }, { Octal, 1 } } },
325 { .name = "mkdirat", .ret_type = 1, .nargs = 3,
326 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
327 { .name = "mkfifo", .ret_type = 1, .nargs = 2,
328 .args = { { Name, 0 }, { Octal, 1 } } },
329 { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
330 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
331 { .name = "mknod", .ret_type = 1, .nargs = 3,
332 .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
333 { .name = "mknodat", .ret_type = 1, .nargs = 4,
334 .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
335 { .name = "mlock", .ret_type = 1, .nargs = 2,
336 .args = { { Ptr, 0 }, { Sizet, 1 } } },
337 { .name = "mlockall", .ret_type = 1, .nargs = 1,
338 .args = { { Mlockall, 0 } } },
339 { .name = "mmap", .ret_type = 1, .nargs = 6,
340 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
341 { Int, 4 }, { QuadHex, 5 } } },
342 { .name = "modfind", .ret_type = 1, .nargs = 1,
343 .args = { { Name | IN, 0 } } },
344 { .name = "mount", .ret_type = 1, .nargs = 4,
345 .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
346 { .name = "mprotect", .ret_type = 1, .nargs = 3,
347 .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
348 { .name = "msync", .ret_type = 1, .nargs = 3,
349 .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
350 { .name = "munlock", .ret_type = 1, .nargs = 2,
351 .args = { { Ptr, 0 }, { Sizet, 1 } } },
352 { .name = "munmap", .ret_type = 1, .nargs = 2,
353 .args = { { Ptr, 0 }, { Sizet, 1 } } },
354 { .name = "nanosleep", .ret_type = 1, .nargs = 1,
355 .args = { { Timespec, 0 } } },
356 { .name = "nmount", .ret_type = 1, .nargs = 3,
357 .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
358 { .name = "open", .ret_type = 1, .nargs = 3,
359 .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
360 { .name = "openat", .ret_type = 1, .nargs = 4,
361 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
363 { .name = "pathconf", .ret_type = 1, .nargs = 2,
364 .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
365 { .name = "pipe", .ret_type = 1, .nargs = 1,
366 .args = { { PipeFds | OUT, 0 } } },
367 { .name = "pipe2", .ret_type = 1, .nargs = 2,
368 .args = { { Ptr, 0 }, { Pipe2, 1 } } },
369 { .name = "poll", .ret_type = 1, .nargs = 3,
370 .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
371 { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
372 .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
374 { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
375 .args = { { Open, 0 } } },
376 { .name = "pread", .ret_type = 1, .nargs = 4,
377 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
379 { .name = "procctl", .ret_type = 1, .nargs = 4,
380 .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
381 { .name = "ptrace", .ret_type = 1, .nargs = 4,
382 .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
383 { .name = "pwrite", .ret_type = 1, .nargs = 4,
384 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
386 { .name = "quotactl", .ret_type = 1, .nargs = 4,
387 .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
388 { .name = "read", .ret_type = 1, .nargs = 3,
389 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
390 { .name = "readlink", .ret_type = 1, .nargs = 3,
391 .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
392 { .name = "readlinkat", .ret_type = 1, .nargs = 4,
393 .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
395 { .name = "readv", .ret_type = 1, .nargs = 3,
396 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
397 { .name = "reboot", .ret_type = 1, .nargs = 1,
398 .args = { { Reboothowto, 0 } } },
399 { .name = "recvfrom", .ret_type = 1, .nargs = 6,
400 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
401 { Msgflags, 3 }, { Sockaddr | OUT, 4 },
402 { Ptr | OUT, 5 } } },
403 { .name = "recvmsg", .ret_type = 1, .nargs = 3,
404 .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
405 { .name = "rename", .ret_type = 1, .nargs = 2,
406 .args = { { Name, 0 }, { Name, 1 } } },
407 { .name = "renameat", .ret_type = 1, .nargs = 4,
408 .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
409 { .name = "rfork", .ret_type = 1, .nargs = 1,
410 .args = { { Rforkflags, 0 } } },
411 { .name = "rmdir", .ret_type = 1, .nargs = 1,
412 .args = { { Name, 0 } } },
413 { .name = "rtprio", .ret_type = 1, .nargs = 3,
414 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
415 { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
416 .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
417 { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
418 .args = { { Schedpolicy, 0 } } },
419 { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
420 .args = { { Schedpolicy, 0 } } },
421 { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
422 .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
423 { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
424 .args = { { Int, 0 } } },
425 { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
426 .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
427 { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
428 .args = { { Int, 0 }, { Schedparam, 1 } } },
429 { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
430 .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
431 { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
432 .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
433 { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
434 { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
435 { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
436 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
437 { Sockaddr | IN, 3 }, { Socklent, 4 },
438 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
439 { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
440 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
441 { Sockaddr | IN, 3 }, { Socklent, 4 },
442 { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
443 { .name = "select", .ret_type = 1, .nargs = 5,
444 .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
446 { .name = "sendmsg", .ret_type = 1, .nargs = 3,
447 .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
448 { .name = "sendto", .ret_type = 1, .nargs = 6,
449 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
450 { Msgflags, 3 }, { Sockaddr | IN, 4 },
451 { Socklent | IN, 5 } } },
452 { .name = "setitimer", .ret_type = 1, .nargs = 3,
453 .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
454 { .name = "setpriority", .ret_type = 1, .nargs = 3,
455 .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
456 { .name = "setrlimit", .ret_type = 1, .nargs = 2,
457 .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
458 { .name = "setsockopt", .ret_type = 1, .nargs = 5,
459 .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
460 { Ptr | IN, 3 }, { Socklent, 4 } } },
461 { .name = "shutdown", .ret_type = 1, .nargs = 2,
462 .args = { { Int, 0 }, { Shutdown, 1 } } },
463 { .name = "sigaction", .ret_type = 1, .nargs = 3,
464 .args = { { Signal, 0 }, { Sigaction | IN, 1 },
465 { Sigaction | OUT, 2 } } },
466 { .name = "sigpending", .ret_type = 1, .nargs = 1,
467 .args = { { Sigset | OUT, 0 } } },
468 { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
469 .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
470 { .name = "sigqueue", .ret_type = 1, .nargs = 3,
471 .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
472 { .name = "sigreturn", .ret_type = 1, .nargs = 1,
473 .args = { { Ptr, 0 } } },
474 { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
475 .args = { { Sigset | IN, 0 } } },
476 { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
477 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
478 { Timespec | IN, 2 } } },
479 { .name = "sigwait", .ret_type = 1, .nargs = 2,
480 .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
481 { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
482 .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
483 { .name = "socket", .ret_type = 1, .nargs = 3,
484 .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
485 { .name = "stat", .ret_type = 1, .nargs = 2,
486 .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
487 { .name = "statfs", .ret_type = 1, .nargs = 2,
488 .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
489 { .name = "symlink", .ret_type = 1, .nargs = 2,
490 .args = { { Name, 0 }, { Name, 1 } } },
491 { .name = "symlinkat", .ret_type = 1, .nargs = 3,
492 .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
493 { .name = "sysarch", .ret_type = 1, .nargs = 2,
494 .args = { { Sysarch, 0 }, { Ptr, 1 } } },
495 { .name = "thr_kill", .ret_type = 1, .nargs = 2,
496 .args = { { Long, 0 }, { Signal, 1 } } },
497 { .name = "thr_self", .ret_type = 1, .nargs = 1,
498 .args = { { Ptr, 0 } } },
499 { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
500 .args = { { Long, 0 }, { Name, 1 } } },
501 { .name = "truncate", .ret_type = 1, .nargs = 2,
502 .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
505 { .name = "umount", .ret_type = 1, .nargs = 2,
506 .args = { { Name, 0 }, { Int, 2 } } },
508 { .name = "unlink", .ret_type = 1, .nargs = 1,
509 .args = { { Name, 0 } } },
510 { .name = "unlinkat", .ret_type = 1, .nargs = 3,
511 .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
512 { .name = "unmount", .ret_type = 1, .nargs = 2,
513 .args = { { Name, 0 }, { Mountflags, 1 } } },
514 { .name = "utimensat", .ret_type = 1, .nargs = 4,
515 .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
517 { .name = "utimes", .ret_type = 1, .nargs = 2,
518 .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
519 { .name = "utrace", .ret_type = 1, .nargs = 1,
520 .args = { { Utrace, 0 } } },
521 { .name = "wait4", .ret_type = 1, .nargs = 4,
522 .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
523 { Rusage | OUT, 3 } } },
524 { .name = "wait6", .ret_type = 1, .nargs = 6,
525 .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
526 { Waitoptions, 3 }, { Rusage | OUT, 4 },
527 { Siginfo | OUT, 5 } } },
528 { .name = "write", .ret_type = 1, .nargs = 3,
529 .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
530 { .name = "writev", .ret_type = 1, .nargs = 3,
531 .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
534 { .name = "linux_access", .ret_type = 1, .nargs = 2,
535 .args = { { Name, 0 }, { Accessmode, 1 } } },
536 { .name = "linux_execve", .ret_type = 1, .nargs = 3,
537 .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
538 { ExecEnv | IN, 2 } } },
539 { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
540 .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
541 { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
542 .args = { { Name | IN, 0 }, { Int, 1 } } },
543 { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
544 .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
545 { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
546 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
547 { .name = "linux_open", .ret_type = 1, .nargs = 3,
548 .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
549 { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
550 .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
551 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
552 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
553 { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
554 .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
556 /* CloudABI system calls. */
557 { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1,
558 .args = { { CloudABIClockID, 0 } } },
559 { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2,
560 .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } },
561 { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3,
562 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } },
563 { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1,
564 .args = { { Int, 0 } } },
565 { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1,
566 .args = { { CloudABIFileType, 0 } } },
567 { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2,
568 .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } },
569 { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1,
570 .args = { { Int, 0 } } },
571 { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1,
572 .args = { { Int, 0 } } },
573 { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2,
574 .args = { { Int, 0 }, { Int, 1 } } },
575 { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3,
576 .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } },
577 { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2,
578 .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } },
579 { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3,
580 .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 },
581 { ClouduABIFDSFlags, 2 } } },
582 { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1,
583 .args = { { Int, 0 } } },
584 { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4,
585 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 },
586 { CloudABIAdvice, 3 } } },
587 { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3,
588 .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
589 { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3,
590 .args = { { Int, 0 }, { BinString | IN, 1 },
591 { CloudABIFileType, 3 } } },
592 { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4,
593 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
594 { Int, 3 }, { BinString | IN, 4 } } },
595 { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4,
596 .args = { { Int, 0 }, { BinString | IN, 1 },
597 { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } },
598 { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4,
599 .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
601 { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4,
602 .args = { { Int, 0 }, { BinString | IN, 1 },
603 { BinString | OUT, 3 }, { Int, 4 } } },
604 { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4,
605 .args = { { Int, 0 }, { BinString | IN, 1 },
606 { Int, 3 }, { BinString | IN, 4 } } },
607 { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2,
608 .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } },
609 { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3,
610 .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 },
611 { CloudABIFSFlags, 2 } } },
612 { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3,
613 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
614 { CloudABIFileStat | OUT, 3 } } },
615 { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4,
616 .args = { { CloudABILookup, 0 }, { BinString | IN, 1 },
617 { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } },
618 { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3,
619 .args = { { BinString | IN, 0 },
620 { Int, 2 }, { BinString | IN, 3 } } },
621 { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3,
622 .args = { { Int, 0 }, { BinString | IN, 1 },
623 { CloudABIULFlags, 3 } } },
624 { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2,
625 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
626 { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3,
627 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } },
628 { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6,
629 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 },
630 { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } },
631 { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3,
632 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } },
633 { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3,
634 .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } },
635 { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2,
636 .args = { { Ptr, 0 }, { Int, 1 } } },
637 { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5,
638 .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
639 { IntArray, 3 }, { Int, 4 } } },
640 { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1,
641 .args = { { Int, 0 } } },
642 { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 },
643 { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1,
644 .args = { { CloudABISignal, 0 } } },
645 { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2,
646 .args = { { BinString | OUT, 0 }, { Int, 1 } } },
647 { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2,
648 .args = { { Int, 0 }, { CloudABISDFlags, 1 } } },
649 { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
650 .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
651 { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
655 static STAILQ_HEAD(, syscall) syscalls;
657 /* Xlat idea taken from strace */
663 #define X(a) { a, #a },
664 #define XEND { 0, NULL }
666 static struct xlat poll_flags[] = {
667 X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
668 X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
669 X(POLLWRBAND) X(POLLINIGNEOF) XEND
672 static struct xlat sigaction_flags[] = {
673 X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
674 X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
677 static struct xlat linux_socketcall_ops[] = {
678 X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
679 X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
680 X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
681 X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
682 X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
687 #define X(a) { CLOUDABI_##a, #a },
689 static struct xlat cloudabi_advice[] = {
690 X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL)
691 X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED)
695 static struct xlat cloudabi_clockid[] = {
696 X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID)
697 X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID)
701 static struct xlat cloudabi_fdflags[] = {
702 X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK)
703 X(FDFLAG_RSYNC) X(FDFLAG_SYNC)
707 static struct xlat cloudabi_fdsflags[] = {
708 X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS)
712 static struct xlat cloudabi_filetype[] = {
713 X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE)
714 X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY)
715 X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE)
716 X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM)
717 X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK)
721 static struct xlat cloudabi_fsflags[] = {
722 X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM)
723 X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE)
727 static struct xlat cloudabi_mflags[] = {
728 X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED)
732 static struct xlat cloudabi_mprot[] = {
733 X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ)
737 static struct xlat cloudabi_msflags[] = {
738 X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC)
742 static struct xlat cloudabi_oflags[] = {
743 X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC)
747 static struct xlat cloudabi_sdflags[] = {
748 X(SHUT_RD) X(SHUT_WR)
752 static struct xlat cloudabi_signal[] = {
753 X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE)
754 X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT)
755 X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP)
756 X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2)
757 X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ)
761 static struct xlat cloudabi_ulflags[] = {
766 static struct xlat cloudabi_whence[] = {
767 X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET)
775 * Searches an xlat array for a value, and returns it if found. Otherwise
776 * return a string representation.
779 lookup(struct xlat *xlat, int val, int base)
783 for (; xlat->str != NULL; xlat++)
784 if (xlat->val == val)
788 sprintf(tmp, "0%o", val);
791 sprintf(tmp, "0x%x", val);
794 sprintf(tmp, "%u", val);
797 errx(1,"Unknown lookup base");
804 xlookup(struct xlat *xlat, int val)
807 return (lookup(xlat, val, 16));
811 * Searches an xlat array containing bitfield values. Remaining bits
812 * set after removing the known ones are printed at the end:
816 xlookup_bits(struct xlat *xlat, int val)
819 static char str[512];
823 for (; xlat->str != NULL; xlat++) {
824 if ((xlat->val & rem) == xlat->val) {
826 * Don't print the "all-bits-zero" string unless all
827 * bits are really zero.
829 if (xlat->val == 0 && val != 0)
831 len += sprintf(str + len, "%s|", xlat->str);
837 * If we have leftover bits or didn't match anything, print
841 len += sprintf(str + len, "0x%x", rem);
842 if (len && str[len - 1] == '|')
849 print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
853 str = decoder(value);
857 fprintf(fp, "%d", value);
861 print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
865 if (!decoder(fp, value, &rem))
866 fprintf(fp, "0x%x", rem);
868 fprintf(fp, "|0x%x", rem);
872 print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
877 if (!decoder(fp, value, &rem))
878 fprintf(fp, "0x%x", rem);
880 fprintf(fp, "|0x%x", rem);
885 * Add argument padding to subsequent system calls afater a Quad
886 * syscall arguments as needed. This used to be done by hand in the
887 * decoded_syscalls table which was ugly and error prone. It is
888 * simpler to do the fixup of offsets at initalization time than when
889 * decoding arguments.
892 quad_fixup(struct syscall *sc)
899 for (i = 0; i < sc->nargs; i++) {
900 /* This arg type is a dummy that doesn't use offset. */
901 if ((sc->args[i].type & ARG_MASK) == PipeFds)
904 assert(prev < sc->args[i].offset);
905 prev = sc->args[i].offset;
906 sc->args[i].offset += offset;
907 switch (sc->args[i].type & ARG_MASK) {
912 * 64-bit arguments on 32-bit powerpc must be
913 * 64-bit aligned. If the current offset is
914 * not aligned, the calling convention inserts
915 * a 32-bit pad argument that should be skipped.
917 if (sc->args[i].offset % 2 == 1) {
918 sc->args[i].offset++;
935 STAILQ_INIT(&syscalls);
936 for (sc = decoded_syscalls; sc->name != NULL; sc++) {
940 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
944 static struct syscall *
945 find_syscall(struct procabi *abi, u_int number)
947 struct extra_syscall *es;
949 if (number < nitems(abi->syscalls))
950 return (abi->syscalls[number]);
951 STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
952 if (es->number == number)
959 add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
961 struct extra_syscall *es;
963 if (number < nitems(abi->syscalls)) {
964 assert(abi->syscalls[number] == NULL);
965 abi->syscalls[number] = sc;
967 es = malloc(sizeof(*es));
970 STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
975 * If/when the list gets big, it might be desirable to do it
976 * as a hash table or binary search.
979 get_syscall(struct threadinfo *t, u_int number, u_int nargs)
986 sc = find_syscall(t->proc->abi, number);
990 name = sysdecode_syscallname(t->proc->abi->abi, number);
992 asprintf(&new_name, "#%d", number);
996 STAILQ_FOREACH(sc, &syscalls, entries) {
997 if (strcmp(name, sc->name) == 0) {
998 add_syscall(t->proc->abi, number, sc);
1004 /* It is unknown. Add it into the list. */
1006 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
1010 sc = calloc(1, sizeof(struct syscall));
1012 if (new_name != NULL)
1016 for (i = 0; i < nargs; i++) {
1017 sc->args[i].offset = i;
1018 /* Treat all unknown arguments as LongHex. */
1019 sc->args[i].type = LongHex;
1021 STAILQ_INSERT_HEAD(&syscalls, sc, entries);
1022 add_syscall(t->proc->abi, number, sc);
1028 * Copy a fixed amount of bytes from the process.
1031 get_struct(pid_t pid, void *offset, void *buf, int len)
1033 struct ptrace_io_desc iorequest;
1035 iorequest.piod_op = PIOD_READ_D;
1036 iorequest.piod_offs = offset;
1037 iorequest.piod_addr = buf;
1038 iorequest.piod_len = len;
1039 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
1044 #define MAXSIZE 4096
1047 * Copy a string from the process. Note that it is
1048 * expected to be a C string, but if max is set, it will
1049 * only get that much.
1052 get_string(pid_t pid, void *addr, int max)
1054 struct ptrace_io_desc iorequest;
1056 size_t offset, size, totalsize;
1062 /* Read up to the end of the current page. */
1063 size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
1068 buf = malloc(totalsize);
1072 iorequest.piod_op = PIOD_READ_D;
1073 iorequest.piod_offs = (char *)addr + offset;
1074 iorequest.piod_addr = buf + offset;
1075 iorequest.piod_len = size;
1076 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
1080 if (memchr(buf + offset, '\0', size) != NULL)
1083 if (totalsize < MAXSIZE && max == 0) {
1084 size = MAXSIZE - totalsize;
1085 if (size > PAGE_SIZE)
1087 nbuf = realloc(buf, totalsize + size);
1089 buf[totalsize - 1] = '\0';
1095 buf[totalsize - 1] = '\0';
1104 static char tmp[32];
1105 const char *signame;
1107 signame = sysdecode_signal(sig);
1108 if (signame == NULL) {
1109 snprintf(tmp, sizeof(tmp), "%d", sig);
1116 print_kevent(FILE *fp, struct kevent *ke)
1119 switch (ke->filter) {
1125 case EVFILT_PROCDESC:
1127 fprintf(fp, "%ju", (uintmax_t)ke->ident);
1130 fputs(strsig2(ke->ident), fp);
1133 fprintf(fp, "%p", (void *)ke->ident);
1136 print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
1138 print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
1140 sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
1141 fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
1145 print_utrace(FILE *fp, void *utrace_addr, size_t len)
1147 unsigned char *utrace_buffer;
1150 if (sysdecode_utrace(fp, utrace_addr, len)) {
1155 utrace_buffer = utrace_addr;
1156 fprintf(fp, "%zu:", len);
1158 fprintf(fp, " %02x", *utrace_buffer++);
1163 print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len)
1166 struct sockaddr_in *lsin;
1167 struct sockaddr_in6 *lsin6;
1168 struct sockaddr_un *sun;
1169 struct sockaddr *sa;
1171 pid_t pid = trussinfo->curthread->proc->pid;
1177 /* If the length is too small, just bail. */
1178 if (len < sizeof(*sa)) {
1179 fprintf(fp, "%p", arg);
1183 sa = calloc(1, len);
1184 if (get_struct(pid, arg, sa, len) == -1) {
1186 fprintf(fp, "%p", arg);
1190 switch (sa->sa_family) {
1192 if (len < sizeof(*lsin))
1193 goto sockaddr_short;
1194 lsin = (struct sockaddr_in *)(void *)sa;
1195 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1196 fprintf(fp, "{ AF_INET %s:%d }", addr,
1197 htons(lsin->sin_port));
1200 if (len < sizeof(*lsin6))
1201 goto sockaddr_short;
1202 lsin6 = (struct sockaddr_in6 *)(void *)sa;
1203 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1205 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1206 htons(lsin6->sin6_port));
1209 sun = (struct sockaddr_un *)sa;
1210 fprintf(fp, "{ AF_UNIX \"%.*s\" }",
1211 (int)(len - offsetof(struct sockaddr_un, sun_path)),
1217 "{ sa_len = %d, sa_family = %d, sa_data = {",
1218 (int)sa->sa_len, (int)sa->sa_family);
1219 for (q = (u_char *)sa->sa_data;
1220 q < (u_char *)sa + len; q++)
1221 fprintf(fp, "%s 0x%02x",
1222 q == (u_char *)sa->sa_data ? "" : ",",
1229 #define IOV_LIMIT 16
1232 print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt)
1234 struct iovec iov[IOV_LIMIT];
1235 size_t max_string = trussinfo->strsize;
1236 char tmp2[max_string + 1], *tmp3;
1238 pid_t pid = trussinfo->curthread->proc->pid;
1240 bool buf_truncated, iov_truncated;
1243 fprintf(fp, "%p", arg);
1246 if (iovcnt > IOV_LIMIT) {
1248 iov_truncated = true;
1250 iov_truncated = false;
1252 if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
1253 fprintf(fp, "%p", arg);
1258 for (i = 0; i < iovcnt; i++) {
1259 len = iov[i].iov_len;
1260 if (len > max_string) {
1262 buf_truncated = true;
1264 buf_truncated = false;
1266 fprintf(fp, "%s{", (i > 0) ? "," : "");
1267 if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) {
1268 tmp3 = malloc(len * 4 + 1);
1270 if (strvisx(tmp3, tmp2, len,
1271 VIS_CSTYLE|VIS_TAB|VIS_NL) <=
1275 buf_truncated = true;
1277 fprintf(fp, "\"%s\"%s", tmp3,
1278 buf_truncated ? "..." : "");
1281 fprintf(fp, "%p", iov[i].iov_base);
1283 fprintf(fp, ",%zu}", iov[i].iov_len);
1285 fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
1289 print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
1294 for (q = CMSG_DATA(cmsghdr);
1295 q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
1296 fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
1302 print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
1304 fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
1305 fprintf(fp, "in=%u,", init->sinit_max_instreams);
1306 fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
1307 fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
1311 print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
1313 fprintf(fp, "{sid=%u,", info->sinfo_stream);
1315 fprintf(fp, "ssn=%u,", info->sinfo_ssn);
1318 sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
1319 fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
1321 fprintf(fp, "ctx=%u,", info->sinfo_context);
1322 fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
1325 fprintf(fp, "tsn=%u,", info->sinfo_tsn);
1326 fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
1328 fprintf(fp, "id=%u}", info->sinfo_assoc_id);
1332 print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
1334 fprintf(fp, "{sid=%u,", info->snd_sid);
1336 print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
1337 fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
1338 fprintf(fp, "ctx=%u,", info->snd_context);
1339 fprintf(fp, "id=%u}", info->snd_assoc_id);
1343 print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
1345 fprintf(fp, "{sid=%u,", info->rcv_sid);
1346 fprintf(fp, "ssn=%u,", info->rcv_ssn);
1348 print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
1349 fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
1350 fprintf(fp, "tsn=%u,", info->rcv_tsn);
1351 fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
1352 fprintf(fp, "ctx=%u,", info->rcv_context);
1353 fprintf(fp, "id=%u}", info->rcv_assoc_id);
1357 print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
1359 fprintf(fp, "{sid=%u,", info->nxt_sid);
1361 print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
1362 fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
1363 fprintf(fp, "len=%u,", info->nxt_length);
1364 fprintf(fp, "id=%u}", info->nxt_assoc_id);
1368 print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
1371 print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
1372 fprintf(fp, ",val=%u}", info->pr_value);
1376 print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
1378 fprintf(fp, "{num=%u}", info->auth_keynumber);
1382 print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
1384 char buf[INET_ADDRSTRLEN];
1387 s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
1389 fprintf(fp, "{addr=%s}", s);
1391 fputs("{addr=???}", fp);
1395 print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
1397 char buf[INET6_ADDRSTRLEN];
1400 s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
1402 fprintf(fp, "{addr=%s}", s);
1404 fputs("{addr=???}", fp);
1408 print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
1413 len = cmsghdr->cmsg_len;
1414 data = CMSG_DATA(cmsghdr);
1415 switch (cmsghdr->cmsg_type) {
1417 if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
1418 print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
1420 print_gen_cmsg(fp, cmsghdr);
1423 if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
1424 print_sctp_sndrcvinfo(fp, receive,
1425 (struct sctp_sndrcvinfo *)data);
1427 print_gen_cmsg(fp, cmsghdr);
1431 if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
1432 print_sctp_extrcvinfo(fp,
1433 (struct sctp_extrcvinfo *)data);
1435 print_gen_cmsg(fp, cmsghdr);
1439 if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
1440 print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
1442 print_gen_cmsg(fp, cmsghdr);
1445 if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
1446 print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
1448 print_gen_cmsg(fp, cmsghdr);
1451 if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
1452 print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
1454 print_gen_cmsg(fp, cmsghdr);
1457 if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
1458 print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
1460 print_gen_cmsg(fp, cmsghdr);
1463 if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
1464 print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
1466 print_gen_cmsg(fp, cmsghdr);
1468 case SCTP_DSTADDRV4:
1469 if (len == CMSG_LEN(sizeof(struct in_addr)))
1470 print_sctp_ipv4_addr(fp, (struct in_addr *)data);
1472 print_gen_cmsg(fp, cmsghdr);
1474 case SCTP_DSTADDRV6:
1475 if (len == CMSG_LEN(sizeof(struct in6_addr)))
1476 print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
1478 print_gen_cmsg(fp, cmsghdr);
1481 print_gen_cmsg(fp, cmsghdr);
1486 print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
1488 struct cmsghdr *cmsghdr;
1495 len = msghdr->msg_controllen;
1500 cmsgbuf = calloc(1, len);
1501 if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) {
1502 fprintf(fp, "%p", msghdr->msg_control);
1506 msghdr->msg_control = cmsgbuf;
1509 for (cmsghdr = CMSG_FIRSTHDR(msghdr);
1511 cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
1512 level = cmsghdr->cmsg_level;
1513 type = cmsghdr->cmsg_type;
1514 len = cmsghdr->cmsg_len;
1515 fprintf(fp, "%s{level=", first ? "" : ",");
1516 print_integer_arg(sysdecode_sockopt_level, fp, level);
1517 fputs(",type=", fp);
1518 temp = sysdecode_cmsg_type(level, type);
1522 fprintf(fp, "%d", type);
1524 fputs(",data=", fp);
1527 print_sctp_cmsg(fp, receive, cmsghdr);
1530 print_gen_cmsg(fp, cmsghdr);
1541 * Converts a syscall argument into a string. Said string is
1542 * allocated via malloc(), so needs to be free()'d. sc is
1543 * a pointer to the syscall description (see above); args is
1544 * an array of all of the system call arguments.
1547 print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
1548 struct trussinfo *trussinfo)
1555 fp = open_memstream(&tmp, &tmplen);
1556 pid = trussinfo->curthread->proc->pid;
1557 switch (sc->type & ARG_MASK) {
1559 fprintf(fp, "0x%x", (int)args[sc->offset]);
1562 fprintf(fp, "0%o", (int)args[sc->offset]);
1565 fprintf(fp, "%d", (int)args[sc->offset]);
1568 fprintf(fp, "%u", (unsigned int)args[sc->offset]);
1573 if (get_struct(pid, (void *)args[sc->offset], &val,
1575 fprintf(fp, "{ %u }", val);
1577 fprintf(fp, "0x%lx", args[sc->offset]);
1581 fprintf(fp, "0x%lx", args[sc->offset]);
1584 fprintf(fp, "%ld", args[sc->offset]);
1587 fprintf(fp, "%zu", (size_t)args[sc->offset]);
1590 /* NULL-terminated string. */
1593 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
1594 fprintf(fp, "\"%s\"", tmp2);
1600 * Binary block of data that might have printable characters.
1601 * XXX If type|OUT, assume that the length is the syscall's
1602 * return value. Otherwise, assume that the length of the block
1603 * is in the next syscall argument.
1605 int max_string = trussinfo->strsize;
1606 char tmp2[max_string + 1], *tmp3;
1613 len = args[sc->offset + 1];
1616 * Don't print more than max_string characters, to avoid word
1617 * wrap. If we have to truncate put some ... after the string.
1619 if (len > max_string) {
1623 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
1625 tmp3 = malloc(len * 4 + 1);
1627 if (strvisx(tmp3, tmp2, len,
1628 VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
1633 fprintf(fp, "\"%s\"%s", tmp3, truncated ?
1637 fprintf(fp, "0x%lx", args[sc->offset]);
1647 char buf[PAGE_SIZE];
1654 * Only parse argv[] and environment arrays from exec calls
1657 if (((sc->type & ARG_MASK) == ExecArgs &&
1658 (trussinfo->flags & EXECVEARGS) == 0) ||
1659 ((sc->type & ARG_MASK) == ExecEnv &&
1660 (trussinfo->flags & EXECVEENVS) == 0)) {
1661 fprintf(fp, "0x%lx", args[sc->offset]);
1666 * Read a page of pointers at a time. Punt if the top-level
1667 * pointer is not aligned. Note that the first read is of
1670 addr = args[sc->offset];
1671 if (addr % sizeof(char *) != 0) {
1672 fprintf(fp, "0x%lx", args[sc->offset]);
1676 len = PAGE_SIZE - (addr & PAGE_MASK);
1677 if (get_struct(pid, (void *)addr, u.buf, len) == -1) {
1678 fprintf(fp, "0x%lx", args[sc->offset]);
1685 while (u.strarray[i] != NULL) {
1686 string = get_string(pid, u.strarray[i], 0);
1687 fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
1692 if (i == len / sizeof(char *)) {
1695 if (get_struct(pid, (void *)addr, u.buf, len) ==
1697 fprintf(fp, ", <inval>");
1708 fprintf(fp, "%ld", args[sc->offset]);
1711 fprintf(fp, "0x%lx", args[sc->offset]);
1716 unsigned long long ll;
1718 #if _BYTE_ORDER == _LITTLE_ENDIAN
1719 ll = (unsigned long long)args[sc->offset + 1] << 32 |
1722 ll = (unsigned long long)args[sc->offset] << 32 |
1723 args[sc->offset + 1];
1725 if ((sc->type & ARG_MASK) == Quad)
1726 fprintf(fp, "%lld", ll);
1728 fprintf(fp, "0x%llx", ll);
1735 if (get_struct(pid, (void *)args[sc->offset], &val,
1737 fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
1739 fprintf(fp, "0x%lx", args[sc->offset]);
1743 fprintf(fp, "0x%lx", args[sc->offset]);
1748 if (retval[0] == -1)
1750 tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]);
1751 fprintf(fp, "\"%s\"", tmp2);
1759 cmd = args[sc->offset];
1760 temp = sysdecode_ioctlname(cmd);
1764 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1765 cmd, cmd & IOC_OUT ? "R" : "",
1766 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
1767 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
1768 cmd & 0xFF, IOCPARM_LEN(cmd));
1775 if (get_struct(pid, (void *)args[sc->offset], &ts,
1777 fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
1780 fprintf(fp, "0x%lx", args[sc->offset]);
1784 struct timespec ts[2];
1788 if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
1792 for (i = 0; i < nitems(ts); i++) {
1795 switch (ts[i].tv_nsec) {
1797 fprintf(fp, "UTIME_NOW");
1800 fprintf(fp, "UTIME_OMIT");
1803 fprintf(fp, "%jd.%09ld",
1804 (intmax_t)ts[i].tv_sec,
1811 fprintf(fp, "0x%lx", args[sc->offset]);
1817 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1819 fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
1822 fprintf(fp, "0x%lx", args[sc->offset]);
1826 struct timeval tv[2];
1828 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1830 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1831 (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
1832 (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
1834 fprintf(fp, "0x%lx", args[sc->offset]);
1838 struct itimerval itv;
1840 if (get_struct(pid, (void *)args[sc->offset], &itv,
1842 fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
1843 (intmax_t)itv.it_interval.tv_sec,
1844 itv.it_interval.tv_usec,
1845 (intmax_t)itv.it_value.tv_sec,
1846 itv.it_value.tv_usec);
1848 fprintf(fp, "0x%lx", args[sc->offset]);
1853 struct linux_socketcall_args largs;
1855 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1856 sizeof(largs)) != -1)
1857 fprintf(fp, "{ %s, 0x%lx }",
1858 lookup(linux_socketcall_ops, largs.what, 10),
1859 (long unsigned int)largs.args);
1861 fprintf(fp, "0x%lx", args[sc->offset]);
1866 * XXX: A Pollfd argument expects the /next/ syscall argument
1867 * to be the number of fds in the array. This matches the poll
1871 int numfds = args[sc->offset + 1];
1872 size_t bytes = sizeof(struct pollfd) * numfds;
1875 if ((pfd = malloc(bytes)) == NULL)
1876 err(1, "Cannot malloc %zu bytes for pollfd array",
1878 if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
1881 for (i = 0; i < numfds; i++) {
1882 fprintf(fp, " %d/%s", pfd[i].fd,
1883 xlookup_bits(poll_flags, pfd[i].events));
1887 fprintf(fp, "0x%lx", args[sc->offset]);
1894 * XXX: A Fd_set argument expects the /first/ syscall argument
1895 * to be the number of fds in the array. This matches the
1899 int numfds = args[0];
1900 size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1903 if ((fds = malloc(bytes)) == NULL)
1904 err(1, "Cannot malloc %zu bytes for fd_set array",
1906 if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
1909 for (i = 0; i < numfds; i++) {
1910 if (FD_ISSET(i, fds))
1911 fprintf(fp, " %d", i);
1915 fprintf(fp, "0x%lx", args[sc->offset]);
1920 fputs(strsig2(args[sc->offset]), fp);
1927 sig = args[sc->offset];
1928 if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1929 sizeof(ss)) == -1) {
1930 fprintf(fp, "0x%lx", args[sc->offset]);
1935 for (i = 1; i < sys_nsig; i++) {
1936 if (sigismember(&ss, i)) {
1937 fprintf(fp, "%s%s", !first ? "|" : "",
1948 print_integer_arg(sysdecode_sigprocmask_how, fp,
1952 /* XXX: Output depends on the value of the previous argument. */
1953 if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
1954 sysdecode_fcntl_arg(fp, args[sc->offset - 1],
1955 args[sc->offset], 16);
1958 print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
1961 print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
1964 print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
1967 print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
1970 print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
1973 print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
1976 print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
1979 print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
1982 print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
1985 print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
1988 print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
1991 print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
1996 if (args[sc->offset] == 0) {
2002 * Extract the address length from the next argument. If
2003 * this is an output sockaddr (OUT is set), then the
2004 * next argument is a pointer to a socklen_t. Otherwise
2005 * the next argument contains a socklen_t by value.
2007 if (sc->type & OUT) {
2008 if (get_struct(pid, (void *)args[sc->offset + 1],
2009 &len, sizeof(len)) == -1) {
2010 fprintf(fp, "0x%lx", args[sc->offset]);
2014 len = args[sc->offset + 1];
2016 print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len);
2020 struct sigaction sa;
2022 if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
2025 if (sa.sa_handler == SIG_DFL)
2026 fputs("SIG_DFL", fp);
2027 else if (sa.sa_handler == SIG_IGN)
2028 fputs("SIG_IGN", fp);
2030 fprintf(fp, "%p", sa.sa_handler);
2031 fprintf(fp, " %s ss_t }",
2032 xlookup_bits(sigaction_flags, sa.sa_flags));
2034 fprintf(fp, "0x%lx", args[sc->offset]);
2039 * XXX XXX: The size of the array is determined by either the
2040 * next syscall argument, or by the syscall return value,
2041 * depending on which argument number we are. This matches the
2042 * kevent syscall, but luckily that's the only syscall that uses
2050 if (sc->offset == 1)
2051 numevents = args[sc->offset+1];
2052 else if (sc->offset == 3 && retval[0] != -1)
2053 numevents = retval[0];
2055 if (numevents >= 0) {
2056 bytes = sizeof(struct kevent) * numevents;
2057 if ((ke = malloc(bytes)) == NULL)
2059 "Cannot malloc %zu bytes for kevent array",
2063 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2066 for (i = 0; i < numevents; i++) {
2068 print_kevent(fp, &ke[i]);
2072 fprintf(fp, "0x%lx", args[sc->offset]);
2078 struct kevent_freebsd11 *ke11;
2084 if (sc->offset == 1)
2085 numevents = args[sc->offset+1];
2086 else if (sc->offset == 3 && retval[0] != -1)
2087 numevents = retval[0];
2089 if (numevents >= 0) {
2090 bytes = sizeof(struct kevent_freebsd11) * numevents;
2091 if ((ke11 = malloc(bytes)) == NULL)
2093 "Cannot malloc %zu bytes for kevent array",
2097 memset(&ke, 0, sizeof(ke));
2098 if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
2099 ke11, bytes) != -1) {
2101 for (i = 0; i < numevents; i++) {
2103 ke.ident = ke11[i].ident;
2104 ke.filter = ke11[i].filter;
2105 ke.flags = ke11[i].flags;
2106 ke.fflags = ke11[i].fflags;
2107 ke.data = ke11[i].data;
2108 ke.udata = ke11[i].udata;
2109 print_kevent(fp, &ke);
2113 fprintf(fp, "0x%lx", args[sc->offset]);
2121 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2125 strmode(st.st_mode, mode);
2127 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2128 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2129 (long)st.st_blksize);
2131 fprintf(fp, "0x%lx", args[sc->offset]);
2136 struct freebsd11_stat st;
2138 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
2142 strmode(st.st_mode, mode);
2144 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
2145 (uintmax_t)st.st_ino, (intmax_t)st.st_size,
2146 (long)st.st_blksize);
2148 fprintf(fp, "0x%lx", args[sc->offset]);
2156 if (get_struct(pid, (void *)args[sc->offset], &buf,
2157 sizeof(buf)) != -1) {
2160 bzero(fsid, sizeof(fsid));
2161 if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
2162 for (i = 0; i < sizeof(buf.f_fsid); i++)
2163 snprintf(&fsid[i*2],
2164 sizeof(fsid) - (i*2), "%02x",
2165 ((u_char *)&buf.f_fsid)[i]);
2168 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
2169 "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
2170 buf.f_mntfromname, fsid);
2172 fprintf(fp, "0x%lx", args[sc->offset]);
2179 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
2182 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
2183 (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
2184 (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
2185 ru.ru_inblock, ru.ru_oublock);
2187 fprintf(fp, "0x%lx", args[sc->offset]);
2193 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
2195 fprintf(fp, "{ cur=%ju,max=%ju }",
2196 rl.rlim_cur, rl.rlim_max);
2198 fprintf(fp, "0x%lx", args[sc->offset]);
2204 if (get_struct(pid, (void *)args[sc->offset], &status,
2205 sizeof(status)) != -1) {
2207 if (WIFCONTINUED(status))
2208 fputs("CONTINUED", fp);
2209 else if (WIFEXITED(status))
2210 fprintf(fp, "EXITED,val=%d",
2211 WEXITSTATUS(status));
2212 else if (WIFSIGNALED(status))
2213 fprintf(fp, "SIGNALED,sig=%s%s",
2214 strsig2(WTERMSIG(status)),
2215 WCOREDUMP(status) ? ",cored" : "");
2217 fprintf(fp, "STOPPED,sig=%s",
2218 strsig2(WTERMSIG(status)));
2221 fprintf(fp, "0x%lx", args[sc->offset]);
2225 print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
2228 print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
2231 print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
2234 print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]);
2237 print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
2240 print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
2243 print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
2246 print_integer_arg(sysdecode_sysarch_number, fp,
2251 * The pipe() system call in the kernel returns its
2252 * two file descriptors via return values. However,
2253 * the interface exposed by libc is that pipe()
2254 * accepts a pointer to an array of descriptors.
2255 * Format the output to match the libc API by printing
2256 * the returned file descriptors as a fake argument.
2258 * Overwrite the first retval to signal a successful
2261 fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
2268 len = args[sc->offset + 1];
2269 utrace_addr = calloc(1, len);
2270 if (get_struct(pid, (void *)args[sc->offset],
2271 (void *)utrace_addr, len) != -1)
2272 print_utrace(fp, utrace_addr, len);
2274 fprintf(fp, "0x%lx", args[sc->offset]);
2279 int descriptors[16];
2280 unsigned long i, ndescriptors;
2283 ndescriptors = args[sc->offset + 1];
2285 if (ndescriptors > nitems(descriptors)) {
2286 ndescriptors = nitems(descriptors);
2289 if (get_struct(pid, (void *)args[sc->offset],
2290 descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
2292 for (i = 0; i < ndescriptors; i++)
2293 fprintf(fp, i == 0 ? " %d" : ", %d",
2295 fprintf(fp, truncated ? ", ... }" : " }");
2297 fprintf(fp, "0x%lx", args[sc->offset]);
2301 print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
2303 case CapFcntlRights: {
2306 if (sc->type & OUT) {
2307 if (get_struct(pid, (void *)args[sc->offset], &rights,
2308 sizeof(rights)) == -1) {
2309 fprintf(fp, "0x%lx", args[sc->offset]);
2313 rights = args[sc->offset];
2314 print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
2318 print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
2323 if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
2324 fprintf(fp, "0x%x", rem);
2326 fprintf(fp, "|0x%x", rem);
2330 print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
2333 print_integer_arg(sysdecode_getfsstat_mode, fp,
2337 print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
2339 case Kldunloadflags:
2340 print_integer_arg(sysdecode_kldunload_flags, fp,
2344 print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
2347 fprintf(fp, "%u", (socklen_t)args[sc->offset]);
2349 case Sockprotocol: {
2351 int domain, protocol;
2353 domain = args[sc->offset - 2];
2354 protocol = args[sc->offset];
2355 if (protocol == 0) {
2358 temp = sysdecode_socket_protocol(domain, protocol);
2362 fprintf(fp, "%d", protocol);
2368 print_integer_arg(sysdecode_sockopt_level, fp,
2375 level = args[sc->offset - 1];
2376 name = args[sc->offset];
2377 temp = sysdecode_sockopt_name(level, name);
2381 fprintf(fp, "%d", name);
2386 print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
2389 cap_rights_t rights;
2391 if (get_struct(pid, (void *)args[sc->offset], &rights,
2392 sizeof(rights)) != -1) {
2394 sysdecode_cap_rights(fp, &rights);
2397 fprintf(fp, "0x%lx", args[sc->offset]);
2401 print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
2403 case Extattrnamespace:
2404 print_integer_arg(sysdecode_extattrnamespace, fp,
2408 print_integer_arg(sysdecode_minherit_inherit, fp,
2412 print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
2415 print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
2418 print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
2421 print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
2424 print_integer_arg(sysdecode_ptrace_request, fp,
2428 if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
2429 fprintf(fp, "%#x", (int)args[sc->offset]);
2432 print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
2435 print_integer_arg(sysdecode_rtprio_function, fp,
2439 print_integer_arg(sysdecode_scheduler_policy, fp,
2443 struct sched_param sp;
2445 if (get_struct(pid, (void *)args[sc->offset], &sp,
2447 fprintf(fp, "{ %d }", sp.sched_priority);
2449 fprintf(fp, "0x%lx", args[sc->offset]);
2455 if (get_struct(pid, (void *)args[sc->offset], &sig,
2457 fprintf(fp, "{ %s }", strsig2(sig));
2459 fprintf(fp, "0x%lx", args[sc->offset]);
2465 if (get_struct(pid, (void *)args[sc->offset], &si,
2466 sizeof(si)) != -1) {
2467 fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
2468 decode_siginfo(fp, &si);
2471 fprintf(fp, "0x%lx", args[sc->offset]);
2476 * Print argument as an array of struct iovec, where the next
2477 * syscall argument is the number of elements of the array.
2480 print_iovec(fp, trussinfo, (void *)args[sc->offset],
2481 (int)args[sc->offset + 1]);
2483 case Sctpsndrcvinfo: {
2484 struct sctp_sndrcvinfo info;
2486 if (get_struct(pid, (void *)args[sc->offset],
2487 &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
2488 fprintf(fp, "0x%lx", args[sc->offset]);
2491 print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
2495 struct msghdr msghdr;
2497 if (get_struct(pid, (void *)args[sc->offset],
2498 &msghdr, sizeof(struct msghdr)) == -1) {
2499 fprintf(fp, "0x%lx", args[sc->offset]);
2503 print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen);
2504 fprintf(fp, ",%d,", msghdr.msg_namelen);
2505 print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen);
2506 fprintf(fp, ",%d,", msghdr.msg_iovlen);
2507 print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
2508 fprintf(fp, ",%u,", msghdr.msg_controllen);
2509 print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
2514 case CloudABIAdvice:
2515 fputs(xlookup(cloudabi_advice, args[sc->offset]), fp);
2517 case CloudABIClockID:
2518 fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp);
2520 case ClouduABIFDSFlags:
2521 fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp);
2523 case CloudABIFDStat: {
2524 cloudabi_fdstat_t fds;
2525 if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds))
2527 fprintf(fp, "{ %s, ",
2528 xlookup(cloudabi_filetype, fds.fs_filetype));
2529 fprintf(fp, "%s, ... }",
2530 xlookup_bits(cloudabi_fdflags, fds.fs_flags));
2532 fprintf(fp, "0x%lx", args[sc->offset]);
2535 case CloudABIFileStat: {
2536 cloudabi_filestat_t fsb;
2537 if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb))
2539 fprintf(fp, "{ %s, %ju }",
2540 xlookup(cloudabi_filetype, fsb.st_filetype),
2541 (uintmax_t)fsb.st_size);
2543 fprintf(fp, "0x%lx", args[sc->offset]);
2546 case CloudABIFileType:
2547 fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp);
2549 case CloudABIFSFlags:
2550 fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp);
2552 case CloudABILookup:
2553 if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0)
2554 fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW",
2555 (int)args[sc->offset]);
2557 fprintf(fp, "%d", (int)args[sc->offset]);
2559 case CloudABIMFlags:
2560 fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp);
2563 fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp);
2565 case CloudABIMSFlags:
2566 fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp);
2568 case CloudABIOFlags:
2569 fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp);
2571 case CloudABISDFlags:
2572 fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp);
2574 case CloudABISignal:
2575 fputs(xlookup(cloudabi_signal, args[sc->offset]), fp);
2577 case CloudABITimestamp:
2578 fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000,
2579 args[sc->offset] % 1000000000);
2581 case CloudABIULFlags:
2582 fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp);
2584 case CloudABIWhence:
2585 fputs(xlookup(cloudabi_whence, args[sc->offset]), fp);
2589 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
2596 * Print (to outfile) the system call and its arguments.
2599 print_syscall(struct trussinfo *trussinfo)
2601 struct threadinfo *t;
2606 t = trussinfo->curthread;
2608 name = t->cs.sc->name;
2609 nargs = t->cs.nargs;
2610 s_args = t->cs.s_args;
2612 len = print_line_prefix(trussinfo);
2613 len += fprintf(trussinfo->outfile, "%s(", name);
2615 for (i = 0; i < nargs; i++) {
2616 if (s_args[i] != NULL)
2617 len += fprintf(trussinfo->outfile, "%s", s_args[i]);
2619 len += fprintf(trussinfo->outfile,
2620 "<missing argument>");
2621 len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
2624 len += fprintf(trussinfo->outfile, ")");
2625 for (i = 0; i < 6 - (len / 8); i++)
2626 fprintf(trussinfo->outfile, "\t");
2630 print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval)
2632 struct timespec timediff;
2633 struct threadinfo *t;
2637 t = trussinfo->curthread;
2639 if (trussinfo->flags & COUNTONLY) {
2640 timespecsubt(&t->after, &t->before, &timediff);
2641 timespecadd(&sc->time, &timediff, &sc->time);
2648 print_syscall(trussinfo);
2649 fflush(trussinfo->outfile);
2651 if (retval == NULL) {
2653 * This system call resulted in the current thread's exit,
2654 * so there is no return value or error to display.
2656 fprintf(trussinfo->outfile, "\n");
2661 error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi,
2663 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0],
2664 error == INT_MAX ? "Unknown error" : strerror(error));
2667 else if (sc->ret_type == 2) {
2670 #if _BYTE_ORDER == _LITTLE_ENDIAN
2671 off = (off_t)retval[1] << 32 | retval[0];
2673 off = (off_t)retval[0] << 32 | retval[1];
2675 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
2680 fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0],
2685 print_summary(struct trussinfo *trussinfo)
2687 struct timespec total = {0, 0};
2691 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
2692 "syscall", "seconds", "calls", "errors");
2694 STAILQ_FOREACH(sc, &syscalls, entries)
2696 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2697 sc->name, (intmax_t)sc->time.tv_sec,
2698 sc->time.tv_nsec, sc->ncalls, sc->nerror);
2699 timespecadd(&total, &sc->time, &total);
2700 ncall += sc->ncalls;
2701 nerror += sc->nerror;
2703 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
2704 "", "-------------", "-------", "-------");
2705 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
2706 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);