parlib: Improve panic() and assert()
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 25 Apr 2017 16:29:51 +0000 (12:29 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 3 May 2017 16:13:02 +0000 (12:13 -0400)
Two things:
- Don't use printf() in panic/assert.  It will soon be illegal to use
  glibc's IO functions (including printf()) from vcore context.
- Force a backtrace on assert/panic.  Note this does not replace glibc's
  assert, so you'd have to #include <parlib/assert.h> to get it.  For now.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/trap.c
user/parlib/include/parlib/assert.h
user/parlib/panic.c
user/vmm/memory.c

index 1958b29..6b365d5 100644 (file)
@@ -553,9 +553,10 @@ static void trap_dispatch(struct hw_trapframe *hw_tf)
        // Handle processor exceptions.
        switch(hw_tf->tf_trapno) {
                case T_BRKPT:
-                       enable_irq();
-                       monitor(hw_tf);
-                       disable_irq();
+                       if (!in_kernel(hw_tf))
+                               backtrace_user_ctx(current, current_ctx);
+                       else
+                               monitor(hw_tf);
                        handled = TRUE;
                        break;
                case T_ILLOP:
index ca8758e..6caa7d4 100644 (file)
@@ -5,20 +5,15 @@
 #include <assert.h>
 /* For __BEGIN_DECLS.  Most every header gets it already from features.h. */
 #include <sys/cdefs.h>
-/* So we can undefine warn */
-#include <err.h>
 
 __BEGIN_DECLS
 
 #undef assert
-#undef warn
 
-void _warn(const char*, int, const char*, ...);
 void _panic(const char*, int, const char*, ...) __attribute__((noreturn));
 void _assert_failed(const char *file, int line, const char *msg)
      __attribute__((noreturn));
 
-#define warn(...) _warn(__FILE__, __LINE__, __VA_ARGS__)
 #define panic(...) _panic(__FILE__, __LINE__, __VA_ARGS__)
 
 #define assert(x)                                                                 \
index de7fc8a..bcee774 100644 (file)
@@ -5,8 +5,6 @@
 #include <stdlib.h>
 #include <parlib/ros_debug.h>
 
-char *argv0;
-
 static void __attribute__((constructor)) parlib_stdio_init(void)
 {
        /* This isn't ideal, since it might affect some stdout streams where our
@@ -16,33 +14,38 @@ static void __attribute__((constructor)) parlib_stdio_init(void)
        setlinebuf(stdout);
 }
 
-/*
- * Panic is called on unresolvable fatal errors.
- * It prints "panic: <message>", then causes a breakpoint exception,
- * which causes ROS to enter the ROS kernel monitor.
- */
-void
-_panic(const char *file, int line, const char *fmt,...)
+static void __attribute__((noreturn)) fatal_backtrace(void)
+{
+       /* This will cause the kernel to print out a backtrace to the console.
+        * Short of reading /proc/self/maps or other stuff, userspace would have a
+        * hard time backtracing itself. */
+       breakpoint();
+       abort();
+}
+
+void _panic(const char *file, int line, const char *fmt, ...)
 {
+       char buf[128];
+       int ret = 0;
        va_list ap;
 
        va_start(ap, fmt);
-
-       // Print the panic message
-       if (argv0)
-               printf("%s: ", argv0);
-       printf("user panic at %s:%d: ", file, line);
-       vprintf(fmt, ap);
-       printf("\n");
-
-       // Cause a breakpoint exception
-       while (1)
-               breakpoint();
+       ret += snprintf(buf + ret, sizeof(buf) - ret,
+                       "[user] panic: PID %d, vcore %d, %s:%d: ",
+                       getpid(), vcore_id(), __FILE__, __LINE__);
+       /* ignore errors (ret < 0) by setting ret to be at least 0 */
+       ret = MAX(ret, 0);
+       ret += vsnprintf(buf + ret, sizeof(buf) - ret, fmt, ap);
+       ret = MAX(ret, 0);
+       ret += snprintf(buf + ret, sizeof(buf) - ret, "\n");
+       ret = MAX(ret, 0);
+       write(2, buf, ret);
+       fatal_backtrace();
 }
 
 void _assert_failed(const char *file, int line, const char *msg)
 {
-       printf("[user] %s:%d, vcore %d, Assertion failed: %s\n", file, line,
-              vcore_id(), msg);
-       abort();
+       debug_printf("[user] %s:%d, vcore %d, Assertion failed: %s\n", file, line,
+                    vcore_id(), msg);
+       fatal_backtrace();
 }
index 518f697..ebfae19 100644 (file)
@@ -9,6 +9,7 @@
 #include <ros/arch/mmu.h>
 #include <vmm/linux_bootparam.h>
 #include <vmm/vmm.h>
+#include <err.h>
 
 #define ALIGNED(p, a)  (!(((uintptr_t)(p)) & ((a)-1)))