Page MenuHomeFreeBSD

D27636.id80775.diff
No OneTemporary

D27636.id80775.diff

Index: usr.bin/truss/main.c
===================================================================
--- usr.bin/truss/main.c
+++ usr.bin/truss/main.c
@@ -87,7 +87,6 @@
trussinfo->strsize = 32;
trussinfo->curthread = NULL;
LIST_INIT(&trussinfo->proclist);
- init_syscalls();
while ((c = getopt(ac, av, "p:o:facedDs:SH")) != -1) {
switch (c) {
case 'p': /* specified pid */
@@ -201,7 +200,7 @@
eventloop(trussinfo);
if (trussinfo->flags & COUNTONLY)
- print_summary(trussinfo);
+ print_summary(trussinfo, /*free_sc=*/true);
fflush(trussinfo->outfile);
Index: usr.bin/truss/setup.c
===================================================================
--- usr.bin/truss/setup.c
+++ usr.bin/truss/setup.c
@@ -459,12 +459,12 @@
}
sc = get_syscall(t, t->cs.number, narg);
- if (sc->unknown)
+ if (sc->info.unknown)
fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d --\n",
t->proc->abi->type, t->cs.number);
- t->cs.nargs = sc->nargs;
- assert(sc->nargs <= nitems(t->cs.s_args));
+ t->cs.nargs = sc->info.nargs;
+ assert(sc->info.nargs <= nitems(t->cs.s_args));
t->cs.sc = sc;
@@ -476,15 +476,16 @@
* passed in *and* out, however.
*/
#if DEBUG
- fprintf(stderr, "syscall %s(", sc->name);
+ fprintf(stderr, "syscall %d %s(", t->cs.number, sc->kernel_name);
#endif
for (i = 0; i < t->cs.nargs; i++) {
#if DEBUG
- fprintf(stderr, "0x%lx%s", t->cs.args[sc->args[i].offset],
+ fprintf(stderr, "%p%s",
+ (void *)t->cs.args[sc->info.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],
+ if (!(sc->info.args[i].type & OUT)) {
+ t->cs.s_args[i] = print_arg(&sc->info.args[i],
t->cs.args, NULL, info);
}
}
@@ -542,19 +543,19 @@
* 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++) {
+ for (i = 0; i < sc->info.nargs; i++) {
char *temp;
- if (sc->args[i].type & OUT) {
+ if (sc->info.args[i].type & OUT) {
/*
* If an error occurred, then don't bother
* getting the data; it may not be valid.
*/
if (psr.sr_error != 0) {
asprintf(&temp, "0x%lx",
- t->cs.args[sc->args[i].offset]);
+ t->cs.args[sc->info.args[i].offset]);
} else {
- temp = print_arg(&sc->args[i],
+ temp = print_arg(&sc->info.args[i],
t->cs.args, psr.sr_retval, info);
}
t->cs.s_args[i] = temp;
Index: usr.bin/truss/syscall.h
===================================================================
--- usr.bin/truss/syscall.h
+++ usr.bin/truss/syscall.h
@@ -216,26 +216,31 @@
_Static_assert(ARG_MASK > MAX_ARG_TYPE,
"ARG_MASK overlaps with Argtype values");
-struct syscall_args {
+struct syscall_arg {
enum Argtype type;
int offset;
};
+struct syscall_cconv {
+ const char *name; /* Name for lookup calling convention lookup */
+ u_int ret_type; /* 0, 1, or 2 return values */
+ u_int nargs; /* actual number of meaningful arguments */
+ /* Hopefully, no syscalls with > 10 args */
+ struct syscall_arg args[10];
+ bool unknown; /* Unknown system call */
+};
+
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 */
- /* Hopefully, no syscalls with > 10 args */
- struct syscall_args args[10];
+ char *kernel_name;
+ struct syscall_cconv info;
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(struct threadinfo *, u_int, u_int);
-char *print_arg(struct syscall_args *, unsigned long*, register_t *,
+char *print_arg(struct syscall_arg *, unsigned long*, register_t *,
struct trussinfo *);
/*
@@ -278,7 +283,6 @@
char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)];
};
-void init_syscalls(void);
void print_syscall(struct trussinfo *);
void print_syscall_ret(struct trussinfo *, int, register_t *);
-void print_summary(struct trussinfo *trussinfo);
+void print_summary(struct trussinfo *trussinfo, bool free_sc);
Index: usr.bin/truss/syscalls.c
===================================================================
--- usr.bin/truss/syscalls.c
+++ usr.bin/truss/syscalls.c
@@ -47,8 +47,10 @@
#include <sys/ioccom.h>
#include <sys/mman.h>
#include <sys/mount.h>
+#include <sys/poll.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
+#include <sys/sched.h>
#include <sys/socket.h>
#define _WANT_FREEBSD11_STAT
#include <sys/stat.h>
@@ -66,8 +68,6 @@
#define _WANT_KERNEL_ERRNO
#include <errno.h>
#include <fcntl.h>
-#include <poll.h>
-#include <sched.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@@ -85,8 +85,13 @@
/*
* This should probably be in its own file, sorted alphabetically.
+ *
+ * Note: We only scan this table on the initial syscall number to calling
+ * convention lookup, i.e. once each time a new syscall is encountered. This
+ * is unlikely to be a performance issue, but if it is we could sort this array
+ * and use a binary search instead.
*/
-static struct syscall decoded_syscalls[] = {
+static const struct syscall_cconv decoded_syscalls[] = {
/* Native ABI */
{ .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
@@ -702,10 +707,8 @@
{ .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2,
.args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } },
{ .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 },
-
- { .name = 0 },
};
-static STAILQ_HEAD(, syscall) syscalls;
+static STAILQ_HEAD(, syscall) seen_syscalls;
/* Xlat idea taken from strace */
struct xlat {
@@ -965,7 +968,7 @@
* decoding arguments.
*/
static void
-quad_fixup(struct syscall *sc)
+quad_fixup(struct syscall_cconv *sc)
{
int offset, prev;
u_int i;
@@ -1003,20 +1006,6 @@
}
#endif
-void
-init_syscalls(void)
-{
- struct syscall *sc;
-
- STAILQ_INIT(&syscalls);
- for (sc = decoded_syscalls; sc->name != NULL; sc++) {
-#ifndef __LP64__
- quad_fixup(sc);
-#endif
- STAILQ_INSERT_HEAD(&syscalls, sc, entries);
- }
-}
-
static struct syscall *
find_syscall(struct procabi *abi, u_int number)
{
@@ -1031,11 +1020,16 @@
return (NULL);
}
-static void
+static struct syscall *
add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
{
struct extra_syscall *es;
+#ifndef __LP64__
+ /* FIXME: should be based on sycall ABI not truss ABI */
+ quad_fixup(&sc->info);
+#endif
+
if (number < nitems(abi->syscalls)) {
assert(abi->syscalls[number] == NULL);
abi->syscalls[number] = sc;
@@ -1045,6 +1039,9 @@
es->number = number;
STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
}
+
+ STAILQ_INSERT_HEAD(&seen_syscalls, sc, entries);
+ return (sc);
}
/*
@@ -1058,6 +1055,7 @@
const char *name;
char *new_name;
u_int i;
+ bool unknown_name = false;
sc = find_syscall(t->proc->abi, number);
if (sc != NULL)
@@ -1066,14 +1064,17 @@
name = sysdecode_syscallname(t->proc->abi->abi, number);
if (name == NULL) {
asprintf(&new_name, "#%d", number);
- name = new_name;
+ unknown_name = true;
} 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);
+ new_name = strdup(name);
+
+ sc = calloc(1, sizeof(*sc));
+ sc->kernel_name = new_name;
+
+ for (i = 0; i < nitems(decoded_syscalls); i++) {
+ if (strcmp(new_name, decoded_syscalls[i].name) == 0) {
+ sc->info = decoded_syscalls[i];
+ return (add_syscall(t->proc->abi, number, sc));
}
}
@@ -1082,22 +1083,20 @@
fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
nargs);
#endif
-
- sc = calloc(1, sizeof(struct syscall));
- sc->name = name;
- if (new_name != NULL)
- sc->unknown = true;
- sc->ret_type = 1;
- sc->nargs = nargs;
+ /*
+ * Note: info.name is either a constant or points to sc->kernel_name
+ * which be free'd toger with sc on exit.
+ */
+ sc->info.name = new_name;
+ sc->info.unknown = unknown_name;
+ sc->info.ret_type = 1; /* Assume 1 return value. */
+ sc->info.nargs = nargs;
for (i = 0; i < nargs; i++) {
- sc->args[i].offset = i;
+ sc->info.args[i].offset = i;
/* Treat all unknown arguments as LongHex. */
- sc->args[i].type = LongHex;
+ sc->info.args[i].type = LongHex;
}
- STAILQ_INSERT_HEAD(&syscalls, sc, entries);
- add_syscall(t->proc->abi, number, sc);
-
- return (sc);
+ return (add_syscall(t->proc->abi, number, sc));
}
/*
@@ -1713,7 +1712,7 @@
* an array of all of the system call arguments.
*/
char *
-print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
+print_arg(struct syscall_arg *sc, unsigned long *args, register_t *retval,
struct trussinfo *trussinfo)
{
FILE *fp;
@@ -2909,7 +2908,7 @@
t = trussinfo->curthread;
- name = t->cs.sc->name;
+ name = t->cs.sc->kernel_name;
nargs = t->cs.nargs;
s_args = t->cs.s_args;
@@ -2988,24 +2987,31 @@
}
void
-print_summary(struct trussinfo *trussinfo)
+print_summary(struct trussinfo *trussinfo, bool free_sc)
{
struct timespec total = {0, 0};
struct syscall *sc;
+ struct syscall *sc_temp;
int ncall, nerror;
fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
"syscall", "seconds", "calls", "errors");
ncall = nerror = 0;
- STAILQ_FOREACH(sc, &syscalls, entries)
+ STAILQ_FOREACH_SAFE(sc, &seen_syscalls, entries, sc_temp) {
if (sc->ncalls) {
fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
- sc->name, (intmax_t)sc->time.tv_sec,
+ sc->kernel_name, (intmax_t)sc->time.tv_sec,
sc->time.tv_nsec, sc->ncalls, sc->nerror);
timespecadd(&total, &sc->time, &total);
ncall += sc->ncalls;
nerror += sc->nerror;
}
+ if (free_sc) {
+ STAILQ_REMOVE(&seen_syscalls, sc, syscall, entries);
+ free(sc->kernel_name);
+ free(sc);
+ }
+ }
fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
"", "-------------", "-------", "-------");
fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 30, 8:55 AM (13 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17854470
Default Alt Text
D27636.id80775.diff (10 KB)

Event Timeline