Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
StackTrace.hGo 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 |