1bbeaf6c0SSean Eric Fagan /* 209d64da3SSean Eric Fagan * Copryight 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 423cf51049SPhilippe Charnier #include <err.h> 43bbeaf6c0SSean Eric Fagan #include <stdio.h> 44bbeaf6c0SSean Eric Fagan #include <stdlib.h> 45bbeaf6c0SSean Eric Fagan #include <string.h> 46bbeaf6c0SSean Eric Fagan #include <unistd.h> 47bbeaf6c0SSean Eric Fagan #include <sys/types.h> 48f0ebbc29SDag-Erling Smørgrav #include <signal.h> 49bbeaf6c0SSean Eric Fagan #include "syscall.h" 50bbeaf6c0SSean Eric Fagan 51bbeaf6c0SSean Eric Fagan /* 52bbeaf6c0SSean Eric Fagan * This should probably be in its own file. 53bbeaf6c0SSean Eric Fagan */ 54bbeaf6c0SSean Eric Fagan 55bbeaf6c0SSean Eric Fagan struct syscall syscalls[] = { 56bbeaf6c0SSean Eric Fagan { "readlink", 1, 3, 57bbeaf6c0SSean Eric Fagan { { String, 0 } , { String | OUT, 1 }, { Int, 2 }}}, 58bbeaf6c0SSean Eric Fagan { "lseek", 2, 3, 59bbeaf6c0SSean Eric Fagan { { Int, 0 }, {Quad, 2 }, { Int, 4 }}}, 60bbeaf6c0SSean Eric Fagan { "mmap", 2, 6, 61bbeaf6c0SSean Eric Fagan { { Hex, 0 }, {Int, 1}, {Hex, 2}, {Hex, 3}, {Int, 4}, {Quad, 6}}}, 62bbeaf6c0SSean Eric Fagan { "open", 1, 3, 63bbeaf6c0SSean Eric Fagan { { String | IN, 0} , { Int, 1}, {Octal, 2}}}, 64bbeaf6c0SSean Eric Fagan { "linux_open", 1, 3, 65bbeaf6c0SSean Eric Fagan { { String, 0 }, { Int, 1}, { Octal, 2 }}}, 66bbeaf6c0SSean Eric Fagan { "close", 1, 1, { { Int, 0 } } }, 67bbeaf6c0SSean Eric Fagan { "fstat", 1, 2, 68bbeaf6c0SSean Eric Fagan { { Int, 0}, {Ptr | OUT , 1 }}}, 69bbeaf6c0SSean Eric Fagan { "stat", 1, 2, 70bbeaf6c0SSean Eric Fagan { { String | IN, 0 }, { Ptr | OUT, 1 }}}, 71a8f37218SSean Eric Fagan { "lstat", 1, 2, 72a8f37218SSean Eric Fagan { { String | IN, 0 }, { Ptr | OUT, 1 }}}, 73bbeaf6c0SSean Eric Fagan { "linux_newstat", 1, 2, 74bbeaf6c0SSean Eric Fagan { { String | IN, 0 }, { Ptr | OUT, 1 }}}, 75bbeaf6c0SSean Eric Fagan { "linux_newfstat", 1, 2, 76bbeaf6c0SSean Eric Fagan { { Int, 0 }, { Ptr | OUT, 1 }}}, 77bbeaf6c0SSean Eric Fagan { "write", 1, 3, 78bbeaf6c0SSean Eric Fagan { { Int, 0}, { Ptr | IN, 1 }, { Int, 2 }}}, 79970649f9SSean Eric Fagan { "ioctl", 1, 3, 80970649f9SSean Eric Fagan { { Int, 0}, { Ioctl, 1 }, { Hex, 2 }}}, 81bbeaf6c0SSean Eric Fagan { "break", 1, 1, { { Hex, 0 }}}, 82bbeaf6c0SSean Eric Fagan { "exit", 0, 1, { { Hex, 0 }}}, 8310714102SDag-Erling Smørgrav { "access", 1, 2, { { String | IN, 0 }, { Int, 1 }}}, 84f0ebbc29SDag-Erling Smørgrav { "sigaction", 1, 3, 85f0ebbc29SDag-Erling Smørgrav { { Signal, 0 }, { Ptr | IN, 1 }, { Ptr | OUT, 2 }}}, 863cf51049SPhilippe Charnier { 0, 0, 0, { { 0, 0 }}}, 87bbeaf6c0SSean Eric Fagan }; 88bbeaf6c0SSean Eric Fagan 893cf51049SPhilippe Charnier char * ioctlname __P((int)); 903cf51049SPhilippe Charnier 91bbeaf6c0SSean Eric Fagan /* 92bbeaf6c0SSean Eric Fagan * If/when the list gets big, it might be desirable to do it 93bbeaf6c0SSean Eric Fagan * as a hash table or binary search. 94bbeaf6c0SSean Eric Fagan */ 95bbeaf6c0SSean Eric Fagan 96bbeaf6c0SSean Eric Fagan struct syscall * 97bbeaf6c0SSean Eric Fagan get_syscall(const char *name) { 98bbeaf6c0SSean Eric Fagan struct syscall *sc = syscalls; 99bbeaf6c0SSean Eric Fagan 100bbeaf6c0SSean Eric Fagan while (sc->name) { 101bbeaf6c0SSean Eric Fagan if (!strcmp(name, sc->name)) 102bbeaf6c0SSean Eric Fagan return sc; 103bbeaf6c0SSean Eric Fagan sc++; 104bbeaf6c0SSean Eric Fagan } 105bbeaf6c0SSean Eric Fagan return NULL; 106bbeaf6c0SSean Eric Fagan } 107bbeaf6c0SSean Eric Fagan 108bbeaf6c0SSean Eric Fagan /* 109bbeaf6c0SSean Eric Fagan * get_string 110bbeaf6c0SSean Eric Fagan * Copy a string from the process. Note that it is 111bbeaf6c0SSean Eric Fagan * expected to be a C string, but if max is set, it will 112bbeaf6c0SSean Eric Fagan * only get that much. 113bbeaf6c0SSean Eric Fagan */ 114bbeaf6c0SSean Eric Fagan 115bbeaf6c0SSean Eric Fagan char * 116bbeaf6c0SSean Eric Fagan get_string(int procfd, void *offset, int max) { 1173cf51049SPhilippe Charnier char *buf; 118bbeaf6c0SSean Eric Fagan int size, len, c; 119bbeaf6c0SSean Eric Fagan FILE *p; 120bbeaf6c0SSean Eric Fagan 1213cf51049SPhilippe Charnier if ((p = fdopen(procfd, "r")) == NULL) 1223cf51049SPhilippe Charnier err(1, "fdopen"); 123bbeaf6c0SSean Eric Fagan buf = malloc( size = (max ? max : 64 ) ); 124bbeaf6c0SSean Eric Fagan len = 0; 125bbeaf6c0SSean Eric Fagan fseek(p, (long)offset, SEEK_SET); 126bbeaf6c0SSean Eric Fagan while ((c = fgetc(p)) != EOF) { 127bbeaf6c0SSean Eric Fagan buf[len++] = c; 128bbeaf6c0SSean Eric Fagan if (c == 0 || len == max) { 129bbeaf6c0SSean Eric Fagan buf[len] = 0; 130bbeaf6c0SSean Eric Fagan break; 131bbeaf6c0SSean Eric Fagan } 132bbeaf6c0SSean Eric Fagan if (len == size) { 133bbeaf6c0SSean Eric Fagan char *tmp = buf; 134bbeaf6c0SSean Eric Fagan tmp = realloc(buf, size+64); 135bbeaf6c0SSean Eric Fagan if (tmp == NULL) { 136bbeaf6c0SSean Eric Fagan buf[len] = 0; 137bbeaf6c0SSean Eric Fagan return buf; 138bbeaf6c0SSean Eric Fagan } 139bbeaf6c0SSean Eric Fagan size += 64; 140bbeaf6c0SSean Eric Fagan } 141bbeaf6c0SSean Eric Fagan } 142bbeaf6c0SSean Eric Fagan return buf; 143bbeaf6c0SSean Eric Fagan } 144bbeaf6c0SSean Eric Fagan 145bbeaf6c0SSean Eric Fagan 146bbeaf6c0SSean Eric Fagan /* 147bbeaf6c0SSean Eric Fagan * Gag. This is really unportable. Multiplication is more portable. 148bbeaf6c0SSean Eric Fagan * But slower, from the code I saw. 149bbeaf6c0SSean Eric Fagan */ 150bbeaf6c0SSean Eric Fagan 151bbeaf6c0SSean Eric Fagan static long long 152bbeaf6c0SSean Eric Fagan make_quad(unsigned long p1, unsigned long p2) { 153bbeaf6c0SSean Eric Fagan union { 154bbeaf6c0SSean Eric Fagan long long ll; 155bbeaf6c0SSean Eric Fagan unsigned long l[2]; 156bbeaf6c0SSean Eric Fagan } t; 157bbeaf6c0SSean Eric Fagan t.l[0] = p1; 158bbeaf6c0SSean Eric Fagan t.l[1] = p2; 159bbeaf6c0SSean Eric Fagan return t.ll; 160bbeaf6c0SSean Eric Fagan } 161bbeaf6c0SSean Eric Fagan 162bbeaf6c0SSean Eric Fagan 163bbeaf6c0SSean Eric Fagan /* 164bbeaf6c0SSean Eric Fagan * print_arg 165bbeaf6c0SSean Eric Fagan * Converts a syscall argument into a string. Said string is 166bbeaf6c0SSean Eric Fagan * allocated via malloc(), so needs to be free()'d. The file 167bbeaf6c0SSean Eric Fagan * descriptor is for the process' memory (via /proc), and is used 168bbeaf6c0SSean Eric Fagan * to get any data (where the argument is a pointer). sc is 169bbeaf6c0SSean Eric Fagan * a pointer to the syscall description (see above); args is 170bbeaf6c0SSean Eric Fagan * an array of all of the system call arguments. 171bbeaf6c0SSean Eric Fagan */ 172bbeaf6c0SSean Eric Fagan 173bbeaf6c0SSean Eric Fagan char * 174bbeaf6c0SSean Eric Fagan print_arg(int fd, struct syscall_args *sc, unsigned long *args) { 1753cf51049SPhilippe Charnier char *tmp = NULL; 176bbeaf6c0SSean Eric Fagan switch (sc->type & ARG_MASK) { 177bbeaf6c0SSean Eric Fagan case Hex: 178bbeaf6c0SSean Eric Fagan tmp = malloc(12); 17922694ebaSBruce Evans sprintf(tmp, "0x%lx", args[sc->offset]); 180bbeaf6c0SSean Eric Fagan break; 181bbeaf6c0SSean Eric Fagan case Octal: 182bbeaf6c0SSean Eric Fagan tmp = malloc(13); 18322694ebaSBruce Evans sprintf(tmp, "0%lo", args[sc->offset]); 184bbeaf6c0SSean Eric Fagan break; 185bbeaf6c0SSean Eric Fagan case Int: 186bbeaf6c0SSean Eric Fagan tmp = malloc(12); 18722694ebaSBruce Evans sprintf(tmp, "%ld", args[sc->offset]); 188bbeaf6c0SSean Eric Fagan break; 189bbeaf6c0SSean Eric Fagan case String: 190bbeaf6c0SSean Eric Fagan { 191bbeaf6c0SSean Eric Fagan char *tmp2; 192bbeaf6c0SSean Eric Fagan tmp2 = get_string(fd, (void*)args[sc->offset], 0); 193bbeaf6c0SSean Eric Fagan tmp = malloc(strlen(tmp2) + 3); 194bbeaf6c0SSean Eric Fagan sprintf(tmp, "\"%s\"", tmp2); 195bbeaf6c0SSean Eric Fagan free(tmp2); 196bbeaf6c0SSean Eric Fagan } 197bbeaf6c0SSean Eric Fagan break; 198bbeaf6c0SSean Eric Fagan case Quad: 199bbeaf6c0SSean Eric Fagan { 200bbeaf6c0SSean Eric Fagan unsigned long long t; 201bbeaf6c0SSean Eric Fagan unsigned long l1, l2; 202bbeaf6c0SSean Eric Fagan l1 = args[sc->offset]; 203bbeaf6c0SSean Eric Fagan l2 = args[sc->offset+1]; 204bbeaf6c0SSean Eric Fagan t = make_quad(l1, l2); 205bbeaf6c0SSean Eric Fagan tmp = malloc(24); 206bbeaf6c0SSean Eric Fagan sprintf(tmp, "0x%qx", t); 207bbeaf6c0SSean Eric Fagan break; 208bbeaf6c0SSean Eric Fagan } 209bbeaf6c0SSean Eric Fagan case Ptr: 210bbeaf6c0SSean Eric Fagan tmp = malloc(12); 21122694ebaSBruce Evans sprintf(tmp, "0x%lx", args[sc->offset]); 212bbeaf6c0SSean Eric Fagan break; 213970649f9SSean Eric Fagan case Ioctl: 214970649f9SSean Eric Fagan { 215970649f9SSean Eric Fagan char *temp = ioctlname(args[sc->offset]); 216970649f9SSean Eric Fagan if (temp) 217970649f9SSean Eric Fagan tmp = strdup(temp); 218970649f9SSean Eric Fagan else { 219970649f9SSean Eric Fagan tmp = malloc(12); 22022694ebaSBruce Evans sprintf(tmp, "0x%lx", args[sc->offset]); 221970649f9SSean Eric Fagan } 222970649f9SSean Eric Fagan } 223f0ebbc29SDag-Erling Smørgrav break; 224f0ebbc29SDag-Erling Smørgrav case Signal: 225f0ebbc29SDag-Erling Smørgrav { 226f0ebbc29SDag-Erling Smørgrav long sig; 227f0ebbc29SDag-Erling Smørgrav 228f0ebbc29SDag-Erling Smørgrav sig = args[sc->offset]; 229f0ebbc29SDag-Erling Smørgrav tmp = malloc(12); 230f0ebbc29SDag-Erling Smørgrav if (sig > 0 && sig < NSIG) { 231f0ebbc29SDag-Erling Smørgrav int i; 232f0ebbc29SDag-Erling Smørgrav sprintf(tmp, "sig%s", sys_signame[sig]); 233f0ebbc29SDag-Erling Smørgrav for (i = 0; tmp[i] != '\0'; ++i) 234f0ebbc29SDag-Erling Smørgrav tmp[i] = toupper(tmp[i]); 235f0ebbc29SDag-Erling Smørgrav } else { 236f0ebbc29SDag-Erling Smørgrav sprintf(tmp, "%ld", sig); 237f0ebbc29SDag-Erling Smørgrav } 238f0ebbc29SDag-Erling Smørgrav } 239f0ebbc29SDag-Erling Smørgrav break; 240bbeaf6c0SSean Eric Fagan } 241bbeaf6c0SSean Eric Fagan return tmp; 242bbeaf6c0SSean Eric Fagan } 243bbeaf6c0SSean Eric Fagan 244bbeaf6c0SSean Eric Fagan /* 245bbeaf6c0SSean Eric Fagan * print_syscall 246bbeaf6c0SSean Eric Fagan * Print (to outfile) the system call and its arguments. Note that 247bbeaf6c0SSean Eric Fagan * nargs is the number of arguments (not the number of words; this is 248bbeaf6c0SSean Eric Fagan * potentially confusing, I know). 249bbeaf6c0SSean Eric Fagan */ 250bbeaf6c0SSean Eric Fagan 251bbeaf6c0SSean Eric Fagan void 252bbeaf6c0SSean Eric Fagan print_syscall(FILE *outfile, const char *name, int nargs, char **s_args) { 253bbeaf6c0SSean Eric Fagan int i; 254bbeaf6c0SSean Eric Fagan fprintf(outfile, "syscall %s(", name); 255bbeaf6c0SSean Eric Fagan for (i = 0; i < nargs; i++) { 256bbeaf6c0SSean Eric Fagan if (s_args[i]) 257bbeaf6c0SSean Eric Fagan fprintf(outfile, "%s", s_args[i]); 258bbeaf6c0SSean Eric Fagan else 259bbeaf6c0SSean Eric Fagan fprintf(outfile, "<missing argument>"); 260bbeaf6c0SSean Eric Fagan fprintf(outfile, "%s", i < (nargs - 1) ? "," : ""); 261bbeaf6c0SSean Eric Fagan } 262bbeaf6c0SSean Eric Fagan fprintf(outfile, ")\n\t"); 263bbeaf6c0SSean Eric Fagan } 264