2 * Copyright 1997 Sean Eric Fagan
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Sean Eric Fagan
15 * 4. Neither the name of the author may be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
36 * This file has routines used to print out system calls and their
40 #include <sys/types.h>
41 #include <sys/event.h>
42 #include <sys/ioccom.h>
44 #include <sys/mount.h>
45 #include <sys/procctl.h>
46 #include <sys/ptrace.h>
47 #include <sys/resource.h>
48 #include <sys/socket.h>
53 #include <machine/sysarch.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
68 #include <sysdecode.h>
73 #include <compat/cloudabi/cloudabi_syscalldefs.h>
79 /* 64-bit alignment on 32-bit platforms. */
80 #if !defined(__LP64__) && defined(__powerpc__)
86 /* Number of slots needed for a 64-bit argument. */
94 * This should probably be in its own file, sorted alphabetically.
96 static struct syscall decoded_syscalls
[] = {
98 { .name
= "__getcwd", .ret_type
= 1, .nargs
= 2,
99 .args
= { { Name
| OUT
, 0 }, { Int
, 1 } } },
100 { .name
= "_umtx_op", .ret_type
= 1, .nargs
= 5,
101 .args
= { { Ptr
, 0 }, { Umtxop
, 1 }, { LongHex
, 2 }, { Ptr
, 3 },
103 { .name
= "accept", .ret_type
= 1, .nargs
= 3,
104 .args
= { { Int
, 0 }, { Sockaddr
| OUT
, 1 }, { Ptr
| OUT
, 2 } } },
105 { .name
= "access", .ret_type
= 1, .nargs
= 2,
106 .args
= { { Name
| IN
, 0 }, { Accessmode
, 1 } } },
107 { .name
= "bind", .ret_type
= 1, .nargs
= 3,
108 .args
= { { Int
, 0 }, { Sockaddr
| IN
, 1 }, { Int
, 2 } } },
109 { .name
= "bindat", .ret_type
= 1, .nargs
= 4,
110 .args
= { { Atfd
, 0 }, { Int
, 1 }, { Sockaddr
| IN
, 2 },
112 { .name
= "break", .ret_type
= 1, .nargs
= 1,
113 .args
= { { Ptr
, 0 } } },
114 { .name
= "chdir", .ret_type
= 1, .nargs
= 1,
115 .args
= { { Name
, 0 } } },
116 { .name
= "chflags", .ret_type
= 1, .nargs
= 2,
117 .args
= { { Name
| IN
, 0 }, { Hex
, 1 } } },
118 { .name
= "chmod", .ret_type
= 1, .nargs
= 2,
119 .args
= { { Name
, 0 }, { Octal
, 1 } } },
120 { .name
= "chown", .ret_type
= 1, .nargs
= 3,
121 .args
= { { Name
, 0 }, { Int
, 1 }, { Int
, 2 } } },
122 { .name
= "chroot", .ret_type
= 1, .nargs
= 1,
123 .args
= { { Name
, 0 } } },
124 { .name
= "clock_gettime", .ret_type
= 1, .nargs
= 2,
125 .args
= { { Int
, 0 }, { Timespec
| OUT
, 1 } } },
126 { .name
= "close", .ret_type
= 1, .nargs
= 1,
127 .args
= { { Int
, 0 } } },
128 { .name
= "connect", .ret_type
= 1, .nargs
= 3,
129 .args
= { { Int
, 0 }, { Sockaddr
| IN
, 1 }, { Int
, 2 } } },
130 { .name
= "connectat", .ret_type
= 1, .nargs
= 4,
131 .args
= { { Atfd
, 0 }, { Int
, 1 }, { Sockaddr
| IN
, 2 },
133 { .name
= "eaccess", .ret_type
= 1, .nargs
= 2,
134 .args
= { { Name
| IN
, 0 }, { Accessmode
, 1 } } },
135 { .name
= "execve", .ret_type
= 1, .nargs
= 3,
136 .args
= { { Name
| IN
, 0 }, { ExecArgs
| IN
, 1 },
137 { ExecEnv
| IN
, 2 } } },
138 { .name
= "exit", .ret_type
= 0, .nargs
= 1,
139 .args
= { { Hex
, 0 } } },
140 { .name
= "faccessat", .ret_type
= 1, .nargs
= 4,
141 .args
= { { Atfd
, 0 }, { Name
| IN
, 1 }, { Accessmode
, 2 },
143 { .name
= "fchmod", .ret_type
= 1, .nargs
= 2,
144 .args
= { { Int
, 0 }, { Octal
, 1 } } },
145 { .name
= "fchmodat", .ret_type
= 1, .nargs
= 4,
146 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Octal
, 2 }, { Atflags
, 3 } } },
147 { .name
= "fchown", .ret_type
= 1, .nargs
= 3,
148 .args
= { { Int
, 0 }, { Int
, 1 }, { Int
, 2 } } },
149 { .name
= "fchownat", .ret_type
= 1, .nargs
= 5,
150 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Int
, 2 }, { Int
, 3 },
152 { .name
= "fcntl", .ret_type
= 1, .nargs
= 3,
153 .args
= { { Int
, 0 }, { Fcntl
, 1 }, { Fcntlflag
, 2 } } },
154 { .name
= "fstat", .ret_type
= 1, .nargs
= 2,
155 .args
= { { Int
, 0 }, { Stat
| OUT
, 1 } } },
156 { .name
= "fstatat", .ret_type
= 1, .nargs
= 4,
157 .args
= { { Atfd
, 0 }, { Name
| IN
, 1 }, { Stat
| OUT
, 2 },
159 { .name
= "fstatfs", .ret_type
= 1, .nargs
= 2,
160 .args
= { { Int
, 0 }, { StatFs
| OUT
, 1 } } },
161 { .name
= "ftruncate", .ret_type
= 1, .nargs
= 2,
162 .args
= { { Int
| IN
, 0 }, { QuadHex
| IN
, 1 + QUAD_ALIGN
} } },
163 { .name
= "futimens", .ret_type
= 1, .nargs
= 2,
164 .args
= { { Int
, 0 }, { Timespec2
| IN
, 1 } } },
165 { .name
= "futimes", .ret_type
= 1, .nargs
= 2,
166 .args
= { { Int
, 0 }, { Timeval2
| IN
, 1 } } },
167 { .name
= "futimesat", .ret_type
= 1, .nargs
= 3,
168 .args
= { { Atfd
, 0 }, { Name
| IN
, 1 }, { Timeval2
| IN
, 2 } } },
169 { .name
= "getitimer", .ret_type
= 1, .nargs
= 2,
170 .args
= { { Int
, 0 }, { Itimerval
| OUT
, 2 } } },
171 { .name
= "getpeername", .ret_type
= 1, .nargs
= 3,
172 .args
= { { Int
, 0 }, { Sockaddr
| OUT
, 1 }, { Ptr
| OUT
, 2 } } },
173 { .name
= "getpgid", .ret_type
= 1, .nargs
= 1,
174 .args
= { { Int
, 0 } } },
175 { .name
= "getrlimit", .ret_type
= 1, .nargs
= 2,
176 .args
= { { Resource
, 0 }, { Rlimit
| OUT
, 1 } } },
177 { .name
= "getrusage", .ret_type
= 1, .nargs
= 2,
178 .args
= { { Int
, 0 }, { Rusage
| OUT
, 1 } } },
179 { .name
= "getsid", .ret_type
= 1, .nargs
= 1,
180 .args
= { { Int
, 0 } } },
181 { .name
= "getsockname", .ret_type
= 1, .nargs
= 3,
182 .args
= { { Int
, 0 }, { Sockaddr
| OUT
, 1 }, { Ptr
| OUT
, 2 } } },
183 { .name
= "gettimeofday", .ret_type
= 1, .nargs
= 2,
184 .args
= { { Timeval
| OUT
, 0 }, { Ptr
, 1 } } },
185 { .name
= "ioctl", .ret_type
= 1, .nargs
= 3,
186 .args
= { { Int
, 0 }, { Ioctl
, 1 }, { Hex
, 2 } } },
187 { .name
= "kevent", .ret_type
= 1, .nargs
= 6,
188 .args
= { { Int
, 0 }, { Kevent
, 1 }, { Int
, 2 }, { Kevent
| OUT
, 3 },
189 { Int
, 4 }, { Timespec
, 5 } } },
190 { .name
= "kill", .ret_type
= 1, .nargs
= 2,
191 .args
= { { Int
| IN
, 0 }, { Signal
| IN
, 1 } } },
192 { .name
= "kldfind", .ret_type
= 1, .nargs
= 1,
193 .args
= { { Name
| IN
, 0 } } },
194 { .name
= "kldfirstmod", .ret_type
= 1, .nargs
= 1,
195 .args
= { { Int
, 0 } } },
196 { .name
= "kldload", .ret_type
= 1, .nargs
= 1,
197 .args
= { { Name
| IN
, 0 } } },
198 { .name
= "kldnext", .ret_type
= 1, .nargs
= 1,
199 .args
= { { Int
, 0 } } },
200 { .name
= "kldstat", .ret_type
= 1, .nargs
= 2,
201 .args
= { { Int
, 0 }, { Ptr
, 1 } } },
202 { .name
= "kldunload", .ret_type
= 1, .nargs
= 1,
203 .args
= { { Int
, 0 } } },
204 { .name
= "kse_release", .ret_type
= 0, .nargs
= 1,
205 .args
= { { Timespec
, 0 } } },
206 { .name
= "lchflags", .ret_type
= 1, .nargs
= 2,
207 .args
= { { Name
| IN
, 0 }, { Hex
, 1 } } },
208 { .name
= "lchmod", .ret_type
= 1, .nargs
= 2,
209 .args
= { { Name
, 0 }, { Octal
, 1 } } },
210 { .name
= "lchown", .ret_type
= 1, .nargs
= 3,
211 .args
= { { Name
, 0 }, { Int
, 1 }, { Int
, 2 } } },
212 { .name
= "link", .ret_type
= 1, .nargs
= 2,
213 .args
= { { Name
, 0 }, { Name
, 1 } } },
214 { .name
= "linkat", .ret_type
= 1, .nargs
= 5,
215 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Atfd
, 2 }, { Name
, 3 },
217 { .name
= "lseek", .ret_type
= 2, .nargs
= 3,
218 .args
= { { Int
, 0 }, { QuadHex
, 1 + QUAD_ALIGN
},
219 { Whence
, 1 + QUAD_SLOTS
+ QUAD_ALIGN
} } },
220 { .name
= "lstat", .ret_type
= 1, .nargs
= 2,
221 .args
= { { Name
| IN
, 0 }, { Stat
| OUT
, 1 } } },
222 { .name
= "lutimes", .ret_type
= 1, .nargs
= 2,
223 .args
= { { Name
| IN
, 0 }, { Timeval2
| IN
, 1 } } },
224 { .name
= "mkdir", .ret_type
= 1, .nargs
= 2,
225 .args
= { { Name
, 0 }, { Octal
, 1 } } },
226 { .name
= "mkdirat", .ret_type
= 1, .nargs
= 3,
227 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Octal
, 2 } } },
228 { .name
= "mkfifo", .ret_type
= 1, .nargs
= 2,
229 .args
= { { Name
, 0 }, { Octal
, 1 } } },
230 { .name
= "mkfifoat", .ret_type
= 1, .nargs
= 3,
231 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Octal
, 2 } } },
232 { .name
= "mknod", .ret_type
= 1, .nargs
= 3,
233 .args
= { { Name
, 0 }, { Octal
, 1 }, { Int
, 2 } } },
234 { .name
= "mknodat", .ret_type
= 1, .nargs
= 4,
235 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Octal
, 2 }, { Int
, 3 } } },
236 { .name
= "mmap", .ret_type
= 1, .nargs
= 6,
237 .args
= { { Ptr
, 0 }, { Int
, 1 }, { Mprot
, 2 }, { Mmapflags
, 3 },
238 { Int
, 4 }, { QuadHex
, 5 + QUAD_ALIGN
} } },
239 { .name
= "modfind", .ret_type
= 1, .nargs
= 1,
240 .args
= { { Name
| IN
, 0 } } },
241 { .name
= "mount", .ret_type
= 1, .nargs
= 4,
242 .args
= { { Name
, 0 }, { Name
, 1 }, { Int
, 2 }, { Ptr
, 3 } } },
243 { .name
= "mprotect", .ret_type
= 1, .nargs
= 3,
244 .args
= { { Ptr
, 0 }, { Int
, 1 }, { Mprot
, 2 } } },
245 { .name
= "munmap", .ret_type
= 1, .nargs
= 2,
246 .args
= { { Ptr
, 0 }, { Int
, 1 } } },
247 { .name
= "nanosleep", .ret_type
= 1, .nargs
= 1,
248 .args
= { { Timespec
, 0 } } },
249 { .name
= "open", .ret_type
= 1, .nargs
= 3,
250 .args
= { { Name
| IN
, 0 }, { Open
, 1 }, { Octal
, 2 } } },
251 { .name
= "openat", .ret_type
= 1, .nargs
= 4,
252 .args
= { { Atfd
, 0 }, { Name
| IN
, 1 }, { Open
, 2 },
254 { .name
= "pathconf", .ret_type
= 1, .nargs
= 2,
255 .args
= { { Name
| IN
, 0 }, { Pathconf
, 1 } } },
256 { .name
= "pipe", .ret_type
= 1, .nargs
= 1,
257 .args
= { { PipeFds
| OUT
, 0 } } },
258 { .name
= "pipe2", .ret_type
= 1, .nargs
= 2,
259 .args
= { { Ptr
, 0 }, { Open
, 1 } } },
260 { .name
= "poll", .ret_type
= 1, .nargs
= 3,
261 .args
= { { Pollfd
, 0 }, { Int
, 1 }, { Int
, 2 } } },
262 { .name
= "posix_openpt", .ret_type
= 1, .nargs
= 1,
263 .args
= { { Open
, 0 } } },
264 { .name
= "procctl", .ret_type
= 1, .nargs
= 4,
265 .args
= { { Idtype
, 0 }, { Quad
, 1 + QUAD_ALIGN
},
266 { Procctl
, 1 + QUAD_ALIGN
+ QUAD_SLOTS
},
267 { Ptr
, 2 + QUAD_ALIGN
+ QUAD_SLOTS
} } },
268 { .name
= "read", .ret_type
= 1, .nargs
= 3,
269 .args
= { { Int
, 0 }, { BinString
| OUT
, 1 }, { Int
, 2 } } },
270 { .name
= "readlink", .ret_type
= 1, .nargs
= 3,
271 .args
= { { Name
, 0 }, { Readlinkres
| OUT
, 1 }, { Int
, 2 } } },
272 { .name
= "readlinkat", .ret_type
= 1, .nargs
= 4,
273 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Readlinkres
| OUT
, 2 },
275 { .name
= "recvfrom", .ret_type
= 1, .nargs
= 6,
276 .args
= { { Int
, 0 }, { BinString
| OUT
, 1 }, { Int
, 2 }, { Hex
, 3 },
277 { Sockaddr
| OUT
, 4 }, { Ptr
| OUT
, 5 } } },
278 { .name
= "rename", .ret_type
= 1, .nargs
= 2,
279 .args
= { { Name
, 0 }, { Name
, 1 } } },
280 { .name
= "renameat", .ret_type
= 1, .nargs
= 4,
281 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Atfd
, 2 }, { Name
, 3 } } },
282 { .name
= "rfork", .ret_type
= 1, .nargs
= 1,
283 .args
= { { Rforkflags
, 0 } } },
284 { .name
= "select", .ret_type
= 1, .nargs
= 5,
285 .args
= { { Int
, 0 }, { Fd_set
, 1 }, { Fd_set
, 2 }, { Fd_set
, 3 },
287 { .name
= "sendto", .ret_type
= 1, .nargs
= 6,
288 .args
= { { Int
, 0 }, { BinString
| IN
, 1 }, { Int
, 2 }, { Hex
, 3 },
289 { Sockaddr
| IN
, 4 }, { Ptr
| IN
, 5 } } },
290 { .name
= "setitimer", .ret_type
= 1, .nargs
= 3,
291 .args
= { { Int
, 0 }, { Itimerval
, 1 }, { Itimerval
| OUT
, 2 } } },
292 { .name
= "setrlimit", .ret_type
= 1, .nargs
= 2,
293 .args
= { { Resource
, 0 }, { Rlimit
| IN
, 1 } } },
294 { .name
= "shutdown", .ret_type
= 1, .nargs
= 2,
295 .args
= { { Int
, 0 }, { Shutdown
, 1 } } },
296 { .name
= "sigaction", .ret_type
= 1, .nargs
= 3,
297 .args
= { { Signal
, 0 }, { Sigaction
| IN
, 1 },
298 { Sigaction
| OUT
, 2 } } },
299 { .name
= "sigpending", .ret_type
= 1, .nargs
= 1,
300 .args
= { { Sigset
| OUT
, 0 } } },
301 { .name
= "sigprocmask", .ret_type
= 1, .nargs
= 3,
302 .args
= { { Sigprocmask
, 0 }, { Sigset
, 1 }, { Sigset
| OUT
, 2 } } },
303 { .name
= "sigqueue", .ret_type
= 1, .nargs
= 3,
304 .args
= { { Int
, 0 }, { Signal
, 1 }, { LongHex
, 2 } } },
305 { .name
= "sigreturn", .ret_type
= 1, .nargs
= 1,
306 .args
= { { Ptr
, 0 } } },
307 { .name
= "sigsuspend", .ret_type
= 1, .nargs
= 1,
308 .args
= { { Sigset
| IN
, 0 } } },
309 { .name
= "sigtimedwait", .ret_type
= 1, .nargs
= 3,
310 .args
= { { Sigset
| IN
, 0 }, { Ptr
, 1 }, { Timespec
| IN
, 2 } } },
311 { .name
= "sigwait", .ret_type
= 1, .nargs
= 2,
312 .args
= { { Sigset
| IN
, 0 }, { Ptr
, 1 } } },
313 { .name
= "sigwaitinfo", .ret_type
= 1, .nargs
= 2,
314 .args
= { { Sigset
| IN
, 0 }, { Ptr
, 1 } } },
315 { .name
= "socket", .ret_type
= 1, .nargs
= 3,
316 .args
= { { Sockdomain
, 0 }, { Socktype
, 1 }, { Int
, 2 } } },
317 { .name
= "stat", .ret_type
= 1, .nargs
= 2,
318 .args
= { { Name
| IN
, 0 }, { Stat
| OUT
, 1 } } },
319 { .name
= "statfs", .ret_type
= 1, .nargs
= 2,
320 .args
= { { Name
| IN
, 0 }, { StatFs
| OUT
, 1 } } },
321 { .name
= "symlink", .ret_type
= 1, .nargs
= 2,
322 .args
= { { Name
, 0 }, { Name
, 1 } } },
323 { .name
= "symlinkat", .ret_type
= 1, .nargs
= 3,
324 .args
= { { Name
, 0 }, { Atfd
, 1 }, { Name
, 2 } } },
325 { .name
= "sysarch", .ret_type
= 1, .nargs
= 2,
326 .args
= { { Sysarch
, 0 }, { Ptr
, 1 } } },
327 { .name
= "thr_kill", .ret_type
= 1, .nargs
= 2,
328 .args
= { { Long
, 0 }, { Signal
, 1 } } },
329 { .name
= "thr_self", .ret_type
= 1, .nargs
= 1,
330 .args
= { { Ptr
, 0 } } },
331 { .name
= "truncate", .ret_type
= 1, .nargs
= 2,
332 .args
= { { Name
| IN
, 0 }, { QuadHex
| IN
, 1 + QUAD_ALIGN
} } },
335 { .name
= "umount", .ret_type
= 1, .nargs
= 2,
336 .args
= { { Name
, 0 }, { Int
, 2 } } },
338 { .name
= "unlink", .ret_type
= 1, .nargs
= 1,
339 .args
= { { Name
, 0 } } },
340 { .name
= "unlinkat", .ret_type
= 1, .nargs
= 3,
341 .args
= { { Atfd
, 0 }, { Name
, 1 }, { Atflags
, 2 } } },
342 { .name
= "unmount", .ret_type
= 1, .nargs
= 2,
343 .args
= { { Name
, 0 }, { Int
, 1 } } },
344 { .name
= "utimensat", .ret_type
= 1, .nargs
= 4,
345 .args
= { { Atfd
, 0 }, { Name
| IN
, 1 }, { Timespec2
| IN
, 2 },
347 { .name
= "utimes", .ret_type
= 1, .nargs
= 2,
348 .args
= { { Name
| IN
, 0 }, { Timeval2
| IN
, 1 } } },
349 { .name
= "utrace", .ret_type
= 1, .nargs
= 1,
350 .args
= { { Utrace
, 0 } } },
351 { .name
= "wait4", .ret_type
= 1, .nargs
= 4,
352 .args
= { { Int
, 0 }, { ExitStatus
| OUT
, 1 }, { Waitoptions
, 2 },
353 { Rusage
| OUT
, 3 } } },
354 { .name
= "wait6", .ret_type
= 1, .nargs
= 6,
355 .args
= { { Idtype
, 0 }, { Quad
, 1 + QUAD_ALIGN
},
356 { ExitStatus
| OUT
, 1 + QUAD_ALIGN
+ QUAD_SLOTS
},
357 { Waitoptions
, 2 + QUAD_ALIGN
+ QUAD_SLOTS
},
358 { Rusage
| OUT
, 3 + QUAD_ALIGN
+ QUAD_SLOTS
},
359 { Ptr
, 4 + QUAD_ALIGN
+ QUAD_SLOTS
} } },
360 { .name
= "write", .ret_type
= 1, .nargs
= 3,
361 .args
= { { Int
, 0 }, { BinString
| IN
, 1 }, { Int
, 2 } } },
364 { .name
= "linux_access", .ret_type
= 1, .nargs
= 2,
365 .args
= { { Name
, 0 }, { Accessmode
, 1 } } },
366 { .name
= "linux_execve", .ret_type
= 1, .nargs
= 3,
367 .args
= { { Name
| IN
, 0 }, { ExecArgs
| IN
, 1 },
368 { ExecEnv
| IN
, 2 } } },
369 { .name
= "linux_lseek", .ret_type
= 2, .nargs
= 3,
370 .args
= { { Int
, 0 }, { Int
, 1 }, { Whence
, 2 } } },
371 { .name
= "linux_mkdir", .ret_type
= 1, .nargs
= 2,
372 .args
= { { Name
| IN
, 0 }, { Int
, 1 } } },
373 { .name
= "linux_newfstat", .ret_type
= 1, .nargs
= 2,
374 .args
= { { Int
, 0 }, { Ptr
| OUT
, 1 } } },
375 { .name
= "linux_newstat", .ret_type
= 1, .nargs
= 2,
376 .args
= { { Name
| IN
, 0 }, { Ptr
| OUT
, 1 } } },
377 { .name
= "linux_open", .ret_type
= 1, .nargs
= 3,
378 .args
= { { Name
, 0 }, { Hex
, 1 }, { Octal
, 2 } } },
379 { .name
= "linux_readlink", .ret_type
= 1, .nargs
= 3,
380 .args
= { { Name
, 0 }, { Name
| OUT
, 1 }, { Int
, 2 } } },
381 { .name
= "linux_socketcall", .ret_type
= 1, .nargs
= 2,
382 .args
= { { Int
, 0 }, { LinuxSockArgs
, 1 } } },
383 { .name
= "linux_stat64", .ret_type
= 1, .nargs
= 3,
384 .args
= { { Name
| IN
, 0 }, { Ptr
| OUT
, 1 }, { Ptr
| IN
, 1 } } },
386 /* CloudABI system calls. */
387 { .name
= "cloudabi_sys_clock_res_get", .ret_type
= 1, .nargs
= 1,
388 .args
= { { CloudABIClockID
, 0 } } },
389 { .name
= "cloudabi_sys_clock_time_get", .ret_type
= 1, .nargs
= 2,
390 .args
= { { CloudABIClockID
, 0 }, { CloudABITimestamp
, 1 } } },
391 { .name
= "cloudabi_sys_condvar_signal", .ret_type
= 1, .nargs
= 3,
392 .args
= { { Ptr
, 0 }, { CloudABIMFlags
, 1 }, { UInt
, 2 } } },
393 { .name
= "cloudabi_sys_fd_close", .ret_type
= 1, .nargs
= 1,
394 .args
= { { Int
, 0 } } },
395 { .name
= "cloudabi_sys_fd_create1", .ret_type
= 1, .nargs
= 1,
396 .args
= { { CloudABIFileType
, 0 } } },
397 { .name
= "cloudabi_sys_fd_create2", .ret_type
= 1, .nargs
= 2,
398 .args
= { { CloudABIFileType
, 0 }, { PipeFds
| OUT
, 0 } } },
399 { .name
= "cloudabi_sys_fd_datasync", .ret_type
= 1, .nargs
= 1,
400 .args
= { { Int
, 0 } } },
401 { .name
= "cloudabi_sys_fd_dup", .ret_type
= 1, .nargs
= 1,
402 .args
= { { Int
, 0 } } },
403 { .name
= "cloudabi_sys_fd_replace", .ret_type
= 1, .nargs
= 2,
404 .args
= { { Int
, 0 }, { Int
, 1 } } },
405 { .name
= "cloudabi_sys_fd_seek", .ret_type
= 1, .nargs
= 3,
406 .args
= { { Int
, 0 }, { Int
, 1 }, { CloudABIWhence
, 2 } } },
407 { .name
= "cloudabi_sys_fd_stat_get", .ret_type
= 1, .nargs
= 2,
408 .args
= { { Int
, 0 }, { CloudABIFDStat
| OUT
, 1 } } },
409 { .name
= "cloudabi_sys_fd_stat_put", .ret_type
= 1, .nargs
= 3,
410 .args
= { { Int
, 0 }, { CloudABIFDStat
| IN
, 1 },
411 { ClouduABIFDSFlags
, 2 } } },
412 { .name
= "cloudabi_sys_fd_sync", .ret_type
= 1, .nargs
= 1,
413 .args
= { { Int
, 0 } } },
414 { .name
= "cloudabi_sys_file_advise", .ret_type
= 1, .nargs
= 4,
415 .args
= { { Int
, 0 }, { Int
, 1 }, { Int
, 2 },
416 { CloudABIAdvice
, 3 } } },
417 { .name
= "cloudabi_sys_file_allocate", .ret_type
= 1, .nargs
= 3,
418 .args
= { { Int
, 0 }, { Int
, 1 }, { Int
, 2 } } },
419 { .name
= "cloudabi_sys_file_create", .ret_type
= 1, .nargs
= 3,
420 .args
= { { Int
, 0 }, { BinString
| IN
, 1 },
421 { CloudABIFileType
, 3 } } },
422 { .name
= "cloudabi_sys_file_link", .ret_type
= 1, .nargs
= 4,
423 .args
= { { CloudABILookup
, 0 }, { BinString
| IN
, 1 },
424 { Int
, 3 }, { BinString
| IN
, 4 } } },
425 { .name
= "cloudabi_sys_file_open", .ret_type
= 1, .nargs
= 4,
426 .args
= { { Int
, 0 }, { BinString
| IN
, 1 },
427 { CloudABIOFlags
, 3 }, { CloudABIFDStat
| IN
, 4 } } },
428 { .name
= "cloudabi_sys_file_readdir", .ret_type
= 1, .nargs
= 4,
429 .args
= { { Int
, 0 }, { BinString
| OUT
, 1 }, { Int
, 2 },
431 { .name
= "cloudabi_sys_file_readlink", .ret_type
= 1, .nargs
= 4,
432 .args
= { { Int
, 0 }, { BinString
| IN
, 1 },
433 { BinString
| OUT
, 3 }, { Int
, 4 } } },
434 { .name
= "cloudabi_sys_file_rename", .ret_type
= 1, .nargs
= 4,
435 .args
= { { Int
, 0 }, { BinString
| IN
, 1 },
436 { Int
, 3 }, { BinString
| IN
, 4 } } },
437 { .name
= "cloudabi_sys_file_stat_fget", .ret_type
= 1, .nargs
= 2,
438 .args
= { { Int
, 0 }, { CloudABIFileStat
| OUT
, 1 } } },
439 { .name
= "cloudabi_sys_file_stat_fput", .ret_type
= 1, .nargs
= 3,
440 .args
= { { Int
, 0 }, { CloudABIFileStat
| IN
, 1 },
441 { CloudABIFSFlags
, 2 } } },
442 { .name
= "cloudabi_sys_file_stat_get", .ret_type
= 1, .nargs
= 3,
443 .args
= { { CloudABILookup
, 0 }, { BinString
| IN
, 1 },
444 { CloudABIFileStat
| OUT
, 3 } } },
445 { .name
= "cloudabi_sys_file_stat_put", .ret_type
= 1, .nargs
= 4,
446 .args
= { { CloudABILookup
, 0 }, { BinString
| IN
, 1 },
447 { CloudABIFileStat
| IN
, 3 }, { CloudABIFSFlags
, 4 } } },
448 { .name
= "cloudabi_sys_file_symlink", .ret_type
= 1, .nargs
= 3,
449 .args
= { { BinString
| IN
, 0 },
450 { Int
, 2 }, { BinString
| IN
, 3 } } },
451 { .name
= "cloudabi_sys_file_unlink", .ret_type
= 1, .nargs
= 3,
452 .args
= { { Int
, 0 }, { BinString
| IN
, 1 },
453 { CloudABIULFlags
, 3 } } },
454 { .name
= "cloudabi_sys_lock_unlock", .ret_type
= 1, .nargs
= 2,
455 .args
= { { Ptr
, 0 }, { CloudABIMFlags
, 1 } } },
456 { .name
= "cloudabi_sys_mem_advise", .ret_type
= 1, .nargs
= 3,
457 .args
= { { Ptr
, 0 }, { Int
, 1 }, { CloudABIAdvice
, 2 } } },
458 { .name
= "cloudabi_sys_mem_lock", .ret_type
= 1, .nargs
= 2,
459 .args
= { { Ptr
, 0 }, { Int
, 1 } } },
460 { .name
= "cloudabi_sys_mem_map", .ret_type
= 1, .nargs
= 6,
461 .args
= { { Ptr
, 0 }, { Int
, 1 }, { CloudABIMProt
, 2 },
462 { CloudABIMFlags
, 3 }, { Int
, 4 }, { Int
, 5 } } },
463 { .name
= "cloudabi_sys_mem_protect", .ret_type
= 1, .nargs
= 3,
464 .args
= { { Ptr
, 0 }, { Int
, 1 }, { CloudABIMProt
, 2 } } },
465 { .name
= "cloudabi_sys_mem_sync", .ret_type
= 1, .nargs
= 3,
466 .args
= { { Ptr
, 0 }, { Int
, 1 }, { CloudABIMSFlags
, 2 } } },
467 { .name
= "cloudabi_sys_mem_unlock", .ret_type
= 1, .nargs
= 2,
468 .args
= { { Ptr
, 0 }, { Int
, 1 } } },
469 { .name
= "cloudabi_sys_mem_unmap", .ret_type
= 1, .nargs
= 2,
470 .args
= { { Ptr
, 0 }, { Int
, 1 } } },
471 { .name
= "cloudabi_sys_proc_exec", .ret_type
= 1, .nargs
= 5,
472 .args
= { { Int
, 0 }, { BinString
| IN
, 1 }, { Int
, 2 },
473 { IntArray
, 3 }, { Int
, 4 } } },
474 { .name
= "cloudabi_sys_proc_exit", .ret_type
= 1, .nargs
= 1,
475 .args
= { { Int
, 0 } } },
476 { .name
= "cloudabi_sys_proc_fork", .ret_type
= 1, .nargs
= 0 },
477 { .name
= "cloudabi_sys_proc_raise", .ret_type
= 1, .nargs
= 1,
478 .args
= { { CloudABISignal
, 0 } } },
479 { .name
= "cloudabi_sys_random_get", .ret_type
= 1, .nargs
= 2,
480 .args
= { { BinString
| OUT
, 0 }, { Int
, 1 } } },
481 { .name
= "cloudabi_sys_sock_accept", .ret_type
= 1, .nargs
= 2,
482 .args
= { { Int
, 0 }, { CloudABISockStat
| OUT
, 1 } } },
483 { .name
= "cloudabi_sys_sock_bind", .ret_type
= 1, .nargs
= 3,
484 .args
= { { Int
, 0 }, { Int
, 1 }, { BinString
| IN
, 2 } } },
485 { .name
= "cloudabi_sys_sock_connect", .ret_type
= 1, .nargs
= 3,
486 .args
= { { Int
, 0 }, { Int
, 1 }, { BinString
| IN
, 2 } } },
487 { .name
= "cloudabi_sys_sock_listen", .ret_type
= 1, .nargs
= 2,
488 .args
= { { Int
, 0 }, { Int
, 1 } } },
489 { .name
= "cloudabi_sys_sock_shutdown", .ret_type
= 1, .nargs
= 2,
490 .args
= { { Int
, 0 }, { CloudABISDFlags
, 1 } } },
491 { .name
= "cloudabi_sys_sock_stat_get", .ret_type
= 1, .nargs
= 3,
492 .args
= { { Int
, 0 }, { CloudABISockStat
| OUT
, 1 },
493 { CloudABISSFlags
, 2 } } },
494 { .name
= "cloudabi_sys_thread_exit", .ret_type
= 1, .nargs
= 2,
495 .args
= { { Ptr
, 0 }, { CloudABIMFlags
, 1 } } },
496 { .name
= "cloudabi_sys_thread_tcb_set", .ret_type
= 1, .nargs
= 1,
497 .args
= { { Ptr
, 0 } } },
498 { .name
= "cloudabi_sys_thread_yield", .ret_type
= 1, .nargs
= 0 },
502 static STAILQ_HEAD(, syscall
) syscalls
;
504 /* Xlat idea taken from strace */
510 #define X(a) { a, #a },
511 #define XEND { 0, NULL }
513 static struct xlat kevent_filters
[] = {
514 X(EVFILT_READ
) X(EVFILT_WRITE
) X(EVFILT_AIO
) X(EVFILT_VNODE
)
515 X(EVFILT_PROC
) X(EVFILT_SIGNAL
) X(EVFILT_TIMER
)
516 X(EVFILT_PROCDESC
) X(EVFILT_FS
) X(EVFILT_LIO
) X(EVFILT_USER
)
517 X(EVFILT_SENDFILE
) XEND
520 static struct xlat kevent_flags
[] = {
521 X(EV_ADD
) X(EV_DELETE
) X(EV_ENABLE
) X(EV_DISABLE
) X(EV_ONESHOT
)
522 X(EV_CLEAR
) X(EV_RECEIPT
) X(EV_DISPATCH
) X(EV_FORCEONESHOT
)
523 X(EV_DROP
) X(EV_FLAG1
) X(EV_ERROR
) X(EV_EOF
) XEND
526 static struct xlat kevent_user_ffctrl
[] = {
527 X(NOTE_FFNOP
) X(NOTE_FFAND
) X(NOTE_FFOR
) X(NOTE_FFCOPY
)
531 static struct xlat kevent_rdwr_fflags
[] = {
532 X(NOTE_LOWAT
) X(NOTE_FILE_POLL
) XEND
535 static struct xlat kevent_vnode_fflags
[] = {
536 X(NOTE_DELETE
) X(NOTE_WRITE
) X(NOTE_EXTEND
) X(NOTE_ATTRIB
)
537 X(NOTE_LINK
) X(NOTE_RENAME
) X(NOTE_REVOKE
) XEND
540 static struct xlat kevent_proc_fflags
[] = {
541 X(NOTE_EXIT
) X(NOTE_FORK
) X(NOTE_EXEC
) X(NOTE_TRACK
) X(NOTE_TRACKERR
)
545 static struct xlat kevent_timer_fflags
[] = {
546 X(NOTE_SECONDS
) X(NOTE_MSECONDS
) X(NOTE_USECONDS
) X(NOTE_NSECONDS
)
550 static struct xlat poll_flags
[] = {
551 X(POLLSTANDARD
) X(POLLIN
) X(POLLPRI
) X(POLLOUT
) X(POLLERR
)
552 X(POLLHUP
) X(POLLNVAL
) X(POLLRDNORM
) X(POLLRDBAND
)
553 X(POLLWRBAND
) X(POLLINIGNEOF
) XEND
556 static struct xlat mmap_flags
[] = {
557 X(MAP_SHARED
) X(MAP_PRIVATE
) X(MAP_FIXED
) X(MAP_RESERVED0020
)
558 X(MAP_RESERVED0040
) X(MAP_RESERVED0080
) X(MAP_RESERVED0100
)
559 X(MAP_HASSEMAPHORE
) X(MAP_STACK
) X(MAP_NOSYNC
) X(MAP_ANON
)
560 X(MAP_EXCL
) X(MAP_NOCORE
) X(MAP_PREFAULT_READ
)
567 static struct xlat mprot_flags
[] = {
568 X(PROT_NONE
) X(PROT_READ
) X(PROT_WRITE
) X(PROT_EXEC
) XEND
571 static struct xlat whence_arg
[] = {
572 X(SEEK_SET
) X(SEEK_CUR
) X(SEEK_END
) X(SEEK_DATA
) X(SEEK_HOLE
) XEND
575 static struct xlat sigaction_flags
[] = {
576 X(SA_ONSTACK
) X(SA_RESTART
) X(SA_RESETHAND
) X(SA_NOCLDSTOP
)
577 X(SA_NODEFER
) X(SA_NOCLDWAIT
) X(SA_SIGINFO
) XEND
580 static struct xlat fcntl_arg
[] = {
581 X(F_DUPFD
) X(F_GETFD
) X(F_SETFD
) X(F_GETFL
) X(F_SETFL
)
582 X(F_GETOWN
) X(F_SETOWN
) X(F_OGETLK
) X(F_OSETLK
) X(F_OSETLKW
)
583 X(F_DUP2FD
) X(F_GETLK
) X(F_SETLK
) X(F_SETLKW
) X(F_SETLK_REMOTE
)
584 X(F_READAHEAD
) X(F_RDAHEAD
) X(F_DUPFD_CLOEXEC
) X(F_DUP2FD_CLOEXEC
)
588 static struct xlat fcntlfd_arg
[] = {
592 static struct xlat fcntlfl_arg
[] = {
593 X(O_APPEND
) X(O_ASYNC
) X(O_FSYNC
) X(O_NONBLOCK
) X(O_NOFOLLOW
)
594 X(FRDAHEAD
) X(O_DIRECT
) XEND
597 static struct xlat sockdomain_arg
[] = {
598 X(PF_UNSPEC
) X(PF_LOCAL
) X(PF_UNIX
) X(PF_INET
) X(PF_IMPLINK
)
599 X(PF_PUP
) X(PF_CHAOS
) X(PF_NETBIOS
) X(PF_ISO
) X(PF_OSI
)
600 X(PF_ECMA
) X(PF_DATAKIT
) X(PF_CCITT
) X(PF_SNA
) X(PF_DECnet
)
601 X(PF_DLI
) X(PF_LAT
) X(PF_HYLINK
) X(PF_APPLETALK
) X(PF_ROUTE
)
602 X(PF_LINK
) X(PF_XTP
) X(PF_COIP
) X(PF_CNT
) X(PF_SIP
) X(PF_IPX
)
603 X(PF_RTIP
) X(PF_PIP
) X(PF_ISDN
) X(PF_KEY
) X(PF_INET6
)
604 X(PF_NATM
) X(PF_ATM
) X(PF_NETGRAPH
) X(PF_SLOW
) X(PF_SCLUSTER
)
605 X(PF_ARP
) X(PF_BLUETOOTH
) X(PF_IEEE80211
) X(PF_INET_SDP
)
609 static struct xlat socktype_arg
[] = {
610 X(SOCK_STREAM
) X(SOCK_DGRAM
) X(SOCK_RAW
) X(SOCK_RDM
)
611 X(SOCK_SEQPACKET
) XEND
614 static struct xlat open_flags
[] = {
615 X(O_RDONLY
) X(O_WRONLY
) X(O_RDWR
) X(O_ACCMODE
) X(O_NONBLOCK
)
616 X(O_APPEND
) X(O_SHLOCK
) X(O_EXLOCK
) X(O_ASYNC
) X(O_FSYNC
)
617 X(O_NOFOLLOW
) X(O_CREAT
) X(O_TRUNC
) X(O_EXCL
) X(O_NOCTTY
)
618 X(O_DIRECT
) X(O_DIRECTORY
) X(O_EXEC
) X(O_TTY_INIT
) X(O_CLOEXEC
)
622 static struct xlat shutdown_arg
[] = {
623 X(SHUT_RD
) X(SHUT_WR
) X(SHUT_RDWR
) XEND
626 static struct xlat resource_arg
[] = {
627 X(RLIMIT_CPU
) X(RLIMIT_FSIZE
) X(RLIMIT_DATA
) X(RLIMIT_STACK
)
628 X(RLIMIT_CORE
) X(RLIMIT_RSS
) X(RLIMIT_MEMLOCK
) X(RLIMIT_NPROC
)
629 X(RLIMIT_NOFILE
) X(RLIMIT_SBSIZE
) X(RLIMIT_VMEM
) X(RLIMIT_NPTS
)
630 X(RLIMIT_SWAP
) X(RLIMIT_KQUEUES
) XEND
633 static struct xlat pathconf_arg
[] = {
634 X(_PC_LINK_MAX
) X(_PC_MAX_CANON
) X(_PC_MAX_INPUT
)
635 X(_PC_NAME_MAX
) X(_PC_PATH_MAX
) X(_PC_PIPE_BUF
)
636 X(_PC_CHOWN_RESTRICTED
) X(_PC_NO_TRUNC
) X(_PC_VDISABLE
)
637 X(_PC_ASYNC_IO
) X(_PC_PRIO_IO
) X(_PC_SYNC_IO
)
638 X(_PC_ALLOC_SIZE_MIN
) X(_PC_FILESIZEBITS
)
639 X(_PC_REC_INCR_XFER_SIZE
) X(_PC_REC_MAX_XFER_SIZE
)
640 X(_PC_REC_MIN_XFER_SIZE
) X(_PC_REC_XFER_ALIGN
)
641 X(_PC_SYMLINK_MAX
) X(_PC_ACL_EXTENDED
) X(_PC_ACL_PATH_MAX
)
642 X(_PC_CAP_PRESENT
) X(_PC_INF_PRESENT
) X(_PC_MAC_PRESENT
)
643 X(_PC_ACL_NFS4
) X(_PC_MIN_HOLE_SIZE
) XEND
646 static struct xlat rfork_flags
[] = {
647 X(RFFDG
) X(RFPROC
) X(RFMEM
) X(RFNOWAIT
) X(RFCFDG
) X(RFTHREAD
)
648 X(RFSIGSHARE
) X(RFLINUXTHPN
) X(RFTSIGZMB
) X(RFPPWAIT
) XEND
651 static struct xlat wait_options
[] = {
652 X(WNOHANG
) X(WUNTRACED
) X(WCONTINUED
) X(WNOWAIT
) X(WEXITED
)
656 static struct xlat idtype_arg
[] = {
657 X(P_PID
) X(P_PPID
) X(P_PGID
) X(P_SID
) X(P_CID
) X(P_UID
) X(P_GID
)
658 X(P_ALL
) X(P_LWPID
) X(P_TASKID
) X(P_PROJID
) X(P_POOLID
) X(P_JAILID
)
659 X(P_CTID
) X(P_CPUID
) X(P_PSETID
) XEND
662 static struct xlat procctl_arg
[] = {
663 X(PROC_SPROTECT
) X(PROC_REAP_ACQUIRE
) X(PROC_REAP_RELEASE
)
664 X(PROC_REAP_STATUS
) X(PROC_REAP_GETPIDS
) X(PROC_REAP_KILL
)
665 X(PROC_TRACE_CTL
) X(PROC_TRACE_STATUS
) XEND
668 static struct xlat umtx_ops
[] = {
669 X(UMTX_OP_RESERVED0
) X(UMTX_OP_RESERVED1
) X(UMTX_OP_WAIT
)
670 X(UMTX_OP_WAKE
) X(UMTX_OP_MUTEX_TRYLOCK
) X(UMTX_OP_MUTEX_LOCK
)
671 X(UMTX_OP_MUTEX_UNLOCK
) X(UMTX_OP_SET_CEILING
) X(UMTX_OP_CV_WAIT
)
672 X(UMTX_OP_CV_SIGNAL
) X(UMTX_OP_CV_BROADCAST
) X(UMTX_OP_WAIT_UINT
)
673 X(UMTX_OP_RW_RDLOCK
) X(UMTX_OP_RW_WRLOCK
) X(UMTX_OP_RW_UNLOCK
)
674 X(UMTX_OP_WAIT_UINT_PRIVATE
) X(UMTX_OP_WAKE_PRIVATE
)
675 X(UMTX_OP_MUTEX_WAIT
) X(UMTX_OP_MUTEX_WAKE
) X(UMTX_OP_SEM_WAIT
)
676 X(UMTX_OP_SEM_WAKE
) X(UMTX_OP_NWAKE_PRIVATE
) X(UMTX_OP_MUTEX_WAKE2
)
677 X(UMTX_OP_SEM2_WAIT
) X(UMTX_OP_SEM2_WAKE
)
681 static struct xlat at_flags
[] = {
682 X(AT_EACCESS
) X(AT_SYMLINK_NOFOLLOW
) X(AT_SYMLINK_FOLLOW
)
686 static struct xlat access_modes
[] = {
687 X(R_OK
) X(W_OK
) X(X_OK
) XEND
690 static struct xlat sysarch_ops
[] = {
691 #if defined(__i386__) || defined(__amd64__)
692 X(I386_GET_LDT
) X(I386_SET_LDT
) X(I386_GET_IOPERM
) X(I386_SET_IOPERM
)
693 X(I386_VM86
) X(I386_GET_FSBASE
) X(I386_SET_FSBASE
) X(I386_GET_GSBASE
)
694 X(I386_SET_GSBASE
) X(I386_GET_XFPUSTATE
) X(AMD64_GET_FSBASE
)
695 X(AMD64_SET_FSBASE
) X(AMD64_GET_GSBASE
) X(AMD64_SET_GSBASE
)
696 X(AMD64_GET_XFPUSTATE
)
701 static struct xlat linux_socketcall_ops
[] = {
702 X(LINUX_SOCKET
) X(LINUX_BIND
) X(LINUX_CONNECT
) X(LINUX_LISTEN
)
703 X(LINUX_ACCEPT
) X(LINUX_GETSOCKNAME
) X(LINUX_GETPEERNAME
)
704 X(LINUX_SOCKETPAIR
) X(LINUX_SEND
) X(LINUX_RECV
) X(LINUX_SENDTO
)
705 X(LINUX_RECVFROM
) X(LINUX_SHUTDOWN
) X(LINUX_SETSOCKOPT
)
706 X(LINUX_GETSOCKOPT
) X(LINUX_SENDMSG
) X(LINUX_RECVMSG
)
710 static struct xlat sigprocmask_ops
[] = {
711 X(SIG_BLOCK
) X(SIG_UNBLOCK
) X(SIG_SETMASK
)
716 #define X(a) { CLOUDABI_##a, #a },
718 static struct xlat cloudabi_advice
[] = {
719 X(ADVICE_DONTNEED
) X(ADVICE_NOREUSE
) X(ADVICE_NORMAL
)
720 X(ADVICE_RANDOM
) X(ADVICE_SEQUENTIAL
) X(ADVICE_WILLNEED
)
724 static struct xlat cloudabi_clockid
[] = {
725 X(CLOCK_MONOTONIC
) X(CLOCK_PROCESS_CPUTIME_ID
)
726 X(CLOCK_REALTIME
) X(CLOCK_THREAD_CPUTIME_ID
)
730 static struct xlat cloudabi_errno
[] = {
731 X(E2BIG
) X(EACCES
) X(EADDRINUSE
) X(EADDRNOTAVAIL
)
732 X(EAFNOSUPPORT
) X(EAGAIN
) X(EALREADY
) X(EBADF
) X(EBADMSG
)
733 X(EBUSY
) X(ECANCELED
) X(ECHILD
) X(ECONNABORTED
) X(ECONNREFUSED
)
734 X(ECONNRESET
) X(EDEADLK
) X(EDESTADDRREQ
) X(EDOM
) X(EDQUOT
)
735 X(EEXIST
) X(EFAULT
) X(EFBIG
) X(EHOSTUNREACH
) X(EIDRM
) X(EILSEQ
)
736 X(EINPROGRESS
) X(EINTR
) X(EINVAL
) X(EIO
) X(EISCONN
) X(EISDIR
)
737 X(ELOOP
) X(EMFILE
) X(EMLINK
) X(EMSGSIZE
) X(EMULTIHOP
)
738 X(ENAMETOOLONG
) X(ENETDOWN
) X(ENETRESET
) X(ENETUNREACH
)
739 X(ENFILE
) X(ENOBUFS
) X(ENODEV
) X(ENOENT
) X(ENOEXEC
) X(ENOLCK
)
740 X(ENOLINK
) X(ENOMEM
) X(ENOMSG
) X(ENOPROTOOPT
) X(ENOSPC
)
741 X(ENOSYS
) X(ENOTCONN
) X(ENOTDIR
) X(ENOTEMPTY
) X(ENOTRECOVERABLE
)
742 X(ENOTSOCK
) X(ENOTSUP
) X(ENOTTY
) X(ENXIO
) X(EOVERFLOW
)
743 X(EOWNERDEAD
) X(EPERM
) X(EPIPE
) X(EPROTO
) X(EPROTONOSUPPORT
)
744 X(EPROTOTYPE
) X(ERANGE
) X(EROFS
) X(ESPIPE
) X(ESRCH
) X(ESTALE
)
745 X(ETIMEDOUT
) X(ETXTBSY
) X(EXDEV
) X(ENOTCAPABLE
)
749 static struct xlat cloudabi_fdflags
[] = {
750 X(FDFLAG_APPEND
) X(FDFLAG_DSYNC
) X(FDFLAG_NONBLOCK
)
751 X(FDFLAG_RSYNC
) X(FDFLAG_SYNC
)
755 static struct xlat cloudabi_fdsflags
[] = {
756 X(FDSTAT_FLAGS
) X(FDSTAT_RIGHTS
)
760 static struct xlat cloudabi_filetype
[] = {
761 X(FILETYPE_UNKNOWN
) X(FILETYPE_BLOCK_DEVICE
)
762 X(FILETYPE_CHARACTER_DEVICE
) X(FILETYPE_DIRECTORY
)
763 X(FILETYPE_FIFO
) X(FILETYPE_POLL
) X(FILETYPE_PROCESS
)
764 X(FILETYPE_REGULAR_FILE
) X(FILETYPE_SHARED_MEMORY
)
765 X(FILETYPE_SOCKET_DGRAM
) X(FILETYPE_SOCKET_SEQPACKET
)
766 X(FILETYPE_SOCKET_STREAM
) X(FILETYPE_SYMBOLIC_LINK
)
770 static struct xlat cloudabi_fsflags
[] = {
771 X(FILESTAT_ATIM
) X(FILESTAT_ATIM_NOW
) X(FILESTAT_MTIM
)
772 X(FILESTAT_MTIM_NOW
) X(FILESTAT_SIZE
)
776 static struct xlat cloudabi_mflags
[] = {
777 X(MAP_ANON
) X(MAP_FIXED
) X(MAP_PRIVATE
) X(MAP_SHARED
)
781 static struct xlat cloudabi_mprot
[] = {
782 X(PROT_EXEC
) X(PROT_WRITE
) X(PROT_READ
)
786 static struct xlat cloudabi_msflags
[] = {
787 X(MS_ASYNC
) X(MS_INVALIDATE
) X(MS_SYNC
)
791 static struct xlat cloudabi_oflags
[] = {
792 X(O_CREAT
) X(O_DIRECTORY
) X(O_EXCL
) X(O_TRUNC
)
796 static struct xlat cloudabi_sa_family
[] = {
797 X(AF_UNSPEC
) X(AF_INET
) X(AF_INET6
) X(AF_UNIX
)
801 static struct xlat cloudabi_sdflags
[] = {
802 X(SHUT_RD
) X(SHUT_WR
)
806 static struct xlat cloudabi_signal
[] = {
807 X(SIGABRT
) X(SIGALRM
) X(SIGBUS
) X(SIGCHLD
) X(SIGCONT
) X(SIGFPE
)
808 X(SIGHUP
) X(SIGILL
) X(SIGINT
) X(SIGKILL
) X(SIGPIPE
) X(SIGQUIT
)
809 X(SIGSEGV
) X(SIGSTOP
) X(SIGSYS
) X(SIGTERM
) X(SIGTRAP
) X(SIGTSTP
)
810 X(SIGTTIN
) X(SIGTTOU
) X(SIGURG
) X(SIGUSR1
) X(SIGUSR2
)
811 X(SIGVTALRM
) X(SIGXCPU
) X(SIGXFSZ
)
815 static struct xlat cloudabi_ssflags
[] = {
816 X(SOCKSTAT_CLEAR_ERROR
)
820 static struct xlat cloudabi_ssstate
[] = {
821 X(SOCKSTAT_ACCEPTCONN
)
825 static struct xlat cloudabi_ulflags
[] = {
830 static struct xlat cloudabi_whence
[] = {
831 X(WHENCE_CUR
) X(WHENCE_END
) X(WHENCE_SET
)
839 * Searches an xlat array for a value, and returns it if found. Otherwise
840 * return a string representation.
843 lookup(struct xlat
*xlat
, int val
, int base
)
847 for (; xlat
->str
!= NULL
; xlat
++)
848 if (xlat
->val
== val
)
852 sprintf(tmp
, "0%o", val
);
855 sprintf(tmp
, "0x%x", val
);
858 sprintf(tmp
, "%u", val
);
861 errx(1,"Unknown lookup base");
868 xlookup(struct xlat
*xlat
, int val
)
871 return (lookup(xlat
, val
, 16));
875 * Searches an xlat array containing bitfield values. Remaining bits
876 * set after removing the known ones are printed at the end:
880 xlookup_bits(struct xlat
*xlat
, int val
)
883 static char str
[512];
887 for (; xlat
->str
!= NULL
; xlat
++) {
888 if ((xlat
->val
& rem
) == xlat
->val
) {
890 * Don't print the "all-bits-zero" string unless all
891 * bits are really zero.
893 if (xlat
->val
== 0 && val
!= 0)
895 len
+= sprintf(str
+ len
, "%s|", xlat
->str
);
901 * If we have leftover bits or didn't match anything, print
905 len
+= sprintf(str
+ len
, "0x%x", rem
);
906 if (len
&& str
[len
- 1] == '|')
917 STAILQ_INIT(&syscalls
);
918 for (sc
= decoded_syscalls
; sc
->name
!= NULL
; sc
++)
919 STAILQ_INSERT_HEAD(&syscalls
, sc
, entries
);
922 * If/when the list gets big, it might be desirable to do it
923 * as a hash table or binary search.
926 get_syscall(const char *name
, int nargs
)
933 STAILQ_FOREACH(sc
, &syscalls
, entries
)
934 if (strcmp(name
, sc
->name
) == 0)
937 /* It is unknown. Add it into the list. */
939 fprintf(stderr
, "unknown syscall %s -- setting args to %d\n", name
,
943 sc
= calloc(1, sizeof(struct syscall
));
944 sc
->name
= strdup(name
);
947 for (i
= 0; i
< nargs
; i
++) {
948 sc
->args
[i
].offset
= i
;
949 /* Treat all unknown arguments as LongHex. */
950 sc
->args
[i
].type
= LongHex
;
952 STAILQ_INSERT_HEAD(&syscalls
, sc
, entries
);
958 * Copy a fixed amount of bytes from the process.
961 get_struct(pid_t pid
, void *offset
, void *buf
, int len
)
963 struct ptrace_io_desc iorequest
;
965 iorequest
.piod_op
= PIOD_READ_D
;
966 iorequest
.piod_offs
= offset
;
967 iorequest
.piod_addr
= buf
;
968 iorequest
.piod_len
= len
;
969 if (ptrace(PT_IO
, pid
, (caddr_t
)&iorequest
, 0) < 0)
977 * Copy a string from the process. Note that it is
978 * expected to be a C string, but if max is set, it will
979 * only get that much.
982 get_string(pid_t pid
, void *addr
, int max
)
984 struct ptrace_io_desc iorequest
;
986 size_t offset
, size
, totalsize
;
992 /* Read up to the end of the current page. */
993 size
= PAGE_SIZE
- ((uintptr_t)addr
% PAGE_SIZE
);
998 buf
= malloc(totalsize
);
1002 iorequest
.piod_op
= PIOD_READ_D
;
1003 iorequest
.piod_offs
= (char *)addr
+ offset
;
1004 iorequest
.piod_addr
= buf
+ offset
;
1005 iorequest
.piod_len
= size
;
1006 if (ptrace(PT_IO
, pid
, (caddr_t
)&iorequest
, 0) < 0) {
1010 if (memchr(buf
+ offset
, '\0', size
) != NULL
)
1013 if (totalsize
< MAXSIZE
&& max
== 0) {
1014 size
= MAXSIZE
- totalsize
;
1015 if (size
> PAGE_SIZE
)
1017 nbuf
= realloc(buf
, totalsize
+ size
);
1019 buf
[totalsize
- 1] = '\0';
1025 buf
[totalsize
- 1] = '\0';
1034 static char tmp
[sizeof(int) * 3 + 1];
1039 snprintf(tmp
, sizeof(tmp
), "%d", sig
);
1046 print_kevent(FILE *fp
, struct kevent
*ke
, int input
)
1049 switch (ke
->filter
) {
1055 case EVFILT_PROCDESC
:
1056 fprintf(fp
, "%ju", (uintmax_t)ke
->ident
);
1059 fputs(strsig2(ke
->ident
), fp
);
1062 fprintf(fp
, "%p", (void *)ke
->ident
);
1064 fprintf(fp
, ",%s,%s,", xlookup(kevent_filters
, ke
->filter
),
1065 xlookup_bits(kevent_flags
, ke
->flags
));
1066 switch (ke
->filter
) {
1069 fputs(xlookup_bits(kevent_rdwr_fflags
, ke
->fflags
), fp
);
1072 fputs(xlookup_bits(kevent_vnode_fflags
, ke
->fflags
), fp
);
1075 case EVFILT_PROCDESC
:
1076 fputs(xlookup_bits(kevent_proc_fflags
, ke
->fflags
), fp
);
1079 fputs(xlookup_bits(kevent_timer_fflags
, ke
->fflags
), fp
);
1084 ctrl
= ke
->fflags
& NOTE_FFCTRLMASK
;
1085 data
= ke
->fflags
& NOTE_FFLAGSMASK
;
1087 fputs(xlookup(kevent_user_ffctrl
, ctrl
), fp
);
1088 if (ke
->fflags
& NOTE_TRIGGER
)
1089 fputs("|NOTE_TRIGGER", fp
);
1091 fprintf(fp
, "|%#x", data
);
1093 fprintf(fp
, "%#x", data
);
1098 fprintf(fp
, "%#x", ke
->fflags
);
1100 fprintf(fp
, ",%p,%p", (void *)ke
->data
, (void *)ke
->udata
);
1104 print_utrace(FILE *fp
, void *utrace_addr
, size_t len
)
1106 unsigned char *utrace_buffer
;
1109 if (sysdecode_utrace(fp
, utrace_addr
, len
)) {
1114 utrace_buffer
= utrace_addr
;
1115 fprintf(fp
, "%zu:", len
);
1117 fprintf(fp
, " %02x", *utrace_buffer
++);
1122 * Converts a syscall argument into a string. Said string is
1123 * allocated via malloc(), so needs to be free()'d. sc is
1124 * a pointer to the syscall description (see above); args is
1125 * an array of all of the system call arguments.
1128 print_arg(struct syscall_args
*sc
, unsigned long *args
, long *retval
,
1129 struct trussinfo
*trussinfo
)
1136 fp
= open_memstream(&tmp
, &tmplen
);
1137 pid
= trussinfo
->curthread
->proc
->pid
;
1138 switch (sc
->type
& ARG_MASK
) {
1140 fprintf(fp
, "0x%x", (int)args
[sc
->offset
]);
1143 fprintf(fp
, "0%o", (int)args
[sc
->offset
]);
1146 fprintf(fp
, "%d", (int)args
[sc
->offset
]);
1149 fprintf(fp
, "%u", (unsigned int)args
[sc
->offset
]);
1152 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1155 fprintf(fp
, "%ld", args
[sc
->offset
]);
1158 /* NULL-terminated string. */
1161 tmp2
= get_string(pid
, (void*)args
[sc
->offset
], 0);
1162 fprintf(fp
, "\"%s\"", tmp2
);
1168 * Binary block of data that might have printable characters.
1169 * XXX If type|OUT, assume that the length is the syscall's
1170 * return value. Otherwise, assume that the length of the block
1171 * is in the next syscall argument.
1173 int max_string
= trussinfo
->strsize
;
1174 char tmp2
[max_string
+ 1], *tmp3
;
1181 len
= args
[sc
->offset
+ 1];
1184 * Don't print more than max_string characters, to avoid word
1185 * wrap. If we have to truncate put some ... after the string.
1187 if (len
> max_string
) {
1191 if (len
&& get_struct(pid
, (void*)args
[sc
->offset
], &tmp2
, len
)
1193 tmp3
= malloc(len
* 4 + 1);
1195 if (strvisx(tmp3
, tmp2
, len
,
1196 VIS_CSTYLE
|VIS_TAB
|VIS_NL
) <= max_string
)
1201 fprintf(fp
, "\"%s\"%s", tmp3
, truncated
?
1205 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1215 char buf
[PAGE_SIZE
];
1222 * Only parse argv[] and environment arrays from exec calls
1225 if (((sc
->type
& ARG_MASK
) == ExecArgs
&&
1226 (trussinfo
->flags
& EXECVEARGS
) == 0) ||
1227 ((sc
->type
& ARG_MASK
) == ExecEnv
&&
1228 (trussinfo
->flags
& EXECVEENVS
) == 0)) {
1229 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1234 * Read a page of pointers at a time. Punt if the top-level
1235 * pointer is not aligned. Note that the first read is of
1238 addr
= args
[sc
->offset
];
1239 if (addr
% sizeof(char *) != 0) {
1240 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1244 len
= PAGE_SIZE
- (addr
& PAGE_MASK
);
1245 if (get_struct(pid
, (void *)addr
, u
.buf
, len
) == -1) {
1246 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1253 while (u
.strarray
[i
] != NULL
) {
1254 string
= get_string(pid
, u
.strarray
[i
], 0);
1255 fprintf(fp
, "%s \"%s\"", first
? "" : ",", string
);
1260 if (i
== len
/ sizeof(char *)) {
1263 if (get_struct(pid
, (void *)addr
, u
.buf
, len
) ==
1265 fprintf(fp
, ", <inval>");
1276 fprintf(fp
, "%ld", args
[sc
->offset
]);
1279 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1284 unsigned long long ll
;
1286 #if _BYTE_ORDER == _LITTLE_ENDIAN
1287 ll
= (unsigned long long)args
[sc
->offset
+ 1] << 32 |
1290 ll
= (unsigned long long)args
[sc
->offset
] << 32 |
1291 args
[sc
->offset
+ 1];
1293 if ((sc
->type
& ARG_MASK
) == Quad
)
1294 fprintf(fp
, "%lld", ll
);
1296 fprintf(fp
, "0x%llx", ll
);
1301 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1306 if (retval
[0] == -1)
1308 tmp2
= get_string(pid
, (void*)args
[sc
->offset
], retval
[0]);
1309 fprintf(fp
, "\"%s\"", tmp2
);
1317 cmd
= args
[sc
->offset
];
1318 temp
= sysdecode_ioctlname(cmd
);
1322 fprintf(fp
, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
1323 cmd
, cmd
& IOC_OUT
? "R" : "",
1324 cmd
& IOC_IN
? "W" : "", IOCGROUP(cmd
),
1325 isprint(IOCGROUP(cmd
)) ? (char)IOCGROUP(cmd
) : '?',
1326 cmd
& 0xFF, IOCPARM_LEN(cmd
));
1333 if (get_struct(pid
, (void *)args
[sc
->offset
], &ts
,
1335 fprintf(fp
, "{ %jd.%09ld }", (intmax_t)ts
.tv_sec
,
1338 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1342 struct timespec ts
[2];
1346 if (get_struct(pid
, (void *)args
[sc
->offset
], &ts
, sizeof(ts
))
1350 for (i
= 0; i
< nitems(ts
); i
++) {
1353 switch (ts
[i
].tv_nsec
) {
1355 fprintf(fp
, "UTIME_NOW");
1358 fprintf(fp
, "UTIME_OMIT");
1361 fprintf(fp
, "%jd.%09ld",
1362 (intmax_t)ts
[i
].tv_sec
,
1369 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1375 if (get_struct(pid
, (void *)args
[sc
->offset
], &tv
, sizeof(tv
))
1377 fprintf(fp
, "{ %jd.%06ld }", (intmax_t)tv
.tv_sec
,
1380 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1384 struct timeval tv
[2];
1386 if (get_struct(pid
, (void *)args
[sc
->offset
], &tv
, sizeof(tv
))
1388 fprintf(fp
, "{ %jd.%06ld, %jd.%06ld }",
1389 (intmax_t)tv
[0].tv_sec
, tv
[0].tv_usec
,
1390 (intmax_t)tv
[1].tv_sec
, tv
[1].tv_usec
);
1392 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1396 struct itimerval itv
;
1398 if (get_struct(pid
, (void *)args
[sc
->offset
], &itv
,
1400 fprintf(fp
, "{ %jd.%06ld, %jd.%06ld }",
1401 (intmax_t)itv
.it_interval
.tv_sec
,
1402 itv
.it_interval
.tv_usec
,
1403 (intmax_t)itv
.it_value
.tv_sec
,
1404 itv
.it_value
.tv_usec
);
1406 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1411 struct linux_socketcall_args largs
;
1413 if (get_struct(pid
, (void *)args
[sc
->offset
], (void *)&largs
,
1414 sizeof(largs
)) != -1)
1415 fprintf(fp
, "{ %s, 0x%lx }",
1416 lookup(linux_socketcall_ops
, largs
.what
, 10),
1417 (long unsigned int)largs
.args
);
1419 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1424 * XXX: A Pollfd argument expects the /next/ syscall argument
1425 * to be the number of fds in the array. This matches the poll
1429 int numfds
= args
[sc
->offset
+ 1];
1430 size_t bytes
= sizeof(struct pollfd
) * numfds
;
1433 if ((pfd
= malloc(bytes
)) == NULL
)
1434 err(1, "Cannot malloc %zu bytes for pollfd array",
1436 if (get_struct(pid
, (void *)args
[sc
->offset
], pfd
, bytes
)
1439 for (i
= 0; i
< numfds
; i
++) {
1440 fprintf(fp
, " %d/%s", pfd
[i
].fd
,
1441 xlookup_bits(poll_flags
, pfd
[i
].events
));
1445 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1452 * XXX: A Fd_set argument expects the /first/ syscall argument
1453 * to be the number of fds in the array. This matches the
1457 int numfds
= args
[0];
1458 size_t bytes
= _howmany(numfds
, _NFDBITS
) * _NFDBITS
;
1461 if ((fds
= malloc(bytes
)) == NULL
)
1462 err(1, "Cannot malloc %zu bytes for fd_set array",
1464 if (get_struct(pid
, (void *)args
[sc
->offset
], fds
, bytes
)
1467 for (i
= 0; i
< numfds
; i
++) {
1468 if (FD_ISSET(i
, fds
))
1469 fprintf(fp
, " %d", i
);
1473 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1478 fputs(strsig2(args
[sc
->offset
]), fp
);
1485 sig
= args
[sc
->offset
];
1486 if (get_struct(pid
, (void *)args
[sc
->offset
], (void *)&ss
,
1487 sizeof(ss
)) == -1) {
1488 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1493 for (i
= 1; i
< sys_nsig
; i
++) {
1494 if (sigismember(&ss
, i
)) {
1495 fprintf(fp
, "%s%s", !first
? "|" : "",
1506 fputs(xlookup(sigprocmask_ops
, args
[sc
->offset
]), fp
);
1510 /* XXX: Output depends on the value of the previous argument. */
1511 switch (args
[sc
->offset
- 1]) {
1513 fputs(xlookup_bits(fcntlfd_arg
, args
[sc
->offset
]), fp
);
1516 fputs(xlookup_bits(fcntlfl_arg
, args
[sc
->offset
]), fp
);
1523 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1529 fputs(xlookup_bits(open_flags
, args
[sc
->offset
]), fp
);
1532 fputs(xlookup(fcntl_arg
, args
[sc
->offset
]), fp
);
1535 fputs(xlookup_bits(mprot_flags
, args
[sc
->offset
]), fp
);
1541 * MAP_ALIGNED can't be handled by xlookup_bits(), so
1542 * generate that string manually and prepend it to the
1543 * string from xlookup_bits(). Have to be careful to
1544 * avoid outputting MAP_ALIGNED|0 if MAP_ALIGNED is
1547 flags
= args
[sc
->offset
] & ~MAP_ALIGNMENT_MASK
;
1548 align
= args
[sc
->offset
] & MAP_ALIGNMENT_MASK
;
1550 if (align
== MAP_ALIGNED_SUPER
)
1551 fputs("MAP_ALIGNED_SUPER", fp
);
1553 fprintf(fp
, "MAP_ALIGNED(%d)",
1554 align
>> MAP_ALIGNMENT_SHIFT
);
1559 fputs(xlookup_bits(mmap_flags
, flags
), fp
);
1563 fputs(xlookup(whence_arg
, args
[sc
->offset
]), fp
);
1566 fputs(xlookup(sockdomain_arg
, args
[sc
->offset
]), fp
);
1571 flags
= args
[sc
->offset
] & (SOCK_CLOEXEC
| SOCK_NONBLOCK
);
1572 type
= args
[sc
->offset
] & ~flags
;
1573 fputs(xlookup(socktype_arg
, type
), fp
);
1574 if (flags
& SOCK_CLOEXEC
)
1575 fprintf(fp
, "|SOCK_CLOEXEC");
1576 if (flags
& SOCK_NONBLOCK
)
1577 fprintf(fp
, "|SOCK_NONBLOCK");
1581 fputs(xlookup(shutdown_arg
, args
[sc
->offset
]), fp
);
1584 fputs(xlookup(resource_arg
, args
[sc
->offset
]), fp
);
1587 fputs(xlookup(pathconf_arg
, args
[sc
->offset
]), fp
);
1590 fputs(xlookup_bits(rfork_flags
, args
[sc
->offset
]), fp
);
1594 struct sockaddr_in
*lsin
;
1595 struct sockaddr_in6
*lsin6
;
1596 struct sockaddr_un
*sun
;
1597 struct sockaddr
*sa
;
1601 if (args
[sc
->offset
] == 0) {
1607 * Extract the address length from the next argument. If
1608 * this is an output sockaddr (OUT is set), then the
1609 * next argument is a pointer to a socklen_t. Otherwise
1610 * the next argument contains a socklen_t by value.
1612 if (sc
->type
& OUT
) {
1613 if (get_struct(pid
, (void *)args
[sc
->offset
+ 1],
1614 &len
, sizeof(len
)) == -1) {
1615 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1619 len
= args
[sc
->offset
+ 1];
1621 /* If the length is too small, just bail. */
1622 if (len
< sizeof(*sa
)) {
1623 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1627 sa
= calloc(1, len
);
1628 if (get_struct(pid
, (void *)args
[sc
->offset
], sa
, len
) == -1) {
1630 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1634 switch (sa
->sa_family
) {
1636 if (len
< sizeof(*lsin
))
1637 goto sockaddr_short
;
1638 lsin
= (struct sockaddr_in
*)(void *)sa
;
1639 inet_ntop(AF_INET
, &lsin
->sin_addr
, addr
, sizeof(addr
));
1640 fprintf(fp
, "{ AF_INET %s:%d }", addr
,
1641 htons(lsin
->sin_port
));
1644 if (len
< sizeof(*lsin6
))
1645 goto sockaddr_short
;
1646 lsin6
= (struct sockaddr_in6
*)(void *)sa
;
1647 inet_ntop(AF_INET6
, &lsin6
->sin6_addr
, addr
,
1649 fprintf(fp
, "{ AF_INET6 [%s]:%d }", addr
,
1650 htons(lsin6
->sin6_port
));
1653 sun
= (struct sockaddr_un
*)sa
;
1654 fprintf(fp
, "{ AF_UNIX \"%.*s\" }",
1655 (int)(len
- offsetof(struct sockaddr_un
, sun_path
)),
1661 "{ sa_len = %d, sa_family = %d, sa_data = {",
1662 (int)sa
->sa_len
, (int)sa
->sa_family
);
1663 for (q
= (u_char
*)sa
->sa_data
;
1664 q
< (u_char
*)sa
+ len
; q
++)
1665 fprintf(fp
, "%s 0x%02x",
1666 q
== (u_char
*)sa
->sa_data
? "" : ",",
1674 struct sigaction sa
;
1676 if (get_struct(pid
, (void *)args
[sc
->offset
], &sa
, sizeof(sa
))
1679 if (sa
.sa_handler
== SIG_DFL
)
1680 fputs("SIG_DFL", fp
);
1681 else if (sa
.sa_handler
== SIG_IGN
)
1682 fputs("SIG_IGN", fp
);
1684 fprintf(fp
, "%p", sa
.sa_handler
);
1685 fprintf(fp
, " %s ss_t }",
1686 xlookup_bits(sigaction_flags
, sa
.sa_flags
));
1688 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1693 * XXX XXX: The size of the array is determined by either the
1694 * next syscall argument, or by the syscall return value,
1695 * depending on which argument number we are. This matches the
1696 * kevent syscall, but luckily that's the only syscall that uses
1704 if (sc
->offset
== 1)
1705 numevents
= args
[sc
->offset
+1];
1706 else if (sc
->offset
== 3 && retval
[0] != -1)
1707 numevents
= retval
[0];
1709 if (numevents
>= 0) {
1710 bytes
= sizeof(struct kevent
) * numevents
;
1711 if ((ke
= malloc(bytes
)) == NULL
)
1713 "Cannot malloc %zu bytes for kevent array",
1717 if (numevents
>= 0 && get_struct(pid
, (void *)args
[sc
->offset
],
1720 for (i
= 0; i
< numevents
; i
++) {
1722 print_kevent(fp
, &ke
[i
], sc
->offset
== 1);
1726 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1734 if (get_struct(pid
, (void *)args
[sc
->offset
], &st
, sizeof(st
))
1738 strmode(st
.st_mode
, mode
);
1740 "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode
,
1741 (uintmax_t)st
.st_ino
, (intmax_t)st
.st_size
,
1742 (long)st
.st_blksize
);
1744 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1752 if (get_struct(pid
, (void *)args
[sc
->offset
], &buf
,
1753 sizeof(buf
)) != -1) {
1756 bzero(fsid
, sizeof(fsid
));
1757 if (buf
.f_fsid
.val
[0] != 0 || buf
.f_fsid
.val
[1] != 0) {
1758 for (i
= 0; i
< sizeof(buf
.f_fsid
); i
++)
1759 snprintf(&fsid
[i
*2],
1760 sizeof(fsid
) - (i
*2), "%02x",
1761 ((u_char
*)&buf
.f_fsid
)[i
]);
1764 "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
1765 "fsid=%s }", buf
.f_fstypename
, buf
.f_mntonname
,
1766 buf
.f_mntfromname
, fsid
);
1768 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1775 if (get_struct(pid
, (void *)args
[sc
->offset
], &ru
, sizeof(ru
))
1778 "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
1779 (intmax_t)ru
.ru_utime
.tv_sec
, ru
.ru_utime
.tv_usec
,
1780 (intmax_t)ru
.ru_stime
.tv_sec
, ru
.ru_stime
.tv_usec
,
1781 ru
.ru_inblock
, ru
.ru_oublock
);
1783 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1789 if (get_struct(pid
, (void *)args
[sc
->offset
], &rl
, sizeof(rl
))
1791 fprintf(fp
, "{ cur=%ju,max=%ju }",
1792 rl
.rlim_cur
, rl
.rlim_max
);
1794 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1800 if (get_struct(pid
, (void *)args
[sc
->offset
], &status
,
1801 sizeof(status
)) != -1) {
1803 if (WIFCONTINUED(status
))
1804 fputs("CONTINUED", fp
);
1805 else if (WIFEXITED(status
))
1806 fprintf(fp
, "EXITED,val=%d",
1807 WEXITSTATUS(status
));
1808 else if (WIFSIGNALED(status
))
1809 fprintf(fp
, "SIGNALED,sig=%s%s",
1810 strsig2(WTERMSIG(status
)),
1811 WCOREDUMP(status
) ? ",cored" : "");
1813 fprintf(fp
, "STOPPED,sig=%s",
1814 strsig2(WTERMSIG(status
)));
1817 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1821 fputs(xlookup_bits(wait_options
, args
[sc
->offset
]), fp
);
1824 fputs(xlookup(idtype_arg
, args
[sc
->offset
]), fp
);
1827 fputs(xlookup(procctl_arg
, args
[sc
->offset
]), fp
);
1830 fputs(xlookup(umtx_ops
, args
[sc
->offset
]), fp
);
1833 if ((int)args
[sc
->offset
] == AT_FDCWD
)
1834 fputs("AT_FDCWD", fp
);
1836 fprintf(fp
, "%d", (int)args
[sc
->offset
]);
1839 fputs(xlookup_bits(at_flags
, args
[sc
->offset
]), fp
);
1842 if (args
[sc
->offset
] == F_OK
)
1845 fputs(xlookup_bits(access_modes
, args
[sc
->offset
]), fp
);
1848 fputs(xlookup(sysarch_ops
, args
[sc
->offset
]), fp
);
1852 * The pipe() system call in the kernel returns its
1853 * two file descriptors via return values. However,
1854 * the interface exposed by libc is that pipe()
1855 * accepts a pointer to an array of descriptors.
1856 * Format the output to match the libc API by printing
1857 * the returned file descriptors as a fake argument.
1859 * Overwrite the first retval to signal a successful
1862 fprintf(fp
, "{ %ld, %ld }", retval
[0], retval
[1]);
1869 len
= args
[sc
->offset
+ 1];
1870 utrace_addr
= calloc(1, len
);
1871 if (get_struct(pid
, (void *)args
[sc
->offset
],
1872 (void *)utrace_addr
, len
) != -1)
1873 print_utrace(fp
, utrace_addr
, len
);
1875 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1880 int descriptors
[16];
1881 unsigned long i
, ndescriptors
;
1884 ndescriptors
= args
[sc
->offset
+ 1];
1886 if (ndescriptors
> nitems(descriptors
)) {
1887 ndescriptors
= nitems(descriptors
);
1890 if (get_struct(pid
, (void *)args
[sc
->offset
],
1891 descriptors
, ndescriptors
* sizeof(descriptors
[0])) != -1) {
1893 for (i
= 0; i
< ndescriptors
; i
++)
1894 fprintf(fp
, i
== 0 ? " %d" : ", %d",
1896 fprintf(fp
, truncated
? ", ... }" : " }");
1898 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1902 case CloudABIAdvice
:
1903 fputs(xlookup(cloudabi_advice
, args
[sc
->offset
]), fp
);
1905 case CloudABIClockID
:
1906 fputs(xlookup(cloudabi_clockid
, args
[sc
->offset
]), fp
);
1908 case ClouduABIFDSFlags
:
1909 fputs(xlookup_bits(cloudabi_fdsflags
, args
[sc
->offset
]), fp
);
1911 case CloudABIFDStat
: {
1912 cloudabi_fdstat_t fds
;
1913 if (get_struct(pid
, (void *)args
[sc
->offset
], &fds
, sizeof(fds
))
1915 fprintf(fp
, "{ %s, ",
1916 xlookup(cloudabi_filetype
, fds
.fs_filetype
));
1917 fprintf(fp
, "%s, ... }",
1918 xlookup_bits(cloudabi_fdflags
, fds
.fs_flags
));
1920 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1923 case CloudABIFileStat
: {
1924 cloudabi_filestat_t fsb
;
1925 if (get_struct(pid
, (void *)args
[sc
->offset
], &fsb
, sizeof(fsb
))
1927 fprintf(fp
, "{ %s, %lu }",
1928 xlookup(cloudabi_filetype
, fsb
.st_filetype
),
1931 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1934 case CloudABIFileType
:
1935 fputs(xlookup(cloudabi_filetype
, args
[sc
->offset
]), fp
);
1937 case CloudABIFSFlags
:
1938 fputs(xlookup_bits(cloudabi_fsflags
, args
[sc
->offset
]), fp
);
1940 case CloudABILookup
:
1941 if ((args
[sc
->offset
] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW
) != 0)
1942 fprintf(fp
, "%d|LOOKUP_SYMLINK_FOLLOW",
1943 (int)args
[sc
->offset
]);
1945 fprintf(fp
, "%d", (int)args
[sc
->offset
]);
1947 case CloudABIMFlags
:
1948 fputs(xlookup_bits(cloudabi_mflags
, args
[sc
->offset
]), fp
);
1951 fputs(xlookup_bits(cloudabi_mprot
, args
[sc
->offset
]), fp
);
1953 case CloudABIMSFlags
:
1954 fputs(xlookup_bits(cloudabi_msflags
, args
[sc
->offset
]), fp
);
1956 case CloudABIOFlags
:
1957 fputs(xlookup_bits(cloudabi_oflags
, args
[sc
->offset
]), fp
);
1959 case CloudABISDFlags
:
1960 fputs(xlookup_bits(cloudabi_sdflags
, args
[sc
->offset
]), fp
);
1962 case CloudABISignal
:
1963 fputs(xlookup(cloudabi_signal
, args
[sc
->offset
]), fp
);
1965 case CloudABISockStat
: {
1966 cloudabi_sockstat_t ss
;
1967 if (get_struct(pid
, (void *)args
[sc
->offset
], &ss
, sizeof(ss
))
1969 fprintf(fp
, "{ %s, ", xlookup(
1970 cloudabi_sa_family
, ss
.ss_sockname
.sa_family
));
1971 fprintf(fp
, "%s, ", xlookup(
1972 cloudabi_sa_family
, ss
.ss_peername
.sa_family
));
1973 fprintf(fp
, "%s, ", xlookup(
1974 cloudabi_errno
, ss
.ss_error
));
1975 fprintf(fp
, "%s }", xlookup_bits(
1976 cloudabi_ssstate
, ss
.ss_state
));
1978 fprintf(fp
, "0x%lx", args
[sc
->offset
]);
1981 case CloudABISSFlags
:
1982 fputs(xlookup_bits(cloudabi_ssflags
, args
[sc
->offset
]), fp
);
1984 case CloudABITimestamp
:
1985 fprintf(fp
, "%lu.%09lus", args
[sc
->offset
] / 1000000000,
1986 args
[sc
->offset
] % 1000000000);
1988 case CloudABIULFlags
:
1989 fputs(xlookup_bits(cloudabi_ulflags
, args
[sc
->offset
]), fp
);
1991 case CloudABIWhence
:
1992 fputs(xlookup(cloudabi_whence
, args
[sc
->offset
]), fp
);
1996 errx(1, "Invalid argument type %d\n", sc
->type
& ARG_MASK
);
2003 * Print (to outfile) the system call and its arguments.
2006 print_syscall(struct trussinfo
*trussinfo
)
2008 struct threadinfo
*t
;
2013 t
= trussinfo
->curthread
;
2016 nargs
= t
->cs
.nargs
;
2017 s_args
= t
->cs
.s_args
;
2019 len
= print_line_prefix(trussinfo
);
2020 len
+= fprintf(trussinfo
->outfile
, "%s(", name
);
2022 for (i
= 0; i
< nargs
; i
++) {
2023 if (s_args
[i
] != NULL
)
2024 len
+= fprintf(trussinfo
->outfile
, "%s", s_args
[i
]);
2026 len
+= fprintf(trussinfo
->outfile
,
2027 "<missing argument>");
2028 len
+= fprintf(trussinfo
->outfile
, "%s", i
< (nargs
- 1) ?
2031 len
+= fprintf(trussinfo
->outfile
, ")");
2032 for (i
= 0; i
< 6 - (len
/ 8); i
++)
2033 fprintf(trussinfo
->outfile
, "\t");
2037 print_syscall_ret(struct trussinfo
*trussinfo
, int errorp
, long *retval
)
2039 struct timespec timediff
;
2040 struct threadinfo
*t
;
2044 t
= trussinfo
->curthread
;
2046 if (trussinfo
->flags
& COUNTONLY
) {
2047 timespecsubt(&t
->after
, &t
->before
, &timediff
);
2048 timespecadd(&sc
->time
, &timediff
, &sc
->time
);
2055 print_syscall(trussinfo
);
2056 fflush(trussinfo
->outfile
);
2058 error
= sysdecode_abi_to_freebsd_errno(t
->proc
->abi
->abi
,
2060 fprintf(trussinfo
->outfile
, " ERR#%ld '%s'\n", retval
[0],
2061 error
== INT_MAX
? "Unknown error" : strerror(error
));
2064 else if (sc
->ret_type
== 2) {
2067 #if _BYTE_ORDER == _LITTLE_ENDIAN
2068 off
= (off_t
)retval
[1] << 32 | retval
[0];
2070 off
= (off_t
)retval
[0] << 32 | retval
[1];
2072 fprintf(trussinfo
->outfile
, " = %jd (0x%jx)\n", (intmax_t)off
,
2077 fprintf(trussinfo
->outfile
, " = %ld (0x%lx)\n", retval
[0],
2082 print_summary(struct trussinfo
*trussinfo
)
2084 struct timespec total
= {0, 0};
2088 fprintf(trussinfo
->outfile
, "%-20s%15s%8s%8s\n",
2089 "syscall", "seconds", "calls", "errors");
2091 STAILQ_FOREACH(sc
, &syscalls
, entries
)
2093 fprintf(trussinfo
->outfile
, "%-20s%5jd.%09ld%8d%8d\n",
2094 sc
->name
, (intmax_t)sc
->time
.tv_sec
,
2095 sc
->time
.tv_nsec
, sc
->ncalls
, sc
->nerror
);
2096 timespecadd(&total
, &sc
->time
, &total
);
2097 ncall
+= sc
->ncalls
;
2098 nerror
+= sc
->nerror
;
2100 fprintf(trussinfo
->outfile
, "%20s%15s%8s%8s\n",
2101 "", "-------------", "-------", "-------");
2102 fprintf(trussinfo
->outfile
, "%-20s%5jd.%09ld%8d%8d\n",
2103 "", (intmax_t)total
.tv_sec
, total
.tv_nsec
, ncall
, nerror
);