[haiku-commits] r35896 - haiku/trunk/src/system/kernel/debug

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 18 Mar 2010 01:47:43 +0100 (CET)

Author: bonefish
Date: 2010-03-18 01:47:43 +0100 (Thu, 18 Mar 2010)
New Revision: 35896
Changeset: http://dev.haiku-os.org/changeset/35896/haiku

Modified:
   haiku/trunk/src/system/kernel/debug/debug.cpp
Log:
* sCurrentKernelDebuggerMessageArgs is no longer used directly. Whenever it
  is passed to some v*printf(), we clone it first. This way we can use it
  repeatedly. It worked only on certain architectures correctly before.
* Changed the panic() semantics a bit: When the format contains the
  (hopefully unusual enough) string "@!" only the part before it is
  considered to belong to the panic message. The part after it is interpreted
  as a command line to be executed directly after entering KDL. This way it
  is possible to provide helpful command invocations only developers somewhat
  familiar with the subsystem might come up with. E.g.:
    panic("dec_vnode_ref_count: called on busy vnode %p"
      "@! vnode -p %p; mount _mount", vnode, vnode);


Modified: haiku/trunk/src/system/kernel/debug/debug.cpp
===================================================================
--- haiku/trunk/src/system/kernel/debug/debug.cpp       2010-03-17 22:56:07 UTC 
(rev 35895)
+++ haiku/trunk/src/system/kernel/debug/debug.cpp       2010-03-18 00:47:43 UTC 
(rev 35896)
@@ -51,6 +51,11 @@
 #include "debug_variables.h"
 
 
+#if __GNUC__ == 2
+#      define va_copy(to, from)        __va_copy(to, from)
+#endif
+
+
 struct debug_memcpy_parameters {
        void*           to;
        const void*     from;
@@ -66,6 +71,8 @@
 
 
 static const char* const kKDLPrompt = "kdebug> ";
+static const char* const kKDLMessageCommandSeparator = "@!";
+       // separates panic() message from command list to execute
 
 extern "C" int kgets(char* buffer, int length);
 
@@ -696,14 +703,6 @@
 }
 
 
-static inline void
-kprintf_args(const char* format, va_list args)
-{
-       if (sDebugOutputFilter != NULL)
-               sDebugOutputFilter->Print(format, args);
-}
-
-
 static void
 print_kernel_debugger_message()
 {
@@ -711,9 +710,36 @@
                        || sCurrentKernelDebuggerMessage != NULL) {
                if (sCurrentKernelDebuggerMessagePrefix != NULL)
                        kprintf("%s", sCurrentKernelDebuggerMessagePrefix);
-               if (sCurrentKernelDebuggerMessage != NULL) {
-                       kprintf_args(sCurrentKernelDebuggerMessage,
-                               sCurrentKernelDebuggerMessageArgs);
+               if (sCurrentKernelDebuggerMessage != NULL
+                               && sDebugOutputFilter != NULL) {
+                       va_list args;
+                       va_copy(args, sCurrentKernelDebuggerMessageArgs);
+
+                       if (const char* commandDelimiter = strstr(
+                                       sCurrentKernelDebuggerMessage,
+                                       kKDLMessageCommandSeparator)) {
+                               // The message string contains a list of 
commands to be
+                               // executed when entering the kernel debugger. 
We don't
+                               // want to print those, so we copy the 
interesting part of
+                               // the format string.
+                               if (commandDelimiter != 
sCurrentKernelDebuggerMessage) {
+                                       size_t length = commandDelimiter
+                                               - sCurrentKernelDebuggerMessage;
+                                       if (char* format = 
(char*)debug_malloc(length + 1)) {
+                                               memcpy(format, 
sCurrentKernelDebuggerMessage, length);
+                                               format[length] = '\0';
+                                               
sDebugOutputFilter->Print(format, args);
+                                               debug_free(format);
+                                       } else {
+                                               // allocation failed -- just 
print everything
+                                               
sDebugOutputFilter->Print(sCurrentKernelDebuggerMessage,
+                                                       args);
+                                       }
+                               }
+                       } else
+                               
sDebugOutputFilter->Print(sCurrentKernelDebuggerMessage, args);
+
+                       va_end(args);
                }
 
                kprintf("\n");
@@ -732,11 +758,8 @@
 
        sCurrentKernelDebuggerMessagePrefix = messagePrefix;
        sCurrentKernelDebuggerMessage = message;
-#if __GNUC__ == 2
-       __va_copy(sCurrentKernelDebuggerMessageArgs, args);
-#else
-       va_copy(sCurrentKernelDebuggerMessageArgs, args);
-#endif
+       if (sCurrentKernelDebuggerMessage != NULL)
+               va_copy(sCurrentKernelDebuggerMessageArgs, args);
 
        print_kernel_debugger_message();
 
@@ -779,8 +802,37 @@
                }
        }
 
-       if (!has_debugger_command("help"))
+       if (has_debugger_command("help")) {
+               // commands are registered already
+               if (sCurrentKernelDebuggerMessage != NULL
+                       && strstr(sCurrentKernelDebuggerMessage,
+                                       kKDLMessageCommandSeparator) != NULL) {
+                       // The panic() message specifies commands to execute.
+                       const size_t kCommandBufferSize = 512;
+                       char* commandBuffer = 
(char*)debug_malloc(kCommandBufferSize);
+                       if (commandBuffer != NULL) {
+                               va_list tempArgs;
+                               va_copy(tempArgs, 
sCurrentKernelDebuggerMessageArgs);
+                               if (vsnprintf(commandBuffer, kCommandBufferSize,
+                                               sCurrentKernelDebuggerMessage, 
tempArgs)
+                                                       < 
(int)kCommandBufferSize) {
+                                       const char* commands = 
strstr(commandBuffer,
+                                               kKDLMessageCommandSeparator);
+                                       if (commands != NULL) {
+                                               commands += 
strlen(kKDLMessageCommandSeparator);
+                                               kprintf("initial commands: 
%s\n", commands);
+                                               
evaluate_debug_command(commands);
+                                       }
+                               }
+                               va_end(tempArgs);
+
+                               debug_free(commandBuffer);
+                       }
+               }
+       } else {
+               // no commands yet -- always print a stack trace at least
                arch_debug_stack_trace();
+       }
 
        int32 continuableLine = -1;
                // Index of the previous command line, if the command returned
@@ -831,7 +883,8 @@
                }
        }
 
-       va_end(sCurrentKernelDebuggerMessageArgs);
+       if (sCurrentKernelDebuggerMessage != NULL)
+               va_end(sCurrentKernelDebuggerMessageArgs);
 
        delete_debug_alloc_pool(allocPool);
 
@@ -1851,7 +1904,7 @@
        if (sDebugOutputFilter != NULL) {
                va_list args;
                va_start(args, format);
-               kprintf_args(format, args);
+               sDebugOutputFilter->Print(format, args);
                va_end(args);
        }
 }


Other related posts: