svn commit: r220267 - in stable/8/usr.bin: kdump ktrace

Dmitry Chagin dchagin at FreeBSD.org
Sat Apr 2 08:29:03 UTC 2011


Author: dchagin
Date: Sat Apr  2 08:29:02 2011
New Revision: 220267
URL: http://svn.freebsd.org/changeset/base/220267

Log:
  MFC r219043:
  
  Teach kdump to understand sv_flags records in the trace files.
  
  MFC r219044:
  
  Update manual page to reflect latest changes of ABI description support.
  
  MFC r219138:
  
  Teach kdump to understand linux syscalls names too.
  
  Fix bug introduced in r219043: the kernel always dump native
  signal numbers, so no need to check the ABI in ktrpsig().

Added:
  stable/8/usr.bin/kdump/linux_syscalls.conf
     - copied unchanged from r219138, head/usr.bin/kdump/linux_syscalls.conf
Modified:
  stable/8/usr.bin/kdump/Makefile
  stable/8/usr.bin/kdump/kdump.1
  stable/8/usr.bin/kdump/kdump.c
  stable/8/usr.bin/ktrace/ktrace.c
  stable/8/usr.bin/ktrace/ktrace.h
Directory Properties:
  stable/8/usr.bin/kdump/   (props changed)
  stable/8/usr.bin/ktrace/   (props changed)

Modified: stable/8/usr.bin/kdump/Makefile
==============================================================================
--- stable/8/usr.bin/kdump/Makefile	Sat Apr  2 07:01:09 2011	(r220266)
+++ stable/8/usr.bin/kdump/Makefile	Sat Apr  2 08:29:02 2011	(r220267)
@@ -1,13 +1,21 @@
 #	@(#)Makefile	8.1 (Berkeley) 6/6/93
 # $FreeBSD$
 
+.if (${MACHINE_ARCH} == "amd64")
+SFX=		32
+.endif
+
 .PATH: ${.CURDIR}/../ktrace
 
 PROG=		kdump
 SRCS=		kdump.c ioctl.c kdump_subr.c subr.c
 CFLAGS+=	-I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../..
 
-CLEANFILES=	ioctl.c kdump_subr.c
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
+SRCS+=		linux_syscalls.c
+.endif
+
+CLEANFILES=	ioctl.c kdump_subr.c linux_syscalls.c
 
 ioctl.c: mkioctls
 	sh ${.CURDIR}/mkioctls ${DESTDIR}/usr/include > ${.TARGET}
@@ -15,4 +23,10 @@ ioctl.c: mkioctls
 kdump_subr.c: mksubr
 	sh ${.CURDIR}/mksubr ${DESTDIR}/usr/include > ${.TARGET}
 
+linux_syscalls.c:
+	/bin/sh ${.CURDIR}/../../sys/kern/makesyscalls.sh \
+	    ${.CURDIR}/../../sys/${MACHINE_ARCH}/linux${SFX}/syscalls.master ${.CURDIR}/linux_syscalls.conf
+	echo "int nlinux_syscalls = sizeof(linux_syscallnames) / sizeof(linux_syscallnames[0]);" \
+	    >> linux_syscalls.c
+
 .include <bsd.prog.mk>

Modified: stable/8/usr.bin/kdump/kdump.1
==============================================================================
--- stable/8/usr.bin/kdump/kdump.1	Sat Apr  2 07:01:09 2011	(r220266)
+++ stable/8/usr.bin/kdump/kdump.1	Sat Apr  2 08:29:02 2011	(r220267)
@@ -40,7 +40,7 @@
 .Nd display kernel trace data
 .Sh SYNOPSIS
 .Nm
-.Op Fl dEnlHRsT
+.Op Fl dEnlHRsTA
 .Op Fl f Ar trfile
 .Op Fl m Ar maxdata
 .Op Fl p Ar pid
@@ -103,6 +103,8 @@ GIDs, dates etc. symbolically instead of
 Suppress display of I/O data.
 .It Fl T
 Display absolute timestamps for each entry (seconds since epoch).
+.It Fl A
+Display description of the ABI of traced process.
 .It Fl t Ar trstr
 See the
 .Fl t

Modified: stable/8/usr.bin/kdump/kdump.c
==============================================================================
--- stable/8/usr.bin/kdump/kdump.c	Sat Apr  2 07:01:09 2011	(r220266)
+++ stable/8/usr.bin/kdump/kdump.c	Sat Apr  2 08:29:02 2011	(r220267)
@@ -59,7 +59,9 @@ extern int errno;
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/sysent.h>
 #include <sys/un.h>
