Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Oct 2015 21:58:39 +0000 (UTC)
From:      Bryan Drewery <bdrewery@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r288957 - in head: lib/libc/sys usr.bin/kdump usr.bin/truss
Message-ID:  <201510062158.t96LwdSr050630@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bdrewery
Date: Tue Oct  6 21:58:38 2015
New Revision: 288957
URL: https://svnweb.freebsd.org/changeset/base/288957

Log:
  truss: Add support for utrace(2).
  
  This uses the kdump(1) utrace support code directly until a common library
  is created.
  
  This allows malloc(3) tracing with MALLOC_CONF=utrace:true and rtld tracing
  with LD_UTRACE=1.  Unknown utrace(2) data is just printed as hex.
  
  PR:		43819 [inspired by]
  Reviewed by:	jhb
  MFC after:	2 weeks
  Relnotes:	yes
  Differential Revision:	https://reviews.freebsd.org/D3819

Added:
  head/usr.bin/kdump/utrace.c   (contents, props changed)
Modified:
  head/lib/libc/sys/utrace.2
  head/usr.bin/kdump/Makefile
  head/usr.bin/kdump/kdump.c
  head/usr.bin/truss/Makefile
  head/usr.bin/truss/syscall.h
  head/usr.bin/truss/syscalls.c
  head/usr.bin/truss/truss.1

Modified: head/lib/libc/sys/utrace.2
==============================================================================
--- head/lib/libc/sys/utrace.2	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/lib/libc/sys/utrace.2	Tue Oct  6 21:58:38 2015	(r288957)
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 1, 2014
+.Dd October 5, 2015
 .Dt UTRACE 2
 .Os
 .Sh NAME
@@ -70,7 +70,8 @@ support
 .Sh SEE ALSO
 .Xr kdump 1 ,
 .Xr ktrace 1 ,
-.Xr ktrace 2
+.Xr ktrace 2 ,
+.Xr truss 1
 .Sh HISTORY
 The
 .Fn utrace

Modified: head/usr.bin/kdump/Makefile
==============================================================================
--- head/usr.bin/kdump/Makefile	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/usr.bin/kdump/Makefile	Tue Oct  6 21:58:38 2015	(r288957)
@@ -6,7 +6,7 @@
 .PATH: ${.CURDIR}/../ktrace
 
 PROG=		kdump
-SRCS=		kdump_subr.c kdump.c ioctl.c subr.c
+SRCS=		kdump_subr.c kdump.c ioctl.c subr.c utrace.c
 DPSRCS=		kdump_subr.h
 CFLAGS+=	-I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I.
 

Modified: head/usr.bin/kdump/kdump.c
==============================================================================
--- head/usr.bin/kdump/kdump.c	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/usr.bin/kdump/kdump.c	Tue Oct  6 21:58:38 2015	(r288957)
@@ -67,7 +67,6 @@ extern int errno;
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <ctype.h>
-#include <dlfcn.h>
 #include <err.h>
 #include <grp.h>
 #include <inttypes.h>
@@ -117,6 +116,7 @@ void ktrfaultend(struct ktr_faultend *);
 void limitfd(int fd);
 void usage(void);
 void ioctlname(unsigned long, int);
+int kdump_print_utrace(FILE *, void *, size_t, int);
 
 #define	TIMESTAMP_NONE		0x0
 #define	TIMESTAMP_ABSOLUTE	0x1
@@ -1536,151 +1536,13 @@ ktrcsw(struct ktr_csw *cs)
 	    cs->user ? "user" : "kernel", cs->wmesg);
 }
 
