Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

StackTrace.h

Go to the documentation of this file.
00001 #ifndef INCLUDED_StackTrace_h_
00002 #define INCLUDED_StackTrace_h_
00003 
00004 #ifdef __APPLE__
00005 #  include <AvailabilityMacros.h>
00006 #endif
00007 // Aperios and Mac OS X 10.4 and prior need the "manual" unroll; otherwise assume execinfo.h and backtrace() are available
00008 #if !defined(PLATFORM_APERIOS) && (!defined(__APPLE__) || defined(MAC_OS_X_VERSION_10_5))
00009 #  define STACKTRACE_USE_BACKTRACE
00010 #endif
00011 
00012 #ifndef __cplusplus
00013 #  include <stddef.h>
00014 
00015 #else
00016 #  include <cstddef>
00017 //! Holds the C-style interface for the stack trace routines
00018 namespace stacktrace {
00019 extern "C" {
00020 #endif /* __cplusplus */
00021 
00022 typedef int machineInstruction; //!< typedef in case type needs to change on other platforms (i.e. long for 64 bit architectures?)
00023 
00024 //! Stores information about a single stack frame
00025 struct StackFrame {
00026 
00027 #ifdef STACKTRACE_USE_BACKTRACE
00028   //! pointer to array of return addresses, shared by all StackFrames in the list
00029   void*** packedRA;
00030   //! pointer to number of entries available at #packedRA
00031   size_t* packedRAUsed;
00032   //! pointer to size of array at #packedRA
00033   size_t* packedRACap;
00034   //! entry in #packedRA corresponding to this frame
00035   size_t depth;
00036   //! return address, points to instruction being executed within current frame
00037   void* ra;
00038 #else
00039   //! stack pointer, points to end of stack frame
00040   void * sp; 
00041 
00042 #  if defined(__PIC__) && (defined(__MIPSEL__) || defined(__MIPS__))
00043   //! return address, points to instruction being executed within current frame
00044   /*! Note that this is the address that is being returned to by the @e sub-function,
00045    *  @e not the address that this frame itself is returning to.
00046    *  When executing position independent code (PIC), this is the address relative
00047    *  to #gp.  In other words, subtract this from #gp to get current memory address,
00048    *  or subtract from the binary's _gp symbol to get link-time address (for looking up file/line) */
00049   size_t ra; 
00050   
00051   //! global offset used in position independent code (PIC)
00052   /*! subtract #ra from this to get the actual run-time memory address of the instruction */
00053   size_t gp;
00054 
00055 #  else
00056   //! return address, points to instruction being executed within current frame
00057   /*! Note that this is the address that is being returned to by the @e sub-function,
00058    *  @e not the address that this frame itself is returning to. */
00059   machineInstruction * ra; 
00060 #  endif /* __PIC__ */
00061 
00062 #  ifdef DEBUG_STACKTRACE
00063   //! if DEBUG_STACKTRACE is defined, this field is available which, if non-zero, will cause debugging info to be displayed on each unroll
00064   int debug;
00065 #  endif
00066 #endif
00067   
00068   //! points to the caller's stack frame (stack frame of function which called this one), may be NULL or self-referential at end of list
00069   /*! a self-referential value indicates the frame is not the last on the stack, but is the last recorded. */
00070   struct StackFrame * caller;
00071   
00072 };
00073 
00074 
00075 //! stores information about the caller's stack frame into @a frame
00076 void getCurrentStackFrame(struct StackFrame* frame);
00077 
00078 //! stores information about the caller to @a curFrame into @a nextFrame
00079 /*! @return 0 if error occurred (i.e. bottom of the stack), non-zero upon success
00080  *  @a nextFrame @e can be the same instance as @a curFrame, will update in place.
00081  *  @a curFrame->caller will be set to @a nextFrame. */
00082 int unrollStackFrame(struct StackFrame* curFrame, struct StackFrame* nextFrame);
00083 
00084 //! frees a list of StackFrames, such as is returned by recordStackTrace
00085 void freeStackTrace(struct StackFrame* frame);
00086 
00087 //! preallocates a stack trace of a particular size (doesn't actually perform a stack trace, merely allocates the linked list)
00088 /*! this is a good idea if you want to do a stack trace within an exception handler, which might have been triggered by running out of heap */
00089 struct StackFrame* allocateStackTrace(unsigned int size);
00090 
00091 //! dumps stored stack trace to stderr
00092 void displayStackTrace(const struct StackFrame* frame);
00093 
00094 #ifndef __cplusplus
00095 
00096 //! dumps current stack trace to stderr, up to @a limit depth and skipping the top @a skip frames
00097 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00098 void displayCurrentStackTrace(unsigned int limit, unsigned int skip);
00099 
00100 //! repeatedly calls unrollStackFrame() until the root frame is reached or @a limit is hit, skipping the top @a skip frames
00101 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00102 struct StackFrame * recordStackTrace(unsigned int limit, unsigned int skip);
00103 //! repeatedly calls unrollStackFrame() until the root frame is reached or end of @a frame list is hit, skipping the top @a skip frames
00104 /*! This is handy for reusing previously allocated frames, returns the unused portion (if return value equals @a frame, none were used -- implies never cleared @a skip) */
00105 struct StackFrame * recordOverStackTrace(struct StackFrame* frame, unsigned int skip);
00106 
00107 #else /* __cplusplus */
00108 
00109 //! dumps current stack trace to stderr, up to @a limit depth and skipping the top @a skip frames
00110 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00111 void displayCurrentStackTrace(unsigned int limit=-1U, unsigned int skip=0);
00112 
00113 //! repeatedly calls unrollStackFrame() until the root frame is reached or @a limit is hit, skipping the top @a skip frames
00114 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00115 struct StackFrame * recordStackTrace(unsigned int limit=-1U, unsigned int skip=0);
00116 //! repeatedly calls unrollStackFrame() until the root frame is reached or end of @a frame list is hit, skipping the top @a skip frames
00117 /*! This is handy for reusing previously allocated frames, returns the unused portion (if return value equals @a frame, none were used -- implies never cleared @a skip) */
00118 struct StackFrame * recordOverStackTrace(struct StackFrame* frame, unsigned int skip=0);
00119 
00120 }
00121 }
00122 
00123 #endif /* __cplusplus */
00124 
00125 /*! @file
00126  * @brief Describes functionality for performing stack traces
00127  * @author ejt (Creator)
00128  */
00129 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:51 2016 by Doxygen 1.6.3