libroot: Add private __arch_get_stack_trace().

It can be used to get a stack trace of the current thread. Note that
this works by walking frame pointers and will not produce anything
useful if an application is compiled with the frame pointers omitted.

The stack base and end addresses have to be provided as arguments and
are used to check that the frame pointers fall within that range. These
values are thread specific and can be retrieved with get_thread_info().
No other sanity checks (like checking for loops in the linked list) are
done.

This is a simplified rewrite of the stack trace code from the kernel
debugger.

As this code is common to x86 and x86_64 but is not generic across
architectures I introduced x86_common as a directory to put such
sources.
This commit is contained in:
Michael Lotz 2015-04-11 23:21:50 +02:00
parent 9ac1c4c25e
commit c012e7e930
4 changed files with 62 additions and 1 deletions

View File

@ -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);

View File

@ -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
;
}
}

View File

@ -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
;
}

View File

@ -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 <libroot_private.h>
/*! 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;
}