-#define	UTRACE_DLOPEN_START		1
-#define	UTRACE_DLOPEN_STOP		2
-#define	UTRACE_DLCLOSE_START		3
-#define	UTRACE_DLCLOSE_STOP		4
-#define	UTRACE_LOAD_OBJECT		5
-#define	UTRACE_UNLOAD_OBJECT		6
-#define	UTRACE_ADD_RUNDEP		7
-#define	UTRACE_PRELOAD_FINISHED		8
-#define	UTRACE_INIT_CALL		9
-#define	UTRACE_FINI_CALL		10
-#define	UTRACE_DLSYM_START		11
-#define	UTRACE_DLSYM_STOP		12
-
-struct utrace_rtld {
-	char sig[4];				/* 'RTLD' */
-	int event;
-	void *handle;
-	void *mapbase;
-	size_t mapsize;
-	int refcnt;
-	char name[MAXPATHLEN];
-};
-
-void
-ktruser_rtld(int len, void *p)
-{
-	struct utrace_rtld *ut = p;
-	unsigned char *cp;
-	void *parent;
-	int mode;
-
-	switch (ut->event) {
-	case UTRACE_DLOPEN_START:
-		mode = ut->refcnt;
-		printf("dlopen(%s, ", ut->name);
-		switch (mode & RTLD_MODEMASK) {
-		case RTLD_NOW:
-			printf("RTLD_NOW");
-			break;
-		case RTLD_LAZY:
-			printf("RTLD_LAZY");
-			break;
-		default:
-			printf("%#x", mode & RTLD_MODEMASK);
-		}
-		if (mode & RTLD_GLOBAL)
-			printf(" | RTLD_GLOBAL");
-		if (mode & RTLD_TRACE)
-			printf(" | RTLD_TRACE");
-		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
-			printf(" | %#x", mode &
-			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
-		printf(")\n");
-		break;
-	case UTRACE_DLOPEN_STOP:
-		printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
-		    ut->refcnt);
-		break;
-	case UTRACE_DLCLOSE_START:
-		printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
-		    ut->refcnt);
-		break;
-	case UTRACE_DLCLOSE_STOP:
-		printf("dlclose(%p) finished\n", ut->handle);
-		break;
-	case UTRACE_LOAD_OBJECT:
-		printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
-		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
-		    ut->name);
-		break;
-	case UTRACE_UNLOAD_OBJECT:
-		printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
-		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
-		    ut->name);
-		break;
-	case UTRACE_ADD_RUNDEP:
-		parent = ut->mapbase;
-		printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
-		    ut->handle, ut->name, ut->refcnt);
-		break;
-	case UTRACE_PRELOAD_FINISHED:
-		printf("RTLD: LD_PRELOAD finished\n");
-		break;
-	case UTRACE_INIT_CALL:
-		printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
-		    ut->name);
-		break;
-	case UTRACE_FINI_CALL:
-		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
-		    ut->name);
-		break;
-	case UTRACE_DLSYM_START:
-		printf("RTLD: dlsym(%p, %s)\n", ut->handle, ut->name);
-		break;
-	case UTRACE_DLSYM_STOP:
-		printf("RTLD: %p = dlsym(%p, %s)\n", ut->mapbase, ut->handle,
-		    ut->name);
-		break;
-	default:
-		cp = p;
-		cp += 4;
-		len -= 4;
-		printf("RTLD: %d ", len);
-		while (len--)
-			if (decimal)
-				printf(" %d", *cp++);
-			else
-				printf(" %02x", *cp++);
-		printf("\n");
-	}
-}
-
-struct utrace_malloc {
-	void *p;
-	size_t s;
-	void *r;
-};
-
-void
-ktruser_malloc(void *p)
-{
-	struct utrace_malloc *ut = p;
-
-	if (ut->p == (void *)(intptr_t)(-1))
-		printf("malloc_init()\n");
-	else if (ut->s == 0)
-		printf("free(%p)\n", ut->p);
-	else if (ut->p == NULL)
-		printf("%p = malloc(%zu)\n", ut->r, ut->s);
-	else
-		printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
-}
-
 void
 ktruser(int len, void *p)
 {
 	unsigned char *cp;
 
-	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
-		ktruser_rtld(len, p);
-		return;
-	}
-
-	if (len == sizeof(struct utrace_malloc)) {
-		ktruser_malloc(p);
+	if (kdump_print_utrace(stdout, p, len, decimal)) {
+		printf("\n");
 		return;
 	}
 

Added: head/usr.bin/kdump/utrace.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.bin/kdump/utrace.c	Tue Oct  6 21:58:38 2015	(r288957)
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <strings.h>
+
+int kdump_print_utrace(FILE *, void *, size_t, int);
+
+#define	UTRACE_DLOPEN_START		1
+#define	UTRACE_DLOPEN_STOP		2
+#define	UTRACE_DLCLOSE_START		3
+#define	UTRACE_DLCLOSE_STOP		4
+#define	UTRACE_LOAD_OBJECT		5
+#define	UTRACE_UNLOAD_OBJECT		6
+#define	UTRACE_ADD_RUNDEP		7
+#define	UTRACE_PRELOAD_FINISHED		8
+#define	UTRACE_INIT_CALL		9
+#define	UTRACE_FINI_CALL		10
+#define	UTRACE_DLSYM_START		11
+#define	UTRACE_DLSYM_STOP		12
+
+struct utrace_rtld {
+	char sig[4];				/* 'RTLD' */
+	int event;
+	void *handle;
+	void *mapbase;
+	size_t mapsize;
+	int refcnt;
+	char name[MAXPATHLEN];
+};
+
+static void
+print_utrace_rtld(FILE *fp, void *p, size_t len, int decimal)
+{
+	struct utrace_rtld *ut = p;
+	unsigned char *cp;
+	void *parent;
+	int mode;
+
+	switch (ut->event) {
+	case UTRACE_DLOPEN_START:
+		mode = ut->refcnt;
+		fprintf(fp, "dlopen(%s, ", ut->name);
+		switch (mode & RTLD_MODEMASK) {
+		case RTLD_NOW:
+			fprintf(fp, "RTLD_NOW");
+			break;
+		case RTLD_LAZY:
+			fprintf(fp, "RTLD_LAZY");
+			break;
+		default:
+			fprintf(fp, "%#x", mode & RTLD_MODEMASK);
+		}
+		if (mode & RTLD_GLOBAL)
+			fprintf(fp, " | RTLD_GLOBAL");
+		if (mode & RTLD_TRACE)
+			fprintf(fp, " | RTLD_TRACE");
+		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
+			fprintf(fp, " | %#x", mode &
+			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
+		fprintf(fp, ")");
+		break;
+	case UTRACE_DLOPEN_STOP:
+		fprintf(fp, "%p = dlopen(%s) ref %d", ut->handle, ut->name,
+		    ut->refcnt);
+		break;
+	case UTRACE_DLCLOSE_START:
+		fprintf(fp, "dlclose(%p) (%s, %d)", ut->handle, ut->name,
+		    ut->refcnt);
+		break;
+	case UTRACE_DLCLOSE_STOP:
+		fprintf(fp, "dlclose(%p) finished", ut->handle);
+		break;
+	case UTRACE_LOAD_OBJECT:
+		fprintf(fp, "RTLD: loaded   %p @ %p - %p (%s)", ut->handle,
+		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
+		    ut->name);
+		break;
+	case UTRACE_UNLOAD_OBJECT:
+		fprintf(fp, "RTLD: unloaded %p @ %p - %p (%s)", ut->handle,
+		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
+		    ut->name);
+		break;
+	case UTRACE_ADD_RUNDEP:
+		parent = ut->mapbase;
+		fprintf(fp, "RTLD: %p now depends on %p (%s, %d)", parent,
+		    ut->handle, ut->name, ut->refcnt);
+		break;
+	case UTRACE_PRELOAD_FINISHED:
+		fprintf(fp, "RTLD: LD_PRELOAD finished");
+		break;
+	case UTRACE_INIT_CALL:
+		fprintf(fp, "RTLD: init %p for %p (%s)", ut->mapbase, ut->handle,
+		    ut->name);
+		break;
+	case UTRACE_FINI_CALL:
+		fprintf(fp, "RTLD: fini %p for %p (%s)", ut->mapbase, ut->handle,
+		    ut->name);
+		break;
+	case UTRACE_DLSYM_START:
+		fprintf(fp, "RTLD: dlsym(%p, %s)", ut->handle, ut->name);
+		break;
+	case UTRACE_DLSYM_STOP:
+		fprintf(fp, "RTLD: %p = dlsym(%p, %s)", ut->mapbase, ut->handle,
+		    ut->name);
+		break;
+	default:
+		cp = p;
+		cp += 4;
+		len -= 4;
+		fprintf(fp, "RTLD: %zu ", len);
+		while (len--)
+			if (decimal)
+				fprintf(fp, " %d", *cp++);
+			else
+				fprintf(fp, " %02x", *cp++);
+	}
+}
+
+struct utrace_malloc {
+	void *p;
+	size_t s;
+	void *r;
+};
+
+static void
+print_utrace_malloc(FILE *fp, void *p)
+{
+	struct utrace_malloc *ut = p;
+
+	if (ut->p == (void *)(intptr_t)(-1))
+		fprintf(fp, "malloc_init()");
+	else if (ut->s == 0)
+		fprintf(fp, "free(%p)", ut->p);
+	else if (ut->p == NULL)
+		fprintf(fp, "%p = malloc(%zu)", ut->r, ut->s);
+	else
+		fprintf(fp, "%p = realloc(%p, %zu)", ut->r, ut->p, ut->s);
+}
+
+int
+kdump_print_utrace(FILE *fp, void *p, size_t len, int decimal)
+{
+
+	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
+		print_utrace_rtld(fp, p, len, decimal);
+		return (1);
+	}
+
+	if (len == sizeof(struct utrace_malloc)) {
+		print_utrace_malloc(fp, p);
+		return (1);
+	}
+	
+	return (0);
+}

Modified: head/usr.bin/truss/Makefile
==============================================================================
--- head/usr.bin/truss/Makefile	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/usr.bin/truss/Makefile	Tue Oct  6 21:58:38 2015	(r288957)
@@ -10,6 +10,9 @@ SRCS+= ${MACHINE_ARCH}-fbsd.c
 SRCS+= ${MACHINE_CPUARCH}-fbsd.c
 .endif
 
+.PATH:	${.CURDIR:H}/kdump
+SRCS+=	utrace.c
+
 CFLAGS+= -I${.CURDIR} -I.
 CLEANFILES= syscalls.master syscalls.h ioctl.c
 

Modified: head/usr.bin/truss/syscall.h
==============================================================================
--- head/usr.bin/truss/syscall.h	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/usr.bin/truss/syscall.h	Tue Oct  6 21:58:38 2015	(r288957)
@@ -27,6 +27,7 @@
  * Sigprocmask -- the first argument to sigprocmask().  Prints the name.
  * Kevent -- a pointer to an array of struct kevents.  Prints all elements.
  * Pathconf -- the 2nd argument of pathconf().
+ * Utrace -- utrace(2) buffer.
  *
  * In addition, the pointer types (String, Ptr) may have OUT masked in --
  * this means that the data is set on *return* from the system call -- or
@@ -43,7 +44,7 @@ enum Argtype { None = 1, Hex, Octal, Int
 	Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2,
 	Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl,
 	LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode, Long,
-	Sysarch, ExecArgs, ExecEnv, PipeFds, QuadHex };
+	Sysarch, ExecArgs, ExecEnv, PipeFds, QuadHex, Utrace };
 
 #define	ARG_MASK	0xff
 #define	OUT	0x100