+#include <sys/queue.h>
 #ifdef IPX
 #include <sys/types.h>
 #include <netipx/ipx.h>
@@ -85,10 +87,12 @@ extern int errno;
 #include "ktrace.h"
 #include "kdump_subr.h"
 
+u_int abidump(struct ktr_header *);
+int fetchprocinfo(struct ktr_header *, u_int *);
 int fread_tail(void *, int, int);
 void dumpheader(struct ktr_header *);
-void ktrsyscall(struct ktr_syscall *);
-void ktrsysret(struct ktr_sysret *);
+void ktrsyscall(struct ktr_syscall *, u_int);
+void ktrsysret(struct ktr_sysret *, u_int);
 void ktrnamei(char *, int);
 void hexdump(char *, int, int);
 void visdump(char *, int, int);
@@ -104,13 +108,57 @@ void sockfamilyname(int);
 const char *ioctlname(u_long);
 
 int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
-    resolv = 0;
+    resolv = 0, abiflag = 0;
 const char *tracefile = DEF_TRACEFILE;
 struct ktr_header ktr_header;
 
 #define TIME_FORMAT	"%b %e %T %Y"
 #define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
 
+#define print_number(i,n,c) do {		\
+	if (decimal)				\
+		printf("%c%ld", c, (long)*i);	\
+	else					\
+		printf("%c%#lx", c, (long)*i);	\
+	i++;					\
+	n--;					\
+	c = ',';				\
+	} while (0);
+
+#if defined(__amd64__) || defined(__i386__)
+
+void linux_ktrsyscall(struct ktr_syscall *);
+void linux_ktrsysret(struct ktr_sysret *);
+extern char *linux_syscallnames[];
+extern int nlinux_syscalls;
+
+/*
+ * from linux.h
+ * Linux syscalls return negative errno's, we do positive and map them
+ */
+static int bsd_to_linux_errno[ELAST + 1] = {
+	-0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9,
+	-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
+	-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
+	-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
+	-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
+	-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
+	-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
+	-116, -66,  -6,  -6,  -6,  -6,  -6, -37, -38,  -9,
+	-6,  -6, -43, -42, -75,-125, -84, -95, -16, -74,
+	-72, -67, -71
+};
+#endif
+
+struct proc_info
+{
+	TAILQ_ENTRY(proc_info)	info;
+	u_int			sv_flags;
+	pid_t			pid;
+};
+
+TAILQ_HEAD(trace_procs, proc_info) trace_procs;
+
 int
 main(int argc, char *argv[])
 {
@@ -119,11 +167,15 @@ main(int argc, char *argv[])
 	int trpoints = ALL_POINTS;
 	int drop_logged;
 	pid_t pid = 0;
+	u_int sv_flags;
 
 	(void) setlocale(LC_CTYPE, "");
 
-	while ((ch = getopt(argc,argv,"f:dElm:np:HRrsTt:")) != -1)
+	while ((ch = getopt(argc,argv,"f:dElm:np:AHRrsTt:")) != -1)
 		switch((char)ch) {
+		case 'A':
+			abiflag = 1;
+			break;
 		case 'f':
 			tracefile = optarg;
 			break;
@@ -177,6 +229,7 @@ main(int argc, char *argv[])
 		errx(1, "%s", strerror(ENOMEM));
 	if (!freopen(tracefile, "r", stdin))
 		err(1, "%s", tracefile);
+	TAILQ_INIT(&trace_procs);
 	drop_logged = 0;
 	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
 		if (ktr_header.ktr_type & KTR_DROP) {
@@ -209,6 +262,9 @@ main(int argc, char *argv[])
 		}
 		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
 			errx(1, "data too short");
+		if (fetchprocinfo(&ktr_header, (u_int *)m) != 0)
+			continue;
+		sv_flags = abidump(&ktr_header);
 		if (pid && ktr_header.ktr_pid != pid)
 			continue;
 		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
@@ -216,10 +272,20 @@ main(int argc, char *argv[])
 		drop_logged = 0;
 		switch (ktr_header.ktr_type) {
 		case KTR_SYSCALL:
-			ktrsyscall((struct ktr_syscall *)m);
+#if defined(__amd64__) || defined(__i386__)
+			if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
+				linux_ktrsyscall((struct ktr_syscall *)m);
+			else
+#endif
+				ktrsyscall((struct ktr_syscall *)m, sv_flags);
 			break;
 		case KTR_SYSRET:
-			ktrsysret((struct ktr_sysret *)m);
+#if defined(__amd64__) || defined(__i386__)
+			if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
+				linux_ktrsysret((struct ktr_sysret *)m);
+			else
+#endif
+				ktrsysret((struct ktr_sysret *)m, sv_flags);
 			break;
 		case KTR_NAMEI:
 		case KTR_SYSCTL:
@@ -262,6 +328,84 @@ fread_tail(void *buf, int size, int num)
 	return (i);
 }
 
+int
+fetchprocinfo(struct ktr_header *kth, u_int *flags)
+{
+	struct proc_info *pi;
+
+	switch (kth->ktr_type) {
+	case KTR_PROCCTOR:
+		TAILQ_FOREACH(pi, &trace_procs, info) {
+			if (pi->pid == kth->ktr_pid) {
+				TAILQ_REMOVE(&trace_procs, pi, info);
+				break;
+			}
+		}
+		pi = malloc(sizeof(struct proc_info));
+		if (pi == NULL)
+			errx(1, "%s", strerror(ENOMEM));
+		pi->sv_flags = *flags;
+		pi->pid = kth->ktr_pid;
+		TAILQ_INSERT_TAIL(&trace_procs, pi, info);
+		return (1);
+
+	case KTR_PROCDTOR:
+		TAILQ_FOREACH(pi, &trace_procs, info) {
+			if (pi->pid == kth->ktr_pid) {
+				TAILQ_REMOVE(&trace_procs, pi, info);
+				free(pi);
+				break;
+			}
+		}
+		return (1);
+	}
+
+	return (0);
+}
+
+u_int
+abidump(struct ktr_header *kth)
+{
+	struct proc_info *pi;
+	const char *abi;
+	const char *arch;
+	u_int flags = 0;
+
+	TAILQ_FOREACH(pi, &trace_procs, info) {
+		if (pi->pid == kth->ktr_pid) {
+			flags = pi->sv_flags;
+			break;
+		}
+	}
+
+	if (abiflag == 0)
+		return (flags);
+
+	switch (flags & SV_ABI_MASK) {
+	case SV_ABI_LINUX:
+		abi = "L";
+		break;
+	case SV_ABI_FREEBSD:
+		abi = "F";
+		break;
+	default:
+		abi = "U";
+		break;
+	}
+
+	if (flags != 0) {
+		if (flags & SV_LP64)
+			arch = "64";
+		else
+			arch = "32";
+	} else
+		arch = "00";
+
+	printf("%s%s  ", abi, arch);
+
+	return (flags);
+}
+
 void
 dumpheader(struct ktr_header *kth)
 {
@@ -297,6 +441,10 @@ dumpheader(struct ktr_header *kth)
 	case KTR_SYSCTL:
 		type = "SCTL";
 		break;
+	case KTR_PROCCTOR:
+		/* FALLTHROUGH */
+	case KTR_PROCDTOR:
+		return;
 	default:
 		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
 		type = unknown;
@@ -341,30 +489,21 @@ dumpheader(struct ktr_header *kth)
 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
 
 void
-ktrsyscall(struct ktr_syscall *ktr)
+ktrsyscall(struct ktr_syscall *ktr, u_int flags)
 {
 	int narg = ktr->ktr_narg;
 	register_t *ip;
 
-	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
+	if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
+	    (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0))
 		(void)printf("[%d]", ktr->ktr_code);
 	else
 		(void)printf("%s", syscallnames[ktr->ktr_code]);
 	ip = &ktr->ktr_args[0];
 	if (narg) {
 		char c = '(';
-		if (fancy) {
-
-#define print_number(i,n,c) do {                      \
-	if (decimal)                                  \
-		(void)printf("%c%ld", c, (long)*i);   \
-	else                                          \
-		(void)printf("%c%#lx", c, (long)*i);  \
-	i++;                                          \
-	n--;                                          \
-	c = ',';                                      \
-	} while (0);
-
+		if (fancy &&
+		    (flags == 0 || (flags & SV_ABI_MASK) == SV_ABI_FREEBSD)) {
 			if (ktr->ktr_code == SYS_ioctl) {
 				const char *cp;
 				print_number(ip,narg,c);
@@ -811,13 +950,14 @@ ktrsyscall(struct ktr_syscall *ktr)
 }
 
 void
-ktrsysret(struct ktr_sysret *ktr)
+ktrsysret(struct ktr_sysret *ktr, u_int flags)
 {
 	register_t ret = ktr->ktr_retval;
 	int error = ktr->ktr_error;
 	int code = ktr->ktr_code;
 
-	if (code >= nsyscalls || code < 0)
+	if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
+	    (code >= nsyscalls || code < 0))
 		(void)printf("[%d] ", code);
 	else
 		(void)printf("%s ", syscallnames[code]);
@@ -1365,10 +1505,71 @@ invalid:
 	printf("invalid record\n");
 }
 
+#if defined(__amd64__) || defined(__i386__)
+void
+linux_ktrsyscall(struct ktr_syscall *ktr)
+{
+	int narg = ktr->ktr_narg;
+	register_t *ip;
+
+	if (ktr->ktr_code >= nlinux_syscalls || ktr->ktr_code < 0)
+		printf("[%d]", ktr->ktr_code);
+	else
+		printf("%s", linux_syscallnames[ktr->ktr_code]);
+	ip = &ktr->ktr_args[0];
+	if (narg) {
+		char c = '(';
+		while (narg > 0)
+			print_number(ip, narg, c);
+		putchar(')');
+	}
+	putchar('\n');
+}
+
+void
+linux_ktrsysret(struct ktr_sysret *ktr)
+{
+	register_t ret = ktr->ktr_retval;
+	int error = ktr->ktr_error;
+	int code = ktr->ktr_code;
+
+	if (code >= nlinux_syscalls || code < 0)
+		printf("[%d] ", code);
+	else
+		printf("%s ", linux_syscallnames[code]);
+
+	if (error == 0) {
+		if (fancy) {
+			printf("%ld", (long)ret);
+			if (ret < 0 || ret > 9)
+				printf("/%#lx", (long)ret);
+		} else {
+			if (decimal)
+				printf("%ld", (long)ret);
+			else
+				printf("%#lx", (long)ret);
+		}
+	} else if (error == ERESTART)
+		printf("RESTART");
+	else if (error == EJUSTRETURN)
+		printf("JUSTRETURN");
+	else {
+		if (ktr->ktr_error <= ELAST + 1)
+			error = abs(bsd_to_linux_errno[ktr->ktr_error]);
+		else
+			error = 999;
+		printf("-1 errno %d", error);
+		if (fancy)
+			printf(" %s", strerror(ktr->ktr_error));
+	}
+	putchar('\n');
+}
+#endif
+
 void
 usage(void)
 {
-	fprintf(stderr, "usage: kdump [-dEnlHRrsT] [-f trfile] "
+	fprintf(stderr, "usage: kdump [-dEnlHRrsTA] [-f trfile] "
 	    "[-m maxdata] [-p pid] [-t trstr]\n");
 	exit(1);
 }

Copied: stable/8/usr.bin/kdump/linux_syscalls.conf (from r219138, head/usr.bin/kdump/linux_syscalls.conf)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.bin/kdump/linux_syscalls.conf	Sat Apr  2 08:29:02 2011	(r220267, copy of r219138, head/usr.bin/kdump/linux_syscalls.conf)
@@ -0,0 +1,11 @@
+# $FreeBSD$
+sysnames="linux_syscalls.c"
+sysproto="/dev/null"
+sysproto_h=_LINUX_SYSPROTO_H_
+syshdr="/dev/null"
+syssw="/dev/null"
+sysmk="/dev/null"
+syscallprefix="LINUX_SYS_"
+switchname="/dev/null"
+namesname="linux_syscallnames"
+systrace="/dev/null"

Modified: stable/8/usr.bin/ktrace/ktrace.c
==============================================================================
--- stable/8/usr.bin/ktrace/ktrace.c	Sat Apr  2 07:01:09 2011	(r220266)
+++ stable/8/usr.bin/ktrace/ktrace.c	Sat Apr  2 08:29:02 2011	(r220267)
@@ -163,6 +163,8 @@ main(int argc, char *argv[])
 	(void)umask(omask);
 	(void)close(fd);
 
+	trpoints |= PROC_ABI_POINTS;
+
 	if (*argv) { 
 		if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
 			err(1, "%s", tracefile);

Modified: stable/8/usr.bin/ktrace/ktrace.h
==============================================================================
--- stable/8/usr.bin/ktrace/ktrace.h	Sat Apr  2 07:01:09 2011	(r220266)
+++ stable/8/usr.bin/ktrace/ktrace.h	Sat Apr  2 08:29:02 2011	(r220267)
@@ -38,7 +38,9 @@
 		    KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \
 		    KTRFAC_STRUCT | KTRFAC_SYSCTL)
 
-#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
+#define PROC_ABI_POINTS (KTRFAC_PROCCTOR | KTRFAC_PROCDTOR)
+
+#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW | PROC_ABI_POINTS)
 
 #define DEF_TRACEFILE	"ktrace.out"
 


More information about the svn-src-all mailing list