From e670fc6f6346a09cd96a8ef01742e835086bb458 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 15 Sep 2008 13:09:14 +0000 Subject: [PATCH] Added new parameter "skipIframes" to arch_debug_get_stack_trace(). That many iframes are supposed to be skipped before recording the stack trace. Currently implemented for x86 only. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27529 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/debug.h | 2 +- src/system/kernel/arch/m68k/arch_debug.cpp | 3 ++- src/system/kernel/arch/ppc/arch_debug.cpp | 9 +++++++ src/system/kernel/arch/x86/arch_debug.cpp | 26 ++++++++++++++++--- src/system/kernel/debug/tracing.cpp | 3 ++- .../kernel/device_manager/io_requests.cpp | 2 +- src/system/kernel/heap.cpp | 2 +- 7 files changed, 39 insertions(+), 8 deletions(-) diff --git a/headers/private/kernel/arch/debug.h b/headers/private/kernel/arch/debug.h index 6efbb5db9b..6d79e579fc 100644 --- a/headers/private/kernel/arch/debug.h +++ b/headers/private/kernel/arch/debug.h @@ -22,7 +22,7 @@ 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); + int32 skipIframes, int32 skipFrames, bool userOnly); void *arch_debug_get_interrupt_pc(); bool arch_debug_contains_call(struct thread *thread, const char *symbol, addr_t start, addr_t end); diff --git a/src/system/kernel/arch/m68k/arch_debug.cpp b/src/system/kernel/arch/m68k/arch_debug.cpp index 155467f049..05da44cd91 100644 --- a/src/system/kernel/arch/m68k/arch_debug.cpp +++ b/src/system/kernel/arch/m68k/arch_debug.cpp @@ -286,8 +286,9 @@ arch_debug_get_caller(void) int32 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, - int32 skipFrames, bool userOnly) + int32 skipIframes, int32 skipFrames, bool userOnly) { +// TODO: Support skipIframes! struct iframe_stack *frameStack; addr_t framePointer; int32 count = 0; diff --git a/src/system/kernel/arch/ppc/arch_debug.cpp b/src/system/kernel/arch/ppc/arch_debug.cpp index 86144f1f76..b642946477 100644 --- a/src/system/kernel/arch/ppc/arch_debug.cpp +++ b/src/system/kernel/arch/ppc/arch_debug.cpp @@ -286,6 +286,15 @@ arch_debug_get_caller(void) } +int32 +arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipIframes, int32 skipFrames, bool userOnly) +{ + // TODO: Implement! + return 0; +} + + void* arch_debug_get_interrupt_pc() { diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index cc81a129a7..50ee2da4b1 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -746,12 +746,27 @@ arch_debug_get_caller(void) } +/*! Captures a stack trace (the return addresses) of the current thread. + \param returnAddresses The array the return address shall be written to. + \param maxCount The maximum number of return addresses to be captured. + \param skipIframes The number of interrupt frames that shall be skipped. If + greater than 0, \a skipFrames is ignored. + \param skipFrames The number of stack frames that shall be skipped. + \param userOnly If \c true, only userland return addresses are captured. + \return The number of return addresses written to the given array. +*/ int32 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, - int32 skipFrames, bool userOnly) + int32 skipIframes, int32 skipFrames, bool userOnly) { - // always skip our own frame - skipFrames++; + // Keep skipping normal stack frames until we've skipped the iframes we're + // supposed to skip. + if (skipIframes > 0) { + skipFrames = INT_MAX; + } else { + // always skip our own frame + skipFrames++; + } struct thread* thread = thread_get_current_thread(); int32 count = 0; @@ -769,6 +784,11 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, struct iframe *frame = (struct iframe*)ebp; eip = frame->eip; nextEbp = frame->ebp; + + if (skipIframes > 0) { + if (--skipIframes == 0) + skipFrames = 1; + } } else { if (get_next_frame(ebp, &nextEbp, &eip) != B_OK) break; diff --git a/src/system/kernel/debug/tracing.cpp b/src/system/kernel/debug/tracing.cpp index b857676424..17390fc367 100644 --- a/src/system/kernel/debug/tracing.cpp +++ b/src/system/kernel/debug/tracing.cpp @@ -1158,7 +1158,8 @@ capture_tracing_stack_trace(int32 maxCount, int32 skipFrames, bool userOnly) if (stackTrace != NULL) { stackTrace->depth = arch_debug_get_stack_trace( - stackTrace->return_addresses, maxCount, skipFrames + 1, userOnly); + stackTrace->return_addresses, maxCount, 0, skipFrames + 1, + userOnly); } return stackTrace; diff --git a/src/system/kernel/device_manager/io_requests.cpp b/src/system/kernel/device_manager/io_requests.cpp index 54f6af9017..2bd8186444 100644 --- a/src/system/kernel/device_manager/io_requests.cpp +++ b/src/system/kernel/device_manager/io_requests.cpp @@ -1224,7 +1224,7 @@ get_caller() // this makes certain assumptions about how the code for the functions // ends up in the kernel object. addr_t returnAddresses[5]; - int32 depth = arch_debug_get_stack_trace(returnAddresses, 5, 1, false); + int32 depth = arch_debug_get_stack_trace(returnAddresses, 5, 0, 1, false); // find the first return address inside the VIP allocator int32 i = 0; diff --git a/src/system/kernel/heap.cpp b/src/system/kernel/heap.cpp index f2f72988a6..000593b7e5 100644 --- a/src/system/kernel/heap.cpp +++ b/src/system/kernel/heap.cpp @@ -267,7 +267,7 @@ get_caller() // this makes certain assumptions about how the code for the functions // ends up in the kernel object. addr_t returnAddresses[5]; - int32 depth = arch_debug_get_stack_trace(returnAddresses, 5, 1, false); + int32 depth = arch_debug_get_stack_trace(returnAddresses, 5, 0, 1, false); for (int32 i = 0; i < depth; i++) { if (returnAddresses[i] < (addr_t)&get_caller || returnAddresses[i] > (addr_t)&malloc_referenced_release) {