Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Jan 2017 21:30:18 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r312084 - stable/11/usr.bin/truss
Message-ID:  <201701132130.v0DLUIun073775@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Fri Jan 13 21:30:18 2017
New Revision: 312084
URL: https://svnweb.freebsd.org/changeset/base/312084

Log:
  MFC 309589: Rework syscall structure lookups.
  
  Avoid always using an O(n^2) loop over known syscall structures with
  strcmp() on each system call.  Instead, use a per-ABI cache indexed by
  the system call number. The first 1024 system calls (which should cover
  all of the normal system calls in currently-supported ABIs) use a flat array
  indexed by the system call number to find system call structure.  For other
  system calls, a linked list of structures storing an integer to structure
  mapping is stored in the ABI.  The linked list isn't very smart, but it
  should only be used by buggy applications invoking unknown system calls.
  
  This also fixes handling of unknown system calls which currently trigger
  a NULL pointer dereference.

Modified:
  stable/11/usr.bin/truss/aarch64-cloudabi64.c
  stable/11/usr.bin/truss/aarch64-freebsd.c
  stable/11/usr.bin/truss/amd64-cloudabi64.c
  stable/11/usr.bin/truss/amd64-freebsd.c
  stable/11/usr.bin/truss/amd64-freebsd32.c
  stable/11/usr.bin/truss/amd64-linux.c
  stable/11/usr.bin/truss/amd64-linux32.c
  stable/11/usr.bin/truss/arm-freebsd.c
  stable/11/usr.bin/truss/i386-freebsd.c
  stable/11/usr.bin/truss/i386-linux.c
  stable/11/usr.bin/truss/mips-freebsd.c
  stable/11/usr.bin/truss/powerpc-freebsd.c
  stable/11/usr.bin/truss/powerpc64-freebsd.c
  stable/11/usr.bin/truss/powerpc64-freebsd32.c
  stable/11/usr.bin/truss/setup.c
  stable/11/usr.bin/truss/sparc64-freebsd.c
  stable/11/usr.bin/truss/syscall.h
  stable/11/usr.bin/truss/syscalls.c
  stable/11/usr.bin/truss/truss.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.bin/truss/aarch64-cloudabi64.c
==============================================================================
--- stable/11/usr.bin/truss/aarch64-cloudabi64.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/aarch64-cloudabi64.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -80,7 +80,9 @@ static struct procabi aarch64_cloudabi64
 	"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);

Modified: stable/11/usr.bin/truss/aarch64-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/aarch64-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/aarch64-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -102,7 +102,9 @@ static struct procabi aarch64_freebsd = 
 	"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);

Modified: stable/11/usr.bin/truss/amd64-cloudabi64.c
==============================================================================
--- stable/11/usr.bin/truss/amd64-cloudabi64.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/amd64-cloudabi64.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -89,7 +89,9 @@ static struct procabi amd64_cloudabi64 =
 	"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);

