diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3 index e13c667f8a5b..1d6cb5632ca5 100644 --- a/lib/libc/net/getaddrinfo.3 +++ b/lib/libc/net/getaddrinfo.3 @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 20, 2015 +.Dd October 5, 2015 .Dt GETADDRINFO 3 .Os .Sh NAME @@ -243,15 +243,14 @@ The list can be traversed by following the pointer in each .Li addrinfo structure until a null pointer is encountered. -The three members +Each returned +.Li addrinfo +structure contains three members that are suitable for a call to +.Xr socket 2 : .Fa ai_family , .Fa ai_socktype , and -.Fa ai_protocol -in each returned -.Li addrinfo -structure are suitable for a call to -.Xr socket 2 . +.Fa ai_protocol . For each .Li addrinfo structure in the list, the diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c index 55fdedad42cf..d46d01e58c0a 100644 --- a/usr.bin/truss/main.c +++ b/usr.bin/truss/main.c @@ -94,6 +94,7 @@ main(int ac, char **av) 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 */ diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c index 4452f9f47c7f..74008e402582 100644 --- a/usr.bin/truss/setup.c +++ b/usr.bin/truss/setup.c @@ -341,17 +341,9 @@ enter_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl) 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 @@ enter_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl) 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 @@ exit_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl) } 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; } } diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h index 18dd33f0a822..3e3a1b9a6859 100644 --- a/usr.bin/truss/syscall.h +++ b/usr.bin/truss/syscall.h @@ -55,6 +55,7 @@ struct syscall_args { }; 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 @@ struct syscall { 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 @@ struct linux_socketcall_args { 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 *); diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 6211baec6778..ddb18915e631 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -89,7 +89,7 @@ __FBSDID("$FreeBSD$"); /* * 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, @@ -253,6 +253,8 @@ static struct syscall syscalls[] = { .args = { { Int, 0 }, { Ptr, 1 } } }, { .name = "kldfirstmod", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, + { .name = "modfind", .ret_type = 1, .nargs = 1, + .args = { { Name | IN, 0 } } }, { .name = "nanosleep", .ret_type = 1, .nargs = 1, .args = { { Timespec, 0 } } }, { .name = "select", .ret_type = 1, .nargs = 5, @@ -370,6 +372,7 @@ static struct syscall syscalls[] = { .args = { { Ptr, 0 } } }, { .name = 0 }, }; +static STAILQ_HEAD(, syscall) syscalls; /* Xlat idea taken from strace */ struct xlat { @@ -659,24 +662,49 @@ xlookup_bits(struct xlat *xlat, int val) 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 +1660,6 @@ print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, 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 +1676,7 @@ print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, 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 +1703,7 @@ print_summary(struct trussinfo *trussinfo) 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,