Index: head/usr.bin/truss/main.c =================================================================== --- head/usr.bin/truss/main.c +++ head/usr.bin/truss/main.c @@ -94,6 +94,7 @@ trussinfo->strsize = 32; trussinfo->curthread = NULL; LIST_INIT(&trussinfo->proclist); + init_syscalls(); while ((c = getopt(ac, av, "p:o:facedDs:S")) != -1) { switch (c) { case 'p': /* specified pid */ Index: head/usr.bin/truss/setup.c =================================================================== --- head/usr.bin/truss/setup.c +++ head/usr.bin/truss/setup.c @@ -341,17 +341,9 @@ fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d --\n", t->proc->abi->type, t->cs.number); - sc = get_syscall(t->cs.name); - if (sc) { - t->cs.nargs = sc->nargs; - assert(sc->nargs <= nitems(t->cs.s_args)); - } else { -#if DEBUG - fprintf(stderr, "unknown syscall %s -- setting " - "args to %d\n", t->cs.name, t->cs.nargs); -#endif - t->cs.nargs = narg; - } + sc = get_syscall(t->cs.name, narg); + t->cs.nargs = sc->nargs; + assert(sc->nargs <= nitems(t->cs.s_args)); t->cs.sc = sc; @@ -372,7 +364,7 @@ t->cs.args[sc->args[i].offset] : t->cs.args[i], i < (t->cs.nargs - 1) ? "," : ""); #endif - if (sc && !(sc->args[i].type & OUT)) { + if (!(sc->args[i].type & OUT)) { t->cs.s_args[i] = print_arg(&sc->args[i], t->cs.args, 0, info); } @@ -407,31 +399,26 @@ } sc = t->cs.sc; - if (sc == NULL) { - for (i = 0; i < t->cs.nargs; i++) - asprintf(&t->cs.s_args[i], "0x%lx", t->cs.args[i]); - } else { - /* - * Here, we only look for arguments that have OUT masked in -- - * otherwise, they were handled in enter_syscall(). - */ - for (i = 0; i < sc->nargs; i++) { - char *temp; + /* + * Here, we only look for arguments that have OUT masked in -- + * otherwise, they were handled in enter_syscall(). + */ + for (i = 0; i < sc->nargs; i++) { + char *temp; - if (sc->args[i].type & OUT) { - /* - * If an error occurred, then don't bother - * getting the data; it may not be valid. - */ - if (errorp) { - asprintf(&temp, "0x%lx", - t->cs.args[sc->args[i].offset]); - } else { - temp = print_arg(&sc->args[i], - t->cs.args, retval, info); - } - t->cs.s_args[i] = temp; + if (sc->args[i].type & OUT) { + /* + * If an error occurred, then don't bother + * getting the data; it may not be valid. + */ + if (errorp) { + asprintf(&temp, "0x%lx", + t->cs.args[sc->args[i].offset]); + } else { + temp = print_arg(&sc->args[i], + t->cs.args, retval, info); } + t->cs.s_args[i] = temp; } } Index: head/usr.bin/truss/syscall.h =================================================================== --- head/usr.bin/truss/syscall.h +++ head/usr.bin/truss/syscall.h @@ -55,6 +55,7 @@ }; struct syscall { + STAILQ_ENTRY(syscall) entries; const char *name; u_int ret_type; /* 0, 1, or 2 return values */ u_int nargs; /* actual number of meaningful arguments */ @@ -65,7 +66,7 @@ int nerror; /* Number of calls that returned with error */ }; -struct syscall *get_syscall(const char*); +struct syscall *get_syscall(const char *, int nargs); char *print_arg(struct syscall_args *, unsigned long*, long *, struct trussinfo *); /* @@ -108,6 +109,7 @@ char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)]; }; +void init_syscalls(void); void print_syscall(struct trussinfo *, const char *, int, char **); void print_syscall_ret(struct trussinfo *, const char *, int, char **, int, long *, struct syscall *); Index: head/usr.bin/truss/syscalls.c =================================================================== --- head/usr.bin/truss/syscalls.c +++ head/usr.bin/truss/syscalls.c @@ -89,7 +89,7 @@ /* * This should probably be in its own file, sorted alphabetically. */ -static struct syscall syscalls[] = { +static struct syscall decoded_syscalls[] = { { .name = "fcntl", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } }, { .name = "rfork", .ret_type = 1, .nargs = 1, @@ -370,6 +370,7 @@ .args = { { Ptr, 0 } } }, { .name = 0 }, }; +static STAILQ_HEAD(, syscall) syscalls; /* Xlat idea taken from strace */ struct xlat { @@ -659,24 +660,49 @@ return (str); } +void +init_syscalls(void) +{ + struct syscall *sc; + + STAILQ_INIT(&syscalls); + for (sc = decoded_syscalls; sc->name != NULL; sc++) + STAILQ_INSERT_HEAD(&syscalls, sc, entries); +} /* * If/when the list gets big, it might be desirable to do it * as a hash table or binary search. */ struct syscall * -get_syscall(const char *name) +get_syscall(const char *name, int nargs) { struct syscall *sc; + int i; - sc = syscalls; if (name == NULL) return (NULL); - while (sc->name) { + STAILQ_FOREACH(sc, &syscalls, entries) if (strcmp(name, sc->name) == 0) return (sc); - sc++; + + /* It is unknown. Add it into the list. */ +#if DEBUG + fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name, + nargs); +#endif + + sc = calloc(1, sizeof(struct syscall)); + sc->name = strdup(name); + sc->ret_type = 1; + sc->nargs = nargs; + for (i = 0; i < nargs; i++) { + sc->args[i].offset = i; + /* Treat all unknown arguments as LongHex. */ + sc->args[i].type = LongHex; } - return (NULL); + STAILQ_INSERT_HEAD(&syscalls, sc, entries); + + return (sc); } /* @@ -1632,8 +1658,6 @@ struct timespec timediff; if (trussinfo->flags & COUNTONLY) { - if (!sc) - return; clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); timespecsubt(&trussinfo->curthread->after, &trussinfo->curthread->before, &timediff); @@ -1650,7 +1674,7 @@ fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0], strerror(retval[0])); #ifndef __LP64__ - else if (sc != NULL && sc->ret_type == 2) { + else if (sc->ret_type == 2) { off_t off; #if _BYTE_ORDER == _LITTLE_ENDIAN @@ -1677,7 +1701,7 @@ fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n", "syscall", "seconds", "calls", "errors"); ncall = nerror = 0; - for (sc = syscalls; sc->name != NULL; sc++) + STAILQ_FOREACH(sc, &syscalls, entries) if (sc->ncalls) { fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", sc->name, (intmax_t)sc->time.tv_sec,