xref: /freebsd/usr.bin/truss/syscalls.c (revision 1e2ec671fc497bcf54a6e3dc2ffea46eaa214f13)
1bbeaf6c0SSean Eric Fagan /*
20a6c71f8SWarner Losh  * Copyright 1997 Sean Eric Fagan
309d64da3SSean Eric Fagan  *
409d64da3SSean Eric Fagan  * Redistribution and use in source and binary forms, with or without
509d64da3SSean Eric Fagan  * modification, are permitted provided that the following conditions
609d64da3SSean Eric Fagan  * are met:
709d64da3SSean Eric Fagan  * 1. Redistributions of source code must retain the above copyright
809d64da3SSean Eric Fagan  *    notice, this list of conditions and the following disclaimer.
909d64da3SSean Eric Fagan  * 2. Redistributions in binary form must reproduce the above copyright
1009d64da3SSean Eric Fagan  *    notice, this list of conditions and the following disclaimer in the
1109d64da3SSean Eric Fagan  *    documentation and/or other materials provided with the distribution.
1209d64da3SSean Eric Fagan  * 3. All advertising materials mentioning features or use of this software
1309d64da3SSean Eric Fagan  *    must display the following acknowledgement:
1409d64da3SSean Eric Fagan  *	This product includes software developed by Sean Eric Fagan
1509d64da3SSean Eric Fagan  * 4. Neither the name of the author may be used to endorse or promote
1609d64da3SSean Eric Fagan  *    products derived from this software without specific prior written
1709d64da3SSean Eric Fagan  *    permission.
1809d64da3SSean Eric Fagan  *
1909d64da3SSean Eric Fagan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2009d64da3SSean Eric Fagan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2109d64da3SSean Eric Fagan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2209d64da3SSean Eric Fagan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2309d64da3SSean Eric Fagan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2409d64da3SSean Eric Fagan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2509d64da3SSean Eric Fagan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2609d64da3SSean Eric Fagan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2709d64da3SSean Eric Fagan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2809d64da3SSean Eric Fagan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2909d64da3SSean Eric Fagan  * SUCH DAMAGE.
3009d64da3SSean Eric Fagan  */
3109d64da3SSean Eric Fagan 
323cf51049SPhilippe Charnier #ifndef lint
333cf51049SPhilippe Charnier static const char rcsid[] =
34c3aac50fSPeter Wemm   "$FreeBSD$";
353cf51049SPhilippe Charnier #endif /* not lint */
363cf51049SPhilippe Charnier 
3709d64da3SSean Eric Fagan /*
38bbeaf6c0SSean Eric Fagan  * This file has routines used to print out system calls and their
39bbeaf6c0SSean Eric Fagan  * arguments.
40bbeaf6c0SSean Eric Fagan  */
41bbeaf6c0SSean Eric Fagan 
429ddd1412SDag-Erling Smørgrav #include <sys/types.h>
4334763d1cSJohn Baldwin #include <sys/mman.h>
4455648840SJohn Baldwin #include <sys/procctl.h>
455d2d083cSXin LI #include <sys/ptrace.h>
469ddd1412SDag-Erling Smørgrav #include <sys/socket.h>
471d631f7eSMike Barcroft #include <sys/time.h>
489ddd1412SDag-Erling Smørgrav #include <sys/un.h>
4934763d1cSJohn Baldwin #include <sys/wait.h>
509ddd1412SDag-Erling Smørgrav #include <netinet/in.h>
519ddd1412SDag-Erling Smørgrav #include <arpa/inet.h>
52081e5c48SPav Lucistnik #include <sys/ioccom.h>
53081e5c48SPav Lucistnik #include <machine/atomic.h>
54081e5c48SPav Lucistnik #include <errno.h>
55081e5c48SPav Lucistnik #include <sys/umtx.h>
56081e5c48SPav Lucistnik #include <sys/event.h>
57081e5c48SPav Lucistnik #include <sys/stat.h>
58081e5c48SPav Lucistnik #include <sys/resource.h>
599ddd1412SDag-Erling Smørgrav 
60dec17687SBrian Feldman #include <ctype.h>
613cf51049SPhilippe Charnier #include <err.h>
62894b8f7aSAlfred Perlstein #include <fcntl.h>
63e45a5a0dSDavid Malone #include <poll.h>
649ddd1412SDag-Erling Smørgrav #include <signal.h>
65e45a5a0dSDavid Malone #include <stdint.h>
66bbeaf6c0SSean Eric Fagan #include <stdio.h>
67bbeaf6c0SSean Eric Fagan #include <stdlib.h>
68bbeaf6c0SSean Eric Fagan #include <string.h>
6937169f94SMatthew N. Dodd #include <time.h>
70bbeaf6c0SSean Eric Fagan #include <unistd.h>
71081e5c48SPav Lucistnik #include <vis.h>
729ddd1412SDag-Erling Smørgrav 
73ec0bed25SMatthew N. Dodd #include "truss.h"
741be5d704SMark Murray #include "extern.h"
75bbeaf6c0SSean Eric Fagan #include "syscall.h"
76bbeaf6c0SSean Eric Fagan 
772c02627fSMarcel Moolenaar /* 64-bit alignment on 32-bit platforms. */
782c02627fSMarcel Moolenaar #ifdef __powerpc__
792c02627fSMarcel Moolenaar #define	QUAD_ALIGN	1
802c02627fSMarcel Moolenaar #else
812c02627fSMarcel Moolenaar #define	QUAD_ALIGN	0
822c02627fSMarcel Moolenaar #endif
832c02627fSMarcel Moolenaar 
842c02627fSMarcel Moolenaar /* Number of slots needed for a 64-bit argument. */
852c02627fSMarcel Moolenaar #ifdef __LP64__
862c02627fSMarcel Moolenaar #define	QUAD_SLOTS	1
872c02627fSMarcel Moolenaar #else
882c02627fSMarcel Moolenaar #define	QUAD_SLOTS	2
892c02627fSMarcel Moolenaar #endif
902c02627fSMarcel Moolenaar 
91bbeaf6c0SSean Eric Fagan /*
92081e5c48SPav Lucistnik  * This should probably be in its own file, sorted alphabetically.
93bbeaf6c0SSean Eric Fagan  */
94a02c83afSEd Schouten static struct syscall syscalls[] = {
95ee3b0f6eSDiomidis Spinellis 	{ .name = "fcntl", .ret_type = 1, .nargs = 3,
9619d63784SJohn Baldwin 	  .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
9776de696dSJaakko Heinonen 	{ .name = "fork", .ret_type = 1, .nargs = 0 },
989e1db66eSMark Johnston 	{ .name = "vfork", .ret_type = 1, .nargs = 0 },
999e1db66eSMark Johnston 	{ .name = "rfork", .ret_type = 1, .nargs = 1,
1009e1db66eSMark Johnston 	  .args = { { Rforkflags, 0 } } },
10176de696dSJaakko Heinonen 	{ .name = "getegid", .ret_type = 1, .nargs = 0 },
10276de696dSJaakko Heinonen 	{ .name = "geteuid", .ret_type = 1, .nargs = 0 },
1031c99a22aSSteven Hartland 	{ .name = "linux_readlink", .ret_type = 1, .nargs = 3,
1041c99a22aSSteven Hartland 	  .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } },
1051c99a22aSSteven Hartland 	{ .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
1061c99a22aSSteven Hartland 	  .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
10776de696dSJaakko Heinonen 	{ .name = "getgid", .ret_type = 1, .nargs = 0 },
10876de696dSJaakko Heinonen 	{ .name = "getpid", .ret_type = 1, .nargs = 0 },
10976de696dSJaakko Heinonen 	{ .name = "getpgid", .ret_type = 1, .nargs = 1,
11076de696dSJaakko Heinonen 	  .args = { { Int, 0 } } },
11176de696dSJaakko Heinonen 	{ .name = "getpgrp", .ret_type = 1, .nargs = 0 },
11276de696dSJaakko Heinonen 	{ .name = "getppid", .ret_type = 1, .nargs = 0 },
11376de696dSJaakko Heinonen 	{ .name = "getsid", .ret_type = 1, .nargs = 1,
11476de696dSJaakko Heinonen 	  .args = { { Int, 0 } } },
11576de696dSJaakko Heinonen 	{ .name = "getuid", .ret_type = 1, .nargs = 0 },
116ee3b0f6eSDiomidis Spinellis 	{ .name = "readlink", .ret_type = 1, .nargs = 3,
117ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Int, 2 } } },
1187d897327SJohn Baldwin 	{ .name = "readlinkat", .ret_type = 1, .nargs = 4,
1197d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
1207d897327SJohn Baldwin 		    { Int, 3 } } },
121ee3b0f6eSDiomidis Spinellis 	{ .name = "lseek", .ret_type = 2, .nargs = 3,
1220a46af44SJohn Baldwin 	  .args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN },
1230a46af44SJohn Baldwin 		    { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } },
124ee3b0f6eSDiomidis Spinellis 	{ .name = "linux_lseek", .ret_type = 2, .nargs = 3,
125ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
126ee3b0f6eSDiomidis Spinellis 	{ .name = "mmap", .ret_type = 2, .nargs = 6,
1270a46af44SJohn Baldwin 	  .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
1280a46af44SJohn Baldwin 		    { Int, 4 }, { Quad, 5 + QUAD_ALIGN } } },
1291c99a22aSSteven Hartland 	{ .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
1301c99a22aSSteven Hartland 	  .args = { { Name | IN, 0 }, { Int, 1 } } },
131ee3b0f6eSDiomidis Spinellis 	{ .name = "mprotect", .ret_type = 1, .nargs = 3,
132ee3b0f6eSDiomidis Spinellis 	  .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
133ee3b0f6eSDiomidis Spinellis 	{ .name = "open", .ret_type = 1, .nargs = 3,
134ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
1357d897327SJohn Baldwin 	{ .name = "openat", .ret_type = 1, .nargs = 4,
1367d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
1377d897327SJohn Baldwin 		    { Octal, 3 } } },
138ee3b0f6eSDiomidis Spinellis 	{ .name = "mkdir", .ret_type = 1, .nargs = 2,
139ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Octal, 1 } } },
1407d897327SJohn Baldwin 	{ .name = "mkdirat", .ret_type = 1, .nargs = 3,
1417d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
142ee3b0f6eSDiomidis Spinellis 	{ .name = "linux_open", .ret_type = 1, .nargs = 3,
143ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
144ee3b0f6eSDiomidis Spinellis 	{ .name = "close", .ret_type = 1, .nargs = 1,
145ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 } } },
146ee3b0f6eSDiomidis Spinellis 	{ .name = "link", .ret_type = 0, .nargs = 2,
147ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Name, 1 } } },
1487d897327SJohn Baldwin 	{ .name = "linkat", .ret_type = 0, .nargs = 5,
1497d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
1507d897327SJohn Baldwin 		    { Atflags, 4 } } },
151ee3b0f6eSDiomidis Spinellis 	{ .name = "unlink", .ret_type = 0, .nargs = 1,
152ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 } } },
1537d897327SJohn Baldwin 	{ .name = "unlinkat", .ret_type = 0, .nargs = 3,
1547d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
155ee3b0f6eSDiomidis Spinellis 	{ .name = "chdir", .ret_type = 0, .nargs = 1,
156ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 } } },
157ee3b0f6eSDiomidis Spinellis 	{ .name = "chroot", .ret_type = 0, .nargs = 1,
158ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 } } },
159e82ce59cSJohn Baldwin 	{ .name = "mkfifo", .ret_type = 0, .nargs = 2,
160e82ce59cSJohn Baldwin 	  .args = { { Name, 0 }, { Octal, 1 } } },
1617d897327SJohn Baldwin 	{ .name = "mkfifoat", .ret_type = 0, .nargs = 3,
1627d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
163ee3b0f6eSDiomidis Spinellis 	{ .name = "mknod", .ret_type = 0, .nargs = 3,
164e82ce59cSJohn Baldwin 	  .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
1657d897327SJohn Baldwin 	{ .name = "mknodat", .ret_type = 0, .nargs = 4,
1667d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
167ee3b0f6eSDiomidis Spinellis 	{ .name = "chmod", .ret_type = 0, .nargs = 2,
168ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Octal, 1 } } },
1697d897327SJohn Baldwin 	{ .name = "fchmod", .ret_type = 0, .nargs = 2,
1707d897327SJohn Baldwin 	  .args = { { Int, 0 }, { Octal, 1 } } },
1717d897327SJohn Baldwin 	{ .name = "lchmod", .ret_type = 0, .nargs = 2,
1727d897327SJohn Baldwin 	  .args = { { Name, 0 }, { Octal, 1 } } },
1737d897327SJohn Baldwin 	{ .name = "fchmodat", .ret_type = 0, .nargs = 4,
1747d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
175ee3b0f6eSDiomidis Spinellis 	{ .name = "chown", .ret_type = 0, .nargs = 3,
176ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
1777d897327SJohn Baldwin 	{ .name = "fchown", .ret_type = 0, .nargs = 3,
1787d897327SJohn Baldwin 	  .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
1797d897327SJohn Baldwin 	{ .name = "lchown", .ret_type = 0, .nargs = 3,
1807d897327SJohn Baldwin 	  .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
1817d897327SJohn Baldwin 	{ .name = "fchownat", .ret_type = 0, .nargs = 5,
1827d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
1837d897327SJohn Baldwin 		    { Atflags, 4 } } },
1841c99a22aSSteven Hartland 	{ .name = "linux_stat64", .ret_type = 1, .nargs = 3,
1851c99a22aSSteven Hartland 	  .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } },
186ee3b0f6eSDiomidis Spinellis 	{ .name = "mount", .ret_type = 0, .nargs = 4,
187ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
188ee3b0f6eSDiomidis Spinellis 	{ .name = "umount", .ret_type = 0, .nargs = 2,
189ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Int, 2 } } },
190ee3b0f6eSDiomidis Spinellis 	{ .name = "fstat", .ret_type = 1, .nargs = 2,
191ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Stat | OUT, 1 } } },
1927d897327SJohn Baldwin 	{ .name = "fstatat", .ret_type = 1, .nargs = 4,
1937d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
1947d897327SJohn Baldwin 		    { Atflags, 3 } } },
195ee3b0f6eSDiomidis Spinellis 	{ .name = "stat", .ret_type = 1, .nargs = 2,
196ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
197ee3b0f6eSDiomidis Spinellis 	{ .name = "lstat", .ret_type = 1, .nargs = 2,
198ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
199ee3b0f6eSDiomidis Spinellis 	{ .name = "linux_newstat", .ret_type = 1, .nargs = 2,
200ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
2011c99a22aSSteven Hartland 	{ .name = "linux_access", .ret_type = 1, .nargs = 2,
2027d897327SJohn Baldwin 	  .args = { { Name, 0 }, { Accessmode, 1 } } },
203ee3b0f6eSDiomidis Spinellis 	{ .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
204ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
205ee3b0f6eSDiomidis Spinellis 	{ .name = "write", .ret_type = 1, .nargs = 3,
206ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } },
207ee3b0f6eSDiomidis Spinellis 	{ .name = "ioctl", .ret_type = 1, .nargs = 3,
208ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } },
209ee3b0f6eSDiomidis Spinellis 	{ .name = "break", .ret_type = 1, .nargs = 1,
210ee3b0f6eSDiomidis Spinellis 	  .args = { { Ptr, 0 } } },
211ee3b0f6eSDiomidis Spinellis 	{ .name = "exit", .ret_type = 0, .nargs = 1,
212ee3b0f6eSDiomidis Spinellis 	  .args = { { Hex, 0 } } },
213ee3b0f6eSDiomidis Spinellis 	{ .name = "access", .ret_type = 1, .nargs = 2,
2147d897327SJohn Baldwin 	  .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
2157d897327SJohn Baldwin 	{ .name = "eaccess", .ret_type = 1, .nargs = 2,
2167d897327SJohn Baldwin 	  .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
2177d897327SJohn Baldwin 	{ .name = "faccessat", .ret_type = 1, .nargs = 4,
2187d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
2197d897327SJohn Baldwin 		    { Atflags, 3 } } },
220ee3b0f6eSDiomidis Spinellis 	{ .name = "sigaction", .ret_type = 1, .nargs = 3,
2210a46af44SJohn Baldwin 	  .args = { { Signal, 0 }, { Sigaction | IN, 1 },
2220a46af44SJohn Baldwin 		    { Sigaction | OUT, 2 } } },
223ee3b0f6eSDiomidis Spinellis 	{ .name = "accept", .ret_type = 1, .nargs = 3,
224ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
225ee3b0f6eSDiomidis Spinellis 	{ .name = "bind", .ret_type = 1, .nargs = 3,
226ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
2277d897327SJohn Baldwin 	{ .name = "bindat", .ret_type = 1, .nargs = 4,
2287d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
2297d897327SJohn Baldwin 		    { Int, 3 } } },
230ee3b0f6eSDiomidis Spinellis 	{ .name = "connect", .ret_type = 1, .nargs = 3,
231ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
2327d897327SJohn Baldwin 	{ .name = "connectat", .ret_type = 1, .nargs = 4,
2337d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
2347d897327SJohn Baldwin 		    { Int, 3 } } },
235ee3b0f6eSDiomidis Spinellis 	{ .name = "getpeername", .ret_type = 1, .nargs = 3,
236ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
237ee3b0f6eSDiomidis Spinellis 	{ .name = "getsockname", .ret_type = 1, .nargs = 3,
238ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
239ee3b0f6eSDiomidis Spinellis 	{ .name = "recvfrom", .ret_type = 1, .nargs = 6,
2400a46af44SJohn Baldwin 	  .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 },
2410a46af44SJohn Baldwin 		    { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
242ee3b0f6eSDiomidis Spinellis 	{ .name = "sendto", .ret_type = 1, .nargs = 6,
2430a46af44SJohn Baldwin 	  .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 },
2440a46af44SJohn Baldwin 		    { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
245ee3b0f6eSDiomidis Spinellis 	{ .name = "execve", .ret_type = 1, .nargs = 3,
2460a46af44SJohn Baldwin 	  .args = { { Name | IN, 0 }, { StringArray | IN, 1 },
2470a46af44SJohn Baldwin 		    { StringArray | IN, 2 } } },
248ee3b0f6eSDiomidis Spinellis 	{ .name = "linux_execve", .ret_type = 1, .nargs = 3,
2490a46af44SJohn Baldwin 	  .args = { { Name | IN, 0 }, { StringArray | IN, 1 },
2500a46af44SJohn Baldwin 		    { StringArray | IN, 2 } } },
251ee3b0f6eSDiomidis Spinellis 	{ .name = "kldload", .ret_type = 0, .nargs = 1,
252ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 } } },
253ee3b0f6eSDiomidis Spinellis 	{ .name = "kldunload", .ret_type = 0, .nargs = 1,
254ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 } } },
255ee3b0f6eSDiomidis Spinellis 	{ .name = "kldfind", .ret_type = 0, .nargs = 1,
256ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 } } },
257ee3b0f6eSDiomidis Spinellis 	{ .name = "kldnext", .ret_type = 0, .nargs = 1,
258ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 } } },
259ee3b0f6eSDiomidis Spinellis 	{ .name = "kldstat", .ret_type = 0, .nargs = 2,
260ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Ptr, 1 } } },
261ee3b0f6eSDiomidis Spinellis 	{ .name = "kldfirstmod", .ret_type = 0, .nargs = 1,
262ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 } } },
263ee3b0f6eSDiomidis Spinellis 	{ .name = "nanosleep", .ret_type = 0, .nargs = 1,
264ee3b0f6eSDiomidis Spinellis 	  .args = { { Timespec, 0 } } },
265ee3b0f6eSDiomidis Spinellis 	{ .name = "select", .ret_type = 1, .nargs = 5,
2660a46af44SJohn Baldwin 	  .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
2670a46af44SJohn Baldwin 		    { Timeval, 4 } } },
268ee3b0f6eSDiomidis Spinellis 	{ .name = "poll", .ret_type = 1, .nargs = 3,
269ee3b0f6eSDiomidis Spinellis 	  .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
270ee3b0f6eSDiomidis Spinellis 	{ .name = "gettimeofday", .ret_type = 1, .nargs = 2,
271ee3b0f6eSDiomidis Spinellis 	  .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
272ee3b0f6eSDiomidis Spinellis 	{ .name = "clock_gettime", .ret_type = 1, .nargs = 2,
273ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
274ee3b0f6eSDiomidis Spinellis 	{ .name = "getitimer", .ret_type = 1, .nargs = 2,
275ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
276ee3b0f6eSDiomidis Spinellis 	{ .name = "setitimer", .ret_type = 1, .nargs = 3,
277ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
278ee3b0f6eSDiomidis Spinellis 	{ .name = "kse_release", .ret_type = 0, .nargs = 1,
279ee3b0f6eSDiomidis Spinellis 	  .args = { { Timespec, 0 } } },
280ee3b0f6eSDiomidis Spinellis 	{ .name = "kevent", .ret_type = 0, .nargs = 6,
2810a46af44SJohn Baldwin 	  .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
2820a46af44SJohn Baldwin 		    { Int, 4 }, { Timespec, 5 } } },
283ee3b0f6eSDiomidis Spinellis 	{ .name = "sigprocmask", .ret_type = 0, .nargs = 3,
284ee3b0f6eSDiomidis Spinellis 	  .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
285ee3b0f6eSDiomidis Spinellis 	{ .name = "unmount", .ret_type = 1, .nargs = 2,
286ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Int, 1 } } },
287ee3b0f6eSDiomidis Spinellis 	{ .name = "socket", .ret_type = 1, .nargs = 3,
288ee3b0f6eSDiomidis Spinellis 	  .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } },
289ee3b0f6eSDiomidis Spinellis 	{ .name = "getrusage", .ret_type = 1, .nargs = 2,
290ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Rusage | OUT, 1 } } },
291ee3b0f6eSDiomidis Spinellis 	{ .name = "__getcwd", .ret_type = 1, .nargs = 2,
292ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | OUT, 0 }, { Int, 1 } } },
293ee3b0f6eSDiomidis Spinellis 	{ .name = "shutdown", .ret_type = 1, .nargs = 2,
294ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { Shutdown, 1 } } },
295ee3b0f6eSDiomidis Spinellis 	{ .name = "getrlimit", .ret_type = 1, .nargs = 2,
296ee3b0f6eSDiomidis Spinellis 	  .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
297ee3b0f6eSDiomidis Spinellis 	{ .name = "setrlimit", .ret_type = 1, .nargs = 2,
298ee3b0f6eSDiomidis Spinellis 	  .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
299ee3b0f6eSDiomidis Spinellis 	{ .name = "utimes", .ret_type = 1, .nargs = 2,
300ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
301ee3b0f6eSDiomidis Spinellis 	{ .name = "lutimes", .ret_type = 1, .nargs = 2,
302ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
303ee3b0f6eSDiomidis Spinellis 	{ .name = "futimes", .ret_type = 1, .nargs = 2,
3047d897327SJohn Baldwin 	  .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
3057d897327SJohn Baldwin 	{ .name = "futimesat", .ret_type = 1, .nargs = 3,
3067d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
3077d897327SJohn Baldwin 	{ .name = "futimens", .ret_type = 1, .nargs = 2,
3087d897327SJohn Baldwin 	  .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
3097d897327SJohn Baldwin 	{ .name = "utimensat", .ret_type = 1, .nargs = 4,
3107d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
3117d897327SJohn Baldwin 		    { Atflags, 3 } } },
312ee3b0f6eSDiomidis Spinellis 	{ .name = "chflags", .ret_type = 1, .nargs = 2,
313ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Hex, 1 } } },
314ee3b0f6eSDiomidis Spinellis 	{ .name = "lchflags", .ret_type = 1, .nargs = 2,
315ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Hex, 1 } } },
316ee3b0f6eSDiomidis Spinellis 	{ .name = "pathconf", .ret_type = 1, .nargs = 2,
317ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
318c059fa2eSJaakko Heinonen 	{ .name = "pipe", .ret_type = 1, .nargs = 1,
319c059fa2eSJaakko Heinonen 	  .args = { { Ptr, 0 } } },
320ee3b0f6eSDiomidis Spinellis 	{ .name = "truncate", .ret_type = 1, .nargs = 3,
321ee3b0f6eSDiomidis Spinellis 	  .args = { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } },
322ee3b0f6eSDiomidis Spinellis 	{ .name = "ftruncate", .ret_type = 1, .nargs = 3,
323ee3b0f6eSDiomidis Spinellis 	  .args = { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } },
324ee3b0f6eSDiomidis Spinellis 	{ .name = "kill", .ret_type = 1, .nargs = 2,
325ee3b0f6eSDiomidis Spinellis 	  .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
326ee3b0f6eSDiomidis Spinellis 	{ .name = "munmap", .ret_type = 1, .nargs = 2,
327ee3b0f6eSDiomidis Spinellis 	  .args = { { Ptr, 0 }, { Int, 1 } } },
328ee3b0f6eSDiomidis Spinellis 	{ .name = "read", .ret_type = 1, .nargs = 3,
329ee3b0f6eSDiomidis Spinellis 	  .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
330ee3b0f6eSDiomidis Spinellis 	{ .name = "rename", .ret_type = 1, .nargs = 2,
331ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Name, 1 } } },
3327d897327SJohn Baldwin 	{ .name = "renameat", .ret_type = 1, .nargs = 4,
3337d897327SJohn Baldwin 	  .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
334ee3b0f6eSDiomidis Spinellis 	{ .name = "symlink", .ret_type = 1, .nargs = 2,
335ee3b0f6eSDiomidis Spinellis 	  .args = { { Name, 0 }, { Name, 1 } } },
3367d897327SJohn Baldwin 	{ .name = "symlinkat", .ret_type = 1, .nargs = 3,
3377d897327SJohn Baldwin 	  .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
3382b6d81c1SEd Schouten 	{ .name = "posix_openpt", .ret_type = 1, .nargs = 1,
3392b6d81c1SEd Schouten 	  .args = { { Open, 0 } } },
34034763d1cSJohn Baldwin 	{ .name = "wait4", .ret_type = 1, .nargs = 4,
34134763d1cSJohn Baldwin 	  .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
34234763d1cSJohn Baldwin 		    { Rusage | OUT, 3 } } },
34334763d1cSJohn Baldwin 	{ .name = "wait6", .ret_type = 1, .nargs = 6,
34434763d1cSJohn Baldwin 	  .args = { { Idtype, 0 }, { Int, 1 }, { ExitStatus | OUT, 2 },
34534763d1cSJohn Baldwin 		    { Waitoptions, 3 }, { Rusage | OUT, 4 }, { Ptr, 5 } } },
34655648840SJohn Baldwin 	{ .name = "procctl", .ret_type = 1, .nargs = 4,
34755648840SJohn Baldwin 	  .args = { { Idtype, 0 }, { Int, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
348fdb5bf37SJohn Baldwin 	{ .name = "_umtx_op", .ret_type = 1, .nargs = 5,
349fdb5bf37SJohn Baldwin 	  .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
350fdb5bf37SJohn Baldwin 		    { Ptr, 4 } } },
351ee3b0f6eSDiomidis Spinellis 	{ .name = 0 },
352bbeaf6c0SSean Eric Fagan };
353bbeaf6c0SSean Eric Fagan 
354081e5c48SPav Lucistnik /* Xlat idea taken from strace */
355081e5c48SPav Lucistnik struct xlat {
356081e5c48SPav Lucistnik 	int val;
3575d2d083cSXin LI 	const char *str;
358081e5c48SPav Lucistnik };
359081e5c48SPav Lucistnik 
360081e5c48SPav Lucistnik #define	X(a)	{ a, #a },
361081e5c48SPav Lucistnik #define	XEND	{ 0, NULL }
362081e5c48SPav Lucistnik 
363081e5c48SPav Lucistnik static struct xlat kevent_filters[] = {
364081e5c48SPav Lucistnik 	X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
365081e5c48SPav Lucistnik 	X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
366d98d7ba0SJohn Baldwin 	X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
367d98d7ba0SJohn Baldwin 	X(EVFILT_SENDFILE) XEND
368081e5c48SPav Lucistnik };
369081e5c48SPav Lucistnik 
370081e5c48SPav Lucistnik static struct xlat kevent_flags[] = {
371081e5c48SPav Lucistnik 	X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
372d98d7ba0SJohn Baldwin 	X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
373d98d7ba0SJohn Baldwin 	X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
374081e5c48SPav Lucistnik };
375081e5c48SPav Lucistnik 
376a02c83afSEd Schouten static struct xlat poll_flags[] = {
377081e5c48SPav Lucistnik 	X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
378081e5c48SPav Lucistnik 	X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
379081e5c48SPav Lucistnik 	X(POLLWRBAND) X(POLLINIGNEOF) XEND
380081e5c48SPav Lucistnik };
381081e5c48SPav Lucistnik 
382081e5c48SPav Lucistnik static struct xlat mmap_flags[] = {
3835817298fSJohn Baldwin 	X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RESERVED0020)
3845817298fSJohn Baldwin 	X(MAP_RESERVED0040) X(MAP_RESERVED0080) X(MAP_RESERVED0100)
385081e5c48SPav Lucistnik 	X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON)
386d98d7ba0SJohn Baldwin 	X(MAP_EXCL) X(MAP_NOCORE) X(MAP_PREFAULT_READ)
387edb572a3SJohn Baldwin #ifdef MAP_32BIT
388edb572a3SJohn Baldwin 	X(MAP_32BIT)
389edb572a3SJohn Baldwin #endif
390edb572a3SJohn Baldwin 	XEND
391081e5c48SPav Lucistnik };
392081e5c48SPav Lucistnik 
393081e5c48SPav Lucistnik static struct xlat mprot_flags[] = {
394081e5c48SPav Lucistnik 	X(PROT_NONE) X(PROT_READ) X(PROT_WRITE) X(PROT_EXEC) XEND
395081e5c48SPav Lucistnik };
396081e5c48SPav Lucistnik 
397081e5c48SPav Lucistnik static struct xlat whence_arg[] = {
398d98d7ba0SJohn Baldwin 	X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) X(SEEK_DATA) X(SEEK_HOLE) XEND
399081e5c48SPav Lucistnik };
400081e5c48SPav Lucistnik 
401081e5c48SPav Lucistnik static struct xlat sigaction_flags[] = {
402081e5c48SPav Lucistnik 	X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
403081e5c48SPav Lucistnik 	X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
404081e5c48SPav Lucistnik };
405081e5c48SPav Lucistnik 
406081e5c48SPav Lucistnik static struct xlat fcntl_arg[] = {
407081e5c48SPav Lucistnik 	X(F_DUPFD) X(F_GETFD) X(F_SETFD) X(F_GETFL) X(F_SETFL)
408d98d7ba0SJohn Baldwin 	X(F_GETOWN) X(F_SETOWN) X(F_OGETLK) X(F_OSETLK) X(F_OSETLKW)
409d98d7ba0SJohn Baldwin 	X(F_DUP2FD) X(F_GETLK) X(F_SETLK) X(F_SETLKW) X(F_SETLK_REMOTE)
410d98d7ba0SJohn Baldwin 	X(F_READAHEAD) X(F_RDAHEAD) X(F_DUPFD_CLOEXEC) X(F_DUP2FD_CLOEXEC)
411d98d7ba0SJohn Baldwin 	XEND
412081e5c48SPav Lucistnik };
413081e5c48SPav Lucistnik 
414081e5c48SPav Lucistnik static struct xlat fcntlfd_arg[] = {
415081e5c48SPav Lucistnik 	X(FD_CLOEXEC) XEND
416081e5c48SPav Lucistnik };
417081e5c48SPav Lucistnik 
418081e5c48SPav Lucistnik static struct xlat fcntlfl_arg[] = {
419081e5c48SPav Lucistnik 	X(O_APPEND) X(O_ASYNC) X(O_FSYNC) X(O_NONBLOCK) X(O_NOFOLLOW)
420d98d7ba0SJohn Baldwin 	X(FRDAHEAD) X(O_DIRECT) XEND
421081e5c48SPav Lucistnik };
422081e5c48SPav Lucistnik 
423081e5c48SPav Lucistnik static struct xlat sockdomain_arg[] = {
424081e5c48SPav Lucistnik 	X(PF_UNSPEC) X(PF_LOCAL) X(PF_UNIX) X(PF_INET) X(PF_IMPLINK)
425081e5c48SPav Lucistnik 	X(PF_PUP) X(PF_CHAOS) X(PF_NETBIOS) X(PF_ISO) X(PF_OSI)
426081e5c48SPav Lucistnik 	X(PF_ECMA) X(PF_DATAKIT) X(PF_CCITT) X(PF_SNA) X(PF_DECnet)
427081e5c48SPav Lucistnik 	X(PF_DLI) X(PF_LAT) X(PF_HYLINK) X(PF_APPLETALK) X(PF_ROUTE)
428081e5c48SPav Lucistnik 	X(PF_LINK) X(PF_XTP) X(PF_COIP) X(PF_CNT) X(PF_SIP) X(PF_IPX)
429081e5c48SPav Lucistnik 	X(PF_RTIP) X(PF_PIP) X(PF_ISDN) X(PF_KEY) X(PF_INET6)
430081e5c48SPav Lucistnik 	X(PF_NATM) X(PF_ATM) X(PF_NETGRAPH) X(PF_SLOW) X(PF_SCLUSTER)
431d98d7ba0SJohn Baldwin 	X(PF_ARP) X(PF_BLUETOOTH) X(PF_IEEE80211) X(PF_INET_SDP)
432d98d7ba0SJohn Baldwin 	X(PF_INET6_SDP) XEND
433081e5c48SPav Lucistnik };
434081e5c48SPav Lucistnik 
435081e5c48SPav Lucistnik static struct xlat socktype_arg[] = {
436081e5c48SPav Lucistnik 	X(SOCK_STREAM) X(SOCK_DGRAM) X(SOCK_RAW) X(SOCK_RDM)
437081e5c48SPav Lucistnik 	X(SOCK_SEQPACKET) XEND
438081e5c48SPav Lucistnik };
439081e5c48SPav Lucistnik 
440081e5c48SPav Lucistnik static struct xlat open_flags[] = {
441081e5c48SPav Lucistnik 	X(O_RDONLY) X(O_WRONLY) X(O_RDWR) X(O_ACCMODE) X(O_NONBLOCK)
442081e5c48SPav Lucistnik 	X(O_APPEND) X(O_SHLOCK) X(O_EXLOCK) X(O_ASYNC) X(O_FSYNC)
443081e5c48SPav Lucistnik 	X(O_NOFOLLOW) X(O_CREAT) X(O_TRUNC) X(O_EXCL) X(O_NOCTTY)
444d98d7ba0SJohn Baldwin 	X(O_DIRECT) X(O_DIRECTORY) X(O_EXEC) X(O_TTY_INIT) X(O_CLOEXEC)
445d98d7ba0SJohn Baldwin 	X(O_VERIFY) XEND
446081e5c48SPav Lucistnik };
447081e5c48SPav Lucistnik 
448081e5c48SPav Lucistnik static struct xlat shutdown_arg[] = {
449081e5c48SPav Lucistnik 	X(SHUT_RD) X(SHUT_WR) X(SHUT_RDWR) XEND
450081e5c48SPav Lucistnik };
451081e5c48SPav Lucistnik 
452081e5c48SPav Lucistnik static struct xlat resource_arg[] = {
453081e5c48SPav Lucistnik 	X(RLIMIT_CPU) X(RLIMIT_FSIZE) X(RLIMIT_DATA) X(RLIMIT_STACK)
454081e5c48SPav Lucistnik 	X(RLIMIT_CORE) X(RLIMIT_RSS) X(RLIMIT_MEMLOCK) X(RLIMIT_NPROC)
455d98d7ba0SJohn Baldwin 	X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) X(RLIMIT_NPTS)
456d98d7ba0SJohn Baldwin 	X(RLIMIT_SWAP) X(RLIMIT_KQUEUES) XEND
457081e5c48SPav Lucistnik };
458081e5c48SPav Lucistnik 
459081e5c48SPav Lucistnik static struct xlat pathconf_arg[] = {
460081e5c48SPav Lucistnik 	X(_PC_LINK_MAX)  X(_PC_MAX_CANON)  X(_PC_MAX_INPUT)
461081e5c48SPav Lucistnik 	X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF)
462081e5c48SPav Lucistnik 	X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE)
463081e5c48SPav Lucistnik 	X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO)
464081e5c48SPav Lucistnik 	X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS)
465081e5c48SPav Lucistnik 	X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE)
466081e5c48SPav Lucistnik 	X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN)
467081e5c48SPav Lucistnik 	X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX)
468081e5c48SPav Lucistnik 	X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT)
469d98d7ba0SJohn Baldwin 	X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND
470081e5c48SPav Lucistnik };
471081e5c48SPav Lucistnik 
4729e1db66eSMark Johnston static struct xlat rfork_flags[] = {
473d98d7ba0SJohn Baldwin 	X(RFFDG) X(RFPROC) X(RFMEM) X(RFNOWAIT) X(RFCFDG) X(RFTHREAD)
474d98d7ba0SJohn Baldwin 	X(RFSIGSHARE) X(RFLINUXTHPN) X(RFTSIGZMB) X(RFPPWAIT) XEND
4759e1db66eSMark Johnston };
4769e1db66eSMark Johnston 
47734763d1cSJohn Baldwin static struct xlat wait_options[] = {
47834763d1cSJohn Baldwin 	X(WNOHANG) X(WUNTRACED) X(WCONTINUED) X(WNOWAIT) X(WEXITED)
47934763d1cSJohn Baldwin 	X(WTRAPPED) XEND
48034763d1cSJohn Baldwin };
48134763d1cSJohn Baldwin 
48234763d1cSJohn Baldwin static struct xlat idtype_arg[] = {
48334763d1cSJohn Baldwin 	X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID)
48434763d1cSJohn Baldwin 	X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID)
48534763d1cSJohn Baldwin 	X(P_CTID) X(P_CPUID) X(P_PSETID) XEND
48634763d1cSJohn Baldwin };
48734763d1cSJohn Baldwin 
48855648840SJohn Baldwin static struct xlat procctl_arg[] = {
48955648840SJohn Baldwin 	X(PROC_SPROTECT) XEND
49055648840SJohn Baldwin };
49155648840SJohn Baldwin 
492fdb5bf37SJohn Baldwin static struct xlat umtx_ops[] = {
493fdb5bf37SJohn Baldwin 	X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT)
494fdb5bf37SJohn Baldwin 	X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK)
495fdb5bf37SJohn Baldwin 	X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT)
496fdb5bf37SJohn Baldwin 	X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT)
497fdb5bf37SJohn Baldwin 	X(UMTX_OP_RW_RDLOCK) X(UMTX_OP_RW_WRLOCK) X(UMTX_OP_RW_UNLOCK)
498fdb5bf37SJohn Baldwin 	X(UMTX_OP_WAIT_UINT_PRIVATE) X(UMTX_OP_WAKE_PRIVATE)
499fdb5bf37SJohn Baldwin 	X(UMTX_OP_MUTEX_WAIT) X(UMTX_OP_MUTEX_WAKE) X(UMTX_OP_SEM_WAIT)
500fdb5bf37SJohn Baldwin 	X(UMTX_OP_SEM_WAKE) X(UMTX_OP_NWAKE_PRIVATE) X(UMTX_OP_MUTEX_WAKE2)
50153e1ffbbSJohn Baldwin 	X(UMTX_OP_SEM2_WAIT) X(UMTX_OP_SEM2_WAKE)
502fdb5bf37SJohn Baldwin 	XEND
503fdb5bf37SJohn Baldwin };
504fdb5bf37SJohn Baldwin 
5057d897327SJohn Baldwin static struct xlat at_flags[] = {
5067d897327SJohn Baldwin 	X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW)
5077d897327SJohn Baldwin 	X(AT_REMOVEDIR) XEND
5087d897327SJohn Baldwin };
5097d897327SJohn Baldwin 
5107d897327SJohn Baldwin static struct xlat access_modes[] = {
5117d897327SJohn Baldwin 	X(R_OK) X(W_OK) X(X_OK) XEND
5127d897327SJohn Baldwin };
5137d897327SJohn Baldwin 
514081e5c48SPav Lucistnik #undef X
515081e5c48SPav Lucistnik #undef XEND
516081e5c48SPav Lucistnik 
517d8984f48SDag-Erling Smørgrav /*
518d8984f48SDag-Erling Smørgrav  * Searches an xlat array for a value, and returns it if found.  Otherwise
519d8984f48SDag-Erling Smørgrav  * return a string representation.
520d8984f48SDag-Erling Smørgrav  */
521d8984f48SDag-Erling Smørgrav static const char *
522d8984f48SDag-Erling Smørgrav lookup(struct xlat *xlat, int val, int base)
523081e5c48SPav Lucistnik {
524081e5c48SPav Lucistnik 	static char tmp[16];
525d8984f48SDag-Erling Smørgrav 
526081e5c48SPav Lucistnik 	for (; xlat->str != NULL; xlat++)
527081e5c48SPav Lucistnik 		if (xlat->val == val)
528d8984f48SDag-Erling Smørgrav 			return (xlat->str);
529081e5c48SPav Lucistnik 	switch (base) {
530081e5c48SPav Lucistnik 		case 8:
531081e5c48SPav Lucistnik 			sprintf(tmp, "0%o", val);
532081e5c48SPav Lucistnik 			break;
533081e5c48SPav Lucistnik 		case 16:
534081e5c48SPav Lucistnik 			sprintf(tmp, "0x%x", val);
535081e5c48SPav Lucistnik 			break;
536081e5c48SPav Lucistnik 		case 10:
537081e5c48SPav Lucistnik 			sprintf(tmp, "%u", val);
538081e5c48SPav Lucistnik 			break;
539081e5c48SPav Lucistnik 		default:
540081e5c48SPav Lucistnik 			errx(1,"Unknown lookup base");
541081e5c48SPav Lucistnik 			break;
542081e5c48SPav Lucistnik 	}
543d8984f48SDag-Erling Smørgrav 	return (tmp);
544081e5c48SPav Lucistnik }
545081e5c48SPav Lucistnik 
5465d2d083cSXin LI static const char *
5475d2d083cSXin LI xlookup(struct xlat *xlat, int val)
548081e5c48SPav Lucistnik {
549d8984f48SDag-Erling Smørgrav 
550d8984f48SDag-Erling Smørgrav 	return (lookup(xlat, val, 16));
551081e5c48SPav Lucistnik }
552081e5c48SPav Lucistnik 
553081e5c48SPav Lucistnik /* Searches an xlat array containing bitfield values.  Remaining bits
554081e5c48SPav Lucistnik    set after removing the known ones are printed at the end:
555081e5c48SPav Lucistnik    IN|0x400 */
556d8984f48SDag-Erling Smørgrav static char *
557d8984f48SDag-Erling Smørgrav xlookup_bits(struct xlat *xlat, int val)
558081e5c48SPav Lucistnik {
55994355cfdSAndrey Zonov 	int len, rem;
560081e5c48SPav Lucistnik 	static char str[512];
561081e5c48SPav Lucistnik 
56294355cfdSAndrey Zonov 	len = 0;
56394355cfdSAndrey Zonov 	rem = val;
564d8984f48SDag-Erling Smørgrav 	for (; xlat->str != NULL; xlat++) {
565d8984f48SDag-Erling Smørgrav 		if ((xlat->val & rem) == xlat->val) {
566081e5c48SPav Lucistnik 			/* don't print the "all-bits-zero" string unless all
567081e5c48SPav Lucistnik 			   bits are really zero */
568081e5c48SPav Lucistnik 			if (xlat->val == 0 && val != 0)
569081e5c48SPav Lucistnik 				continue;
570081e5c48SPav Lucistnik 			len += sprintf(str + len, "%s|", xlat->str);
571081e5c48SPav Lucistnik 			rem &= ~(xlat->val);
572081e5c48SPav Lucistnik 		}
573081e5c48SPav Lucistnik 	}
574081e5c48SPav Lucistnik 	/* if we have leftover bits or didn't match anything */
575081e5c48SPav Lucistnik 	if (rem || len == 0)
576081e5c48SPav Lucistnik 		len += sprintf(str + len, "0x%x", rem);
577081e5c48SPav Lucistnik 	if (len && str[len - 1] == '|')
578081e5c48SPav Lucistnik 		len--;
579081e5c48SPav Lucistnik 	str[len] = 0;
580d8984f48SDag-Erling Smørgrav 	return (str);
581081e5c48SPav Lucistnik }
582081e5c48SPav Lucistnik 
583bbeaf6c0SSean Eric Fagan /*
584bbeaf6c0SSean Eric Fagan  * If/when the list gets big, it might be desirable to do it
585bbeaf6c0SSean Eric Fagan  * as a hash table or binary search.
586bbeaf6c0SSean Eric Fagan  */
587bbeaf6c0SSean Eric Fagan 
588bbeaf6c0SSean Eric Fagan struct syscall *
589d8984f48SDag-Erling Smørgrav get_syscall(const char *name)
590d8984f48SDag-Erling Smørgrav {
59194355cfdSAndrey Zonov 	struct syscall *sc;
592bbeaf6c0SSean Eric Fagan 
59394355cfdSAndrey Zonov 	sc = syscalls;
594d10f73b3SAlfred Perlstein 	if (name == NULL)
595d10f73b3SAlfred Perlstein 		return (NULL);
596bbeaf6c0SSean Eric Fagan 	while (sc->name) {
59794355cfdSAndrey Zonov 		if (strcmp(name, sc->name) == 0)
598d8984f48SDag-Erling Smørgrav 			return (sc);
599bbeaf6c0SSean Eric Fagan 		sc++;
600bbeaf6c0SSean Eric Fagan 	}
601d8984f48SDag-Erling Smørgrav 	return (NULL);
602bbeaf6c0SSean Eric Fagan }
603bbeaf6c0SSean Eric Fagan 
604bbeaf6c0SSean Eric Fagan /*
6059ddd1412SDag-Erling Smørgrav  * get_struct
6069ddd1412SDag-Erling Smørgrav  *
6079ddd1412SDag-Erling Smørgrav  * Copy a fixed amount of bytes from the process.
6089ddd1412SDag-Erling Smørgrav  */
6099ddd1412SDag-Erling Smørgrav 
6101be5d704SMark Murray static int
611be305c9cSAndrey Zonov get_struct(pid_t pid, void *offset, void *buf, int len)
612d8984f48SDag-Erling Smørgrav {
6135d2d083cSXin LI 	struct ptrace_io_desc iorequest;
6149ddd1412SDag-Erling Smørgrav 
6155d2d083cSXin LI 	iorequest.piod_op = PIOD_READ_D;
6165d2d083cSXin LI 	iorequest.piod_offs = offset;
6175d2d083cSXin LI 	iorequest.piod_addr = buf;
6185d2d083cSXin LI 	iorequest.piod_len = len;
6195d2d083cSXin LI 	if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
620d8984f48SDag-Erling Smørgrav 		return (-1);
621d8984f48SDag-Erling Smørgrav 	return (0);
6229ddd1412SDag-Erling Smørgrav }
6239ddd1412SDag-Erling Smørgrav 
6245d2d083cSXin LI #define	MAXSIZE		4096
625abb3f965SJohn Baldwin 
6269ddd1412SDag-Erling Smørgrav /*
627bbeaf6c0SSean Eric Fagan  * get_string
628bbeaf6c0SSean Eric Fagan  * Copy a string from the process.  Note that it is
629bbeaf6c0SSean Eric Fagan  * expected to be a C string, but if max is set, it will
630bbeaf6c0SSean Eric Fagan  * only get that much.
631bbeaf6c0SSean Eric Fagan  */
6325d2d083cSXin LI static char *
633abb3f965SJohn Baldwin get_string(pid_t pid, void *addr, int max)
634d8984f48SDag-Erling Smørgrav {
6355d2d083cSXin LI 	struct ptrace_io_desc iorequest;
636abb3f965SJohn Baldwin 	char *buf, *nbuf;
637abb3f965SJohn Baldwin 	size_t offset, size, totalsize;
638bbeaf6c0SSean Eric Fagan 
639abb3f965SJohn Baldwin 	offset = 0;
640abb3f965SJohn Baldwin 	if (max)
641abb3f965SJohn Baldwin 		size = max + 1;
642abb3f965SJohn Baldwin 	else {
643abb3f965SJohn Baldwin 		/* Read up to the end of the current page. */
644abb3f965SJohn Baldwin 		size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
645abb3f965SJohn Baldwin 		if (size > MAXSIZE)
646abb3f965SJohn Baldwin 			size = MAXSIZE;
647abb3f965SJohn Baldwin 	}
648abb3f965SJohn Baldwin 	totalsize = size;
6495d2d083cSXin LI 	buf = malloc(totalsize);
6505d2d083cSXin LI 	if (buf == NULL)
651d8984f48SDag-Erling Smørgrav 		return (NULL);
6525d2d083cSXin LI 	for (;;) {
6535d2d083cSXin LI 		iorequest.piod_op = PIOD_READ_D;
654abb3f965SJohn Baldwin 		iorequest.piod_offs = (char *)addr + offset;
655abb3f965SJohn Baldwin 		iorequest.piod_addr = buf + offset;
6565d2d083cSXin LI 		iorequest.piod_len = size;
6575d2d083cSXin LI 		if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
6585d2d083cSXin LI 			free(buf);
659d8984f48SDag-Erling Smørgrav 			return (NULL);
660bbeaf6c0SSean Eric Fagan 		}
661abb3f965SJohn Baldwin 		if (memchr(buf + offset, '\0', size) != NULL)
662abb3f965SJohn Baldwin 			return (buf);
663abb3f965SJohn Baldwin 		offset += size;
664abb3f965SJohn Baldwin 		if (totalsize < MAXSIZE && max == 0) {
665abb3f965SJohn Baldwin 			size = MAXSIZE - totalsize;
666abb3f965SJohn Baldwin 			if (size > PAGE_SIZE)
667abb3f965SJohn Baldwin 				size = PAGE_SIZE;
668abb3f965SJohn Baldwin 			nbuf = realloc(buf, totalsize + size);
669abb3f965SJohn Baldwin 			if (nbuf == NULL) {
670abb3f965SJohn Baldwin 				buf[totalsize - 1] = '\0';
6714e92419dSMarcel Moolenaar 				return (buf);
672bbeaf6c0SSean Eric Fagan 			}
673abb3f965SJohn Baldwin 			buf = nbuf;
674abb3f965SJohn Baldwin 			totalsize += size;
675d8984f48SDag-Erling Smørgrav 		} else {
676cdfc719cSJaakko Heinonen 			buf[totalsize - 1] = '\0';
677d8984f48SDag-Erling Smørgrav 			return (buf);
6785d2d083cSXin LI 		}
6795d2d083cSXin LI 	}
6805d2d083cSXin LI }
681bbeaf6c0SSean Eric Fagan 
68234763d1cSJohn Baldwin static char *
68334763d1cSJohn Baldwin strsig2(int sig)
68434763d1cSJohn Baldwin {
68534763d1cSJohn Baldwin 	char *tmp;
68634763d1cSJohn Baldwin 
68734763d1cSJohn Baldwin 	tmp = strsig(sig);
68834763d1cSJohn Baldwin 	if (tmp == NULL)
68934763d1cSJohn Baldwin 		asprintf(&tmp, "%d", sig);
69034763d1cSJohn Baldwin 	return (tmp);
69134763d1cSJohn Baldwin }
692bbeaf6c0SSean Eric Fagan 
693bbeaf6c0SSean Eric Fagan /*
694bbeaf6c0SSean Eric Fagan  * print_arg
695bbeaf6c0SSean Eric Fagan  * Converts a syscall argument into a string.  Said string is
696bbeaf6c0SSean Eric Fagan  * allocated via malloc(), so needs to be free()'d.  The file
697bbeaf6c0SSean Eric Fagan  * descriptor is for the process' memory (via /proc), and is used
698bbeaf6c0SSean Eric Fagan  * to get any data (where the argument is a pointer).  sc is
699bbeaf6c0SSean Eric Fagan  * a pointer to the syscall description (see above); args is
700bbeaf6c0SSean Eric Fagan  * an array of all of the system call arguments.
701bbeaf6c0SSean Eric Fagan  */
702bbeaf6c0SSean Eric Fagan 
703bbeaf6c0SSean Eric Fagan char *
70494355cfdSAndrey Zonov print_arg(struct syscall_args *sc, unsigned long *args, long retval,
70594355cfdSAndrey Zonov     struct trussinfo *trussinfo)
706d8984f48SDag-Erling Smørgrav {
70794355cfdSAndrey Zonov 	char *tmp;
70894355cfdSAndrey Zonov 	pid_t pid;
709d8984f48SDag-Erling Smørgrav 
71094355cfdSAndrey Zonov 	tmp = NULL;
71194355cfdSAndrey Zonov 	pid = trussinfo->pid;
712bbeaf6c0SSean Eric Fagan 	switch (sc->type & ARG_MASK) {
713bbeaf6c0SSean Eric Fagan 	case Hex:
714f2359950SMarcel Moolenaar 		asprintf(&tmp, "0x%x", (int)args[sc->offset]);
715bbeaf6c0SSean Eric Fagan 		break;
716bbeaf6c0SSean Eric Fagan 	case Octal:
717f2359950SMarcel Moolenaar 		asprintf(&tmp, "0%o", (int)args[sc->offset]);
718bbeaf6c0SSean Eric Fagan 		break;
719bbeaf6c0SSean Eric Fagan 	case Int:
720f2359950SMarcel Moolenaar 		asprintf(&tmp, "%d", (int)args[sc->offset]);
721bbeaf6c0SSean Eric Fagan 		break;
722fdb5bf37SJohn Baldwin 	case LongHex:
723fdb5bf37SJohn Baldwin 		asprintf(&tmp, "0x%lx", args[sc->offset]);
724fdb5bf37SJohn Baldwin 		break;
725d8984f48SDag-Erling Smørgrav 	case Name: {
726081e5c48SPav Lucistnik 		/* NULL-terminated string. */
727bbeaf6c0SSean Eric Fagan 		char *tmp2;
7285d2d083cSXin LI 		tmp2 = get_string(pid, (void*)args[sc->offset], 0);
7291bcb5f5aSMarcel Moolenaar 		asprintf(&tmp, "\"%s\"", tmp2);
730bbeaf6c0SSean Eric Fagan 		free(tmp2);
731bbeaf6c0SSean Eric Fagan 		break;
732d8984f48SDag-Erling Smørgrav 	}
733d8984f48SDag-Erling Smørgrav 	case BinString: {
734081e5c48SPav Lucistnik 		/* Binary block of data that might have printable characters.
735081e5c48SPav Lucistnik 		   XXX If type|OUT, assume that the length is the syscall's
736081e5c48SPav Lucistnik 		   return value.  Otherwise, assume that the length of the block
737081e5c48SPav Lucistnik 		   is in the next syscall argument. */
738081e5c48SPav Lucistnik 		int max_string = trussinfo->strsize;
739081e5c48SPav Lucistnik 		char tmp2[max_string+1], *tmp3;
740081e5c48SPav Lucistnik 		int len;
741081e5c48SPav Lucistnik 		int truncated = 0;
742081e5c48SPav Lucistnik 
743081e5c48SPav Lucistnik 		if (sc->type & OUT)
744081e5c48SPav Lucistnik 			len = retval;
745081e5c48SPav Lucistnik 		else
746081e5c48SPav Lucistnik 			len = args[sc->offset + 1];
747081e5c48SPav Lucistnik 
748081e5c48SPav Lucistnik 		/* Don't print more than max_string characters, to avoid word
749081e5c48SPav Lucistnik 		   wrap.  If we have to truncate put some ... after the string.
750081e5c48SPav Lucistnik 		*/
751081e5c48SPav Lucistnik 		if (len > max_string) {
752081e5c48SPav Lucistnik 			len = max_string;
753081e5c48SPav Lucistnik 			truncated = 1;
754081e5c48SPav Lucistnik 		}
75594355cfdSAndrey Zonov 		if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
75694355cfdSAndrey Zonov 		    != -1) {
757081e5c48SPav Lucistnik 			tmp3 = malloc(len * 4 + 1);
758081e5c48SPav Lucistnik 			while (len) {
75994355cfdSAndrey Zonov 				if (strvisx(tmp3, tmp2, len,
76094355cfdSAndrey Zonov 				    VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
761081e5c48SPav Lucistnik 					break;
762081e5c48SPav Lucistnik 				len--;
763081e5c48SPav Lucistnik 				truncated = 1;
764081e5c48SPav Lucistnik 			};
76594355cfdSAndrey Zonov 			asprintf(&tmp, "\"%s\"%s", tmp3, truncated ?
76694355cfdSAndrey Zonov 			    "..." : "");
767081e5c48SPav Lucistnik 			free(tmp3);
768d8984f48SDag-Erling Smørgrav 		} else {
769081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
770081e5c48SPav Lucistnik 		}
771081e5c48SPav Lucistnik 		break;
772d8984f48SDag-Erling Smørgrav 	}
773d8984f48SDag-Erling Smørgrav 	case StringArray: {
7749897b203SMatthew N. Dodd 		int num, size, i;
7759897b203SMatthew N. Dodd 		char *tmp2;
7769897b203SMatthew N. Dodd 		char *string;
7779897b203SMatthew N. Dodd 		char *strarray[100];	/* XXX This is ugly. */
7789897b203SMatthew N. Dodd 
77994355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset],
78094355cfdSAndrey Zonov 		    (void *)&strarray, sizeof(strarray)) == -1)
7819897b203SMatthew N. Dodd 			err(1, "get_struct %p", (void *)args[sc->offset]);
7829897b203SMatthew N. Dodd 		num = 0;
7839897b203SMatthew N. Dodd 		size = 0;
7849897b203SMatthew N. Dodd 
7859897b203SMatthew N. Dodd 		/* Find out how large of a buffer we'll need. */
7869897b203SMatthew N. Dodd 		while (strarray[num] != NULL) {
7875d2d083cSXin LI 			string = get_string(pid, (void*)strarray[num], 0);
7889897b203SMatthew N. Dodd 			size += strlen(string);
7899897b203SMatthew N. Dodd 			free(string);
7909897b203SMatthew N. Dodd 			num++;
7919897b203SMatthew N. Dodd 		}
7929897b203SMatthew N. Dodd 		size += 4 + (num * 4);
7939897b203SMatthew N. Dodd 		tmp = (char *)malloc(size);
7949897b203SMatthew N. Dodd 		tmp2 = tmp;
7959897b203SMatthew N. Dodd 
7969897b203SMatthew N. Dodd 		tmp2 += sprintf(tmp2, " [");
7979897b203SMatthew N. Dodd 		for (i = 0; i < num; i++) {
7985d2d083cSXin LI 			string = get_string(pid, (void*)strarray[i], 0);
79994355cfdSAndrey Zonov 			tmp2 += sprintf(tmp2, " \"%s\"%c", string,
80094355cfdSAndrey Zonov 			    (i + 1 == num) ? ' ' : ',');
8019897b203SMatthew N. Dodd 			free(string);
8029897b203SMatthew N. Dodd 		}
8039897b203SMatthew N. Dodd 		tmp2 += sprintf(tmp2, "]");
8049897b203SMatthew N. Dodd 		break;
805d8984f48SDag-Erling Smørgrav 	}
80610aeefc9SMarcel Moolenaar #ifdef __LP64__
80710aeefc9SMarcel Moolenaar 	case Quad:
80810aeefc9SMarcel Moolenaar 		asprintf(&tmp, "0x%lx", args[sc->offset]);
80910aeefc9SMarcel Moolenaar 		break;
81010aeefc9SMarcel Moolenaar #else
811d8984f48SDag-Erling Smørgrav 	case Quad: {
81210aeefc9SMarcel Moolenaar 		unsigned long long ll;
81310aeefc9SMarcel Moolenaar 		ll = *(unsigned long long *)(args + sc->offset);
81410aeefc9SMarcel Moolenaar 		asprintf(&tmp, "0x%llx", ll);
815bbeaf6c0SSean Eric Fagan 		break;
816bbeaf6c0SSean Eric Fagan 	}
81710aeefc9SMarcel Moolenaar #endif
818bbeaf6c0SSean Eric Fagan 	case Ptr:
8191bcb5f5aSMarcel Moolenaar 		asprintf(&tmp, "0x%lx", args[sc->offset]);
820bbeaf6c0SSean Eric Fagan 		break;
821d8984f48SDag-Erling Smørgrav 	case Readlinkres: {
8222bae4eb3SAlfred Perlstein 		char *tmp2;
8232bae4eb3SAlfred Perlstein 		if (retval == -1) {
8242bae4eb3SAlfred Perlstein 			tmp = strdup("");
8252bae4eb3SAlfred Perlstein 			break;
8262bae4eb3SAlfred Perlstein 		}
8275d2d083cSXin LI 		tmp2 = get_string(pid, (void*)args[sc->offset], retval);
8282bae4eb3SAlfred Perlstein 		asprintf(&tmp, "\"%s\"", tmp2);
8292bae4eb3SAlfred Perlstein 		free(tmp2);
8302bae4eb3SAlfred Perlstein 		break;
831d8984f48SDag-Erling Smørgrav 	}
832d8984f48SDag-Erling Smørgrav 	case Ioctl: {
8331be5d704SMark Murray 		const char *temp = ioctlname(args[sc->offset]);
83494355cfdSAndrey Zonov 		if (temp)
835970649f9SSean Eric Fagan 			tmp = strdup(temp);
83694355cfdSAndrey Zonov 		else {
837081e5c48SPav Lucistnik 			unsigned long arg = args[sc->offset];
83894355cfdSAndrey Zonov 			asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
83994355cfdSAndrey Zonov 			    arg, arg & IOC_OUT ? "R" : "",
84094355cfdSAndrey Zonov 			    arg & IOC_IN ? "W" : "", IOCGROUP(arg),
84194355cfdSAndrey Zonov 			    isprint(IOCGROUP(arg)) ? (char)IOCGROUP(arg) : '?',
842081e5c48SPav Lucistnik 			    arg & 0xFF, IOCPARM_LEN(arg));
843081e5c48SPav Lucistnik 		}
844081e5c48SPav Lucistnik 		break;
845d8984f48SDag-Erling Smørgrav 	}
846d8984f48SDag-Erling Smørgrav 	case Timespec: {
847e45a5a0dSDavid Malone 		struct timespec ts;
84894355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &ts,
84994355cfdSAndrey Zonov 		    sizeof(ts)) != -1)
85094355cfdSAndrey Zonov 			asprintf(&tmp, "{ %ld.%09ld }", (long)ts.tv_sec,
85194355cfdSAndrey Zonov 			    ts.tv_nsec);
852e45a5a0dSDavid Malone 		else
853e45a5a0dSDavid Malone 			asprintf(&tmp, "0x%lx", args[sc->offset]);
854e45a5a0dSDavid Malone 		break;
855d8984f48SDag-Erling Smørgrav 	}
8567d897327SJohn Baldwin 	case Timespec2: {
8577d897327SJohn Baldwin 		struct timespec ts[2];
8587d897327SJohn Baldwin 		FILE *fp;
8597d897327SJohn Baldwin 		size_t len;
8607d897327SJohn Baldwin 		const char *sep;
8617d897327SJohn Baldwin 		unsigned int i;
8627d897327SJohn Baldwin 
8637d897327SJohn Baldwin 		if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
8647d897327SJohn Baldwin 		    != -1) {
8657d897327SJohn Baldwin 			fp = open_memstream(&tmp, &len);
866*1e2ec671SJohn Baldwin 			fputs("{ ", fp);
8677d897327SJohn Baldwin 			sep = "";
8687d897327SJohn Baldwin 			for (i = 0; i < nitems(ts); i++) {
8697d897327SJohn Baldwin 				fputs(sep, fp);
8707d897327SJohn Baldwin 				sep = ", ";
8717d897327SJohn Baldwin 				switch (ts[i].tv_nsec) {
8727d897327SJohn Baldwin 				case UTIME_NOW:
8737d897327SJohn Baldwin 					fprintf(fp, "UTIME_NOW");
8747d897327SJohn Baldwin 					break;
8757d897327SJohn Baldwin 				case UTIME_OMIT:
8767d897327SJohn Baldwin 					fprintf(fp, "UTIME_OMIT");
8777d897327SJohn Baldwin 					break;
8787d897327SJohn Baldwin 				default:
8797d897327SJohn Baldwin 					fprintf(fp, "%ld.%09ld",
8807d897327SJohn Baldwin 					    (long)ts[i].tv_sec, ts[i].tv_nsec);
8817d897327SJohn Baldwin 					break;
8827d897327SJohn Baldwin 				}
8837d897327SJohn Baldwin 			}
884*1e2ec671SJohn Baldwin 			fputs(" }", fp);
8857d897327SJohn Baldwin 			fclose(fp);
8867d897327SJohn Baldwin 		} else
8877d897327SJohn Baldwin 			asprintf(&tmp, "0x%lx", args[sc->offset]);
8887d897327SJohn Baldwin 		break;
8897d897327SJohn Baldwin 	}
890d8984f48SDag-Erling Smørgrav 	case Timeval: {
891e45a5a0dSDavid Malone 		struct timeval tv;
89294355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
89394355cfdSAndrey Zonov 		    != -1)
89494355cfdSAndrey Zonov 			asprintf(&tmp, "{ %ld.%06ld }", (long)tv.tv_sec,
89594355cfdSAndrey Zonov 			    tv.tv_usec);
896081e5c48SPav Lucistnik 		else
897081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
898081e5c48SPav Lucistnik 		break;
899d8984f48SDag-Erling Smørgrav 	}
900d8984f48SDag-Erling Smørgrav 	case Timeval2: {
901081e5c48SPav Lucistnik 		struct timeval tv[2];
90294355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
90394355cfdSAndrey Zonov 		    != -1)
904081e5c48SPav Lucistnik 			asprintf(&tmp, "{ %ld.%06ld, %ld.%06ld }",
905081e5c48SPav Lucistnik 			    (long)tv[0].tv_sec, tv[0].tv_usec,
906081e5c48SPav Lucistnik 			    (long)tv[1].tv_sec, tv[1].tv_usec);
907e45a5a0dSDavid Malone 		else
908e45a5a0dSDavid Malone 			asprintf(&tmp, "0x%lx", args[sc->offset]);
909e45a5a0dSDavid Malone 		break;
910d8984f48SDag-Erling Smørgrav 	}
911d8984f48SDag-Erling Smørgrav 	case Itimerval: {
912e45a5a0dSDavid Malone 		struct itimerval itv;
91394355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &itv,
91494355cfdSAndrey Zonov 		    sizeof(itv)) != -1)
915081e5c48SPav Lucistnik 			asprintf(&tmp, "{ %ld.%06ld, %ld.%06ld }",
916081e5c48SPav Lucistnik 			    (long)itv.it_interval.tv_sec,
917081e5c48SPav Lucistnik 			    itv.it_interval.tv_usec,
918081e5c48SPav Lucistnik 			    (long)itv.it_value.tv_sec,
919081e5c48SPav Lucistnik 			    itv.it_value.tv_usec);
920e45a5a0dSDavid Malone 		else
921e45a5a0dSDavid Malone 			asprintf(&tmp, "0x%lx", args[sc->offset]);
922e45a5a0dSDavid Malone 		break;
923d8984f48SDag-Erling Smørgrav 	}
9241c99a22aSSteven Hartland 	case LinuxSockArgs:
9251c99a22aSSteven Hartland 	{
9261c99a22aSSteven Hartland 		struct linux_socketcall_args largs;
9271c99a22aSSteven Hartland 		if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
9281c99a22aSSteven Hartland 		    sizeof(largs)) == -1) {
9291c99a22aSSteven Hartland 			err(1, "get_struct %p", (void *)args[sc->offset]);
9301c99a22aSSteven Hartland 		}
9311c99a22aSSteven Hartland 		const char *what;
9321c99a22aSSteven Hartland 		char buf[30];
9331c99a22aSSteven Hartland 
9341c99a22aSSteven Hartland 		switch (largs.what) {
9351c99a22aSSteven Hartland 		case LINUX_SOCKET:
9361c99a22aSSteven Hartland 			what = "LINUX_SOCKET";
9371c99a22aSSteven Hartland 			break;
9381c99a22aSSteven Hartland 		case LINUX_BIND:
9391c99a22aSSteven Hartland 			what = "LINUX_BIND";
9401c99a22aSSteven Hartland 			break;
9411c99a22aSSteven Hartland 		case LINUX_CONNECT:
9421c99a22aSSteven Hartland 			what = "LINUX_CONNECT";
9431c99a22aSSteven Hartland 			break;
9441c99a22aSSteven Hartland 		case LINUX_LISTEN:
9451c99a22aSSteven Hartland 			what = "LINUX_LISTEN";
9461c99a22aSSteven Hartland 			break;
9471c99a22aSSteven Hartland 		case LINUX_ACCEPT:
9481c99a22aSSteven Hartland 			what = "LINUX_ACCEPT";
9491c99a22aSSteven Hartland 			break;
9501c99a22aSSteven Hartland 		case LINUX_GETSOCKNAME:
9511c99a22aSSteven Hartland 			what = "LINUX_GETSOCKNAME";
9521c99a22aSSteven Hartland 			break;
9531c99a22aSSteven Hartland 		case LINUX_GETPEERNAME:
9541c99a22aSSteven Hartland 			what = "LINUX_GETPEERNAME";
9551c99a22aSSteven Hartland 			break;
9561c99a22aSSteven Hartland 		case LINUX_SOCKETPAIR:
9571c99a22aSSteven Hartland 			what = "LINUX_SOCKETPAIR";
9581c99a22aSSteven Hartland 			break;
9591c99a22aSSteven Hartland 		case LINUX_SEND:
9601c99a22aSSteven Hartland 			what = "LINUX_SEND";
9611c99a22aSSteven Hartland 			break;
9621c99a22aSSteven Hartland 		case LINUX_RECV:
9631c99a22aSSteven Hartland 			what = "LINUX_RECV";
9641c99a22aSSteven Hartland 			break;
9651c99a22aSSteven Hartland 		case LINUX_SENDTO:
9661c99a22aSSteven Hartland 			what = "LINUX_SENDTO";
9671c99a22aSSteven Hartland 			break;
9681c99a22aSSteven Hartland 		case LINUX_RECVFROM:
9691c99a22aSSteven Hartland 			what = "LINUX_RECVFROM";
9701c99a22aSSteven Hartland 			break;
9711c99a22aSSteven Hartland 		case LINUX_SHUTDOWN:
9721c99a22aSSteven Hartland 			what = "LINUX_SHUTDOWN";
9731c99a22aSSteven Hartland 			break;
9741c99a22aSSteven Hartland 		case LINUX_SETSOCKOPT:
9751c99a22aSSteven Hartland 			what = "LINUX_SETSOCKOPT";
9761c99a22aSSteven Hartland 			break;
9771c99a22aSSteven Hartland 		case LINUX_GETSOCKOPT:
9781c99a22aSSteven Hartland 			what = "LINUX_GETSOCKOPT";
9791c99a22aSSteven Hartland 			break;
9801c99a22aSSteven Hartland 		case LINUX_SENDMSG:
9811c99a22aSSteven Hartland 			what = "LINUX_SENDMSG";
9821c99a22aSSteven Hartland 			break;
9831c99a22aSSteven Hartland 		case LINUX_RECVMSG:
9841c99a22aSSteven Hartland 			what = "LINUX_RECVMSG";
9851c99a22aSSteven Hartland 			break;
9861c99a22aSSteven Hartland 		default:
9871c99a22aSSteven Hartland 			sprintf(buf, "%d", largs.what);
9881c99a22aSSteven Hartland 			what = buf;
9891c99a22aSSteven Hartland 			break;
9901c99a22aSSteven Hartland 		}
9910a46af44SJohn Baldwin 		asprintf(&tmp, "(0x%lx)%s, 0x%lx", args[sc->offset], what,
9920a46af44SJohn Baldwin 		    (long unsigned int)largs.args);
9931c99a22aSSteven Hartland 		break;
9941c99a22aSSteven Hartland 	}
995d8984f48SDag-Erling Smørgrav 	case Pollfd: {
996e45a5a0dSDavid Malone 		/*
99794355cfdSAndrey Zonov 		 * XXX: A Pollfd argument expects the /next/ syscall argument
99894355cfdSAndrey Zonov 		 * to be the number of fds in the array. This matches the poll
99994355cfdSAndrey Zonov 		 * syscall.
1000e45a5a0dSDavid Malone 		 */
1001e45a5a0dSDavid Malone 		struct pollfd *pfd;
1002e45a5a0dSDavid Malone 		int numfds = args[sc->offset+1];
1003e45a5a0dSDavid Malone 		int bytes = sizeof(struct pollfd) * numfds;
1004e45a5a0dSDavid Malone 		int i, tmpsize, u, used;
1005e45a5a0dSDavid Malone 		const int per_fd = 100;
1006e45a5a0dSDavid Malone 
1007e45a5a0dSDavid Malone 		if ((pfd = malloc(bytes)) == NULL)
100894355cfdSAndrey Zonov 			err(1, "Cannot malloc %d bytes for pollfd array",
100994355cfdSAndrey Zonov 			    bytes);
101094355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
101194355cfdSAndrey Zonov 		    != -1) {
1012e45a5a0dSDavid Malone 			used = 0;
1013e45a5a0dSDavid Malone 			tmpsize = 1 + per_fd * numfds + 2;
1014e45a5a0dSDavid Malone 			if ((tmp = malloc(tmpsize)) == NULL)
101594355cfdSAndrey Zonov 				err(1, "Cannot alloc %d bytes for poll output",
101694355cfdSAndrey Zonov 				    tmpsize);
1017e45a5a0dSDavid Malone 
1018e45a5a0dSDavid Malone 			tmp[used++] = '{';
1019*1e2ec671SJohn Baldwin 			tmp[used++] = ' ';
1020e45a5a0dSDavid Malone 			for (i = 0; i < numfds; i++) {
1021e45a5a0dSDavid Malone 
102294355cfdSAndrey Zonov 				u = snprintf(tmp + used, per_fd, "%s%d/%s",
102394355cfdSAndrey Zonov 				    i > 0 ? " " : "", pfd[i].fd,
1024081e5c48SPav Lucistnik 				    xlookup_bits(poll_flags, pfd[i].events));
1025e45a5a0dSDavid Malone 				if (u > 0)
1026e45a5a0dSDavid Malone 					used += u < per_fd ? u : per_fd;
1027e45a5a0dSDavid Malone 			}
1028*1e2ec671SJohn Baldwin 			tmp[used++] = ' ';
1029e45a5a0dSDavid Malone 			tmp[used++] = '}';
1030e45a5a0dSDavid Malone 			tmp[used++] = '\0';
1031d8984f48SDag-Erling Smørgrav 		} else {
1032e45a5a0dSDavid Malone 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1033e45a5a0dSDavid Malone 		}
1034d8984f48SDag-Erling Smørgrav 		free(pfd);
1035e45a5a0dSDavid Malone 		break;
1036d8984f48SDag-Erling Smørgrav 	}
1037d8984f48SDag-Erling Smørgrav 	case Fd_set: {
1038e45a5a0dSDavid Malone 		/*
103994355cfdSAndrey Zonov 		 * XXX: A Fd_set argument expects the /first/ syscall argument
104094355cfdSAndrey Zonov 		 * to be the number of fds in the array.  This matches the
104194355cfdSAndrey Zonov 		 * select syscall.
1042e45a5a0dSDavid Malone 		 */
1043e45a5a0dSDavid Malone 		fd_set *fds;
1044e45a5a0dSDavid Malone 		int numfds = args[0];
1045e45a5a0dSDavid Malone 		int bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
1046e45a5a0dSDavid Malone 		int i, tmpsize, u, used;
1047e45a5a0dSDavid Malone 		const int per_fd = 20;
1048e45a5a0dSDavid Malone 
1049e45a5a0dSDavid Malone 		if ((fds = malloc(bytes)) == NULL)
105094355cfdSAndrey Zonov 			err(1, "Cannot malloc %d bytes for fd_set array",
105194355cfdSAndrey Zonov 			    bytes);
105294355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
105394355cfdSAndrey Zonov 		    != -1) {
1054e45a5a0dSDavid Malone 			used = 0;
1055e45a5a0dSDavid Malone 			tmpsize = 1 + numfds * per_fd + 2;
1056e45a5a0dSDavid Malone 			if ((tmp = malloc(tmpsize)) == NULL)
105794355cfdSAndrey Zonov 				err(1, "Cannot alloc %d bytes for fd_set "
105894355cfdSAndrey Zonov 				    "output", tmpsize);
1059e45a5a0dSDavid Malone 
1060e45a5a0dSDavid Malone 			tmp[used++] = '{';
1061*1e2ec671SJohn Baldwin 			tmp[used++] = ' ';
1062e45a5a0dSDavid Malone 			for (i = 0; i < numfds; i++) {
1063e45a5a0dSDavid Malone 				if (FD_ISSET(i, fds)) {
106494355cfdSAndrey Zonov 					u = snprintf(tmp + used, per_fd, "%d ",
106594355cfdSAndrey Zonov 					    i);
1066e45a5a0dSDavid Malone 					if (u > 0)
1067e45a5a0dSDavid Malone 						used += u < per_fd ? u : per_fd;
1068e45a5a0dSDavid Malone 				}
1069e45a5a0dSDavid Malone 			}
1070e45a5a0dSDavid Malone 			tmp[used++] = '}';
1071e45a5a0dSDavid Malone 			tmp[used++] = '\0';
107294355cfdSAndrey Zonov 		} else
1073e45a5a0dSDavid Malone 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1074d8984f48SDag-Erling Smørgrav 		free(fds);
1075e45a5a0dSDavid Malone 		break;
1076d8984f48SDag-Erling Smørgrav 	}
107734763d1cSJohn Baldwin 	case Signal:
107834763d1cSJohn Baldwin 		tmp = strsig2(args[sc->offset]);
1079f0ebbc29SDag-Erling Smørgrav 		break;
1080d8984f48SDag-Erling Smørgrav 	case Sigset: {
1081081e5c48SPav Lucistnik 		long sig;
1082081e5c48SPav Lucistnik 		sigset_t ss;
1083081e5c48SPav Lucistnik 		int i, used;
108434763d1cSJohn Baldwin 		char *signame;
1085081e5c48SPav Lucistnik 
1086081e5c48SPav Lucistnik 		sig = args[sc->offset];
108794355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
108894355cfdSAndrey Zonov 		    sizeof(ss)) == -1) {
1089081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1090081e5c48SPav Lucistnik 			break;
1091081e5c48SPav Lucistnik 		}
1092081e5c48SPav Lucistnik 		tmp = malloc(sys_nsig * 8); /* 7 bytes avg per signal name */
1093081e5c48SPav Lucistnik 		used = 0;
1094d8984f48SDag-Erling Smørgrav 		for (i = 1; i < sys_nsig; i++) {
109534763d1cSJohn Baldwin 			if (sigismember(&ss, i)) {
109634763d1cSJohn Baldwin 				signame = strsig(i);
109734763d1cSJohn Baldwin 				used += sprintf(tmp + used, "%s|", signame);
109834763d1cSJohn Baldwin 				free(signame);
109934763d1cSJohn Baldwin 			}
1100081e5c48SPav Lucistnik 		}
1101081e5c48SPav Lucistnik 		if (used)
1102081e5c48SPav Lucistnik 			tmp[used-1] = 0;
1103081e5c48SPav Lucistnik 		else
1104081e5c48SPav Lucistnik 			strcpy(tmp, "0x0");
1105081e5c48SPav Lucistnik 		break;
1106d8984f48SDag-Erling Smørgrav 	}
1107d8984f48SDag-Erling Smørgrav 	case Sigprocmask: {
1108894b8f7aSAlfred Perlstein 		switch (args[sc->offset]) {
1109894b8f7aSAlfred Perlstein #define	S(a)	case a: tmp = strdup(#a); break;
1110081e5c48SPav Lucistnik 			S(SIG_BLOCK);
1111081e5c48SPav Lucistnik 			S(SIG_UNBLOCK);
1112081e5c48SPav Lucistnik 			S(SIG_SETMASK);
1113894b8f7aSAlfred Perlstein #undef S
1114894b8f7aSAlfred Perlstein 		}
1115894b8f7aSAlfred Perlstein 		if (tmp == NULL)
1116894b8f7aSAlfred Perlstein 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1117894b8f7aSAlfred Perlstein 		break;
1118d8984f48SDag-Erling Smørgrav 	}
1119d8984f48SDag-Erling Smørgrav 	case Fcntlflag: {
1120081e5c48SPav Lucistnik 		/* XXX output depends on the value of the previous argument */
1121081e5c48SPav Lucistnik 		switch (args[sc->offset-1]) {
1122081e5c48SPav Lucistnik 		case F_SETFD:
112394355cfdSAndrey Zonov 			tmp = strdup(xlookup_bits(fcntlfd_arg,
112494355cfdSAndrey Zonov 			    args[sc->offset]));
1125081e5c48SPav Lucistnik 			break;
1126081e5c48SPav Lucistnik 		case F_SETFL:
112794355cfdSAndrey Zonov 			tmp = strdup(xlookup_bits(fcntlfl_arg,
112894355cfdSAndrey Zonov 			    args[sc->offset]));
1129081e5c48SPav Lucistnik 			break;
1130081e5c48SPav Lucistnik 		case F_GETFD:
1131081e5c48SPav Lucistnik 		case F_GETFL:
1132081e5c48SPav Lucistnik 		case F_GETOWN:
1133081e5c48SPav Lucistnik 			tmp = strdup("");
1134081e5c48SPav Lucistnik 			break;
1135081e5c48SPav Lucistnik 		default:
1136081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1137081e5c48SPav Lucistnik 			break;
1138081e5c48SPav Lucistnik 		}
1139081e5c48SPav Lucistnik 		break;
1140d8984f48SDag-Erling Smørgrav 	}
1141081e5c48SPav Lucistnik 	case Open:
1142081e5c48SPav Lucistnik 		tmp = strdup(xlookup_bits(open_flags, args[sc->offset]));
1143081e5c48SPav Lucistnik 		break;
1144081e5c48SPav Lucistnik 	case Fcntl:
1145081e5c48SPav Lucistnik 		tmp = strdup(xlookup(fcntl_arg, args[sc->offset]));
1146081e5c48SPav Lucistnik 		break;
1147894b8f7aSAlfred Perlstein 	case Mprot:
1148081e5c48SPav Lucistnik 		tmp = strdup(xlookup_bits(mprot_flags, args[sc->offset]));
1149894b8f7aSAlfred Perlstein 		break;
11505aa60b6fSJohn Baldwin 	case Mmapflags: {
1151bf59b2c5SJohn Baldwin 		char *base, *alignstr;
11525aa60b6fSJohn Baldwin 		int align, flags;
11535aa60b6fSJohn Baldwin 
11545aa60b6fSJohn Baldwin 		/*
11555aa60b6fSJohn Baldwin 		 * MAP_ALIGNED can't be handled by xlookup_bits(), so
11565aa60b6fSJohn Baldwin 		 * generate that string manually and prepend it to the
11575aa60b6fSJohn Baldwin 		 * string from xlookup_bits().  Have to be careful to
11585aa60b6fSJohn Baldwin 		 * avoid outputting MAP_ALIGNED|0 if MAP_ALIGNED is
11595aa60b6fSJohn Baldwin 		 * the only flag.
11605aa60b6fSJohn Baldwin 		 */
11615aa60b6fSJohn Baldwin 		flags = args[sc->offset] & ~MAP_ALIGNMENT_MASK;
11625aa60b6fSJohn Baldwin 		align = args[sc->offset] & MAP_ALIGNMENT_MASK;
11635aa60b6fSJohn Baldwin 		if (align != 0) {
11645aa60b6fSJohn Baldwin 			if (align == MAP_ALIGNED_SUPER)
11655aa60b6fSJohn Baldwin 				alignstr = strdup("MAP_ALIGNED_SUPER");
11665aa60b6fSJohn Baldwin 			else
11675aa60b6fSJohn Baldwin 				asprintf(&alignstr, "MAP_ALIGNED(%d)",
11685aa60b6fSJohn Baldwin 				    align >> MAP_ALIGNMENT_SHIFT);
11695aa60b6fSJohn Baldwin 			if (flags == 0) {
11705aa60b6fSJohn Baldwin 				tmp = alignstr;
1171894b8f7aSAlfred Perlstein 				break;
11725aa60b6fSJohn Baldwin 			}
11735aa60b6fSJohn Baldwin 		} else
11745aa60b6fSJohn Baldwin 			alignstr = NULL;
11755aa60b6fSJohn Baldwin 		base = strdup(xlookup_bits(mmap_flags, flags));
11765aa60b6fSJohn Baldwin 		if (alignstr == NULL) {
11775aa60b6fSJohn Baldwin 			tmp = base;
11785aa60b6fSJohn Baldwin 			break;
11795aa60b6fSJohn Baldwin 		}
11805aa60b6fSJohn Baldwin 		asprintf(&tmp, "%s|%s", alignstr, base);
11815aa60b6fSJohn Baldwin 		free(alignstr);
11825aa60b6fSJohn Baldwin 		free(base);
11835aa60b6fSJohn Baldwin 		break;
11845aa60b6fSJohn Baldwin 	}
1185fde3a7d1SAlfred Perlstein 	case Whence:
1186081e5c48SPav Lucistnik 		tmp = strdup(xlookup(whence_arg, args[sc->offset]));
1187081e5c48SPav Lucistnik 		break;
1188081e5c48SPav Lucistnik 	case Sockdomain:
1189081e5c48SPav Lucistnik 		tmp = strdup(xlookup(sockdomain_arg, args[sc->offset]));
1190081e5c48SPav Lucistnik 		break;
1191081e5c48SPav Lucistnik 	case Socktype:
1192081e5c48SPav Lucistnik 		tmp = strdup(xlookup(socktype_arg, args[sc->offset]));
1193081e5c48SPav Lucistnik 		break;
1194081e5c48SPav Lucistnik 	case Shutdown:
1195081e5c48SPav Lucistnik 		tmp = strdup(xlookup(shutdown_arg, args[sc->offset]));
1196081e5c48SPav Lucistnik 		break;
1197081e5c48SPav Lucistnik 	case Resource:
1198081e5c48SPav Lucistnik 		tmp = strdup(xlookup(resource_arg, args[sc->offset]));
1199081e5c48SPav Lucistnik 		break;
1200081e5c48SPav Lucistnik 	case Pathconf:
1201081e5c48SPav Lucistnik 		tmp = strdup(xlookup(pathconf_arg, args[sc->offset]));
1202fde3a7d1SAlfred Perlstein 		break;
12039e1db66eSMark Johnston 	case Rforkflags:
12049e1db66eSMark Johnston 		tmp = strdup(xlookup_bits(rfork_flags, args[sc->offset]));
12059e1db66eSMark Johnston 		break;
1206d8984f48SDag-Erling Smørgrav 	case Sockaddr: {
1207dec17687SBrian Feldman 		struct sockaddr_storage ss;
12089ddd1412SDag-Erling Smørgrav 		char addr[64];
12091be5d704SMark Murray 		struct sockaddr_in *lsin;
12101be5d704SMark Murray 		struct sockaddr_in6 *lsin6;
1211dec17687SBrian Feldman 		struct sockaddr_un *sun;
1212dec17687SBrian Feldman 		struct sockaddr *sa;
1213dec17687SBrian Feldman 		char *p;
1214dec17687SBrian Feldman 		u_char *q;
1215dec17687SBrian Feldman 		int i;
12169ddd1412SDag-Erling Smørgrav 
1217a7a08c7eSMarcel Moolenaar 		if (args[sc->offset] == 0) {
1218a7a08c7eSMarcel Moolenaar 			asprintf(&tmp, "NULL");
1219a7a08c7eSMarcel Moolenaar 			break;
1220a7a08c7eSMarcel Moolenaar 		}
1221a7a08c7eSMarcel Moolenaar 
1222dec17687SBrian Feldman 		/* yuck: get ss_len */
12235d2d083cSXin LI 		if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
1224dec17687SBrian Feldman 		    sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1)
1225dec17687SBrian Feldman 			err(1, "get_struct %p", (void *)args[sc->offset]);
12266a656761SAlfred Perlstein 		/*
12276a656761SAlfred Perlstein 		 * If ss_len is 0, then try to guess from the sockaddr type.
12286a656761SAlfred Perlstein 		 * AF_UNIX may be initialized incorrectly, so always frob
12296a656761SAlfred Perlstein 		 * it by using the "right" size.
12306a656761SAlfred Perlstein 		 */
12316a656761SAlfred Perlstein 		if (ss.ss_len == 0 || ss.ss_family == AF_UNIX) {
12326a656761SAlfred Perlstein 			switch (ss.ss_family) {
12336a656761SAlfred Perlstein 			case AF_INET:
12346a656761SAlfred Perlstein 				ss.ss_len = sizeof(*lsin);
12356a656761SAlfred Perlstein 				break;
12366a656761SAlfred Perlstein 			case AF_UNIX:
12376a656761SAlfred Perlstein 				ss.ss_len = sizeof(*sun);
12386a656761SAlfred Perlstein 				break;
12396a656761SAlfred Perlstein 			default:
12406a656761SAlfred Perlstein 				/* hurrrr */
12416a656761SAlfred Perlstein 				break;
12426a656761SAlfred Perlstein 			}
12436a656761SAlfred Perlstein 		}
124494355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
124594355cfdSAndrey Zonov 		    ss.ss_len) == -1) {
1246dec17687SBrian Feldman 			err(2, "get_struct %p", (void *)args[sc->offset]);
12479ddd1412SDag-Erling Smørgrav 		}
1248dec17687SBrian Feldman 
1249dec17687SBrian Feldman 		switch (ss.ss_family) {
1250dec17687SBrian Feldman 		case AF_INET:
12511be5d704SMark Murray 			lsin = (struct sockaddr_in *)&ss;
12521be5d704SMark Murray 			inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr);
125394355cfdSAndrey Zonov 			asprintf(&tmp, "{ AF_INET %s:%d }", addr,
125494355cfdSAndrey Zonov 			    htons(lsin->sin_port));
1255dec17687SBrian Feldman 			break;
1256dec17687SBrian Feldman 		case AF_INET6:
12571be5d704SMark Murray 			lsin6 = (struct sockaddr_in6 *)&ss;
125894355cfdSAndrey Zonov 			inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
125994355cfdSAndrey Zonov 			    sizeof addr);
126094355cfdSAndrey Zonov 			asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr,
126194355cfdSAndrey Zonov 			    htons(lsin6->sin6_port));
1262dec17687SBrian Feldman 			break;
1263dec17687SBrian Feldman 		case AF_UNIX:
1264dec17687SBrian Feldman 			sun = (struct sockaddr_un *)&ss;
1265dec17687SBrian Feldman 			asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path);
1266dec17687SBrian Feldman 			break;
1267dec17687SBrian Feldman 		default:
1268dec17687SBrian Feldman 			sa = (struct sockaddr *)&ss;
126994355cfdSAndrey Zonov 			asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data "
1270*1e2ec671SJohn Baldwin 			    "= { %n%*s } }", (int)sa->sa_len,
1271*1e2ec671SJohn Baldwin 			    (int)sa->sa_family, &i,
1272*1e2ec671SJohn Baldwin 			    6 * (int)(sa->sa_len - ((char *)&sa->sa_data -
127394355cfdSAndrey Zonov 			    (char *)sa)), "");
1274dec17687SBrian Feldman 			if (tmp != NULL) {
1275dec17687SBrian Feldman 				p = tmp + i;
127694355cfdSAndrey Zonov 				for (q = (u_char *)&sa->sa_data;
127794355cfdSAndrey Zonov 				    q < (u_char *)sa + sa->sa_len; q++)
1278dec17687SBrian Feldman 					p += sprintf(p, " %#02x,", *q);
1279dec17687SBrian Feldman 			}
1280dec17687SBrian Feldman 		}
12819ddd1412SDag-Erling Smørgrav 		break;
1282d8984f48SDag-Erling Smørgrav 	}
1283d8984f48SDag-Erling Smørgrav 	case Sigaction: {
1284e45a5a0dSDavid Malone 		struct sigaction sa;
1285e45a5a0dSDavid Malone 		char *hand;
1286e45a5a0dSDavid Malone 		const char *h;
1287e45a5a0dSDavid Malone 
128894355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
128994355cfdSAndrey Zonov 		    != -1) {
1290e45a5a0dSDavid Malone 			asprintf(&hand, "%p", sa.sa_handler);
1291e45a5a0dSDavid Malone 			if (sa.sa_handler == SIG_DFL)
1292e45a5a0dSDavid Malone 				h = "SIG_DFL";
1293e45a5a0dSDavid Malone 			else if (sa.sa_handler == SIG_IGN)
1294e45a5a0dSDavid Malone 				h = "SIG_IGN";
1295e45a5a0dSDavid Malone 			else
1296e45a5a0dSDavid Malone 				h = hand;
1297081e5c48SPav Lucistnik 
129894355cfdSAndrey Zonov 			asprintf(&tmp, "{ %s %s ss_t }", h,
1299081e5c48SPav Lucistnik 			    xlookup_bits(sigaction_flags, sa.sa_flags));
1300e45a5a0dSDavid Malone 			free(hand);
130194355cfdSAndrey Zonov 		} else
1302e45a5a0dSDavid Malone 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1303e45a5a0dSDavid Malone 		break;
1304d8984f48SDag-Erling Smørgrav 	}
1305d8984f48SDag-Erling Smørgrav 	case Kevent: {
1306081e5c48SPav Lucistnik 		/*
1307081e5c48SPav Lucistnik 		 * XXX XXX: the size of the array is determined by either the
1308081e5c48SPav Lucistnik 		 * next syscall argument, or by the syscall returnvalue,
1309081e5c48SPav Lucistnik 		 * depending on which argument number we are.  This matches the
1310081e5c48SPav Lucistnik 		 * kevent syscall, but luckily that's the only syscall that uses
1311081e5c48SPav Lucistnik 		 * them.
1312081e5c48SPav Lucistnik 		 */
1313081e5c48SPav Lucistnik 		struct kevent *ke;
1314081e5c48SPav Lucistnik 		int numevents = -1;
1315081e5c48SPav Lucistnik 		int bytes = 0;
1316081e5c48SPav Lucistnik 		int i, tmpsize, u, used;
1317081e5c48SPav Lucistnik 		const int per_ke = 100;
1318081e5c48SPav Lucistnik 
1319081e5c48SPav Lucistnik 		if (sc->offset == 1)
1320081e5c48SPav Lucistnik 			numevents = args[sc->offset+1];
1321081e5c48SPav Lucistnik 		else if (sc->offset == 3 && retval != -1)
1322081e5c48SPav Lucistnik 			numevents = retval;
1323081e5c48SPav Lucistnik 
1324081e5c48SPav Lucistnik 		if (numevents >= 0)
1325081e5c48SPav Lucistnik 			bytes = sizeof(struct kevent) * numevents;
1326081e5c48SPav Lucistnik 		if ((ke = malloc(bytes)) == NULL)
132794355cfdSAndrey Zonov 			err(1, "Cannot malloc %d bytes for kevent array",
132894355cfdSAndrey Zonov 			    bytes);
132994355cfdSAndrey Zonov 		if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
133094355cfdSAndrey Zonov 		    ke, bytes) != -1) {
1331081e5c48SPav Lucistnik 			used = 0;
1332081e5c48SPav Lucistnik 			tmpsize = 1 + per_ke * numevents + 2;
1333081e5c48SPav Lucistnik 			if ((tmp = malloc(tmpsize)) == NULL)
133494355cfdSAndrey Zonov 				err(1, "Cannot alloc %d bytes for kevent "
133594355cfdSAndrey Zonov 				    "output", tmpsize);
1336081e5c48SPav Lucistnik 
1337081e5c48SPav Lucistnik 			tmp[used++] = '{';
1338*1e2ec671SJohn Baldwin 			tmp[used++] = ' ';
1339081e5c48SPav Lucistnik 			for (i = 0; i < numevents; i++) {
1340081e5c48SPav Lucistnik 				u = snprintf(tmp + used, per_ke,
1341081e5c48SPav Lucistnik 				    "%s%p,%s,%s,%d,%p,%p",
1342081e5c48SPav Lucistnik 				    i > 0 ? " " : "",
1343081e5c48SPav Lucistnik 				    (void *)ke[i].ident,
1344081e5c48SPav Lucistnik 				    xlookup(kevent_filters, ke[i].filter),
1345081e5c48SPav Lucistnik 				    xlookup_bits(kevent_flags, ke[i].flags),
1346081e5c48SPav Lucistnik 				    ke[i].fflags,
1347081e5c48SPav Lucistnik 				    (void *)ke[i].data,
1348081e5c48SPav Lucistnik 				    (void *)ke[i].udata);
1349081e5c48SPav Lucistnik 				if (u > 0)
1350081e5c48SPav Lucistnik 					used += u < per_ke ? u : per_ke;
1351081e5c48SPav Lucistnik 			}
1352*1e2ec671SJohn Baldwin 			tmp[used++] = ' ';
1353081e5c48SPav Lucistnik 			tmp[used++] = '}';
1354081e5c48SPav Lucistnik 			tmp[used++] = '\0';
1355d8984f48SDag-Erling Smørgrav 		} else {
1356081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1357081e5c48SPav Lucistnik 		}
1358d8984f48SDag-Erling Smørgrav 		free(ke);
1359081e5c48SPav Lucistnik 		break;
1360d8984f48SDag-Erling Smørgrav 	}
1361d8984f48SDag-Erling Smørgrav 	case Stat: {
1362081e5c48SPav Lucistnik 		struct stat st;
136394355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
136494355cfdSAndrey Zonov 		    != -1) {
1365081e5c48SPav Lucistnik 			char mode[12];
1366081e5c48SPav Lucistnik 			strmode(st.st_mode, mode);
136794355cfdSAndrey Zonov 			asprintf(&tmp,
136894355cfdSAndrey Zonov 			    "{ mode=%s,inode=%jd,size=%jd,blksize=%ld }", mode,
136994355cfdSAndrey Zonov 			    (intmax_t)st.st_ino, (intmax_t)st.st_size,
137094355cfdSAndrey Zonov 			    (long)st.st_blksize);
1371d8984f48SDag-Erling Smørgrav 		} else {
1372081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1373081e5c48SPav Lucistnik 		}
1374081e5c48SPav Lucistnik 		break;
1375d8984f48SDag-Erling Smørgrav 	}
1376d8984f48SDag-Erling Smørgrav 	case Rusage: {
1377081e5c48SPav Lucistnik 		struct rusage ru;
137894355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
137994355cfdSAndrey Zonov 		    != -1) {
138094355cfdSAndrey Zonov 			asprintf(&tmp,
138194355cfdSAndrey Zonov 			    "{ u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld }",
1382081e5c48SPav Lucistnik 			    (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
1383081e5c48SPav Lucistnik 			    (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
1384081e5c48SPav Lucistnik 			    ru.ru_inblock, ru.ru_oublock);
138594355cfdSAndrey Zonov 		} else
1386081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1387081e5c48SPav Lucistnik 		break;
1388d8984f48SDag-Erling Smørgrav 	}
1389d8984f48SDag-Erling Smørgrav 	case Rlimit: {
1390081e5c48SPav Lucistnik 		struct rlimit rl;
139194355cfdSAndrey Zonov 		if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
139294355cfdSAndrey Zonov 		    != -1) {
1393081e5c48SPav Lucistnik 			asprintf(&tmp, "{ cur=%ju,max=%ju }",
1394081e5c48SPav Lucistnik 			    rl.rlim_cur, rl.rlim_max);
139594355cfdSAndrey Zonov 		} else
1396081e5c48SPav Lucistnik 			asprintf(&tmp, "0x%lx", args[sc->offset]);
1397081e5c48SPav Lucistnik 		break;
1398d8984f48SDag-Erling Smørgrav 	}
139934763d1cSJohn Baldwin 	case ExitStatus: {
140034763d1cSJohn Baldwin 		char *signame;
140134763d1cSJohn Baldwin 		int status;
140234763d1cSJohn Baldwin 		signame = NULL;
140334763d1cSJohn Baldwin 		if (get_struct(pid, (void *)args[sc->offset], &status,
140434763d1cSJohn Baldwin 		    sizeof(status)) != -1) {
140534763d1cSJohn Baldwin 			if (WIFCONTINUED(status))
140634763d1cSJohn Baldwin 				tmp = strdup("{ CONTINUED }");
140734763d1cSJohn Baldwin 			else if (WIFEXITED(status))
140834763d1cSJohn Baldwin 				asprintf(&tmp, "{ EXITED,val=%d }",
140934763d1cSJohn Baldwin 				    WEXITSTATUS(status));
141034763d1cSJohn Baldwin 			else if (WIFSIGNALED(status))
141134763d1cSJohn Baldwin 				asprintf(&tmp, "{ SIGNALED,sig=%s%s }",
141234763d1cSJohn Baldwin 				    signame = strsig2(WTERMSIG(status)),
141334763d1cSJohn Baldwin 				    WCOREDUMP(status) ? ",cored" : "");
141434763d1cSJohn Baldwin 			else
141534763d1cSJohn Baldwin 				asprintf(&tmp, "{ STOPPED,sig=%s }",
141634763d1cSJohn Baldwin 				    signame = strsig2(WTERMSIG(status)));
141734763d1cSJohn Baldwin 		} else
141834763d1cSJohn Baldwin 			asprintf(&tmp, "0x%lx", args[sc->offset]);
141934763d1cSJohn Baldwin 		free(signame);
142034763d1cSJohn Baldwin 		break;
142134763d1cSJohn Baldwin 	}
142234763d1cSJohn Baldwin 	case Waitoptions:
142334763d1cSJohn Baldwin 		tmp = strdup(xlookup_bits(wait_options, args[sc->offset]));
142434763d1cSJohn Baldwin 		break;
142534763d1cSJohn Baldwin 	case Idtype:
142634763d1cSJohn Baldwin 		tmp = strdup(xlookup(idtype_arg, args[sc->offset]));
142734763d1cSJohn Baldwin 		break;
142855648840SJohn Baldwin 	case Procctl:
142955648840SJohn Baldwin 		tmp = strdup(xlookup(procctl_arg, args[sc->offset]));
143055648840SJohn Baldwin 		break;
1431fdb5bf37SJohn Baldwin 	case Umtxop:
1432fdb5bf37SJohn Baldwin 		tmp = strdup(xlookup(umtx_ops, args[sc->offset]));
1433fdb5bf37SJohn Baldwin 		break;
14347d897327SJohn Baldwin 	case Atfd:
14357d897327SJohn Baldwin 		if ((int)args[sc->offset] == AT_FDCWD)
14367d897327SJohn Baldwin 			tmp = strdup("AT_FDCWD");
14377d897327SJohn Baldwin 		else
14387d897327SJohn Baldwin 			asprintf(&tmp, "%d", (int)args[sc->offset]);
14397d897327SJohn Baldwin 		break;
14407d897327SJohn Baldwin 	case Atflags:
14417d897327SJohn Baldwin 		tmp = strdup(xlookup_bits(at_flags, args[sc->offset]));
14427d897327SJohn Baldwin 		break;
14437d897327SJohn Baldwin 	case Accessmode:
14447d897327SJohn Baldwin 		if (args[sc->offset] == F_OK)
14457d897327SJohn Baldwin 			tmp = strdup("F_OK");
14467d897327SJohn Baldwin 		else
14477d897327SJohn Baldwin 			tmp = strdup(xlookup_bits(access_modes,
14487d897327SJohn Baldwin 				args[sc->offset]));
14497d897327SJohn Baldwin 		break;
1450081e5c48SPav Lucistnik 	default:
1451081e5c48SPav Lucistnik 		errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
1452bbeaf6c0SSean Eric Fagan 	}
1453d8984f48SDag-Erling Smørgrav 	return (tmp);
1454bbeaf6c0SSean Eric Fagan }
1455bbeaf6c0SSean Eric Fagan 
1456bbeaf6c0SSean Eric Fagan /*
1457bbeaf6c0SSean Eric Fagan  * print_syscall
1458bbeaf6c0SSean Eric Fagan  * Print (to outfile) the system call and its arguments.  Note that
1459bbeaf6c0SSean Eric Fagan  * nargs is the number of arguments (not the number of words; this is
1460bbeaf6c0SSean Eric Fagan  * potentially confusing, I know).
1461bbeaf6c0SSean Eric Fagan  */
1462bbeaf6c0SSean Eric Fagan 
1463bbeaf6c0SSean Eric Fagan void
146494355cfdSAndrey Zonov print_syscall(struct trussinfo *trussinfo, const char *name, int nargs,
146594355cfdSAndrey Zonov     char **s_args)
1466d8984f48SDag-Erling Smørgrav {
1467203098d8SMatthew N. Dodd 	struct timespec timediff;
146894355cfdSAndrey Zonov 	int i, len;
14690d0bd00eSMatthew N. Dodd 
147094355cfdSAndrey Zonov 	len = 0;
1471c03bfcc8SMatthew N. Dodd 	if (trussinfo->flags & FOLLOWFORKS)
1472c03bfcc8SMatthew N. Dodd 		len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid);
1473c03bfcc8SMatthew N. Dodd 
147494355cfdSAndrey Zonov 	if (name != NULL && (strcmp(name, "execve") == 0 ||
147594355cfdSAndrey Zonov 	    strcmp(name, "exit") == 0)) {
14765695afdeSAndrey Zonov 		clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after);
14770d0bd00eSMatthew N. Dodd 	}
14780d0bd00eSMatthew N. Dodd 
14790d0bd00eSMatthew N. Dodd 	if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
1480d9dcc463SXin LI 		timespecsubt(&trussinfo->curthread->after,
14815695afdeSAndrey Zonov 		    &trussinfo->start_time, &timediff);
148237169f94SMatthew N. Dodd 		len += fprintf(trussinfo->outfile, "%ld.%09ld ",
1483fb034d05SMatthew N. Dodd 		    (long)timediff.tv_sec, timediff.tv_nsec);
14840d0bd00eSMatthew N. Dodd 	}
14850d0bd00eSMatthew N. Dodd 
14860d0bd00eSMatthew N. Dodd 	if (trussinfo->flags & RELATIVETIMESTAMPS) {
1487d9dcc463SXin LI 		timespecsubt(&trussinfo->curthread->after,
14885695afdeSAndrey Zonov 		    &trussinfo->curthread->before, &timediff);
148937169f94SMatthew N. Dodd 		len += fprintf(trussinfo->outfile, "%ld.%09ld ",
1490fb034d05SMatthew N. Dodd 		    (long)timediff.tv_sec, timediff.tv_nsec);
14910d0bd00eSMatthew N. Dodd 	}
14920d0bd00eSMatthew N. Dodd 
1493ec0bed25SMatthew N. Dodd 	len += fprintf(trussinfo->outfile, "%s(", name);
1494c03bfcc8SMatthew N. Dodd 
1495bbeaf6c0SSean Eric Fagan 	for (i = 0; i < nargs; i++) {
1496bbeaf6c0SSean Eric Fagan 		if (s_args[i])
1497ec0bed25SMatthew N. Dodd 			len += fprintf(trussinfo->outfile, "%s", s_args[i]);
1498bbeaf6c0SSean Eric Fagan 		else
149994355cfdSAndrey Zonov 			len += fprintf(trussinfo->outfile,
150094355cfdSAndrey Zonov 			    "<missing argument>");
150194355cfdSAndrey Zonov 		len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
150294355cfdSAndrey Zonov 		    "," : "");
1503bbeaf6c0SSean Eric Fagan 	}
1504ec0bed25SMatthew N. Dodd 	len += fprintf(trussinfo->outfile, ")");
15056cb533feSSean Eric Fagan 	for (i = 0; i < 6 - (len / 8); i++)
1506ec0bed25SMatthew N. Dodd 		fprintf(trussinfo->outfile, "\t");
15076cb533feSSean Eric Fagan }
15086cb533feSSean Eric Fagan 
15096cb533feSSean Eric Fagan void
15101bcb5f5aSMarcel Moolenaar print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs,
1511ee3b0f6eSDiomidis Spinellis     char **s_args, int errorp, long retval, struct syscall *sc)
15121bcb5f5aSMarcel Moolenaar {
1513ee3b0f6eSDiomidis Spinellis 	struct timespec timediff;
1514ee3b0f6eSDiomidis Spinellis 
1515ee3b0f6eSDiomidis Spinellis 	if (trussinfo->flags & COUNTONLY) {
1516ee3b0f6eSDiomidis Spinellis 		if (!sc)
1517ee3b0f6eSDiomidis Spinellis 			return;
15185695afdeSAndrey Zonov 		clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after);
1519d9dcc463SXin LI 		timespecsubt(&trussinfo->curthread->after,
15205695afdeSAndrey Zonov 		    &trussinfo->curthread->before, &timediff);
1521d9dcc463SXin LI 		timespecadd(&sc->time, &timediff, &sc->time);
1522ee3b0f6eSDiomidis Spinellis 		sc->ncalls++;
1523ee3b0f6eSDiomidis Spinellis 		if (errorp)
1524ee3b0f6eSDiomidis Spinellis 			sc->nerror++;
1525ee3b0f6eSDiomidis Spinellis 		return;
1526ee3b0f6eSDiomidis Spinellis 	}
1527d8984f48SDag-Erling Smørgrav 
1528ec0bed25SMatthew N. Dodd 	print_syscall(trussinfo, name, nargs, s_args);
15290cf21b4fSBrian Somers 	fflush(trussinfo->outfile);
153094355cfdSAndrey Zonov 	if (errorp)
153194355cfdSAndrey Zonov 		fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval,
153294355cfdSAndrey Zonov 		    strerror(retval));
153394355cfdSAndrey Zonov 	else {
1534c059fa2eSJaakko Heinonen 		/*
1535c059fa2eSJaakko Heinonen 		 * Because pipe(2) has a special assembly glue to provide the
1536c059fa2eSJaakko Heinonen 		 * libc API, we have to adjust retval.
1537c059fa2eSJaakko Heinonen 		 */
153894355cfdSAndrey Zonov 		if (name != NULL && strcmp(name, "pipe") == 0)
1539c059fa2eSJaakko Heinonen 			retval = 0;
15401bcb5f5aSMarcel Moolenaar 		fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval, retval);
15416cb533feSSean Eric Fagan 	}
1542bbeaf6c0SSean Eric Fagan }
1543ee3b0f6eSDiomidis Spinellis 
1544ee3b0f6eSDiomidis Spinellis void
1545ee3b0f6eSDiomidis Spinellis print_summary(struct trussinfo *trussinfo)
1546ee3b0f6eSDiomidis Spinellis {
1547ee3b0f6eSDiomidis Spinellis 	struct timespec total = {0, 0};
154894355cfdSAndrey Zonov 	struct syscall *sc;
1549ee3b0f6eSDiomidis Spinellis 	int ncall, nerror;
1550ee3b0f6eSDiomidis Spinellis 
1551ee3b0f6eSDiomidis Spinellis 	fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
1552ee3b0f6eSDiomidis Spinellis 	    "syscall", "seconds", "calls", "errors");
1553ee3b0f6eSDiomidis Spinellis 	ncall = nerror = 0;
1554ee3b0f6eSDiomidis Spinellis 	for (sc = syscalls; sc->name != NULL; sc++)
1555ee3b0f6eSDiomidis Spinellis 		if (sc->ncalls) {
155655a8d2bbSJaakko Heinonen 			fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
155755a8d2bbSJaakko Heinonen 			    sc->name, (intmax_t)sc->time.tv_sec,
155855a8d2bbSJaakko Heinonen 			    sc->time.tv_nsec, sc->ncalls, sc->nerror);
1559d9dcc463SXin LI 			timespecadd(&total, &sc->time, &total);
1560ee3b0f6eSDiomidis Spinellis 			ncall += sc->ncalls;
1561ee3b0f6eSDiomidis Spinellis 			nerror += sc->nerror;
1562ee3b0f6eSDiomidis Spinellis 		}
1563ee3b0f6eSDiomidis Spinellis 	fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
1564ee3b0f6eSDiomidis Spinellis 	    "", "-------------", "-------", "-------");
156555a8d2bbSJaakko Heinonen 	fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
156655a8d2bbSJaakko Heinonen 	    "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);
1567ee3b0f6eSDiomidis Spinellis }
1568