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 {