Subject: panicstr in crash dump change
To: None <tech-kern@netbsd.org>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-kern
Date: 04/20/2001 15:41:31
From an idea from Jason Thorpe a long time ago, here's some mods to
save pointers to the formatted panic string (in the msgbuf) instead of
the unformatted one.  If for some reason the msgbuf can't be read, it
reverts to the unformatted panicstr.

Before:

	alpha:/var/crash 25# /var/tmp/savecore/savecore /var/crash
	savecore: reboot after panic: this is %s %s %s
	savecore: system went down at Fri Apr 20 11:23:59 2001

After:
	alpha:/var/crash 26# /var/tmp/savecore/savecore /var/crash
	savecore: reboot after panic: panic: this is a panic message
	savecore: system went down at Fri Apr 20 11:23:59 2001

The savecore.c changes aren't exactly pretty, but I couldn't think of
anything cleaner.

Anyone see any problems with this?

Simon.
--
Simon Burge                            <simonb@wasabisystems.com>
NetBSD CDs, Support and Service:    http://www.wasabisystems.com/


Index: sys/kern/subr_prf.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/subr_prf.c,v
retrieving revision 1.77
diff -d -p -u -r1.77 subr_prf.c
--- sys/kern/subr_prf.c	2001/03/09 13:35:50	1.77
+++ sys/kern/subr_prf.c	2001/04/20 05:37:45
@@ -146,6 +146,8 @@ extern	struct tty *constty;	/* pointer t
 extern	int log_open;	/* subr_log: is /dev/klog open? */
 const	char *panicstr; /* arg to first call to panic (used as a flag
 			   to indicate that panic has already been called). */
+long	panicstart, panicend;	/* position in the msgbuf of the start and
+				   end of the formatted panicstr. */
 int	doing_shutdown;	/* set to indicate shutdown in progress */
 
 /*
@@ -193,6 +195,7 @@ panic(fmt, va_alist)
 	va_dcl
 #endif
 {
+	struct kern_msgbuf *mbp;
 	int bootopt;
 	va_list ap;
 
@@ -202,12 +205,19 @@ panic(fmt, va_alist)
 	if (!panicstr)
 		panicstr = fmt;
 	doing_shutdown = 1;
+
+	mbp = msgbufp;
+	if (mbp->msg_magic == MSG_MAGIC)
+		panicstart = mbp->msg_bufx;
 	
 	va_start(ap, fmt);
 	printf("panic: ");
 	vprintf(fmt, ap);
 	printf("\n");
 	va_end(ap);
+
+	if (mbp->msg_magic == MSG_MAGIC)
+		panicend = mbp->msg_bufx;
 
 #ifdef IPKDB
 	ipkdb_panic();
Index: sbin/savecore/savecore.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/savecore/savecore.c,v
retrieving revision 1.50
diff -d -p -u -r1.50 savecore.c
--- sbin/savecore/savecore.c	2001/01/11 20:27:12	1.50
+++ sbin/savecore/savecore.c	2001/04/20 05:37:46
@@ -48,8 +48,8 @@ __RCSID("$NetBSD: savecore.c,v 1.50 2001
 #endif /* not lint */
 
 #include <sys/param.h>
-#include <sys/stat.h>
 #include <sys/mount.h>
+#include <sys/msgbuf.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
 
@@ -58,6 +58,7 @@ __RCSID("$NetBSD: savecore.c,v 1.50 2001
 #include <fcntl.h>
 #include <nlist.h>
 #include <paths.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -69,24 +70,30 @@ __RCSID("$NetBSD: savecore.c,v 1.50 2001
 
 extern FILE *zopen(const char *fname, const char *mode);
 
-#define KREAD(kd, addr, p)\
+#define	KREAD(kd, addr, p)\
 	(kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)))
 
 struct nlist current_nl[] = {	/* Namelist for currently running system. */
-#define X_DUMPDEV	0
+#define	X_DUMPDEV	0
 	{ "_dumpdev" },
-#define X_DUMPLO	1
+#define	X_DUMPLO	1
 	{ "_dumplo" },
-#define X_TIME		2
+#define	X_TIME		2
 	{ "_time" },
 #define	X_DUMPSIZE	3
 	{ "_dumpsize" },
-#define X_VERSION	4
+#define	X_VERSION	4
 	{ "_version" },
-#define X_PANICSTR	5
-	{ "_panicstr" },
-#define	X_DUMPMAG	6
+#define	X_DUMPMAG	5
 	{ "_dumpmag" },
+#define	X_PANICSTR	6
+	{ "_panicstr" },
+#define	X_PANICSTART	7
+	{ "_panicstart" },
+#define	X_PANICEND	8
+	{ "_panicend" },
+#define	X_MSGBUF	9
+	{ "_msgbufp" },
 	{ NULL },
 };
 int cursyms[] = { X_DUMPDEV, X_DUMPLO, X_VERSION, X_DUMPMAG, -1 };
