From 46ec23016212f35b99bc1ba02b7421eb287033e1 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 12 Aug 2008 17:09:42 +0000 Subject: [PATCH] When in the kernel debugger we do now record the relevant information (fault address, pc, read/write) when a page fault occurs, and print them in case this caused the termination of a debugger command. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26949 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/debug.h | 25 ++++++++--- src/system/kernel/arch/x86/arch_int.c | 4 +- src/system/kernel/debug/debug.cpp | 51 ++++++++++++++-------- src/system/kernel/debug/debug_commands.cpp | 13 +++++- 4 files changed, 69 insertions(+), 24 deletions(-) diff --git a/headers/private/kernel/debug.h b/headers/private/kernel/debug.h index ddd8cb131b..4badc0c87f 100644 --- a/headers/private/kernel/debug.h +++ b/headers/private/kernel/debug.h @@ -16,8 +16,8 @@ #define KDEBUG 1 #if DEBUG -/* - * The kernel debug level. +/* + * The kernel debug level. * Level 1 is usual asserts, > 1 should be used for very expensive runtime checks */ # define KDEBUG 1 @@ -37,7 +37,7 @@ #if KDEBUG # define ASSERT(x) ASSERT_ALWAYS(x) # define ASSERT_PRINT(x, format...) ASSERT_ALWAYS_PRINT(x, format) -#else +#else # define ASSERT(x) do { } while(0) # define ASSERT_PRINT(x, format...) do { } while(0) #endif @@ -69,6 +69,18 @@ struct debugger_module_info { extern int dbg_register_file[B_MAX_CPU_COUNT][14]; +typedef struct debug_page_fault_info { + addr_t fault_address; + addr_t pc; + uint32 flags; +} debug_page_fault_info; + +// debug_page_fault_info::flags +#define DEBUG_PAGE_FAULT_WRITE 0x01 /* write fault */ +#define DEBUG_PAGE_FAULT_NO_INFO 0x02 /* fault address and read/write + unknown */ + + #ifdef __cplusplus extern "C" { #endif @@ -83,6 +95,9 @@ extern void debug_puts(const char *s, int32 length); extern bool debug_debugger_running(void); extern bool debug_screen_output_enabled(void); extern void debug_stop_screen_debug_output(void); +extern void debug_set_page_fault_info(addr_t faultAddress, addr_t pc, + uint32 flags); +extern debug_page_fault_info* debug_get_page_fault_info(); extern void kputs(const char *string); extern void kputs_unfiltered(const char *string); @@ -109,11 +124,11 @@ extern status_t add_debugger_command_alias(const char* newName, const char* oldName, const char* description); extern bool print_debugger_command_usage(const char* command); -extern void _user_debug_output(const char *userString); - extern void debug_set_demangle_hook(const char *(*hook)(const char *)); extern const char *debug_demangle(const char *); +extern void _user_debug_output(const char *userString); + #ifdef __cplusplus } #endif diff --git a/src/system/kernel/arch/x86/arch_int.c b/src/system/kernel/arch/x86/arch_int.c index 47defdadad..16a663ac46 100644 --- a/src/system/kernel/arch/x86/arch_int.c +++ b/src/system/kernel/arch/x86/arch_int.c @@ -222,7 +222,7 @@ x86_set_task_gate(int32 n, int32 segment) /** Tests if the interrupt in-service register of the responsible - * PIC is set for interrupts 7 and 15, and if that's not the case, + * PIC is set for interrupts 7 and 15, and if that's not the case, * it must assume it's a spurious interrupt. */ @@ -838,6 +838,8 @@ page_fault_exception(struct iframe* frame) if (kernelDebugger) { // if this thread has a fault handler, we're allowed to be here if (thread && thread->fault_handler != 0) { + debug_set_page_fault_info(cr2, frame->eip, + (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); frame->eip = thread->fault_handler; return; } diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 3b39d04ddd..c5bab56ab2 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -49,6 +49,8 @@ extern "C" int kgets(char *buffer, int length); int dbg_register_file[B_MAX_CPU_COUNT][14]; /* XXXmpetit -- must be made generic */ +static debug_page_fault_info sPageFaultInfo; + static bool sSerialDebugEnabled = true; static bool sSyslogOutputEnabled = true; static bool sBlueScreenEnabled = false; @@ -1132,6 +1134,22 @@ debug_init_post_modules(struct kernel_args *args) } +void +debug_set_page_fault_info(addr_t faultAddress, addr_t pc, uint32 flags) +{ + sPageFaultInfo.fault_address = faultAddress; + sPageFaultInfo.pc = pc; + sPageFaultInfo.flags = flags; +} + + +debug_page_fault_info* +debug_get_page_fault_info() +{ + return &sPageFaultInfo; +} + + // #pragma mark - public API @@ -1392,6 +1410,22 @@ kprintf_unfiltered(const char *format, ...) } +extern void +debug_set_demangle_hook(const char *(*hook)(const char *)) +{ + sDemangleHook = hook; +} + + +extern const char * +debug_demangle(const char *sym) +{ + if (sDemangleHook) + return sDemangleHook(sym); + return sym; +} + + // #pragma mark - // userland syscalls @@ -1451,20 +1485,3 @@ dump_block(const char *buffer, int size, const char *prefix) dprintf("\n"); } } - - -extern void -debug_set_demangle_hook(const char *(*hook)(const char *)) -{ - sDemangleHook = hook; -} - - -extern const char * -debug_demangle(const char *sym) -{ - if (sDemangleHook) - return sDemangleHook(sym); - return sym; -} - diff --git a/src/system/kernel/debug/debug_commands.cpp b/src/system/kernel/debug/debug_commands.cpp index 6e6bc890eb..469f5f6199 100644 --- a/src/system/kernel/debug/debug_commands.cpp +++ b/src/system/kernel/debug/debug_commands.cpp @@ -299,8 +299,19 @@ error: INVOKE_COMMAND_FAULT); case INVOKE_COMMAND_FAULT: - kprintf_unfiltered("\n[*** READ/WRITE FAULT ***]\n"); + { + debug_page_fault_info* info = debug_get_page_fault_info(); + if ((info->flags & DEBUG_PAGE_FAULT_NO_INFO) == 0) { + kprintf_unfiltered("\n[*** %s FAULT at %#lx, pc: %#lx ***]\n", + (info->flags & DEBUG_PAGE_FAULT_NO_INFO) != 0 + ? "WRITE" : "READ", + info->fault_address, info->pc); + } else { + kprintf_unfiltered("\n[*** READ/WRITE FAULT (?), " + "pc: %#lx ***]\n", info->pc); + } break; + } case INVOKE_COMMAND_ERROR: // command aborted (no page fault) break;