diff options
Diffstat (limited to 'usr.bin/truss/syscalls.c')
-rw-r--r-- | usr.bin/truss/syscalls.c | 136 |
1 files changed, 75 insertions, 61 deletions
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 33a1c0b..5eff8d6 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -41,6 +41,7 @@ static const char rcsid[] = #include <sys/mman.h> #include <sys/types.h> +#include <sys/ptrace.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/un.h> @@ -216,7 +217,7 @@ struct syscall syscalls[] = { /* Xlat idea taken from strace */ struct xlat { int val; - char *str; + const char *str; }; #define X(a) { a, #a }, @@ -324,7 +325,8 @@ static struct xlat pathconf_arg[] = { /* Searches an xlat array for a value, and returns it if found. Otherwise return a string representation. */ -char *lookup(struct xlat *xlat, int val, int base) +static const char +*lookup(struct xlat *xlat, int val, int base) { static char tmp[16]; for (; xlat->str != NULL; xlat++) @@ -347,7 +349,8 @@ char *lookup(struct xlat *xlat, int val, int base) return tmp; } -char *xlookup(struct xlat *xlat, int val) +static const char * +xlookup(struct xlat *xlat, int val) { return lookup(xlat, val, 16); } @@ -355,7 +358,8 @@ char *xlookup(struct xlat *xlat, int val) /* Searches an xlat array containing bitfield values. Remaining bits set after removing the known ones are printed at the end: IN|0x400 */ -char *xlookup_bits(struct xlat *xlat, int val) +static char +*xlookup_bits(struct xlat *xlat, int val) { static char str[512]; int len = 0; @@ -408,13 +412,20 @@ get_syscall(const char *name) { */ static int -get_struct(int procfd, void *offset, void *buf, int len) { - - if (pread(procfd, buf, len, (uintptr_t)offset) != len) - return -1; +get_struct(int pid, void *offset, void *buf, int len) { + struct ptrace_io_desc iorequest; + + iorequest.piod_op = PIOD_READ_D; + iorequest.piod_offs = offset; + iorequest.piod_addr = buf; + iorequest.piod_len = len; + if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) + return -1; return 0; } +#define MAXSIZE 4096 +#define BLOCKSIZE 1024 /* * get_string * Copy a string from the process. Note that it is @@ -422,39 +433,42 @@ get_struct(int procfd, void *offset, void *buf, int len) { * only get that much. */ -char * -get_string(int procfd, void *offset, int max) { +static char * +get_string(pid_t pid, void *offset, int max) { char *buf; - int size, len, c, fd; - FILE *p; - - if ((fd = dup(procfd)) == -1) - err(1, "dup"); - if ((p = fdopen(fd, "r")) == NULL) - err(1, "fdopen"); - buf = malloc( size = (max ? max + 1 : 64 ) ); - len = 0; - buf[0] = 0; - if (fseeko(p, (uintptr_t)offset, SEEK_SET) == 0) { - while ((c = fgetc(p)) != EOF) { - buf[len++] = c; - if (c == 0 || len == max) - break; - if (len == size) { - char *tmp; - tmp = realloc(buf, size+64); - if (tmp == NULL) { - buf[len] = 0; - break; - } - size += 64; - buf = tmp; - } + struct ptrace_io_desc iorequest; + int totalsize, size; + int diff = 0; + int i; + + totalsize = size = max ? (max + 1) : BLOCKSIZE; + buf = malloc(totalsize); + if (buf == NULL) + return NULL; + for(;;) { + diff = totalsize - size; + iorequest.piod_op = PIOD_READ_D; + iorequest.piod_offs = (char *)offset + diff; + iorequest.piod_addr = buf + diff; + iorequest.piod_len = size; + if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) { + free(buf); + return NULL; + } + for (i = 0 ; i < size; i++) { + if (buf[diff + i] == '\0') + return (buf); + } + if (totalsize < MAXSIZE - BLOCKSIZE && max == 0) { + totalsize += BLOCKSIZE; + buf = realloc(buf, totalsize); + size = BLOCKSIZE; + } + else { + buf[totalsize] = '\0'; + return buf; } - buf[len] = 0; } - fclose(p); - return (buf); } @@ -469,9 +483,9 @@ get_string(int procfd, void *offset, int max) { */ char * -print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) { +print_arg(struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) { char *tmp = NULL; - + int pid = trussinfo->pid; switch (sc->type & ARG_MASK) { case Hex: asprintf(&tmp, "0x%lx", args[sc->offset]); @@ -486,7 +500,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str { /* NULL-terminated string. */ char *tmp2; - tmp2 = get_string(fd, (void*)args[sc->offset], 0); + tmp2 = get_string(pid, (void*)args[sc->offset], 0); asprintf(&tmp, "\"%s\"", tmp2); free(tmp2); } @@ -514,7 +528,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str len = max_string; truncated = 1; } - if (len && get_struct(fd, (void*)args[sc->offset], &tmp2, len) != -1) { + if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len) != -1) { tmp3 = malloc(len * 4 + 1); while (len) { if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) @@ -535,7 +549,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str char *string; char *strarray[100]; /* XXX This is ugly. */ - if (get_struct(fd, (void *)args[sc->offset], (void *)&strarray, + if (get_struct(pid, (void *)args[sc->offset], (void *)&strarray, sizeof(strarray)) == -1) { err(1, "get_struct %p", (void *)args[sc->offset]); } @@ -544,7 +558,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str /* Find out how large of a buffer we'll need. */ while (strarray[num] != NULL) { - string = get_string(fd, (void*)strarray[num], 0); + string = get_string(pid, (void*)strarray[num], 0); size += strlen(string); free(string); num++; @@ -555,7 +569,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str tmp2 += sprintf(tmp2, " ["); for (i = 0; i < num; i++) { - string = get_string(fd, (void*)strarray[i], 0); + string = get_string(pid, (void*)strarray[i], 0); tmp2 += sprintf(tmp2, " \"%s\"%c", string, (i+1 == num) ? ' ' : ','); free(string); } @@ -585,7 +599,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str tmp = strdup(""); break; } - tmp2 = get_string(fd, (void*)args[sc->offset], retval); + tmp2 = get_string(pid, (void*)args[sc->offset], retval); asprintf(&tmp, "\"%s\"", tmp2); free(tmp2); } @@ -608,7 +622,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Umtx: { struct umtx umtx; - if (get_struct(fd, (void *)args[sc->offset], &umtx, sizeof(umtx)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &umtx, sizeof(umtx)) != -1) asprintf(&tmp, "{0x%lx}", (long)umtx.u_owner); else asprintf(&tmp, "0x%lx", args[sc->offset]); @@ -617,7 +631,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Timespec: { struct timespec ts; - if (get_struct(fd, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) asprintf(&tmp, "{%ld.%09ld}", (long)ts.tv_sec, ts.tv_nsec); else asprintf(&tmp, "0x%lx", args[sc->offset]); @@ -626,7 +640,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Timeval: { struct timeval tv; - if (get_struct(fd, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) asprintf(&tmp, "{%ld.%06ld}", (long)tv.tv_sec, tv.tv_usec); else asprintf(&tmp, "0x%lx", args[sc->offset]); @@ -635,7 +649,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Timeval2: { struct timeval tv[2]; - if (get_struct(fd, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}", (long)tv[0].tv_sec, tv[0].tv_usec, (long)tv[1].tv_sec, tv[1].tv_usec); @@ -646,7 +660,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Itimerval: { struct itimerval itv; - if (get_struct(fd, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}", (long)itv.it_interval.tv_sec, itv.it_interval.tv_usec, @@ -670,7 +684,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str if ((pfd = malloc(bytes)) == NULL) err(1, "Cannot malloc %d bytes for pollfd array", bytes); - if (get_struct(fd, (void *)args[sc->offset], pfd, bytes) != -1) { + if (get_struct(pid, (void *)args[sc->offset], pfd, bytes) != -1) { used = 0; tmpsize = 1 + per_fd * numfds + 2; @@ -709,7 +723,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str if ((fds = malloc(bytes)) == NULL) err(1, "Cannot malloc %d bytes for fd_set array", bytes); - if (get_struct(fd, (void *)args[sc->offset], fds, bytes) != -1) { + if (get_struct(pid, (void *)args[sc->offset], fds, bytes) != -1) { used = 0; tmpsize = 1 + numfds * per_fd + 2; if ((tmp = malloc(tmpsize)) == NULL) @@ -749,7 +763,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str int i, used; sig = args[sc->offset]; - if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, sizeof(ss)) == -1) { asprintf(&tmp, "0x%lx", args[sc->offset]); @@ -853,7 +867,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str } /* yuck: get ss_len */ - if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) err(1, "get_struct %p", (void *)args[sc->offset]); /* @@ -874,7 +888,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str break; } } - if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, ss.ss_len) + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, ss.ss_len) == -1) { err(2, "get_struct %p", (void *)args[sc->offset]); } @@ -913,7 +927,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str char *hand; const char *h; - if (get_struct(fd, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { + if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { asprintf(&hand, "%p", sa.sa_handler); if (sa.sa_handler == SIG_DFL) @@ -956,7 +970,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str bytes = sizeof(struct kevent) * numevents; if ((ke = malloc(bytes)) == NULL) err(1, "Cannot malloc %d bytes for kevent array", bytes); - if (numevents >= 0 && get_struct(fd, (void *)args[sc->offset], ke, bytes) != -1) { + if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset], ke, bytes) != -1) { used = 0; tmpsize = 1 + per_ke * numevents + 2; if ((tmp = malloc(tmpsize)) == NULL) @@ -986,7 +1000,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Stat: { struct stat st; - if (get_struct(fd, (void *)args[sc->offset], &st, sizeof(st)) != -1) { + if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st)) != -1) { char mode[12]; strmode(st.st_mode, mode); asprintf(&tmp, "{mode=%s,inode=%jd,size=%jd,blksize=%ld}", @@ -999,7 +1013,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Rusage: { struct rusage ru; - if (get_struct(fd, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) asprintf(&tmp, "{u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld}", (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, @@ -1011,7 +1025,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str case Rlimit: { struct rlimit rl; - if (get_struct(fd, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) + if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) asprintf(&tmp, "{cur=%ju,max=%ju}", rl.rlim_cur, rl.rlim_max); else |