diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index 85036df0bf..1d5fad3045 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -44,6 +44,8 @@ bigtime_t __get_system_time_offset(); void __init_pwd_backend(void); void __reinit_pwd_backend_after_fork(void); void* __arch_get_caller(void); +int32 __arch_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipFrames, addr_t stackBase, addr_t stackEnd); void __set_stack_protection(void); diff --git a/src/system/libroot/os/arch/x86/Jamfile b/src/system/libroot/os/arch/x86/Jamfile index e04e18a5d6..98821562b8 100644 --- a/src/system/libroot/os/arch/x86/Jamfile +++ b/src/system/libroot/os/arch/x86/Jamfile @@ -17,6 +17,8 @@ for architectureObject in [ MultiArchSubDirSetup x86 x86_gcc2 ] { ; } + SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) x86_common ] ; + MergeObject <$(architecture)>os_arch_$(TARGET_ARCH).o : atomic.S byteorder.S @@ -28,6 +30,9 @@ for architectureObject in [ MultiArchSubDirSetup x86 x86_gcc2 ] { tls.c $(compatibilitySources) + + # sources from x86_common + stack_trace.cpp ; } } diff --git a/src/system/libroot/os/arch/x86_64/Jamfile b/src/system/libroot/os/arch/x86_64/Jamfile index fcf8b591bd..61d76d6335 100644 --- a/src/system/libroot/os/arch/x86_64/Jamfile +++ b/src/system/libroot/os/arch/x86_64/Jamfile @@ -12,7 +12,10 @@ for architectureObject in [ MultiArchSubDirSetup x86_64 ] { # TODO in time.c! UsePrivateSystemHeaders ; - SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + SEARCH_SOURCE += + [ FDirName $(SUBDIR) $(DOTDOT) generic ] + [ FDirName $(SUBDIR) $(DOTDOT) x86_common ] + ; MergeObject <$(architecture)>os_arch_$(TARGET_ARCH).o : byteorder.S @@ -23,6 +26,10 @@ for architectureObject in [ MultiArchSubDirSetup x86_64 ] { time.cpp tls.cpp + # sources from x86_common + stack_trace.cpp + + # sources from generic generic_atomic.cpp ; } diff --git a/src/system/libroot/os/arch/x86_common/stack_trace.cpp b/src/system/libroot/os/arch/x86_common/stack_trace.cpp new file mode 100644 index 0000000000..48b82ae0df --- /dev/null +++ b/src/system/libroot/os/arch/x86_common/stack_trace.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + +#include + + +/*! 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 skipFrames The number of stack frames that shall be skipped. + \param stackBase The base address of the thread stack. + \param stackEnd The first address past the thread stack. + \return The number of return addresses written to the given array. +*/ +int32 +__arch_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipFrames, addr_t stackBase, addr_t stackEnd) +{ + int32 count = 0; + addr_t basePointer = (addr_t)get_stack_frame(); + + while (basePointer != 0 && count < maxCount) { + if (basePointer < stackBase || basePointer >= stackEnd) + break; + + struct stack_frame { + addr_t previous; + addr_t return_address; + }; + + stack_frame* frame = (stack_frame*)basePointer; + + if (skipFrames <= 0) + returnAddresses[count++] = frame->return_address; + else + skipFrames--; + + basePointer = frame->previous; + } + + return count; +}