Index: usr.bin/truss/aarch64-cloudabi64.c =================================================================== --- usr.bin/truss/aarch64-cloudabi64.c +++ usr.bin/truss/aarch64-cloudabi64.c @@ -80,7 +80,9 @@ "CloudABI ELF64", SYSDECODE_ABI_CLOUDABI64, aarch64_cloudabi64_fetch_args, - aarch64_cloudabi64_fetch_retval + aarch64_cloudabi64_fetch_retval, + STAILQ_HEAD_INITIALIZER(aarch64_cloudabi64.extra_syscalls), + { NULL } }; PROCABI(aarch64_cloudabi64); Index: usr.bin/truss/aarch64-freebsd.c =================================================================== --- usr.bin/truss/aarch64-freebsd.c +++ usr.bin/truss/aarch64-freebsd.c @@ -102,7 +102,9 @@ "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, aarch64_fetch_args, - aarch64_fetch_retval + aarch64_fetch_retval, + STAILQ_HEAD_INITIALIZER(aarch64_freebsd.extra_syscalls), + { NULL } }; PROCABI(aarch64_freebsd); Index: usr.bin/truss/amd64-cloudabi64.c =================================================================== --- usr.bin/truss/amd64-cloudabi64.c +++ usr.bin/truss/amd64-cloudabi64.c @@ -89,7 +89,9 @@ "CloudABI ELF64", SYSDECODE_ABI_CLOUDABI64, amd64_cloudabi64_fetch_args, - amd64_cloudabi64_fetch_retval + amd64_cloudabi64_fetch_retval, + STAILQ_HEAD_INITIALIZER(amd64_cloudabi64.extra_syscalls), + { NULL } }; PROCABI(amd64_cloudabi64); Index: usr.bin/truss/amd64-freebsd.c =================================================================== --- usr.bin/truss/amd64-freebsd.c +++ usr.bin/truss/amd64-freebsd.c @@ -124,7 +124,9 @@ "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, amd64_fetch_args, - amd64_fetch_retval + amd64_fetch_retval, + STAILQ_HEAD_INITIALIZER(amd64_freebsd.extra_syscalls), + { NULL } }; PROCABI(amd64_freebsd); Index: usr.bin/truss/amd64-freebsd32.c =================================================================== --- usr.bin/truss/amd64-freebsd32.c +++ usr.bin/truss/amd64-freebsd32.c @@ -120,7 +120,9 @@ "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD32, amd64_freebsd32_fetch_args, - amd64_freebsd32_fetch_retval + amd64_freebsd32_fetch_retval, + STAILQ_HEAD_INITIALIZER(amd64_freebsd32.extra_syscalls), + { NULL } }; PROCABI(amd64_freebsd32); @@ -129,7 +131,9 @@ "FreeBSD a.out", SYSDECODE_ABI_FREEBSD32, amd64_freebsd32_fetch_args, - amd64_freebsd32_fetch_retval + amd64_freebsd32_fetch_retval, + STAILQ_HEAD_INITIALIZER(amd64_freebsd32.extra_syscalls), + { NULL } }; PROCABI(amd64_freebsd32_aout); Index: usr.bin/truss/amd64-linux.c =================================================================== --- usr.bin/truss/amd64-linux.c +++ usr.bin/truss/amd64-linux.c @@ -99,7 +99,9 @@ "Linux ELF64", SYSDECODE_ABI_LINUX, amd64_linux_fetch_args, - amd64_linux_fetch_retval + amd64_linux_fetch_retval, + STAILQ_HEAD_INITIALIZER(amd64_linux.extra_syscalls), + { NULL } }; PROCABI(amd64_linux); Index: usr.bin/truss/amd64-linux32.c =================================================================== --- usr.bin/truss/amd64-linux32.c +++ usr.bin/truss/amd64-linux32.c @@ -109,7 +109,9 @@ "Linux ELF32", SYSDECODE_ABI_LINUX32, amd64_linux32_fetch_args, - amd64_linux32_fetch_retval + amd64_linux32_fetch_retval, + STAILQ_HEAD_INITIALIZER(amd64_linux32.extra_syscalls), + { NULL } }; PROCABI(amd64_linux32); Index: usr.bin/truss/arm-freebsd.c =================================================================== --- usr.bin/truss/arm-freebsd.c +++ usr.bin/truss/arm-freebsd.c @@ -131,7 +131,9 @@ "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD, arm_fetch_args, - arm_fetch_retval + arm_fetch_retval, + STAILQ_HEAD_INITIALIZER(arm_freebsd.extra_syscalls), + { NULL } }; PROCABI(arm_freebsd); Index: usr.bin/truss/i386-freebsd.c =================================================================== --- usr.bin/truss/i386-freebsd.c +++ usr.bin/truss/i386-freebsd.c @@ -113,7 +113,9 @@ "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD, i386_fetch_args, - i386_fetch_retval + i386_fetch_retval, + STAILQ_HEAD_INITIALIZER(i386_freebsd.extra_syscalls), + { NULL } }; PROCABI(i386_freebsd); @@ -122,7 +124,9 @@ "FreeBSD a.out", SYSDECODE_ABI_FREEBSD, i386_fetch_args, - i386_fetch_retval + i386_fetch_retval, + STAILQ_HEAD_INITIALIZER(i386_freebsd_aout.extra_syscalls), + { NULL } }; PROCABI(i386_freebsd_aout); Index: usr.bin/truss/i386-linux.c =================================================================== --- usr.bin/truss/i386-linux.c +++ usr.bin/truss/i386-linux.c @@ -106,7 +106,9 @@ "Linux ELF", SYSDECODE_ABI_LINUX, i386_linux_fetch_args, - i386_linux_fetch_retval + i386_linux_fetch_retval, + STAILQ_HEAD_INITIALIZER(i386_linux.extra_syscalls), + { NULL } }; PROCABI(i386_linux); Index: usr.bin/truss/mips-freebsd.c =================================================================== --- usr.bin/truss/mips-freebsd.c +++ usr.bin/truss/mips-freebsd.c @@ -134,7 +134,9 @@ #endif SYSDECODE_ABI_FREEBSD, mips_fetch_args, - mips_fetch_retval + mips_fetch_retval, + STAILQ_HEAD_INITIALIZER(mips_freebsd.extra_syscalls), + { NULL } }; PROCABI(mips_freebsd); Index: usr.bin/truss/powerpc-freebsd.c =================================================================== --- usr.bin/truss/powerpc-freebsd.c +++ usr.bin/truss/powerpc-freebsd.c @@ -115,7 +115,9 @@ "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD, powerpc_fetch_args, - powerpc_fetch_retval + powerpc_fetch_retval, + STAILQ_HEAD_INITIALIZER(powerpc_freebsd.extra_syscalls), + { NULL } }; PROCABI(powerpc_freebsd); Index: usr.bin/truss/powerpc64-freebsd.c =================================================================== --- usr.bin/truss/powerpc64-freebsd.c +++ usr.bin/truss/powerpc64-freebsd.c @@ -111,7 +111,9 @@ "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, powerpc64_fetch_args, - powerpc64_fetch_retval + powerpc64_fetch_retval, + STAILQ_HEAD_INITIALIZER(powerpc64_freebsd.extra_syscalls), + { NULL } }; PROCABI(powerpc64_freebsd); Index: usr.bin/truss/powerpc64-freebsd32.c =================================================================== --- usr.bin/truss/powerpc64-freebsd32.c +++ usr.bin/truss/powerpc64-freebsd32.c @@ -120,7 +120,9 @@ "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD32, powerpc64_freebsd32_fetch_args, - powerpc64_freebsd32_fetch_retval + powerpc64_freebsd32_fetch_retval, + STAILQ_HEAD_INITIALIZER(powerpc64_freebsd32.extra_syscalls), + { NULL } }; PROCABI(powerpc64_freebsd32); Index: usr.bin/truss/setup.c =================================================================== --- usr.bin/truss/setup.c +++ usr.bin/truss/setup.c @@ -344,7 +344,7 @@ assert(t->in_syscall == 0); assert(t->cs.number == 0); - assert(t->cs.name == NULL); + assert(t->cs.sc == NULL); assert(t->cs.nargs == 0); for (i = 0; i < nitems(t->cs.s_args); i++) assert(t->cs.s_args[i] == NULL); @@ -378,12 +378,11 @@ return; } - t->cs.name = sysdecode_syscallname(t->proc->abi->abi, t->cs.number); - if (t->cs.name == NULL) + sc = get_syscall(t, t->cs.number, narg); + if (sc->unknown) fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d --\n", t->proc->abi->type, t->cs.number); - sc = get_syscall(t->cs.name, narg); t->cs.nargs = sc->nargs; assert(sc->nargs <= nitems(t->cs.s_args)); @@ -396,25 +395,22 @@ * now. This doesn't currently support arguments that are * passed in *and* out, however. */ - if (t->cs.name != NULL) { #if DEBUG - fprintf(stderr, "syscall %s(", t->cs.name); + fprintf(stderr, "syscall %s(", sc->name); #endif - for (i = 0; i < t->cs.nargs; i++) { + for (i = 0; i < t->cs.nargs; i++) { #if DEBUG - fprintf(stderr, "0x%lx%s", sc ? - t->cs.args[sc->args[i].offset] : t->cs.args[i], - i < (t->cs.nargs - 1) ? "," : ""); + fprintf(stderr, "0x%lx%s", t->cs.args[sc->args[i].offset], + i < (t->cs.nargs - 1) ? "," : ""); #endif - if (!(sc->args[i].type & OUT)) { - t->cs.s_args[i] = print_arg(&sc->args[i], - t->cs.args, 0, info); - } + if (!(sc->args[i].type & OUT)) { + t->cs.s_args[i] = print_arg(&sc->args[i], + t->cs.args, 0, info); } + } #if DEBUG - fprintf(stderr, ")\n"); + fprintf(stderr, ")\n"); #endif - } clock_gettime(CLOCK_REALTIME, &t->before); } Index: usr.bin/truss/sparc64-freebsd.c =================================================================== --- usr.bin/truss/sparc64-freebsd.c +++ usr.bin/truss/sparc64-freebsd.c @@ -118,7 +118,9 @@ "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, sparc64_fetch_args, - sparc64_fetch_retval + sparc64_fetch_retval, + STAILQ_HEAD_INITIALIZER(sparc64_freebsd.extra_syscalls), + { NULL } }; PROCABI(sparc64_freebsd); Index: usr.bin/truss/syscall.h =================================================================== --- usr.bin/truss/syscall.h +++ usr.bin/truss/syscall.h @@ -72,9 +72,10 @@ struct timespec time; /* Time spent for this call */ int ncalls; /* Number of calls */ int nerror; /* Number of calls that returned with error */ + bool unknown; /* Unknown system call */ }; -struct syscall *get_syscall(const char *, int nargs); +struct syscall *get_syscall(struct threadinfo *, u_int, u_int); char *print_arg(struct syscall_args *, unsigned long*, long *, struct trussinfo *); /* Index: usr.bin/truss/syscalls.c =================================================================== --- usr.bin/truss/syscalls.c +++ usr.bin/truss/syscalls.c @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -819,21 +820,66 @@ for (sc = decoded_syscalls; sc->name != NULL; sc++) STAILQ_INSERT_HEAD(&syscalls, sc, entries); } + +static struct syscall * +find_syscall(struct procabi *abi, u_int number) +{ + struct extra_syscall *es; + + if (number < nitems(abi->syscalls)) + return (abi->syscalls[number]); + STAILQ_FOREACH(es, &abi->extra_syscalls, entries) { + if (es->number == number) + return (es->sc); + } + return (NULL); +} + +static void +add_syscall(struct procabi *abi, u_int number, struct syscall *sc) +{ + struct extra_syscall *es; + + if (number < nitems(abi->syscalls)) { + assert(abi->syscalls[number] == NULL); + abi->syscalls[number] = sc; + } else { + es = malloc(sizeof(*es)); + es->sc = sc; + es->number = number; + STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, 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, int nargs) +get_syscall(struct threadinfo *t, u_int number, u_int nargs) { struct syscall *sc; - int i; - - if (name == NULL) - return (NULL); - STAILQ_FOREACH(sc, &syscalls, entries) - if (strcmp(name, sc->name) == 0) + const char *name; + char *new_name; + u_int i; + + sc = find_syscall(t->proc->abi, number); + if (sc != NULL) + return (sc); + + name = sysdecode_syscallname(t->proc->abi->abi, number); + if (name == NULL) { + asprintf(&new_name, "#%d", number); + name = new_name; + } else + new_name = NULL; + STAILQ_FOREACH(sc, &syscalls, entries) { + if (strcmp(name, sc->name) == 0) { + add_syscall(t->proc->abi, number, sc); + free(new_name); return (sc); + } + } /* It is unknown. Add it into the list. */ #if DEBUG @@ -842,7 +888,9 @@ #endif sc = calloc(1, sizeof(struct syscall)); - sc->name = strdup(name); + sc->name = name; + if (new_name != NULL) + sc->unknown = true; sc->ret_type = 1; sc->nargs = nargs; for (i = 0; i < nargs; i++) { @@ -851,6 +899,7 @@ sc->args[i].type = LongHex; } STAILQ_INSERT_HEAD(&syscalls, sc, entries); + add_syscall(t->proc->abi, number, sc); return (sc); } @@ -1866,7 +1915,7 @@ t = trussinfo->curthread; - name = t->cs.name; + name = t->cs.sc->name; nargs = t->cs.nargs; s_args = t->cs.s_args; Index: usr.bin/truss/truss.h =================================================================== --- usr.bin/truss/truss.h +++ usr.bin/truss/truss.h @@ -38,13 +38,29 @@ #define DISPLAYTIDS 0x00000080 struct procinfo; +struct syscall; struct trussinfo; +/* + * The lookup of normal system calls are optimized by using a fixed + * array for the first 1024 system calls that can be indexed directly. + * Unknown system calls with other IDs are stored in a linked list. + */ +#define SYSCALL_NORMAL_COUNT 1024 + +struct extra_syscall { + STAILQ_ENTRY(extra_syscall) entries; + struct syscall *sc; + u_int number; +}; + struct procabi { const char *type; enum sysdecode_abi abi; int (*fetch_args)(struct trussinfo *, u_int); int (*fetch_retval)(struct trussinfo *, long *, int *); + STAILQ_HEAD(, extra_syscall) extra_syscalls; + struct syscall *syscalls[SYSCALL_NORMAL_COUNT]; }; #define PROCABI(abi) DATA_SET(procabi, abi) @@ -64,10 +80,9 @@ */ struct current_syscall { struct syscall *sc; - const char *name; - int number; - unsigned long args[10]; + unsigned int number; unsigned int nargs; + unsigned long args[10]; char *s_args[10]; /* the printable arguments */ };