Modified: stable/11/usr.bin/truss/amd64-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/amd64-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/amd64-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -124,7 +124,9 @@ static struct procabi amd64_freebsd = {
 	"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);

Modified: stable/11/usr.bin/truss/amd64-freebsd32.c
==============================================================================
--- stable/11/usr.bin/truss/amd64-freebsd32.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/amd64-freebsd32.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -120,7 +120,9 @@ static struct procabi amd64_freebsd32 = 
 	"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 @@ static struct procabi amd64_freebsd32_ao
 	"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);

Modified: stable/11/usr.bin/truss/amd64-linux.c
==============================================================================
--- stable/11/usr.bin/truss/amd64-linux.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/amd64-linux.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -99,7 +99,9 @@ static struct procabi amd64_linux = {
 	"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);

Modified: stable/11/usr.bin/truss/amd64-linux32.c
==============================================================================
--- stable/11/usr.bin/truss/amd64-linux32.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/amd64-linux32.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -109,7 +109,9 @@ static struct procabi amd64_linux32 = {
 	"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);

Modified: stable/11/usr.bin/truss/arm-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/arm-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/arm-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -131,7 +131,9 @@ static struct procabi arm_freebsd = {
 	"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);

Modified: stable/11/usr.bin/truss/i386-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/i386-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/i386-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -113,7 +113,9 @@ static struct procabi i386_freebsd = {
 	"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 @@ static struct procabi i386_freebsd_aout 
 	"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);

Modified: stable/11/usr.bin/truss/i386-linux.c
==============================================================================
--- stable/11/usr.bin/truss/i386-linux.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/i386-linux.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -106,7 +106,9 @@ static struct procabi i386_linux = {
 	"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);

Modified: stable/11/usr.bin/truss/mips-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/mips-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/mips-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -134,7 +134,9 @@ static struct procabi mips_freebsd = {
 #endif
 	SYSDECODE_ABI_FREEBSD,
 	mips_fetch_args,
-	mips_fetch_retval
+	mips_fetch_retval,
+	STAILQ_HEAD_INITIALIZER(mips_freebsd.extra_syscalls),
+	{ NULL }
 };
 
 PROCABI(mips_freebsd);

Modified: stable/11/usr.bin/truss/powerpc-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/powerpc-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/powerpc-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -115,7 +115,9 @@ static struct procabi powerpc_freebsd = 
 	"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);

Modified: stable/11/usr.bin/truss/powerpc64-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/powerpc64-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/powerpc64-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -111,7 +111,9 @@ static struct procabi powerpc64_freebsd 
 	"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);

Modified: stable/11/usr.bin/truss/powerpc64-freebsd32.c
==============================================================================
--- stable/11/usr.bin/truss/powerpc64-freebsd32.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/powerpc64-freebsd32.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -120,7 +120,9 @@ static struct procabi powerpc64_freebsd3
 	"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);

Modified: stable/11/usr.bin/truss/setup.c
==============================================================================
--- stable/11/usr.bin/truss/setup.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/setup.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -344,7 +344,7 @@ alloc_syscall(struct threadinfo *t, stru
 
 	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 @@ enter_syscall(struct trussinfo *info, st
 		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 @@ enter_syscall(struct trussinfo *info, st
 	 * 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);
 }

Modified: stable/11/usr.bin/truss/sparc64-freebsd.c
==============================================================================
--- stable/11/usr.bin/truss/sparc64-freebsd.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/sparc64-freebsd.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -118,7 +118,9 @@ static struct procabi sparc64_freebsd = 
 	"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);

Modified: stable/11/usr.bin/truss/syscall.h
==============================================================================
--- stable/11/usr.bin/truss/syscall.h	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/syscall.h	Fri Jan 13 21:30:18 2017	(r312084)
@@ -72,9 +72,10 @@ struct syscall {
 	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 *);
 
 /*

Modified: stable/11/usr.bin/truss/syscalls.c
==============================================================================
--- stable/11/usr.bin/truss/syscalls.c	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/syscalls.c	Fri Jan 13 21:30:18 2017	(r312084)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include <assert.h>
 #include <ctype.h>
 #include <err.h>
 #include <fcntl.h>
@@ -819,21 +820,66 @@ init_syscalls(void)
 	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;
+	const char *name;
+	char *new_name;
+	u_int i;
 
-	if (name == NULL)
-		return (NULL);
-	STAILQ_FOREACH(sc, &syscalls, entries)
-		if (strcmp(name, sc->name) == 0)
+	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 @@ get_syscall(const char *name, int nargs)
 #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 @@ get_syscall(const char *name, int nargs)
 		sc->args[i].type = LongHex;
 	}
 	STAILQ_INSERT_HEAD(&syscalls, sc, entries);
+	add_syscall(t->proc->abi, number, sc);
 
 	return (sc);
 }
@@ -1866,7 +1915,7 @@ print_syscall(struct trussinfo *trussinf
 
 	t = trussinfo->curthread;
 
-	name = t->cs.name;
+	name = t->cs.sc->name;
 	nargs = t->cs.nargs;
 	s_args = t->cs.s_args;
 

Modified: stable/11/usr.bin/truss/truss.h
==============================================================================
--- stable/11/usr.bin/truss/truss.h	Fri Jan 13 19:41:02 2017	(r312083)
+++ stable/11/usr.bin/truss/truss.h	Fri Jan 13 21:30:18 2017	(r312084)
@@ -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 procabi {
  */
 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 */
 };
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201701132130.v0DLUIun073775>