Save previous session's debug syslog during boot
Add boot loader debug menu option "Save syslog from previous session during boot". If enabled (defaults to true), the previous session's debug syslog data is copy to a separate buffer and passed to the kernel, which writes it back to the file /var/log/previous_syslog. As long as Haiku still boots, this should now be the most convenient way to retrieve the output from a kernel crash.
This commit is contained in:
@@ -82,8 +82,21 @@ typedef struct kernel_args {
|
||||
FixedWidthPointer<void> edid_info;
|
||||
|
||||
FixedWidthPointer<void> debug_output;
|
||||
// If keep_debug_output_buffer, points to a ring_buffer, else to a
|
||||
// simple flat buffer. In either case it stores the debug output from
|
||||
// the boot loader.
|
||||
FixedWidthPointer<void> previous_debug_output;
|
||||
// A flat pointer to a buffer containing the debug output from the
|
||||
// previous session. May be NULL.
|
||||
uint32 debug_size;
|
||||
// If keep_debug_output_buffer, the size of the ring buffer, otherwise
|
||||
// the size of the flat buffer debug_output points to.
|
||||
uint32 previous_debug_size;
|
||||
// The size of the buffer previous_debug_output points to. Used as a
|
||||
// boolean indicator whether to save the previous session's debug output
|
||||
// until initialized for the kernel.
|
||||
bool keep_debug_output_buffer;
|
||||
// If true, debug_output is a ring buffer, otherwise a flat buffer.
|
||||
|
||||
platform_kernel_args platform_args;
|
||||
arch_kernel_args arch_args;
|
||||
|
||||
@@ -39,6 +39,8 @@ main(stage2_args *args)
|
||||
// set debug syslog default
|
||||
#if KDEBUG_ENABLE_DEBUG_SYSLOG
|
||||
gKernelArgs.keep_debug_output_buffer = true;
|
||||
gKernelArgs.previous_debug_size = true;
|
||||
// used as a boolean indicator until initialized for the kernel
|
||||
#endif
|
||||
|
||||
add_stage2_driver_settings(args);
|
||||
|
||||
@@ -1026,6 +1026,14 @@ debug_menu_toggle_debug_syslog(Menu* menu, MenuItem* item)
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
debug_menu_toggle_previous_debug_syslog(Menu* menu, MenuItem* item)
|
||||
{
|
||||
gKernelArgs.previous_debug_size = item->IsMarked();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
debug_menu_save_previous_syslog(Menu* menu, MenuItem* item)
|
||||
{
|
||||
@@ -1280,6 +1288,20 @@ add_debug_menu()
|
||||
item->SetHelpText("Enables a special in-memory syslog buffer for this "
|
||||
"session that the boot loader will be able to access after rebooting.");
|
||||
|
||||
ring_buffer* syslogBuffer
|
||||
= (ring_buffer*)gKernelArgs.debug_output.Pointer();
|
||||
bool hasPreviousSyslog
|
||||
= syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0;
|
||||
if (hasPreviousSyslog) {
|
||||
menu->AddItem(item = new(nothrow) MenuItem(
|
||||
"Save syslog from previous session during boot"));
|
||||
item->SetType(MENU_ITEM_MARKABLE);
|
||||
item->SetMarked(gKernelArgs.previous_debug_size);
|
||||
item->SetTarget(&debug_menu_toggle_previous_debug_syslog);
|
||||
item->SetHelpText("Saves the syslog from the previous Haiku session to "
|
||||
"/var/log/previous_syslog when booting.");
|
||||
}
|
||||
|
||||
bool currentLogItemVisible = platform_debug_get_log_buffer(NULL) != NULL;
|
||||
if (currentLogItemVisible) {
|
||||
menu->AddSeparatorItem();
|
||||
@@ -1291,9 +1313,7 @@ add_debug_menu()
|
||||
"Displays the debug info the boot loader has logged.");
|
||||
}
|
||||
|
||||
ring_buffer* syslogBuffer
|
||||
= (ring_buffer*)gKernelArgs.debug_output.Pointer();
|
||||
if (syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0) {
|
||||
if (hasPreviousSyslog) {
|
||||
if (!currentLogItemVisible)
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
|
||||
@@ -172,6 +172,23 @@ void
|
||||
debug_cleanup(void)
|
||||
{
|
||||
if (sDebugSyslogBuffer != NULL) {
|
||||
// If desired, store the debug syslog data from the previous session for
|
||||
// the kernel.
|
||||
size_t bytesReadable = 0;
|
||||
if (gKernelArgs.previous_debug_size != 0) {
|
||||
bytesReadable = ring_buffer_readable(sDebugSyslogBuffer);
|
||||
gKernelArgs.previous_debug_size = bytesReadable;
|
||||
}
|
||||
|
||||
if (bytesReadable != 0) {
|
||||
if (uint8* buffer = (uint8*)kernel_args_malloc(bytesReadable)) {
|
||||
ring_buffer_read(sDebugSyslogBuffer, buffer, bytesReadable);
|
||||
gKernelArgs.previous_debug_output = buffer;
|
||||
} else
|
||||
gKernelArgs.previous_debug_size = 0;
|
||||
}
|
||||
|
||||
// Prepare the debug syslog buffer for this session.
|
||||
size_t signatureLength = strlen(kDebugSyslogSignature);
|
||||
void* buffer
|
||||
= (void*)ROUNDDOWN((addr_t)sDebugSyslogBuffer, B_PAGE_SIZE);
|
||||
|
||||
@@ -13,8 +13,17 @@
|
||||
|
||||
#include "blue_screen.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <cpu.h>
|
||||
#include <debug.h>
|
||||
@@ -39,13 +48,6 @@
|
||||
|
||||
#include <syslog_daemon.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "debug_builtin_commands.h"
|
||||
#include "debug_commands.h"
|
||||
#include "debug_output_filter.h"
|
||||
@@ -106,6 +108,9 @@ static size_t sSyslogDebuggerOffset = 0;
|
||||
// (relative) buffer offset of the kernel debugger messages of the current
|
||||
// KDL session
|
||||
|
||||
static void* sPreviousSessionSyslogBuffer = NULL;
|
||||
static size_t sPreviousSessionSyslogBufferSize = 0;
|
||||
|
||||
static const char* sCurrentKernelDebuggerMessagePrefix;
|
||||
static const char* sCurrentKernelDebuggerMessage;
|
||||
static va_list sCurrentKernelDebuggerMessageArgs;
|
||||
@@ -1406,6 +1411,17 @@ syslog_init_post_vm(struct kernel_args* args)
|
||||
args->debug_size, false);
|
||||
}
|
||||
|
||||
// Allocate memory for the previous session's debug syslog output. In
|
||||
// syslog_init_post_modules() we'll write it back to disk and free it.
|
||||
if (args->previous_debug_output != NULL) {
|
||||
sPreviousSessionSyslogBuffer = malloc(args->previous_debug_size);
|
||||
if (sPreviousSessionSyslogBuffer != NULL) {
|
||||
sPreviousSessionSyslogBufferSize = args->previous_debug_size;
|
||||
memcpy(sPreviousSessionSyslogBuffer, args->previous_debug_output,
|
||||
sPreviousSessionSyslogBufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
char revisionBuffer[64];
|
||||
length = snprintf(revisionBuffer, sizeof(revisionBuffer),
|
||||
"Welcome to syslog debug output!\nHaiku revision: %s\n",
|
||||
@@ -1429,6 +1445,28 @@ err1:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
syslog_init_post_modules()
|
||||
{
|
||||
if (sPreviousSessionSyslogBuffer == NULL)
|
||||
return;
|
||||
|
||||
void* buffer = sPreviousSessionSyslogBuffer;
|
||||
size_t bufferSize = sPreviousSessionSyslogBufferSize;
|
||||
sPreviousSessionSyslogBuffer = NULL;
|
||||
sPreviousSessionSyslogBufferSize = 0;
|
||||
MemoryDeleter bufferDeleter(buffer);
|
||||
|
||||
int fd = open("/var/log/previous_syslog", O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd < 0) {
|
||||
dprintf("Failed to open previous syslog file: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
write(fd, buffer, bufferSize);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static status_t
|
||||
syslog_init(struct kernel_args* args)
|
||||
@@ -1713,7 +1751,7 @@ debug_init_post_settings(struct kernel_args* args)
|
||||
void
|
||||
debug_init_post_modules(struct kernel_args* args)
|
||||
{
|
||||
void* cookie;
|
||||
syslog_init_post_modules();
|
||||
|
||||
// check for dupped lines every 10/10 second
|
||||
register_kernel_daemon(check_pending_repeats, NULL, 10);
|
||||
@@ -1724,7 +1762,7 @@ debug_init_post_modules(struct kernel_args* args)
|
||||
|
||||
static const char* kDemanglePrefix = "debugger/demangle/";
|
||||
|
||||
cookie = open_module_list("debugger");
|
||||
void* cookie = open_module_list("debugger");
|
||||
uint32 count = 0;
|
||||
while (count < kMaxDebuggerModules) {
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
|
||||
Reference in New Issue
Block a user