From 4dd0a2c7b6c006741e8a14fbe8a3a1817e10e1ad Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 27 Apr 2008 02:54:27 +0000 Subject: [PATCH] Added arch_debug_get_stack_trace() that can be used to get a stack trace (the list of return addresses) for the current stack. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25204 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/debug.h | 4 ++- src/system/kernel/arch/x86/arch_debug.cpp | 44 ++++++++++++++++++++--- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/headers/private/kernel/arch/debug.h b/headers/private/kernel/arch/debug.h index c52b1d2f98..5a273bfa57 100644 --- a/headers/private/kernel/arch/debug.h +++ b/headers/private/kernel/arch/debug.h @@ -21,8 +21,10 @@ extern "C" { status_t arch_debug_init(kernel_args *args); void *arch_debug_get_caller(void); +int32 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipFrames, bool userOnly); bool arch_debug_contains_call(struct thread *thread, const char *symbol, - addr_t start, addr_t end); + addr_t start, addr_t end); void arch_debug_save_registers(int *); #ifdef __cplusplus diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index 2538fd5642..e0ae1302c4 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -582,15 +582,51 @@ arch_debug_contains_call(struct thread *thread, const char *symbol, void * arch_debug_get_caller(void) { - // It looks like you would get the wrong stack frame here, but - // since read_ebp() is an assembler inline macro, GCC seems to - // be smart enough to save its original value. struct stack_frame *frame = (struct stack_frame *)x86_read_ebp(); - return (void *)frame->previous->return_address; } +int32 +arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipFrames, bool userOnly) +{ + // always skip our own frame + skipFrames++; + + struct thread* thread = thread_get_current_thread(); + int32 count = 0; + addr_t ebp = x86_read_ebp(); + bool onKernelStack = true; + + while (ebp != 0 && count < maxCount) { + onKernelStack = onKernelStack + && is_kernel_stack_address(thread, ebp); + + addr_t eip; + addr_t nextEbp; + + if (onKernelStack && is_iframe(thread, ebp)) { + struct iframe *frame = (struct iframe*)ebp; + eip = frame->eip; + nextEbp = frame->ebp; + } else { + if (get_next_frame(ebp, &nextEbp, &eip) != B_OK) + break; + } + + if (skipFrames <= 0 && (!userOnly || IS_USER_ADDRESS(ebp))) + returnAddresses[count++] = eip; + else + skipFrames--; + + ebp = nextEbp; + } + + return count; +} + + status_t arch_debug_init(kernel_args *args) {