* 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); git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35896 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6365627b33
commit
64c15cfc27
@ -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 @@ struct debug_strlcpy_parameters {
|
||||
|
||||
|
||||
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 @@ kgets(char* buffer, int length)
|
||||
}
|
||||
|
||||
|
||||
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 @@ print_kernel_debugger_message()
|
||||
|| 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 @@ kernel_debugger_loop(const char* messagePrefix, const char* message,
|
||||
|
||||
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 @@ kernel_debugger_loop(const char* messagePrefix, const char* message,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ kernel_debugger_loop(const char* messagePrefix, const char* message,
|
||||
}
|
||||
}
|
||||
|
||||
va_end(sCurrentKernelDebuggerMessageArgs);
|
||||
if (sCurrentKernelDebuggerMessage != NULL)
|
||||
va_end(sCurrentKernelDebuggerMessageArgs);
|
||||
|
||||
delete_debug_alloc_pool(allocPool);
|
||||
|
||||
@ -1851,7 +1904,7 @@ kprintf(const char* format, ...)
|
||||
if (sDebugOutputFilter != NULL) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
kprintf_args(format, args);
|
||||
sDebugOutputFilter->Print(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user