@@ -98,8 +105,11 @@ struct nlist dump_nl[] = {	/* Name list 
 	{ "_time" },
 	{ "_dumpsize" },
 	{ "_version" },
-	{ "_panicstr" },
 	{ "_dumpmag" },
+	{ "_panicstr" },
+	{ "_panicstart" },
+	{ "_panicend" },
+	{ "_msgbufp" },
 	{ NULL },
 };
 
@@ -116,7 +126,7 @@ int	dumpfd;				/* read/write descriptor 
 kvm_t	*kd_dump;			/* kvm descriptor on block dev	*/
 time_t	now;				/* current date */
 char	panic_mesg[1024];
-long	panicstr;
+long	panicstr, panicstart, panicend;
 char	vers[1024];
 
 static int	clear, compress, force, verbose;	/* flags */
@@ -314,7 +324,8 @@ kmem_setup(void)
 void
 check_kmem(void)
 {
-	char *cp;
+	char *cp, *bufdata;
+	struct kern_msgbuf msgbuf, *bufp;
 	long panicloc;
 	char core_vers[1024];
 
@@ -327,12 +338,66 @@ check_kmem(void)
 		    "warning: %s version mismatch:\n\t%s\nand\t%s\n",
 		    kernel, vers, core_vers);
 
+	if (KREAD(kd_dump, dump_nl[X_PANICSTART].n_value, &panicstart) != 0) {
+		if (verbose)
+		    syslog(LOG_WARNING, "kvm_read: %s", kvm_geterr(kd_dump));
+		goto nomsguf;
+	}
+	if (KREAD(kd_dump, dump_nl[X_PANICEND].n_value, &panicend) != 0) {
+		if (verbose)
+		    syslog(LOG_WARNING, "kvm_read: %s", kvm_geterr(kd_dump));
+		goto nomsguf;
+	}
+	if (panicstart != 0 && panicend != 0) {
+		if (KREAD(kd_dump, dump_nl[X_MSGBUF].n_value, &bufp)) {
+			if (verbose)
+				syslog(LOG_WARNING, "kvm_read: %s", kvm_geterr(kd_dump));
+			goto nomsguf;
+		}
+		if (kvm_read(kd_dump, (long)bufp, &msgbuf,
+		    offsetof(struct kern_msgbuf, msg_bufc)) !=
+		    offsetof(struct kern_msgbuf, msg_bufc)) {
+			if (verbose)
+				syslog(LOG_WARNING, "kvm_read: %s", kvm_geterr(kd_dump));
+			goto nomsguf;
+		}
+		if (msgbuf.msg_magic != MSG_MAGIC) {
+			if (verbose)
+				syslog(LOG_WARNING, "msgbuf magic incorrect");
+			goto nomsguf;
+		}
+		bufdata = malloc(msgbuf.msg_bufs);
+		if (bufdata == NULL) {
+			if (verbose)
+				syslog(LOG_WARNING, "couldn't allocate space for msgbuf data");
+			goto nomsguf;
+		}
+		if (kvm_read(kd_dump, (long)&bufp->msg_bufc, bufdata,
+		    msgbuf.msg_bufs) != msgbuf.msg_bufs) {
+			if (verbose)
+				syslog(LOG_WARNING, "kvm_read: %s", kvm_geterr(kd_dump));
+			goto nomsguf;
+		}
+		cp = panic_mesg;
+		while (panicstart != panicend && cp < &panic_mesg[sizeof(panic_mesg)-1]) {
+			*cp++ = bufdata[panicstart];
+			panicstart++;
+			if (panicstart >= msgbuf.msg_bufs)
+				panicstart = 0;
+		}
+		/* Don't end in a new-line */
+		cp = &panic_mesg[strlen(panic_mesg)] - 1;
+		if (*cp == '\n')
+			*cp = '\0';
+		panic_mesg[sizeof(panic_mesg) - 1] = '\0';
+	}
+nomsguf:
 	if (KREAD(kd_dump, dump_nl[X_PANICSTR].n_value, &panicstr) != 0) {
 		if (verbose)
 		    syslog(LOG_WARNING, "kvm_read: %s", kvm_geterr(kd_dump));
 		return;
 	}
-	if (panicstr) {
+	if (panicstr && panic_mesg[0] == '\0') {
 		cp = panic_mesg;
 		panicloc = panicstr;
 		do {