Add a caller backtrace feature (enabled by default), which records part of
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 20 Jun 2005 20:37:28 +0000 (20:37 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 20 Jun 2005 20:37:28 +0000 (20:37 +0000)
the call chain leading up to the traced function.  Two call chain instruction
addresses are recorded.

sys/conf/files.i386
sys/cpu/i386/misc/ktr.c [new file with mode: 0644]
sys/i386/i386/ktr.c [new file with mode: 0644]
sys/kern/kern_ktr.c
sys/sys/ktr.h

index 7521698..67ad366 100644 (file)
@@ -2,7 +2,7 @@
 # files marked standard are always included.
 #
 # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $
-# $DragonFly: src/sys/conf/Attic/files.i386,v 1.31 2005/06/11 09:03:48 swildner Exp $
+# $DragonFly: src/sys/conf/Attic/files.i386,v 1.32 2005/06/20 20:37:23 dillon Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -166,6 +166,7 @@ i386/i386/identcpu.c                standard
 i386/i386/in_cksum2.s          optional        inet
 i386/i386/initcpu.c            standard
 i386/i386/k6_mem.c             standard
+i386/i386/ktr.c                        optional        ktr
 i386/i386/tls.c                        standard
 # locore.s needs to be handled in Makefile to put it first.  Otherwise it's
 # now normal.
diff --git a/sys/cpu/i386/misc/ktr.c b/sys/cpu/i386/misc/ktr.c
new file mode 100644 (file)
index 0000000..e35495b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
+ * 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.
+ * 3. Neither the name of The DragonFly Project 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ *
+ * $DragonFly: src/sys/cpu/i386/misc/ktr.c,v 1.1 2005/06/20 20:37:28 dillon Exp $
+ */
+/*
+ * Kernel tracepoint facility.
+ */
+
+#include "opt_ddb.h"
+#include "opt_ktr.h"
+
+#include <sys/param.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/ktr.h>
+
+/*
+ * This routine fills in the ktr_caller1 and ktr_caller2 fields by
+ * tracing back through the kernel stack to locate the stack frames
+ * and return addresses.
+ *
+ *
+ *     [first argument]
+ *     [retpc]
+ *     [frameptr]              -> points to caller's frame pointer
+ * sp ->[junk]
+ */
+
+static __inline 
+void **
+FRAMEUP(void **frameptr)
+{
+    void **newframeptr;
+
+    newframeptr = (void **)frameptr[0];
+    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
+       newframeptr = frameptr;
+    return(newframeptr);
+}
+
+void
+cpu_ktr_caller(struct ktr_entry *_ktr)
+{
+    struct ktr_entry *ktr;
+    void **frameptr;
+
+    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
+    ktr = _ktr;
+    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
+    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
+    ktr->ktr_caller1 = frameptr[1];
+    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
+    ktr->ktr_caller2 = frameptr[1];
+}
+
diff --git a/sys/i386/i386/ktr.c b/sys/i386/i386/ktr.c
new file mode 100644 (file)
index 0000000..851da78
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
+ * 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.
+ * 3. Neither the name of The DragonFly Project 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ *
+ * $DragonFly: src/sys/i386/i386/Attic/ktr.c,v 1.1 2005/06/20 20:37:28 dillon Exp $
+ */
+/*
+ * Kernel tracepoint facility.
+ */
+
+#include "opt_ddb.h"
+#include "opt_ktr.h"
+
+#include <sys/param.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/ktr.h>
+
+/*
+ * This routine fills in the ktr_caller1 and ktr_caller2 fields by
+ * tracing back through the kernel stack to locate the stack frames
+ * and return addresses.
+ *
+ *
+ *     [first argument]
+ *     [retpc]
+ *     [frameptr]              -> points to caller's frame pointer
+ * sp ->[junk]
+ */
+
+static __inline 
+void **
+FRAMEUP(void **frameptr)
+{
+    void **newframeptr;
+
+    newframeptr = (void **)frameptr[0];
+    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
+       newframeptr = frameptr;
+    return(newframeptr);
+}
+
+void
+cpu_ktr_caller(struct ktr_entry *_ktr)
+{
+    struct ktr_entry *ktr;
+    void **frameptr;
+
+    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
+    ktr = _ktr;
+    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
+    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
+    ktr->ktr_caller1 = frameptr[1];
+    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
+    ktr->ktr_caller2 = frameptr[1];
+}
+
index 5f536af..704d9ba 100644 (file)
@@ -62,7 +62,7 @@
  * SUCH DAMAGE.
  */
 /*
- * $DragonFly: src/sys/kern/kern_ktr.c,v 1.5 2005/06/20 17:59:32 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_ktr.c,v 1.6 2005/06/20 20:37:24 dillon Exp $
  */
 /*
  * Kernel tracepoint facility.
@@ -100,16 +100,19 @@ MALLOC_DEFINE(M_KTR, "ktr", "ktr buffers");
 
 SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RW, 0, "ktr");
 
-int32_t        ktr_cpumask = -1;
+static int32_t ktr_cpumask = -1;
 TUNABLE_INT("debug.ktr.cpumask", &ktr_cpumask);
 SYSCTL_INT(_debug_ktr, OID_AUTO, cpumask, CTLFLAG_RW, &ktr_cpumask, 0, "");
 
-int    ktr_entries = KTR_ENTRIES;
+static int     ktr_entries = KTR_ENTRIES;
 SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0, "");
 
-int    ktr_version = KTR_VERSION;
+static int     ktr_version = KTR_VERSION;
 SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD, &ktr_version, 0, "");
 
+static int     ktr_stacktrace = 1;
+SYSCTL_INT(_debug_ktr, OID_AUTO, stacktrace, CTLFLAG_RD, &ktr_stacktrace, 0, "");
+
 /*
  * Give cpu0 a static buffer so the tracepoint facility can be used during
  * early boot (note however that we still use a critical section, XXX).
@@ -162,6 +165,8 @@ ktr_write_entry(struct ktr_info *info, const char *file, int line,
                        bcopyi(ptr, entry->ktr_data, KTR_BUFSIZE);
                else
                        bcopyi(ptr, entry->ktr_data, info->kf_data_size);
+               if (ktr_stacktrace)
+                       cpu_ktr_caller(entry);
        }
 #ifdef KTR_VERBOSE
        if (ktr_verbose && info->kf_format) {
@@ -182,15 +187,19 @@ ktr_log(struct ktr_info *info, const char *file, int line, ...)
 {
        __va_list va;
 
-       __va_start(va, line);
-       ktr_write_entry(info, file, line, va);
-       __va_end(va);
+       if (panicstr == NULL) {
+               __va_start(va, line);
+               ktr_write_entry(info, file, line, va);
+               __va_end(va);
+       }
 }
 
 void
 ktr_log_ptr(struct ktr_info *info, const char *file, int line, const void *ptr)
 {
-       ktr_write_entry(info, file, line, ptr);
+       if (panicstr == NULL) {
+               ktr_write_entry(info, file, line, ptr);
+       }
 }
 
 #ifdef DDB
@@ -315,8 +324,9 @@ db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx)
                    kp->ktr_file, kp->ktr_line);
        }
        db_printf("%s\t", kp->ktr_info->kf_name);
+       db_printf("from(%p,%p) ", kp->ktr_caller1, kp->ktr_caller2);
        if (kp->ktr_info->kf_format) {
-               int32_t *args = (int32_t *)kp->ktr_data;
+               int32_t *args = kp->ktr_data;
                db_printf(kp->ktr_info->kf_format,
                          args[0], args[1], args[2], args[3],
                          args[4], args[5], args[6], args[7],
index b259de5..1ade243 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/sys/ktr.h,v 1.5 2005/06/20 17:59:30 dillon Exp $
+ * $DragonFly: src/sys/sys/ktr.h,v 1.6 2005/06/20 20:37:26 dillon Exp $
  */
 /*
  * Generic Kernel trace buffer support.  
@@ -69,11 +69,12 @@ struct ktr_entry {
        void    *ktr_caller2;
        int32_t ktr_line;
        int32_t ktr_unused;
-       char    ktr_data[KTR_BUFSIZE];
+       int32_t ktr_data[KTR_BUFSIZE / sizeof(int32_t)];
 };
 
 void   ktr_log(struct ktr_info *info, const char *file, int line, ...);
 void   ktr_log_ptr(struct ktr_info *info, const char *file, int line, const void *ptr);
+void    cpu_ktr_caller(struct ktr_entry *ktr);
 
 /*
  * Take advantage of constant integer optimizations by the compiler