summaryrefslogtreecommitdiffstats
path: root/usr.bin/truss/syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/truss/syscalls.c')
-rw-r--r--usr.bin/truss/syscalls.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index 6211bae..8218b77 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,
@@ -370,6 +370,7 @@ static struct syscall syscalls[] = {
.args = { { Ptr, 0 } } },
{ .name = 0 },
};
+static STAILQ_HEAD(, syscall) syscalls;
/* Xlat idea taken from strace */
struct xlat {
@@ -659,24 +660,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 +1658,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 +1674,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 +1701,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,
OpenPOWER on IntegriCloud