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 42894b8f7aSAlfred Perlstein #include <sys/mman.h> 439ddd1412SDag-Erling Smørgrav #include <sys/types.h> 445d2d083cSXin LI #include <sys/ptrace.h> 459ddd1412SDag-Erling Smørgrav #include <sys/socket.h> 461d631f7eSMike Barcroft #include <sys/time.h> 479ddd1412SDag-Erling Smørgrav #include <sys/un.h> 489ddd1412SDag-Erling Smørgrav #include <netinet/in.h> 499ddd1412SDag-Erling Smørgrav #include <arpa/inet.h> 50081e5c48SPav Lucistnik #include <sys/ioccom.h> 51081e5c48SPav Lucistnik #include <machine/atomic.h> 52081e5c48SPav Lucistnik #include <errno.h> 53081e5c48SPav Lucistnik #include <sys/umtx.h> 54081e5c48SPav Lucistnik #include <sys/event.h> 55081e5c48SPav Lucistnik #include <sys/stat.h> 56081e5c48SPav Lucistnik #include <sys/resource.h> 579ddd1412SDag-Erling Smørgrav 58dec17687SBrian Feldman #include <ctype.h> 593cf51049SPhilippe Charnier #include <err.h> 60894b8f7aSAlfred Perlstein #include <fcntl.h> 61e45a5a0dSDavid Malone #include <poll.h> 629ddd1412SDag-Erling Smørgrav #include <signal.h> 63e45a5a0dSDavid Malone #include <stdint.h> 64bbeaf6c0SSean Eric Fagan #include <stdio.h> 65bbeaf6c0SSean Eric Fagan #include <stdlib.h> 66bbeaf6c0SSean Eric Fagan #include <string.h> 6737169f94SMatthew N. Dodd #include <time.h> 68bbeaf6c0SSean Eric Fagan #include <unistd.h> 69081e5c48SPav Lucistnik #include <vis.h> 709ddd1412SDag-Erling Smørgrav 71ec0bed25SMatthew N. Dodd #include "truss.h" 721be5d704SMark Murray #include "extern.h" 73bbeaf6c0SSean Eric Fagan #include "syscall.h" 74bbeaf6c0SSean Eric Fagan 752c02627fSMarcel Moolenaar /* 64-bit alignment on 32-bit platforms. */ 762c02627fSMarcel Moolenaar #ifdef __powerpc__ 772c02627fSMarcel Moolenaar #define QUAD_ALIGN 1 782c02627fSMarcel Moolenaar #else 792c02627fSMarcel Moolenaar #define QUAD_ALIGN 0 802c02627fSMarcel Moolenaar #endif 812c02627fSMarcel Moolenaar 822c02627fSMarcel Moolenaar /* Number of slots needed for a 64-bit argument. */ 832c02627fSMarcel Moolenaar #ifdef __LP64__ 842c02627fSMarcel Moolenaar #define QUAD_SLOTS 1 852c02627fSMarcel Moolenaar #else 862c02627fSMarcel Moolenaar #define QUAD_SLOTS 2 872c02627fSMarcel Moolenaar #endif 882c02627fSMarcel Moolenaar 89bbeaf6c0SSean Eric Fagan /* 90081e5c48SPav Lucistnik * This should probably be in its own file, sorted alphabetically. 91bbeaf6c0SSean Eric Fagan */ 92a02c83afSEd Schouten static struct syscall syscalls[] = { 93ee3b0f6eSDiomidis Spinellis { .name = "fcntl", .ret_type = 1, .nargs = 3, 94ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 } , { Fcntl, 1 }, { Fcntlflag | OUT, 2 } } }, 9576de696dSJaakko Heinonen { .name = "fork", .ret_type = 1, .nargs = 0 }, 9676de696dSJaakko Heinonen { .name = "getegid", .ret_type = 1, .nargs = 0 }, 9776de696dSJaakko Heinonen { .name = "geteuid", .ret_type = 1, .nargs = 0 }, 9876de696dSJaakko Heinonen { .name = "getgid", .ret_type = 1, .nargs = 0 }, 9976de696dSJaakko Heinonen { .name = "getpid", .ret_type = 1, .nargs = 0 }, 10076de696dSJaakko Heinonen { .name = "getpgid", .ret_type = 1, .nargs = 1, 10176de696dSJaakko Heinonen .args = { { Int, 0 } } }, 10276de696dSJaakko Heinonen { .name = "getpgrp", .ret_type = 1, .nargs = 0 }, 10376de696dSJaakko Heinonen { .name = "getppid", .ret_type = 1, .nargs = 0 }, 10476de696dSJaakko Heinonen { .name = "getsid", .ret_type = 1, .nargs = 1, 10576de696dSJaakko Heinonen .args = { { Int, 0 } } }, 10676de696dSJaakko Heinonen { .name = "getuid", .ret_type = 1, .nargs = 0 }, 107ee3b0f6eSDiomidis Spinellis { .name = "readlink", .ret_type = 1, .nargs = 3, 108ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 } } }, 109ee3b0f6eSDiomidis Spinellis { .name = "lseek", .ret_type = 2, .nargs = 3, 110ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } }, 111ee3b0f6eSDiomidis Spinellis { .name = "linux_lseek", .ret_type = 2, .nargs = 3, 112ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } }, 113ee3b0f6eSDiomidis Spinellis { .name = "mmap", .ret_type = 2, .nargs = 6, 114ee3b0f6eSDiomidis Spinellis .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { Int, 4 }, { Quad, 5 + QUAD_ALIGN } } }, 115ee3b0f6eSDiomidis Spinellis { .name = "mprotect", .ret_type = 1, .nargs = 3, 116ee3b0f6eSDiomidis Spinellis .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } }, 117ee3b0f6eSDiomidis Spinellis { .name = "open", .ret_type = 1, .nargs = 3, 118ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 } , { Open, 1 }, { Octal, 2 } } }, 119ee3b0f6eSDiomidis Spinellis { .name = "mkdir", .ret_type = 1, .nargs = 2, 120ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 } , { Octal, 1 } } }, 121ee3b0f6eSDiomidis Spinellis { .name = "linux_open", .ret_type = 1, .nargs = 3, 122ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } }, 123ee3b0f6eSDiomidis Spinellis { .name = "close", .ret_type = 1, .nargs = 1, 124ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 } } }, 125ee3b0f6eSDiomidis Spinellis { .name = "link", .ret_type = 0, .nargs = 2, 126ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Name, 1 } } }, 127ee3b0f6eSDiomidis Spinellis { .name = "unlink", .ret_type = 0, .nargs = 1, 128ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 } } }, 129ee3b0f6eSDiomidis Spinellis { .name = "chdir", .ret_type = 0, .nargs = 1, 130ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 } } }, 131ee3b0f6eSDiomidis Spinellis { .name = "chroot", .ret_type = 0, .nargs = 1, 132ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 } } }, 133ee3b0f6eSDiomidis Spinellis { .name = "mknod", .ret_type = 0, .nargs = 3, 134ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Octal, 1 }, { Int, 3 } } }, 135ee3b0f6eSDiomidis Spinellis { .name = "chmod", .ret_type = 0, .nargs = 2, 136ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Octal, 1 } } }, 137ee3b0f6eSDiomidis Spinellis { .name = "chown", .ret_type = 0, .nargs = 3, 138ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, 139ee3b0f6eSDiomidis Spinellis { .name = "mount", .ret_type = 0, .nargs = 4, 140ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } }, 141ee3b0f6eSDiomidis Spinellis { .name = "umount", .ret_type = 0, .nargs = 2, 142ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Int, 2 } } }, 143ee3b0f6eSDiomidis Spinellis { .name = "fstat", .ret_type = 1, .nargs = 2, 144ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Stat | OUT , 1 } } }, 145ee3b0f6eSDiomidis Spinellis { .name = "stat", .ret_type = 1, .nargs = 2, 146ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, 147ee3b0f6eSDiomidis Spinellis { .name = "lstat", .ret_type = 1, .nargs = 2, 148ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, 149ee3b0f6eSDiomidis Spinellis { .name = "linux_newstat", .ret_type = 1, .nargs = 2, 150ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } }, 151ee3b0f6eSDiomidis Spinellis { .name = "linux_newfstat", .ret_type = 1, .nargs = 2, 152ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Ptr | OUT, 1 } } }, 153ee3b0f6eSDiomidis Spinellis { .name = "write", .ret_type = 1, .nargs = 3, 154ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } }, 155ee3b0f6eSDiomidis Spinellis { .name = "ioctl", .ret_type = 1, .nargs = 3, 156ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } }, 157ee3b0f6eSDiomidis Spinellis { .name = "break", .ret_type = 1, .nargs = 1, 158ee3b0f6eSDiomidis Spinellis .args = { { Ptr, 0 } } }, 159ee3b0f6eSDiomidis Spinellis { .name = "exit", .ret_type = 0, .nargs = 1, 160ee3b0f6eSDiomidis Spinellis .args = { { Hex, 0 } } }, 161ee3b0f6eSDiomidis Spinellis { .name = "access", .ret_type = 1, .nargs = 2, 162ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Int, 1 } } }, 163ee3b0f6eSDiomidis Spinellis { .name = "sigaction", .ret_type = 1, .nargs = 3, 164ee3b0f6eSDiomidis Spinellis .args = { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 } } }, 165ee3b0f6eSDiomidis Spinellis { .name = "accept", .ret_type = 1, .nargs = 3, 166ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, 167ee3b0f6eSDiomidis Spinellis { .name = "bind", .ret_type = 1, .nargs = 3, 168ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, 169ee3b0f6eSDiomidis Spinellis { .name = "connect", .ret_type = 1, .nargs = 3, 170ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, 171ee3b0f6eSDiomidis Spinellis { .name = "getpeername", .ret_type = 1, .nargs = 3, 172ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, 173ee3b0f6eSDiomidis Spinellis { .name = "getsockname", .ret_type = 1, .nargs = 3, 174ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, 175ee3b0f6eSDiomidis Spinellis { .name = "recvfrom", .ret_type = 1, .nargs = 6, 176ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 }, { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } }, 177ee3b0f6eSDiomidis Spinellis { .name = "sendto", .ret_type = 1, .nargs = 6, 178ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } }, 179ee3b0f6eSDiomidis Spinellis { .name = "execve", .ret_type = 1, .nargs = 3, 180ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, 181ee3b0f6eSDiomidis Spinellis { .name = "linux_execve", .ret_type = 1, .nargs = 3, 182ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, 183ee3b0f6eSDiomidis Spinellis { .name = "kldload", .ret_type = 0, .nargs = 1, 184ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 } } }, 185ee3b0f6eSDiomidis Spinellis { .name = "kldunload", .ret_type = 0, .nargs = 1, 186ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 } } }, 187ee3b0f6eSDiomidis Spinellis { .name = "kldfind", .ret_type = 0, .nargs = 1, 188ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 } } }, 189ee3b0f6eSDiomidis Spinellis { .name = "kldnext", .ret_type = 0, .nargs = 1, 190ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 } } }, 191ee3b0f6eSDiomidis Spinellis { .name = "kldstat", .ret_type = 0, .nargs = 2, 192ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Ptr, 1 } } }, 193ee3b0f6eSDiomidis Spinellis { .name = "kldfirstmod", .ret_type = 0, .nargs = 1, 194ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 } } }, 195ee3b0f6eSDiomidis Spinellis { .name = "nanosleep", .ret_type = 0, .nargs = 1, 196ee3b0f6eSDiomidis Spinellis .args = { { Timespec, 0 } } }, 197ee3b0f6eSDiomidis Spinellis { .name = "select", .ret_type = 1, .nargs = 5, 198ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { Timeval, 4 } } }, 199ee3b0f6eSDiomidis Spinellis { .name = "poll", .ret_type = 1, .nargs = 3, 200ee3b0f6eSDiomidis Spinellis .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } }, 201ee3b0f6eSDiomidis Spinellis { .name = "gettimeofday", .ret_type = 1, .nargs = 2, 202ee3b0f6eSDiomidis Spinellis .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } }, 203ee3b0f6eSDiomidis Spinellis { .name = "clock_gettime", .ret_type = 1, .nargs = 2, 204ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Timespec | OUT, 1 } } }, 205ee3b0f6eSDiomidis Spinellis { .name = "getitimer", .ret_type = 1, .nargs = 2, 206ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Itimerval | OUT, 2 } } }, 207ee3b0f6eSDiomidis Spinellis { .name = "setitimer", .ret_type = 1, .nargs = 3, 208ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Itimerval, 1 } , { Itimerval | OUT, 2 } } }, 209ee3b0f6eSDiomidis Spinellis { .name = "kse_release", .ret_type = 0, .nargs = 1, 210ee3b0f6eSDiomidis Spinellis .args = { { Timespec, 0 } } }, 211ee3b0f6eSDiomidis Spinellis { .name = "kevent", .ret_type = 0, .nargs = 6, 212ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } }, 213ee3b0f6eSDiomidis Spinellis { .name = "_umtx_lock", .ret_type = 0, .nargs = 1, 214ee3b0f6eSDiomidis Spinellis .args = { { Umtx, 0 } } }, 215ee3b0f6eSDiomidis Spinellis { .name = "_umtx_unlock", .ret_type = 0, .nargs = 1, 216ee3b0f6eSDiomidis Spinellis .args = { { Umtx, 0 } } }, 217ee3b0f6eSDiomidis Spinellis { .name = "sigprocmask", .ret_type = 0, .nargs = 3, 218ee3b0f6eSDiomidis Spinellis .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } }, 219ee3b0f6eSDiomidis Spinellis { .name = "unmount", .ret_type = 1, .nargs = 2, 220ee3b0f6eSDiomidis Spinellis .args = { { Name, 0 }, { Int, 1 } } }, 221ee3b0f6eSDiomidis Spinellis { .name = "socket", .ret_type = 1, .nargs = 3, 222ee3b0f6eSDiomidis Spinellis .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } }, 223ee3b0f6eSDiomidis Spinellis { .name = "getrusage", .ret_type = 1, .nargs = 2, 224ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Rusage | OUT, 1 } } }, 225ee3b0f6eSDiomidis Spinellis { .name = "__getcwd", .ret_type = 1, .nargs = 2, 226ee3b0f6eSDiomidis Spinellis .args = { { Name | OUT, 0 }, { Int, 1 } } }, 227ee3b0f6eSDiomidis Spinellis { .name = "shutdown", .ret_type = 1, .nargs = 2, 228ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Shutdown, 1 } } }, 229ee3b0f6eSDiomidis Spinellis { .name = "getrlimit", .ret_type = 1, .nargs = 2, 230ee3b0f6eSDiomidis Spinellis .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } }, 231ee3b0f6eSDiomidis Spinellis { .name = "setrlimit", .ret_type = 1, .nargs = 2, 232ee3b0f6eSDiomidis Spinellis .args = { { Resource, 0 }, { Rlimit | IN, 1 } } }, 233ee3b0f6eSDiomidis Spinellis { .name = "utimes", .ret_type = 1, .nargs = 2, 234ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, 235ee3b0f6eSDiomidis Spinellis { .name = "lutimes", .ret_type = 1, .nargs = 2, 236ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, 237ee3b0f6eSDiomidis Spinellis { .name = "futimes", .ret_type = 1, .nargs = 2, 238ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { Timeval | IN, 1 } } }, 239ee3b0f6eSDiomidis Spinellis { .name = "chflags", .ret_type = 1, .nargs = 2, 240ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Hex, 1 } } }, 241ee3b0f6eSDiomidis Spinellis { .name = "lchflags", .ret_type = 1, .nargs = 2, 242ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Hex, 1 } } }, 243ee3b0f6eSDiomidis Spinellis { .name = "pathconf", .ret_type = 1, .nargs = 2, 244ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Pathconf, 1 } } }, 245c059fa2eSJaakko Heinonen { .name = "pipe", .ret_type = 1, .nargs = 1, 246c059fa2eSJaakko Heinonen .args = { { Ptr, 0 } } }, 247ee3b0f6eSDiomidis Spinellis { .name = "truncate", .ret_type = 1, .nargs = 3, 248ee3b0f6eSDiomidis Spinellis .args = { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, 249ee3b0f6eSDiomidis Spinellis { .name = "ftruncate", .ret_type = 1, .nargs = 3, 250ee3b0f6eSDiomidis Spinellis .args = { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, 251ee3b0f6eSDiomidis Spinellis { .name = "kill", .ret_type = 1, .nargs = 2, 252ee3b0f6eSDiomidis Spinellis .args = { { Int | IN, 0 }, { Signal | IN, 1 } } }, 253ee3b0f6eSDiomidis Spinellis { .name = "munmap", .ret_type = 1, .nargs = 2, 254ee3b0f6eSDiomidis Spinellis .args = { { Ptr, 0 }, { Int, 1 } } }, 255ee3b0f6eSDiomidis Spinellis { .name = "read", .ret_type = 1, .nargs = 3, 256ee3b0f6eSDiomidis Spinellis .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } }, 257ee3b0f6eSDiomidis Spinellis { .name = "rename", .ret_type = 1, .nargs = 2, 258ee3b0f6eSDiomidis Spinellis .args = { { Name , 0 } , { Name, 1 } } }, 259ee3b0f6eSDiomidis Spinellis { .name = "symlink", .ret_type = 1, .nargs = 2, 260ee3b0f6eSDiomidis Spinellis .args = { { Name , 0 } , { Name, 1 } } }, 2612b6d81c1SEd Schouten { .name = "posix_openpt", .ret_type = 1, .nargs = 1, 2622b6d81c1SEd Schouten .args = { { Open, 0 } } }, 263ee3b0f6eSDiomidis Spinellis { .name = 0 }, 264bbeaf6c0SSean Eric Fagan }; 265bbeaf6c0SSean Eric Fagan 266081e5c48SPav Lucistnik /* Xlat idea taken from strace */ 267081e5c48SPav Lucistnik struct xlat { 268081e5c48SPav Lucistnik int val; 2695d2d083cSXin LI const char *str; 270081e5c48SPav Lucistnik }; 271081e5c48SPav Lucistnik 272081e5c48SPav Lucistnik #define X(a) { a, #a }, 273081e5c48SPav Lucistnik #define XEND { 0, NULL } 274081e5c48SPav Lucistnik 275081e5c48SPav Lucistnik static struct xlat kevent_filters[] = { 276081e5c48SPav Lucistnik X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE) 277081e5c48SPav Lucistnik X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER) 278a6fffd6cSBrooks Davis X(EVFILT_FS) X(EVFILT_READ) XEND 279081e5c48SPav Lucistnik }; 280081e5c48SPav Lucistnik 281081e5c48SPav Lucistnik static struct xlat kevent_flags[] = { 282081e5c48SPav Lucistnik X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT) 283081e5c48SPav Lucistnik X(EV_CLEAR) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND 284081e5c48SPav Lucistnik }; 285081e5c48SPav Lucistnik 286a02c83afSEd Schouten static struct xlat poll_flags[] = { 287081e5c48SPav Lucistnik X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR) 288081e5c48SPav Lucistnik X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND) 289081e5c48SPav Lucistnik X(POLLWRBAND) X(POLLINIGNEOF) XEND 290081e5c48SPav Lucistnik }; 291081e5c48SPav Lucistnik 292081e5c48SPav Lucistnik static struct xlat mmap_flags[] = { 293081e5c48SPav Lucistnik X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RENAME) 294081e5c48SPav Lucistnik X(MAP_NORESERVE) X(MAP_RESERVED0080) X(MAP_RESERVED0100) 295081e5c48SPav Lucistnik X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON) 296081e5c48SPav Lucistnik X(MAP_NOCORE) XEND 297081e5c48SPav Lucistnik }; 298081e5c48SPav Lucistnik 299081e5c48SPav Lucistnik static struct xlat mprot_flags[] = { 300081e5c48SPav Lucistnik X(PROT_NONE) X(PROT_READ) X(PROT_WRITE) X(PROT_EXEC) XEND 301081e5c48SPav Lucistnik }; 302081e5c48SPav Lucistnik 303081e5c48SPav Lucistnik static struct xlat whence_arg[] = { 304081e5c48SPav Lucistnik X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) XEND 305081e5c48SPav Lucistnik }; 306081e5c48SPav Lucistnik 307081e5c48SPav Lucistnik static struct xlat sigaction_flags[] = { 308081e5c48SPav Lucistnik X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP) 309081e5c48SPav Lucistnik X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND 310081e5c48SPav Lucistnik }; 311081e5c48SPav Lucistnik 312081e5c48SPav Lucistnik static struct xlat fcntl_arg[] = { 313081e5c48SPav Lucistnik X(F_DUPFD) X(F_GETFD) X(F_SETFD) X(F_GETFL) X(F_SETFL) 314081e5c48SPav Lucistnik X(F_GETOWN) X(F_SETOWN) X(F_GETLK) X(F_SETLK) X(F_SETLKW) XEND 315081e5c48SPav Lucistnik }; 316081e5c48SPav Lucistnik 317081e5c48SPav Lucistnik static struct xlat fcntlfd_arg[] = { 318081e5c48SPav Lucistnik X(FD_CLOEXEC) XEND 319081e5c48SPav Lucistnik }; 320081e5c48SPav Lucistnik 321081e5c48SPav Lucistnik static struct xlat fcntlfl_arg[] = { 322081e5c48SPav Lucistnik X(O_APPEND) X(O_ASYNC) X(O_FSYNC) X(O_NONBLOCK) X(O_NOFOLLOW) 323081e5c48SPav Lucistnik X(O_DIRECT) XEND 324081e5c48SPav Lucistnik }; 325081e5c48SPav Lucistnik 326081e5c48SPav Lucistnik static struct xlat sockdomain_arg[] = { 327081e5c48SPav Lucistnik X(PF_UNSPEC) X(PF_LOCAL) X(PF_UNIX) X(PF_INET) X(PF_IMPLINK) 328081e5c48SPav Lucistnik X(PF_PUP) X(PF_CHAOS) X(PF_NETBIOS) X(PF_ISO) X(PF_OSI) 329081e5c48SPav Lucistnik X(PF_ECMA) X(PF_DATAKIT) X(PF_CCITT) X(PF_SNA) X(PF_DECnet) 330081e5c48SPav Lucistnik X(PF_DLI) X(PF_LAT) X(PF_HYLINK) X(PF_APPLETALK) X(PF_ROUTE) 331081e5c48SPav Lucistnik X(PF_LINK) X(PF_XTP) X(PF_COIP) X(PF_CNT) X(PF_SIP) X(PF_IPX) 332081e5c48SPav Lucistnik X(PF_RTIP) X(PF_PIP) X(PF_ISDN) X(PF_KEY) X(PF_INET6) 333081e5c48SPav Lucistnik X(PF_NATM) X(PF_ATM) X(PF_NETGRAPH) X(PF_SLOW) X(PF_SCLUSTER) 334081e5c48SPav Lucistnik X(PF_ARP) X(PF_BLUETOOTH) XEND 335081e5c48SPav Lucistnik }; 336081e5c48SPav Lucistnik 337081e5c48SPav Lucistnik static struct xlat socktype_arg[] = { 338081e5c48SPav Lucistnik X(SOCK_STREAM) X(SOCK_DGRAM) X(SOCK_RAW) X(SOCK_RDM) 339081e5c48SPav Lucistnik X(SOCK_SEQPACKET) XEND 340081e5c48SPav Lucistnik }; 341081e5c48SPav Lucistnik 342081e5c48SPav Lucistnik static struct xlat open_flags[] = { 343081e5c48SPav Lucistnik X(O_RDONLY) X(O_WRONLY) X(O_RDWR) X(O_ACCMODE) X(O_NONBLOCK) 344081e5c48SPav Lucistnik X(O_APPEND) X(O_SHLOCK) X(O_EXLOCK) X(O_ASYNC) X(O_FSYNC) 345081e5c48SPav Lucistnik X(O_NOFOLLOW) X(O_CREAT) X(O_TRUNC) X(O_EXCL) X(O_NOCTTY) 346081e5c48SPav Lucistnik X(O_DIRECT) XEND 347081e5c48SPav Lucistnik }; 348081e5c48SPav Lucistnik 349081e5c48SPav Lucistnik static struct xlat shutdown_arg[] = { 350081e5c48SPav Lucistnik X(SHUT_RD) X(SHUT_WR) X(SHUT_RDWR) XEND 351081e5c48SPav Lucistnik }; 352081e5c48SPav Lucistnik 353081e5c48SPav Lucistnik static struct xlat resource_arg[] = { 354081e5c48SPav Lucistnik X(RLIMIT_CPU) X(RLIMIT_FSIZE) X(RLIMIT_DATA) X(RLIMIT_STACK) 355081e5c48SPav Lucistnik X(RLIMIT_CORE) X(RLIMIT_RSS) X(RLIMIT_MEMLOCK) X(RLIMIT_NPROC) 356081e5c48SPav Lucistnik X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) XEND 357081e5c48SPav Lucistnik }; 358081e5c48SPav Lucistnik 359081e5c48SPav Lucistnik static struct xlat pathconf_arg[] = { 360081e5c48SPav Lucistnik X(_PC_LINK_MAX) X(_PC_MAX_CANON) X(_PC_MAX_INPUT) 361081e5c48SPav Lucistnik X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF) 362081e5c48SPav Lucistnik X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE) 363081e5c48SPav Lucistnik X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO) 364081e5c48SPav Lucistnik X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS) 365081e5c48SPav Lucistnik X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE) 366081e5c48SPav Lucistnik X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN) 367081e5c48SPav Lucistnik X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX) 368081e5c48SPav Lucistnik X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT) 369081e5c48SPav Lucistnik XEND 370081e5c48SPav Lucistnik }; 371081e5c48SPav Lucistnik 372081e5c48SPav Lucistnik #undef X 373081e5c48SPav Lucistnik #undef XEND 374081e5c48SPav Lucistnik 375d8984f48SDag-Erling Smørgrav /* 376d8984f48SDag-Erling Smørgrav * Searches an xlat array for a value, and returns it if found. Otherwise 377d8984f48SDag-Erling Smørgrav * return a string representation. 378d8984f48SDag-Erling Smørgrav */ 379d8984f48SDag-Erling Smørgrav static const char * 380d8984f48SDag-Erling Smørgrav lookup(struct xlat *xlat, int val, int base) 381081e5c48SPav Lucistnik { 382081e5c48SPav Lucistnik static char tmp[16]; 383d8984f48SDag-Erling Smørgrav 384081e5c48SPav Lucistnik for (; xlat->str != NULL; xlat++) 385081e5c48SPav Lucistnik if (xlat->val == val) 386d8984f48SDag-Erling Smørgrav return (xlat->str); 387081e5c48SPav Lucistnik switch (base) { 388081e5c48SPav Lucistnik case 8: 389081e5c48SPav Lucistnik sprintf(tmp, "0%o", val); 390081e5c48SPav Lucistnik break; 391081e5c48SPav Lucistnik case 16: 392081e5c48SPav Lucistnik sprintf(tmp, "0x%x", val); 393081e5c48SPav Lucistnik break; 394081e5c48SPav Lucistnik case 10: 395081e5c48SPav Lucistnik sprintf(tmp, "%u", val); 396081e5c48SPav Lucistnik break; 397081e5c48SPav Lucistnik default: 398081e5c48SPav Lucistnik errx(1,"Unknown lookup base"); 399081e5c48SPav Lucistnik break; 400081e5c48SPav Lucistnik } 401d8984f48SDag-Erling Smørgrav return (tmp); 402081e5c48SPav Lucistnik } 403081e5c48SPav Lucistnik 4045d2d083cSXin LI static const char * 4055d2d083cSXin LI xlookup(struct xlat *xlat, int val) 406081e5c48SPav Lucistnik { 407d8984f48SDag-Erling Smørgrav 408d8984f48SDag-Erling Smørgrav return (lookup(xlat, val, 16)); 409081e5c48SPav Lucistnik } 410081e5c48SPav Lucistnik 411081e5c48SPav Lucistnik /* Searches an xlat array containing bitfield values. Remaining bits 412081e5c48SPav Lucistnik set after removing the known ones are printed at the end: 413081e5c48SPav Lucistnik IN|0x400 */ 414d8984f48SDag-Erling Smørgrav static char * 415d8984f48SDag-Erling Smørgrav xlookup_bits(struct xlat *xlat, int val) 416081e5c48SPav Lucistnik { 41794355cfdSAndrey Zonov int len, rem; 418081e5c48SPav Lucistnik static char str[512]; 419081e5c48SPav Lucistnik 42094355cfdSAndrey Zonov len = 0; 42194355cfdSAndrey Zonov rem = val; 422d8984f48SDag-Erling Smørgrav for (; xlat->str != NULL; xlat++) { 423d8984f48SDag-Erling Smørgrav if ((xlat->val & rem) == xlat->val) { 424081e5c48SPav Lucistnik /* don't print the "all-bits-zero" string unless all 425081e5c48SPav Lucistnik bits are really zero */ 426081e5c48SPav Lucistnik if (xlat->val == 0 && val != 0) 427081e5c48SPav Lucistnik continue; 428081e5c48SPav Lucistnik len += sprintf(str + len, "%s|", xlat->str); 429081e5c48SPav Lucistnik rem &= ~(xlat->val); 430081e5c48SPav Lucistnik } 431081e5c48SPav Lucistnik } 432081e5c48SPav Lucistnik /* if we have leftover bits or didn't match anything */ 433081e5c48SPav Lucistnik if (rem || len == 0) 434081e5c48SPav Lucistnik len += sprintf(str + len, "0x%x", rem); 435081e5c48SPav Lucistnik if (len && str[len - 1] == '|') 436081e5c48SPav Lucistnik len--; 437081e5c48SPav Lucistnik str[len] = 0; 438d8984f48SDag-Erling Smørgrav return (str); 439081e5c48SPav Lucistnik } 440081e5c48SPav Lucistnik 441bbeaf6c0SSean Eric Fagan /* 442bbeaf6c0SSean Eric Fagan * If/when the list gets big, it might be desirable to do it 443bbeaf6c0SSean Eric Fagan * as a hash table or binary search. 444bbeaf6c0SSean Eric Fagan */ 445bbeaf6c0SSean Eric Fagan 446bbeaf6c0SSean Eric Fagan struct syscall * 447d8984f48SDag-Erling Smørgrav get_syscall(const char *name) 448d8984f48SDag-Erling Smørgrav { 44994355cfdSAndrey Zonov struct syscall *sc; 450bbeaf6c0SSean Eric Fagan 45194355cfdSAndrey Zonov sc = syscalls; 452d10f73b3SAlfred Perlstein if (name == NULL) 453d10f73b3SAlfred Perlstein return (NULL); 454bbeaf6c0SSean Eric Fagan while (sc->name) { 45594355cfdSAndrey Zonov if (strcmp(name, sc->name) == 0) 456d8984f48SDag-Erling Smørgrav return (sc); 457bbeaf6c0SSean Eric Fagan sc++; 458bbeaf6c0SSean Eric Fagan } 459d8984f48SDag-Erling Smørgrav return (NULL); 460bbeaf6c0SSean Eric Fagan } 461bbeaf6c0SSean Eric Fagan 462bbeaf6c0SSean Eric Fagan /* 4639ddd1412SDag-Erling Smørgrav * get_struct 4649ddd1412SDag-Erling Smørgrav * 4659ddd1412SDag-Erling Smørgrav * Copy a fixed amount of bytes from the process. 4669ddd1412SDag-Erling Smørgrav */ 4679ddd1412SDag-Erling Smørgrav 4681be5d704SMark Murray static int 469be305c9cSAndrey Zonov get_struct(pid_t pid, void *offset, void *buf, int len) 470d8984f48SDag-Erling Smørgrav { 4715d2d083cSXin LI struct ptrace_io_desc iorequest; 4729ddd1412SDag-Erling Smørgrav 4735d2d083cSXin LI iorequest.piod_op = PIOD_READ_D; 4745d2d083cSXin LI iorequest.piod_offs = offset; 4755d2d083cSXin LI iorequest.piod_addr = buf; 4765d2d083cSXin LI iorequest.piod_len = len; 4775d2d083cSXin LI if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) 478d8984f48SDag-Erling Smørgrav return (-1); 479d8984f48SDag-Erling Smørgrav return (0); 4809ddd1412SDag-Erling Smørgrav } 4819ddd1412SDag-Erling Smørgrav 4825d2d083cSXin LI #define MAXSIZE 4096 4835d2d083cSXin LI #define BLOCKSIZE 1024 4849ddd1412SDag-Erling Smørgrav /* 485bbeaf6c0SSean Eric Fagan * get_string 486bbeaf6c0SSean Eric Fagan * Copy a string from the process. Note that it is 487bbeaf6c0SSean Eric Fagan * expected to be a C string, but if max is set, it will 488bbeaf6c0SSean Eric Fagan * only get that much. 489bbeaf6c0SSean Eric Fagan */ 490bbeaf6c0SSean Eric Fagan 4915d2d083cSXin LI static char * 492d8984f48SDag-Erling Smørgrav get_string(pid_t pid, void *offset, int max) 493d8984f48SDag-Erling Smørgrav { 4945d2d083cSXin LI struct ptrace_io_desc iorequest; 49594355cfdSAndrey Zonov char *buf; 49694355cfdSAndrey Zonov int diff, i, size, totalsize; 497bbeaf6c0SSean Eric Fagan 49894355cfdSAndrey Zonov diff = 0; 4995d2d083cSXin LI totalsize = size = max ? (max + 1) : BLOCKSIZE; 5005d2d083cSXin LI buf = malloc(totalsize); 5015d2d083cSXin LI if (buf == NULL) 502d8984f48SDag-Erling Smørgrav return (NULL); 5035d2d083cSXin LI for (;;) { 5045d2d083cSXin LI diff = totalsize - size; 5055d2d083cSXin LI iorequest.piod_op = PIOD_READ_D; 5065d2d083cSXin LI iorequest.piod_offs = (char *)offset + diff; 5075d2d083cSXin LI iorequest.piod_addr = buf + diff; 5085d2d083cSXin LI iorequest.piod_len = size; 5095d2d083cSXin LI if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) { 5105d2d083cSXin LI free(buf); 511d8984f48SDag-Erling Smørgrav return (NULL); 512bbeaf6c0SSean Eric Fagan } 5135d2d083cSXin LI for (i = 0 ; i < size; i++) { 5145d2d083cSXin LI if (buf[diff + i] == '\0') 5154e92419dSMarcel Moolenaar return (buf); 516bbeaf6c0SSean Eric Fagan } 5175d2d083cSXin LI if (totalsize < MAXSIZE - BLOCKSIZE && max == 0) { 5185d2d083cSXin LI totalsize += BLOCKSIZE; 5195d2d083cSXin LI buf = realloc(buf, totalsize); 5205d2d083cSXin LI size = BLOCKSIZE; 521d8984f48SDag-Erling Smørgrav } else { 522cdfc719cSJaakko Heinonen buf[totalsize - 1] = '\0'; 523d8984f48SDag-Erling Smørgrav return (buf); 5245d2d083cSXin LI } 5255d2d083cSXin LI } 5265d2d083cSXin LI } 527bbeaf6c0SSean Eric Fagan 528bbeaf6c0SSean Eric Fagan 529bbeaf6c0SSean Eric Fagan /* 530bbeaf6c0SSean Eric Fagan * print_arg 531bbeaf6c0SSean Eric Fagan * Converts a syscall argument into a string. Said string is 532bbeaf6c0SSean Eric Fagan * allocated via malloc(), so needs to be free()'d. The file 533bbeaf6c0SSean Eric Fagan * descriptor is for the process' memory (via /proc), and is used 534bbeaf6c0SSean Eric Fagan * to get any data (where the argument is a pointer). sc is 535bbeaf6c0SSean Eric Fagan * a pointer to the syscall description (see above); args is 536bbeaf6c0SSean Eric Fagan * an array of all of the system call arguments. 537bbeaf6c0SSean Eric Fagan */ 538bbeaf6c0SSean Eric Fagan 539bbeaf6c0SSean Eric Fagan char * 54094355cfdSAndrey Zonov print_arg(struct syscall_args *sc, unsigned long *args, long retval, 54194355cfdSAndrey Zonov struct trussinfo *trussinfo) 542d8984f48SDag-Erling Smørgrav { 54394355cfdSAndrey Zonov char *tmp; 54494355cfdSAndrey Zonov pid_t pid; 545d8984f48SDag-Erling Smørgrav 54694355cfdSAndrey Zonov tmp = NULL; 54794355cfdSAndrey Zonov pid = trussinfo->pid; 548bbeaf6c0SSean Eric Fagan switch (sc->type & ARG_MASK) { 549bbeaf6c0SSean Eric Fagan case Hex: 550f2359950SMarcel Moolenaar asprintf(&tmp, "0x%x", (int)args[sc->offset]); 551bbeaf6c0SSean Eric Fagan break; 552bbeaf6c0SSean Eric Fagan case Octal: 553f2359950SMarcel Moolenaar asprintf(&tmp, "0%o", (int)args[sc->offset]); 554bbeaf6c0SSean Eric Fagan break; 555bbeaf6c0SSean Eric Fagan case Int: 556f2359950SMarcel Moolenaar asprintf(&tmp, "%d", (int)args[sc->offset]); 557bbeaf6c0SSean Eric Fagan break; 558d8984f48SDag-Erling Smørgrav case Name: { 559081e5c48SPav Lucistnik /* NULL-terminated string. */ 560bbeaf6c0SSean Eric Fagan char *tmp2; 5615d2d083cSXin LI tmp2 = get_string(pid, (void*)args[sc->offset], 0); 5621bcb5f5aSMarcel Moolenaar asprintf(&tmp, "\"%s\"", tmp2); 563bbeaf6c0SSean Eric Fagan free(tmp2); 564bbeaf6c0SSean Eric Fagan break; 565d8984f48SDag-Erling Smørgrav } 566d8984f48SDag-Erling Smørgrav case BinString: { 567081e5c48SPav Lucistnik /* Binary block of data that might have printable characters. 568081e5c48SPav Lucistnik XXX If type|OUT, assume that the length is the syscall's 569081e5c48SPav Lucistnik return value. Otherwise, assume that the length of the block 570081e5c48SPav Lucistnik is in the next syscall argument. */ 571081e5c48SPav Lucistnik int max_string = trussinfo->strsize; 572081e5c48SPav Lucistnik char tmp2[max_string+1], *tmp3; 573081e5c48SPav Lucistnik int len; 574081e5c48SPav Lucistnik int truncated = 0; 575081e5c48SPav Lucistnik 576081e5c48SPav Lucistnik if (sc->type & OUT) 577081e5c48SPav Lucistnik len = retval; 578081e5c48SPav Lucistnik else 579081e5c48SPav Lucistnik len = args[sc->offset + 1]; 580081e5c48SPav Lucistnik 581081e5c48SPav Lucistnik /* Don't print more than max_string characters, to avoid word 582081e5c48SPav Lucistnik wrap. If we have to truncate put some ... after the string. 583081e5c48SPav Lucistnik */ 584081e5c48SPav Lucistnik if (len > max_string) { 585081e5c48SPav Lucistnik len = max_string; 586081e5c48SPav Lucistnik truncated = 1; 587081e5c48SPav Lucistnik } 58894355cfdSAndrey Zonov if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len) 58994355cfdSAndrey Zonov != -1) { 590081e5c48SPav Lucistnik tmp3 = malloc(len * 4 + 1); 591081e5c48SPav Lucistnik while (len) { 59294355cfdSAndrey Zonov if (strvisx(tmp3, tmp2, len, 59394355cfdSAndrey Zonov VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) 594081e5c48SPav Lucistnik break; 595081e5c48SPav Lucistnik len--; 596081e5c48SPav Lucistnik truncated = 1; 597081e5c48SPav Lucistnik }; 59894355cfdSAndrey Zonov asprintf(&tmp, "\"%s\"%s", tmp3, truncated ? 59994355cfdSAndrey Zonov "..." : ""); 600081e5c48SPav Lucistnik free(tmp3); 601d8984f48SDag-Erling Smørgrav } else { 602081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 603081e5c48SPav Lucistnik } 604081e5c48SPav Lucistnik break; 605d8984f48SDag-Erling Smørgrav } 606d8984f48SDag-Erling Smørgrav case StringArray: { 6079897b203SMatthew N. Dodd int num, size, i; 6089897b203SMatthew N. Dodd char *tmp2; 6099897b203SMatthew N. Dodd char *string; 6109897b203SMatthew N. Dodd char *strarray[100]; /* XXX This is ugly. */ 6119897b203SMatthew N. Dodd 61294355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], 61394355cfdSAndrey Zonov (void *)&strarray, sizeof(strarray)) == -1) 6149897b203SMatthew N. Dodd err(1, "get_struct %p", (void *)args[sc->offset]); 6159897b203SMatthew N. Dodd num = 0; 6169897b203SMatthew N. Dodd size = 0; 6179897b203SMatthew N. Dodd 6189897b203SMatthew N. Dodd /* Find out how large of a buffer we'll need. */ 6199897b203SMatthew N. Dodd while (strarray[num] != NULL) { 6205d2d083cSXin LI string = get_string(pid, (void*)strarray[num], 0); 6219897b203SMatthew N. Dodd size += strlen(string); 6229897b203SMatthew N. Dodd free(string); 6239897b203SMatthew N. Dodd num++; 6249897b203SMatthew N. Dodd } 6259897b203SMatthew N. Dodd size += 4 + (num * 4); 6269897b203SMatthew N. Dodd tmp = (char *)malloc(size); 6279897b203SMatthew N. Dodd tmp2 = tmp; 6289897b203SMatthew N. Dodd 6299897b203SMatthew N. Dodd tmp2 += sprintf(tmp2, " ["); 6309897b203SMatthew N. Dodd for (i = 0; i < num; i++) { 6315d2d083cSXin LI string = get_string(pid, (void*)strarray[i], 0); 63294355cfdSAndrey Zonov tmp2 += sprintf(tmp2, " \"%s\"%c", string, 63394355cfdSAndrey Zonov (i + 1 == num) ? ' ' : ','); 6349897b203SMatthew N. Dodd free(string); 6359897b203SMatthew N. Dodd } 6369897b203SMatthew N. Dodd tmp2 += sprintf(tmp2, "]"); 6379897b203SMatthew N. Dodd break; 638d8984f48SDag-Erling Smørgrav } 63910aeefc9SMarcel Moolenaar #ifdef __LP64__ 64010aeefc9SMarcel Moolenaar case Quad: 64110aeefc9SMarcel Moolenaar asprintf(&tmp, "0x%lx", args[sc->offset]); 64210aeefc9SMarcel Moolenaar break; 64310aeefc9SMarcel Moolenaar #else 644d8984f48SDag-Erling Smørgrav case Quad: { 64510aeefc9SMarcel Moolenaar unsigned long long ll; 64610aeefc9SMarcel Moolenaar ll = *(unsigned long long *)(args + sc->offset); 64710aeefc9SMarcel Moolenaar asprintf(&tmp, "0x%llx", ll); 648bbeaf6c0SSean Eric Fagan break; 649bbeaf6c0SSean Eric Fagan } 65010aeefc9SMarcel Moolenaar #endif 651bbeaf6c0SSean Eric Fagan case Ptr: 6521bcb5f5aSMarcel Moolenaar asprintf(&tmp, "0x%lx", args[sc->offset]); 653bbeaf6c0SSean Eric Fagan break; 654d8984f48SDag-Erling Smørgrav case Readlinkres: { 6552bae4eb3SAlfred Perlstein char *tmp2; 6562bae4eb3SAlfred Perlstein if (retval == -1) { 6572bae4eb3SAlfred Perlstein tmp = strdup(""); 6582bae4eb3SAlfred Perlstein break; 6592bae4eb3SAlfred Perlstein } 6605d2d083cSXin LI tmp2 = get_string(pid, (void*)args[sc->offset], retval); 6612bae4eb3SAlfred Perlstein asprintf(&tmp, "\"%s\"", tmp2); 6622bae4eb3SAlfred Perlstein free(tmp2); 6632bae4eb3SAlfred Perlstein break; 664d8984f48SDag-Erling Smørgrav } 665d8984f48SDag-Erling Smørgrav case Ioctl: { 6661be5d704SMark Murray const char *temp = ioctlname(args[sc->offset]); 66794355cfdSAndrey Zonov if (temp) 668970649f9SSean Eric Fagan tmp = strdup(temp); 66994355cfdSAndrey Zonov else { 670081e5c48SPav Lucistnik unsigned long arg = args[sc->offset]; 67194355cfdSAndrey Zonov asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }", 67294355cfdSAndrey Zonov arg, arg & IOC_OUT ? "R" : "", 67394355cfdSAndrey Zonov arg & IOC_IN ? "W" : "", IOCGROUP(arg), 67494355cfdSAndrey Zonov isprint(IOCGROUP(arg)) ? (char)IOCGROUP(arg) : '?', 675081e5c48SPav Lucistnik arg & 0xFF, IOCPARM_LEN(arg)); 676081e5c48SPav Lucistnik } 677081e5c48SPav Lucistnik break; 678d8984f48SDag-Erling Smørgrav } 679d8984f48SDag-Erling Smørgrav case Umtx: { 680081e5c48SPav Lucistnik struct umtx umtx; 68194355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &umtx, 68294355cfdSAndrey Zonov sizeof(umtx)) != -1) 683081e5c48SPav Lucistnik asprintf(&tmp, "{ 0x%lx }", (long)umtx.u_owner); 684081e5c48SPav Lucistnik else 6851bcb5f5aSMarcel Moolenaar asprintf(&tmp, "0x%lx", args[sc->offset]); 686f0ebbc29SDag-Erling Smørgrav break; 687d8984f48SDag-Erling Smørgrav } 688d8984f48SDag-Erling Smørgrav case Timespec: { 689e45a5a0dSDavid Malone struct timespec ts; 69094355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &ts, 69194355cfdSAndrey Zonov sizeof(ts)) != -1) 69294355cfdSAndrey Zonov asprintf(&tmp, "{%ld.%09ld }", (long)ts.tv_sec, 69394355cfdSAndrey Zonov ts.tv_nsec); 694e45a5a0dSDavid Malone else 695e45a5a0dSDavid Malone asprintf(&tmp, "0x%lx", args[sc->offset]); 696e45a5a0dSDavid Malone break; 697d8984f48SDag-Erling Smørgrav } 698d8984f48SDag-Erling Smørgrav case Timeval: { 699e45a5a0dSDavid Malone struct timeval tv; 70094355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) 70194355cfdSAndrey Zonov != -1) 70294355cfdSAndrey Zonov asprintf(&tmp, "{%ld.%06ld }", (long)tv.tv_sec, 70394355cfdSAndrey Zonov tv.tv_usec); 704081e5c48SPav Lucistnik else 705081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 706081e5c48SPav Lucistnik break; 707d8984f48SDag-Erling Smørgrav } 708d8984f48SDag-Erling Smørgrav case Timeval2: { 709081e5c48SPav Lucistnik struct timeval tv[2]; 71094355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) 71194355cfdSAndrey Zonov != -1) 712081e5c48SPav Lucistnik asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }", 713081e5c48SPav Lucistnik (long)tv[0].tv_sec, tv[0].tv_usec, 714081e5c48SPav Lucistnik (long)tv[1].tv_sec, tv[1].tv_usec); 715e45a5a0dSDavid Malone else 716e45a5a0dSDavid Malone asprintf(&tmp, "0x%lx", args[sc->offset]); 717e45a5a0dSDavid Malone break; 718d8984f48SDag-Erling Smørgrav } 719d8984f48SDag-Erling Smørgrav case Itimerval: { 720e45a5a0dSDavid Malone struct itimerval itv; 72194355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &itv, 72294355cfdSAndrey Zonov sizeof(itv)) != -1) 723081e5c48SPav Lucistnik asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }", 724081e5c48SPav Lucistnik (long)itv.it_interval.tv_sec, 725081e5c48SPav Lucistnik itv.it_interval.tv_usec, 726081e5c48SPav Lucistnik (long)itv.it_value.tv_sec, 727081e5c48SPav Lucistnik itv.it_value.tv_usec); 728e45a5a0dSDavid Malone else 729e45a5a0dSDavid Malone asprintf(&tmp, "0x%lx", args[sc->offset]); 730e45a5a0dSDavid Malone break; 731d8984f48SDag-Erling Smørgrav } 732d8984f48SDag-Erling Smørgrav case Pollfd: { 733e45a5a0dSDavid Malone /* 73494355cfdSAndrey Zonov * XXX: A Pollfd argument expects the /next/ syscall argument 73594355cfdSAndrey Zonov * to be the number of fds in the array. This matches the poll 73694355cfdSAndrey Zonov * syscall. 737e45a5a0dSDavid Malone */ 738e45a5a0dSDavid Malone struct pollfd *pfd; 739e45a5a0dSDavid Malone int numfds = args[sc->offset+1]; 740e45a5a0dSDavid Malone int bytes = sizeof(struct pollfd) * numfds; 741e45a5a0dSDavid Malone int i, tmpsize, u, used; 742e45a5a0dSDavid Malone const int per_fd = 100; 743e45a5a0dSDavid Malone 744e45a5a0dSDavid Malone if ((pfd = malloc(bytes)) == NULL) 74594355cfdSAndrey Zonov err(1, "Cannot malloc %d bytes for pollfd array", 74694355cfdSAndrey Zonov bytes); 74794355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], pfd, bytes) 74894355cfdSAndrey Zonov != -1) { 749e45a5a0dSDavid Malone used = 0; 750e45a5a0dSDavid Malone tmpsize = 1 + per_fd * numfds + 2; 751e45a5a0dSDavid Malone if ((tmp = malloc(tmpsize)) == NULL) 75294355cfdSAndrey Zonov err(1, "Cannot alloc %d bytes for poll output", 75394355cfdSAndrey Zonov tmpsize); 754e45a5a0dSDavid Malone 755e45a5a0dSDavid Malone tmp[used++] = '{'; 756e45a5a0dSDavid Malone for (i = 0; i < numfds; i++) { 757e45a5a0dSDavid Malone 75894355cfdSAndrey Zonov u = snprintf(tmp + used, per_fd, "%s%d/%s", 75994355cfdSAndrey Zonov i > 0 ? " " : "", pfd[i].fd, 760081e5c48SPav Lucistnik xlookup_bits(poll_flags, pfd[i].events)); 761e45a5a0dSDavid Malone if (u > 0) 762e45a5a0dSDavid Malone used += u < per_fd ? u : per_fd; 763e45a5a0dSDavid Malone } 764e45a5a0dSDavid Malone tmp[used++] = '}'; 765e45a5a0dSDavid Malone tmp[used++] = '\0'; 766d8984f48SDag-Erling Smørgrav } else { 767e45a5a0dSDavid Malone asprintf(&tmp, "0x%lx", args[sc->offset]); 768e45a5a0dSDavid Malone } 769d8984f48SDag-Erling Smørgrav free(pfd); 770e45a5a0dSDavid Malone break; 771d8984f48SDag-Erling Smørgrav } 772d8984f48SDag-Erling Smørgrav case Fd_set: { 773e45a5a0dSDavid Malone /* 77494355cfdSAndrey Zonov * XXX: A Fd_set argument expects the /first/ syscall argument 77594355cfdSAndrey Zonov * to be the number of fds in the array. This matches the 77694355cfdSAndrey Zonov * select syscall. 777e45a5a0dSDavid Malone */ 778e45a5a0dSDavid Malone fd_set *fds; 779e45a5a0dSDavid Malone int numfds = args[0]; 780e45a5a0dSDavid Malone int bytes = _howmany(numfds, _NFDBITS) * _NFDBITS; 781e45a5a0dSDavid Malone int i, tmpsize, u, used; 782e45a5a0dSDavid Malone const int per_fd = 20; 783e45a5a0dSDavid Malone 784e45a5a0dSDavid Malone if ((fds = malloc(bytes)) == NULL) 78594355cfdSAndrey Zonov err(1, "Cannot malloc %d bytes for fd_set array", 78694355cfdSAndrey Zonov bytes); 78794355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], fds, bytes) 78894355cfdSAndrey Zonov != -1) { 789e45a5a0dSDavid Malone used = 0; 790e45a5a0dSDavid Malone tmpsize = 1 + numfds * per_fd + 2; 791e45a5a0dSDavid Malone if ((tmp = malloc(tmpsize)) == NULL) 79294355cfdSAndrey Zonov err(1, "Cannot alloc %d bytes for fd_set " 79394355cfdSAndrey Zonov "output", tmpsize); 794e45a5a0dSDavid Malone 795e45a5a0dSDavid Malone tmp[used++] = '{'; 796e45a5a0dSDavid Malone for (i = 0; i < numfds; i++) { 797e45a5a0dSDavid Malone if (FD_ISSET(i, fds)) { 79894355cfdSAndrey Zonov u = snprintf(tmp + used, per_fd, "%d ", 79994355cfdSAndrey Zonov i); 800e45a5a0dSDavid Malone if (u > 0) 801e45a5a0dSDavid Malone used += u < per_fd ? u : per_fd; 802e45a5a0dSDavid Malone } 803e45a5a0dSDavid Malone } 804e45a5a0dSDavid Malone if (tmp[used-1] == ' ') 805e45a5a0dSDavid Malone used--; 806e45a5a0dSDavid Malone tmp[used++] = '}'; 807e45a5a0dSDavid Malone tmp[used++] = '\0'; 80894355cfdSAndrey Zonov } else 809e45a5a0dSDavid Malone asprintf(&tmp, "0x%lx", args[sc->offset]); 810d8984f48SDag-Erling Smørgrav free(fds); 811e45a5a0dSDavid Malone break; 812d8984f48SDag-Erling Smørgrav } 813d8984f48SDag-Erling Smørgrav case Signal: { 814f0ebbc29SDag-Erling Smørgrav long sig; 815f0ebbc29SDag-Erling Smørgrav 816f0ebbc29SDag-Erling Smørgrav sig = args[sc->offset]; 817d75300bfSAlfred Perlstein tmp = strsig(sig); 818d75300bfSAlfred Perlstein if (tmp == NULL) 8191bcb5f5aSMarcel Moolenaar asprintf(&tmp, "%ld", sig); 820f0ebbc29SDag-Erling Smørgrav break; 821d8984f48SDag-Erling Smørgrav } 822d8984f48SDag-Erling Smørgrav case Sigset: { 823081e5c48SPav Lucistnik long sig; 824081e5c48SPav Lucistnik sigset_t ss; 825081e5c48SPav Lucistnik int i, used; 826081e5c48SPav Lucistnik 827081e5c48SPav Lucistnik sig = args[sc->offset]; 82894355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, 82994355cfdSAndrey Zonov sizeof(ss)) == -1) { 830081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 831081e5c48SPav Lucistnik break; 832081e5c48SPav Lucistnik } 833081e5c48SPav Lucistnik tmp = malloc(sys_nsig * 8); /* 7 bytes avg per signal name */ 834081e5c48SPav Lucistnik used = 0; 835d8984f48SDag-Erling Smørgrav for (i = 1; i < sys_nsig; i++) { 83694355cfdSAndrey Zonov if (sigismember(&ss, i)) 837081e5c48SPav Lucistnik used += sprintf(tmp + used, "%s|", strsig(i)); 838081e5c48SPav Lucistnik } 839081e5c48SPav Lucistnik if (used) 840081e5c48SPav Lucistnik tmp[used-1] = 0; 841081e5c48SPav Lucistnik else 842081e5c48SPav Lucistnik strcpy(tmp, "0x0"); 843081e5c48SPav Lucistnik break; 844d8984f48SDag-Erling Smørgrav } 845d8984f48SDag-Erling Smørgrav case Sigprocmask: { 846894b8f7aSAlfred Perlstein switch (args[sc->offset]) { 847894b8f7aSAlfred Perlstein #define S(a) case a: tmp = strdup(#a); break; 848081e5c48SPav Lucistnik S(SIG_BLOCK); 849081e5c48SPav Lucistnik S(SIG_UNBLOCK); 850081e5c48SPav Lucistnik S(SIG_SETMASK); 851894b8f7aSAlfred Perlstein #undef S 852894b8f7aSAlfred Perlstein } 853894b8f7aSAlfred Perlstein if (tmp == NULL) 854894b8f7aSAlfred Perlstein asprintf(&tmp, "0x%lx", args[sc->offset]); 855894b8f7aSAlfred Perlstein break; 856d8984f48SDag-Erling Smørgrav } 857d8984f48SDag-Erling Smørgrav case Fcntlflag: { 858081e5c48SPav Lucistnik /* XXX output depends on the value of the previous argument */ 859081e5c48SPav Lucistnik switch (args[sc->offset-1]) { 860081e5c48SPav Lucistnik case F_SETFD: 86194355cfdSAndrey Zonov tmp = strdup(xlookup_bits(fcntlfd_arg, 86294355cfdSAndrey Zonov args[sc->offset])); 863081e5c48SPav Lucistnik break; 864081e5c48SPav Lucistnik case F_SETFL: 86594355cfdSAndrey Zonov tmp = strdup(xlookup_bits(fcntlfl_arg, 86694355cfdSAndrey Zonov args[sc->offset])); 867081e5c48SPav Lucistnik break; 868081e5c48SPav Lucistnik case F_GETFD: 869081e5c48SPav Lucistnik case F_GETFL: 870081e5c48SPav Lucistnik case F_GETOWN: 871081e5c48SPav Lucistnik tmp = strdup(""); 872081e5c48SPav Lucistnik break; 873081e5c48SPav Lucistnik default: 874081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 875081e5c48SPav Lucistnik break; 876081e5c48SPav Lucistnik } 877081e5c48SPav Lucistnik break; 878d8984f48SDag-Erling Smørgrav } 879081e5c48SPav Lucistnik case Open: 880081e5c48SPav Lucistnik tmp = strdup(xlookup_bits(open_flags, args[sc->offset])); 881081e5c48SPav Lucistnik break; 882081e5c48SPav Lucistnik case Fcntl: 883081e5c48SPav Lucistnik tmp = strdup(xlookup(fcntl_arg, args[sc->offset])); 884081e5c48SPav Lucistnik break; 885894b8f7aSAlfred Perlstein case Mprot: 886081e5c48SPav Lucistnik tmp = strdup(xlookup_bits(mprot_flags, args[sc->offset])); 887894b8f7aSAlfred Perlstein break; 888894b8f7aSAlfred Perlstein case Mmapflags: 889081e5c48SPav Lucistnik tmp = strdup(xlookup_bits(mmap_flags, args[sc->offset])); 890894b8f7aSAlfred Perlstein break; 891fde3a7d1SAlfred Perlstein case Whence: 892081e5c48SPav Lucistnik tmp = strdup(xlookup(whence_arg, args[sc->offset])); 893081e5c48SPav Lucistnik break; 894081e5c48SPav Lucistnik case Sockdomain: 895081e5c48SPav Lucistnik tmp = strdup(xlookup(sockdomain_arg, args[sc->offset])); 896081e5c48SPav Lucistnik break; 897081e5c48SPav Lucistnik case Socktype: 898081e5c48SPav Lucistnik tmp = strdup(xlookup(socktype_arg, args[sc->offset])); 899081e5c48SPav Lucistnik break; 900081e5c48SPav Lucistnik case Shutdown: 901081e5c48SPav Lucistnik tmp = strdup(xlookup(shutdown_arg, args[sc->offset])); 902081e5c48SPav Lucistnik break; 903081e5c48SPav Lucistnik case Resource: 904081e5c48SPav Lucistnik tmp = strdup(xlookup(resource_arg, args[sc->offset])); 905081e5c48SPav Lucistnik break; 906081e5c48SPav Lucistnik case Pathconf: 907081e5c48SPav Lucistnik tmp = strdup(xlookup(pathconf_arg, args[sc->offset])); 908fde3a7d1SAlfred Perlstein break; 909d8984f48SDag-Erling Smørgrav case Sockaddr: { 910dec17687SBrian Feldman struct sockaddr_storage ss; 9119ddd1412SDag-Erling Smørgrav char addr[64]; 9121be5d704SMark Murray struct sockaddr_in *lsin; 9131be5d704SMark Murray struct sockaddr_in6 *lsin6; 914dec17687SBrian Feldman struct sockaddr_un *sun; 915dec17687SBrian Feldman struct sockaddr *sa; 916dec17687SBrian Feldman char *p; 917dec17687SBrian Feldman u_char *q; 918dec17687SBrian Feldman int i; 9199ddd1412SDag-Erling Smørgrav 920a7a08c7eSMarcel Moolenaar if (args[sc->offset] == 0) { 921a7a08c7eSMarcel Moolenaar asprintf(&tmp, "NULL"); 922a7a08c7eSMarcel Moolenaar break; 923a7a08c7eSMarcel Moolenaar } 924a7a08c7eSMarcel Moolenaar 925dec17687SBrian Feldman /* yuck: get ss_len */ 9265d2d083cSXin LI if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, 927dec17687SBrian Feldman sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) 928dec17687SBrian Feldman err(1, "get_struct %p", (void *)args[sc->offset]); 9296a656761SAlfred Perlstein /* 9306a656761SAlfred Perlstein * If ss_len is 0, then try to guess from the sockaddr type. 9316a656761SAlfred Perlstein * AF_UNIX may be initialized incorrectly, so always frob 9326a656761SAlfred Perlstein * it by using the "right" size. 9336a656761SAlfred Perlstein */ 9346a656761SAlfred Perlstein if (ss.ss_len == 0 || ss.ss_family == AF_UNIX) { 9356a656761SAlfred Perlstein switch (ss.ss_family) { 9366a656761SAlfred Perlstein case AF_INET: 9376a656761SAlfred Perlstein ss.ss_len = sizeof(*lsin); 9386a656761SAlfred Perlstein break; 9396a656761SAlfred Perlstein case AF_UNIX: 9406a656761SAlfred Perlstein ss.ss_len = sizeof(*sun); 9416a656761SAlfred Perlstein break; 9426a656761SAlfred Perlstein default: 9436a656761SAlfred Perlstein /* hurrrr */ 9446a656761SAlfred Perlstein break; 9456a656761SAlfred Perlstein } 9466a656761SAlfred Perlstein } 94794355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, 94894355cfdSAndrey Zonov ss.ss_len) == -1) { 949dec17687SBrian Feldman err(2, "get_struct %p", (void *)args[sc->offset]); 9509ddd1412SDag-Erling Smørgrav } 951dec17687SBrian Feldman 952dec17687SBrian Feldman switch (ss.ss_family) { 953dec17687SBrian Feldman case AF_INET: 9541be5d704SMark Murray lsin = (struct sockaddr_in *)&ss; 9551be5d704SMark Murray inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr); 95694355cfdSAndrey Zonov asprintf(&tmp, "{ AF_INET %s:%d }", addr, 95794355cfdSAndrey Zonov htons(lsin->sin_port)); 958dec17687SBrian Feldman break; 959dec17687SBrian Feldman case AF_INET6: 9601be5d704SMark Murray lsin6 = (struct sockaddr_in6 *)&ss; 96194355cfdSAndrey Zonov inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, 96294355cfdSAndrey Zonov sizeof addr); 96394355cfdSAndrey Zonov asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr, 96494355cfdSAndrey Zonov htons(lsin6->sin6_port)); 965dec17687SBrian Feldman break; 966dec17687SBrian Feldman case AF_UNIX: 967dec17687SBrian Feldman sun = (struct sockaddr_un *)&ss; 968dec17687SBrian Feldman asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path); 969dec17687SBrian Feldman break; 970dec17687SBrian Feldman default: 971dec17687SBrian Feldman sa = (struct sockaddr *)&ss; 97294355cfdSAndrey Zonov asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data " 97394355cfdSAndrey Zonov "= {%n%*s } }", (int)sa->sa_len, (int)sa->sa_family, 97494355cfdSAndrey Zonov &i, 6 * (int)(sa->sa_len - ((char *)&sa->sa_data - 97594355cfdSAndrey Zonov (char *)sa)), ""); 976dec17687SBrian Feldman if (tmp != NULL) { 977dec17687SBrian Feldman p = tmp + i; 97894355cfdSAndrey Zonov for (q = (u_char *)&sa->sa_data; 97994355cfdSAndrey Zonov q < (u_char *)sa + sa->sa_len; q++) 980dec17687SBrian Feldman p += sprintf(p, " %#02x,", *q); 981dec17687SBrian Feldman } 982dec17687SBrian Feldman } 9839ddd1412SDag-Erling Smørgrav break; 984d8984f48SDag-Erling Smørgrav } 985d8984f48SDag-Erling Smørgrav case Sigaction: { 986e45a5a0dSDavid Malone struct sigaction sa; 987e45a5a0dSDavid Malone char *hand; 988e45a5a0dSDavid Malone const char *h; 989e45a5a0dSDavid Malone 99094355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa)) 99194355cfdSAndrey Zonov != -1) { 992e45a5a0dSDavid Malone asprintf(&hand, "%p", sa.sa_handler); 993e45a5a0dSDavid Malone if (sa.sa_handler == SIG_DFL) 994e45a5a0dSDavid Malone h = "SIG_DFL"; 995e45a5a0dSDavid Malone else if (sa.sa_handler == SIG_IGN) 996e45a5a0dSDavid Malone h = "SIG_IGN"; 997e45a5a0dSDavid Malone else 998e45a5a0dSDavid Malone h = hand; 999081e5c48SPav Lucistnik 100094355cfdSAndrey Zonov asprintf(&tmp, "{ %s %s ss_t }", h, 1001081e5c48SPav Lucistnik xlookup_bits(sigaction_flags, sa.sa_flags)); 1002e45a5a0dSDavid Malone free(hand); 100394355cfdSAndrey Zonov } else 1004e45a5a0dSDavid Malone asprintf(&tmp, "0x%lx", args[sc->offset]); 1005e45a5a0dSDavid Malone break; 1006d8984f48SDag-Erling Smørgrav } 1007d8984f48SDag-Erling Smørgrav case Kevent: { 1008081e5c48SPav Lucistnik /* 1009081e5c48SPav Lucistnik * XXX XXX: the size of the array is determined by either the 1010081e5c48SPav Lucistnik * next syscall argument, or by the syscall returnvalue, 1011081e5c48SPav Lucistnik * depending on which argument number we are. This matches the 1012081e5c48SPav Lucistnik * kevent syscall, but luckily that's the only syscall that uses 1013081e5c48SPav Lucistnik * them. 1014081e5c48SPav Lucistnik */ 1015081e5c48SPav Lucistnik struct kevent *ke; 1016081e5c48SPav Lucistnik int numevents = -1; 1017081e5c48SPav Lucistnik int bytes = 0; 1018081e5c48SPav Lucistnik int i, tmpsize, u, used; 1019081e5c48SPav Lucistnik const int per_ke = 100; 1020081e5c48SPav Lucistnik 1021081e5c48SPav Lucistnik if (sc->offset == 1) 1022081e5c48SPav Lucistnik numevents = args[sc->offset+1]; 1023081e5c48SPav Lucistnik else if (sc->offset == 3 && retval != -1) 1024081e5c48SPav Lucistnik numevents = retval; 1025081e5c48SPav Lucistnik 1026081e5c48SPav Lucistnik if (numevents >= 0) 1027081e5c48SPav Lucistnik bytes = sizeof(struct kevent) * numevents; 1028081e5c48SPav Lucistnik if ((ke = malloc(bytes)) == NULL) 102994355cfdSAndrey Zonov err(1, "Cannot malloc %d bytes for kevent array", 103094355cfdSAndrey Zonov bytes); 103194355cfdSAndrey Zonov if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset], 103294355cfdSAndrey Zonov ke, bytes) != -1) { 1033081e5c48SPav Lucistnik used = 0; 1034081e5c48SPav Lucistnik tmpsize = 1 + per_ke * numevents + 2; 1035081e5c48SPav Lucistnik if ((tmp = malloc(tmpsize)) == NULL) 103694355cfdSAndrey Zonov err(1, "Cannot alloc %d bytes for kevent " 103794355cfdSAndrey Zonov "output", tmpsize); 1038081e5c48SPav Lucistnik 1039081e5c48SPav Lucistnik tmp[used++] = '{'; 1040081e5c48SPav Lucistnik for (i = 0; i < numevents; i++) { 1041081e5c48SPav Lucistnik u = snprintf(tmp + used, per_ke, 1042081e5c48SPav Lucistnik "%s%p,%s,%s,%d,%p,%p", 1043081e5c48SPav Lucistnik i > 0 ? " " : "", 1044081e5c48SPav Lucistnik (void *)ke[i].ident, 1045081e5c48SPav Lucistnik xlookup(kevent_filters, ke[i].filter), 1046081e5c48SPav Lucistnik xlookup_bits(kevent_flags, ke[i].flags), 1047081e5c48SPav Lucistnik ke[i].fflags, 1048081e5c48SPav Lucistnik (void *)ke[i].data, 1049081e5c48SPav Lucistnik (void *)ke[i].udata); 1050081e5c48SPav Lucistnik if (u > 0) 1051081e5c48SPav Lucistnik used += u < per_ke ? u : per_ke; 1052081e5c48SPav Lucistnik } 1053081e5c48SPav Lucistnik tmp[used++] = '}'; 1054081e5c48SPav Lucistnik tmp[used++] = '\0'; 1055d8984f48SDag-Erling Smørgrav } else { 1056081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 1057081e5c48SPav Lucistnik } 1058d8984f48SDag-Erling Smørgrav free(ke); 1059081e5c48SPav Lucistnik break; 1060d8984f48SDag-Erling Smørgrav } 1061d8984f48SDag-Erling Smørgrav case Stat: { 1062081e5c48SPav Lucistnik struct stat st; 106394355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st)) 106494355cfdSAndrey Zonov != -1) { 1065081e5c48SPav Lucistnik char mode[12]; 1066081e5c48SPav Lucistnik strmode(st.st_mode, mode); 106794355cfdSAndrey Zonov asprintf(&tmp, 106894355cfdSAndrey Zonov "{ mode=%s,inode=%jd,size=%jd,blksize=%ld }", mode, 106994355cfdSAndrey Zonov (intmax_t)st.st_ino, (intmax_t)st.st_size, 107094355cfdSAndrey Zonov (long)st.st_blksize); 1071d8984f48SDag-Erling Smørgrav } else { 1072081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 1073081e5c48SPav Lucistnik } 1074081e5c48SPav Lucistnik break; 1075d8984f48SDag-Erling Smørgrav } 1076d8984f48SDag-Erling Smørgrav case Rusage: { 1077081e5c48SPav Lucistnik struct rusage ru; 107894355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru)) 107994355cfdSAndrey Zonov != -1) { 108094355cfdSAndrey Zonov asprintf(&tmp, 108194355cfdSAndrey Zonov "{ u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld }", 1082081e5c48SPav Lucistnik (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, 1083081e5c48SPav Lucistnik (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, 1084081e5c48SPav Lucistnik ru.ru_inblock, ru.ru_oublock); 108594355cfdSAndrey Zonov } else 1086081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 1087081e5c48SPav Lucistnik break; 1088d8984f48SDag-Erling Smørgrav } 1089d8984f48SDag-Erling Smørgrav case Rlimit: { 1090081e5c48SPav Lucistnik struct rlimit rl; 109194355cfdSAndrey Zonov if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl)) 109294355cfdSAndrey Zonov != -1) { 1093081e5c48SPav Lucistnik asprintf(&tmp, "{ cur=%ju,max=%ju }", 1094081e5c48SPav Lucistnik rl.rlim_cur, rl.rlim_max); 109594355cfdSAndrey Zonov } else 1096081e5c48SPav Lucistnik asprintf(&tmp, "0x%lx", args[sc->offset]); 1097081e5c48SPav Lucistnik break; 1098d8984f48SDag-Erling Smørgrav } 1099081e5c48SPav Lucistnik default: 1100081e5c48SPav Lucistnik errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); 1101bbeaf6c0SSean Eric Fagan } 1102d8984f48SDag-Erling Smørgrav return (tmp); 1103bbeaf6c0SSean Eric Fagan } 1104bbeaf6c0SSean Eric Fagan 1105bbeaf6c0SSean Eric Fagan /* 1106bbeaf6c0SSean Eric Fagan * print_syscall 1107bbeaf6c0SSean Eric Fagan * Print (to outfile) the system call and its arguments. Note that 1108bbeaf6c0SSean Eric Fagan * nargs is the number of arguments (not the number of words; this is 1109bbeaf6c0SSean Eric Fagan * potentially confusing, I know). 1110bbeaf6c0SSean Eric Fagan */ 1111bbeaf6c0SSean Eric Fagan 1112bbeaf6c0SSean Eric Fagan void 111394355cfdSAndrey Zonov print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, 111494355cfdSAndrey Zonov char **s_args) 1115d8984f48SDag-Erling Smørgrav { 1116203098d8SMatthew N. Dodd struct timespec timediff; 111794355cfdSAndrey Zonov int i, len; 11180d0bd00eSMatthew N. Dodd 111994355cfdSAndrey Zonov len = 0; 1120c03bfcc8SMatthew N. Dodd if (trussinfo->flags & FOLLOWFORKS) 1121c03bfcc8SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid); 1122c03bfcc8SMatthew N. Dodd 112394355cfdSAndrey Zonov if (name != NULL && (strcmp(name, "execve") == 0 || 112494355cfdSAndrey Zonov strcmp(name, "exit") == 0)) { 11255695afdeSAndrey Zonov clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); 11260d0bd00eSMatthew N. Dodd } 11270d0bd00eSMatthew N. Dodd 11280d0bd00eSMatthew N. Dodd if (trussinfo->flags & ABSOLUTETIMESTAMPS) { 1129*d9dcc463SXin LI timespecsubt(&trussinfo->curthread->after, 11305695afdeSAndrey Zonov &trussinfo->start_time, &timediff); 113137169f94SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%ld.%09ld ", 1132fb034d05SMatthew N. Dodd (long)timediff.tv_sec, timediff.tv_nsec); 11330d0bd00eSMatthew N. Dodd } 11340d0bd00eSMatthew N. Dodd 11350d0bd00eSMatthew N. Dodd if (trussinfo->flags & RELATIVETIMESTAMPS) { 1136*d9dcc463SXin LI timespecsubt(&trussinfo->curthread->after, 11375695afdeSAndrey Zonov &trussinfo->curthread->before, &timediff); 113837169f94SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%ld.%09ld ", 1139fb034d05SMatthew N. Dodd (long)timediff.tv_sec, timediff.tv_nsec); 11400d0bd00eSMatthew N. Dodd } 11410d0bd00eSMatthew N. Dodd 1142ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%s(", name); 1143c03bfcc8SMatthew N. Dodd 1144bbeaf6c0SSean Eric Fagan for (i = 0; i < nargs; i++) { 1145bbeaf6c0SSean Eric Fagan if (s_args[i]) 1146ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%s", s_args[i]); 1147bbeaf6c0SSean Eric Fagan else 114894355cfdSAndrey Zonov len += fprintf(trussinfo->outfile, 114994355cfdSAndrey Zonov "<missing argument>"); 115094355cfdSAndrey Zonov len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? 115194355cfdSAndrey Zonov "," : ""); 1152bbeaf6c0SSean Eric Fagan } 1153ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, ")"); 11546cb533feSSean Eric Fagan for (i = 0; i < 6 - (len / 8); i++) 1155ec0bed25SMatthew N. Dodd fprintf(trussinfo->outfile, "\t"); 11566cb533feSSean Eric Fagan } 11576cb533feSSean Eric Fagan 11586cb533feSSean Eric Fagan void 11591bcb5f5aSMarcel Moolenaar print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, 1160ee3b0f6eSDiomidis Spinellis char **s_args, int errorp, long retval, struct syscall *sc) 11611bcb5f5aSMarcel Moolenaar { 1162ee3b0f6eSDiomidis Spinellis struct timespec timediff; 1163ee3b0f6eSDiomidis Spinellis 1164ee3b0f6eSDiomidis Spinellis if (trussinfo->flags & COUNTONLY) { 1165ee3b0f6eSDiomidis Spinellis if (!sc) 1166ee3b0f6eSDiomidis Spinellis return; 11675695afdeSAndrey Zonov clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); 1168*d9dcc463SXin LI timespecsubt(&trussinfo->curthread->after, 11695695afdeSAndrey Zonov &trussinfo->curthread->before, &timediff); 1170*d9dcc463SXin LI timespecadd(&sc->time, &timediff, &sc->time); 1171ee3b0f6eSDiomidis Spinellis sc->ncalls++; 1172ee3b0f6eSDiomidis Spinellis if (errorp) 1173ee3b0f6eSDiomidis Spinellis sc->nerror++; 1174ee3b0f6eSDiomidis Spinellis return; 1175ee3b0f6eSDiomidis Spinellis } 1176d8984f48SDag-Erling Smørgrav 1177ec0bed25SMatthew N. Dodd print_syscall(trussinfo, name, nargs, s_args); 11780cf21b4fSBrian Somers fflush(trussinfo->outfile); 117994355cfdSAndrey Zonov if (errorp) 118094355cfdSAndrey Zonov fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval, 118194355cfdSAndrey Zonov strerror(retval)); 118294355cfdSAndrey Zonov else { 1183c059fa2eSJaakko Heinonen /* 1184c059fa2eSJaakko Heinonen * Because pipe(2) has a special assembly glue to provide the 1185c059fa2eSJaakko Heinonen * libc API, we have to adjust retval. 1186c059fa2eSJaakko Heinonen */ 118794355cfdSAndrey Zonov if (name != NULL && strcmp(name, "pipe") == 0) 1188c059fa2eSJaakko Heinonen retval = 0; 11891bcb5f5aSMarcel Moolenaar fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval, retval); 11906cb533feSSean Eric Fagan } 1191bbeaf6c0SSean Eric Fagan } 1192ee3b0f6eSDiomidis Spinellis 1193ee3b0f6eSDiomidis Spinellis void 1194ee3b0f6eSDiomidis Spinellis print_summary(struct trussinfo *trussinfo) 1195ee3b0f6eSDiomidis Spinellis { 1196ee3b0f6eSDiomidis Spinellis struct timespec total = {0, 0}; 119794355cfdSAndrey Zonov struct syscall *sc; 1198ee3b0f6eSDiomidis Spinellis int ncall, nerror; 1199ee3b0f6eSDiomidis Spinellis 1200ee3b0f6eSDiomidis Spinellis fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n", 1201ee3b0f6eSDiomidis Spinellis "syscall", "seconds", "calls", "errors"); 1202ee3b0f6eSDiomidis Spinellis ncall = nerror = 0; 1203ee3b0f6eSDiomidis Spinellis for (sc = syscalls; sc->name != NULL; sc++) 1204ee3b0f6eSDiomidis Spinellis if (sc->ncalls) { 120555a8d2bbSJaakko Heinonen fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", 120655a8d2bbSJaakko Heinonen sc->name, (intmax_t)sc->time.tv_sec, 120755a8d2bbSJaakko Heinonen sc->time.tv_nsec, sc->ncalls, sc->nerror); 1208*d9dcc463SXin LI timespecadd(&total, &sc->time, &total); 1209ee3b0f6eSDiomidis Spinellis ncall += sc->ncalls; 1210ee3b0f6eSDiomidis Spinellis nerror += sc->nerror; 1211ee3b0f6eSDiomidis Spinellis } 1212ee3b0f6eSDiomidis Spinellis fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n", 1213ee3b0f6eSDiomidis Spinellis "", "-------------", "-------", "-------"); 121455a8d2bbSJaakko Heinonen fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", 121555a8d2bbSJaakko Heinonen "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror); 1216ee3b0f6eSDiomidis Spinellis } 1217