Modified: head/usr.bin/truss/syscalls.c
==============================================================================
--- head/usr.bin/truss/syscalls.c	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/usr.bin/truss/syscalls.c	Tue Oct  6 21:58:38 2015	(r288957)
@@ -72,6 +72,9 @@ __FBSDID("$FreeBSD$");
 #include "extern.h"
 #include "syscall.h"
 
+/* usr.bin/kdump/utrace.c */
+int kdump_print_utrace(FILE *, void *, size_t, int);
+
 /* 64-bit alignment on 32-bit platforms. */
 #if !defined(__LP64__) && defined(__powerpc__)
 #define	QUAD_ALIGN	1
@@ -342,6 +345,8 @@ static struct syscall decoded_syscalls[]
 		    { Atflags, 3 } } },
 	{ .name = "utimes", .ret_type = 1, .nargs = 2,
 	  .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
+	{ .name = "utrace", .ret_type = 1, .nargs = 1,
+	  .args = { { Utrace, 0 } } },
 	{ .name = "wait4", .ret_type = 1, .nargs = 4,
 	  .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
 		    { Rusage | OUT, 3 } } },
@@ -860,6 +865,24 @@ print_kevent(FILE *fp, struct kevent *ke
 	fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
 }
 
+static void
+print_utrace(FILE *fp, void *utrace_addr, size_t len)
+{
+	unsigned char *utrace_buffer;
+
+	fprintf(fp, "{ ");
+	if (kdump_print_utrace(fp, utrace_addr, len, 0)) {
+		fprintf(fp, " }");
+		return;
+	}
+
+	utrace_buffer = utrace_addr;
+	fprintf(fp, "%zu:", len);
+	while (len--)
+		fprintf(fp, " %02x", *utrace_buffer++);
+	fprintf(fp, " }");
+}
+
 /*
  * Converts a syscall argument into a string.  Said string is
  * allocated via malloc(), so needs to be free()'d.  sc is
@@ -1601,6 +1624,20 @@ print_arg(struct syscall_args *sc, unsig
 		fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
 		retval[0] = 0;
 		break;
+	case Utrace: {
+		size_t len;
+		void *utrace_addr;
+
+		len = args[sc->offset + 1];
+		utrace_addr = calloc(1, len);
+		if (get_struct(pid, (void *)args[sc->offset],
+		    (void *)utrace_addr, len) != -1)
+			print_utrace(fp, utrace_addr, len);
+		else
+			fprintf(fp, "0x%lx", args[sc->offset]);
+		free(utrace_addr);
+		break;
+	}
 	default:
 		errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
 	}

Modified: head/usr.bin/truss/truss.1
==============================================================================
--- head/usr.bin/truss/truss.1	Tue Oct  6 21:44:48 2015	(r288956)
+++ head/usr.bin/truss/truss.1	Tue Oct  6 21:58:38 2015	(r288957)
@@ -1,6 +1,6 @@
 .\" $FreeBSD$
 .\"
-.Dd May 12, 2009
+.Dd October 5, 2015
 .Dt TRUSS 1
 .Os
 .Sh NAME
@@ -95,7 +95,8 @@ options are mutually exclusive.)
 .Sh SEE ALSO
 .Xr kdump 1 ,
 .Xr ktrace 1 ,
-.Xr ptrace 2
+.Xr ptrace 2 ,
+.Xr utrace 2
 .Sh HISTORY
 The
 .Nm



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