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 #include <stdlib.h>
00005 
00006 #ifdef __cplusplus
00007 //! Holds the C-style interface for the stack trace routines
00008 namespace stacktrace {
00009 extern "C" {
00010 #endif /* __cplusplus */
00011 
00012 typedef int machineInstruction; //!< typedef in case type needs to change on other platforms (i.e. long for 64 bit architectures?)
00013 
00014 //! Must be called with the object file containing debugging symbols before symbolic output can be displayed
00015 /*! @param objfile the file containing debugging symbols, in a format supported by libBFD; generally this is the executable itself (compiled with -g), so pass argv[0]
00016  *
00017  *  Display done before this has been called will display numeric addresses, which may
00018  *  still be decoded externally -- this is handy for embedded systems which may not be
00019  *  able to hold the debugging symbols and BFD library themselves, but the numerical
00020  *  values can be looked up on the desktop workstation.
00021  *  @return zero on success, negative if file could not be found, positive if it could not be parsed (wrong file type) or any other internal error */
00022 int loadStackTraceSymbols(const char* objfile);
00023   
00024 //! Stores information about a single stack frame
00025 struct StackFrame {
00026 
00027   //! stack pointer, points to end of stack frame
00028   void * sp; 
00029 
00030 #ifdef __pic__
00031   //! return address, points to instruction being executed within current frame
00032   /*! Note that this is the address that is being returned to by the @e sub-function,
00033    *  @e not the address that this frame itself is returning to.
00034    *  When executing position independent code (pic), this is the address relative
00035    *  to #gp.  In other words, subtract this from #gp to get current memory address,
00036    *  or subtract from the binary's _gp symbol to get link-time address (for looking up file/line) */
00037   size_t ra; 
00038   
00039   //! global offset used in position independent code (pic)
00040   /*! subtract #ra from this to get the actual run-time memory address of the instruction */
00041   size_t gp;
00042 
00043 #else
00044   //! return address, points to instruction being executed within current frame
00045   /*! Note that this is the address that is being returned to by the @e sub-function,
00046    *  @e not the address that this frame itself is returning to. */
00047   machineInstruction * ra; 
00048 #endif /* __pic__ */
00049 
00050   //! 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
00051   /*! a self-referential value indicates the frame is not the last on the stack, but is the last recorded. */
00052   struct StackFrame * caller;
00053 
00054 #ifdef DEBUG_STACKTRACE
00055   //! if DEBUG_STACKTRACE is defined, this field is available which, if non-zero, will cause debugging info to be displayed on each unroll
00056   int debug;
00057 #endif
00058 };
00059 
00060 
00061 //! stores information about the caller's stack frame into @a frame
00062 void getCurrentStackFrame(struct StackFrame* frame);
00063 
00064 //! stores information about the caller to @a curFrame into @a nextFrame
00065 /*! @return 0 if error occurred (i.e. bottom of the stack), non-zero upon success
00066  *  @a nextFrame @e can be the same instance as @a curFrame, will update in place.
00067  *  @a curFrame->caller will be set to @a nextFrame. */
00068 int unrollStackFrame(struct StackFrame* curFrame, struct StackFrame* nextFrame);
00069 
00070 //! frees a list of StackFrames, such as is returned by recordStackTrace
00071 void freeStackTrace(struct StackFrame* frame);
00072 
00073 //! preallocates a stack trace of a particular size (doesn't actually perform a stack trace, merely allocates the linked list)
00074 /*! 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 */
00075 struct StackFrame* allocateStackTrace(unsigned int size);
00076 
00077 //! dumps stored stack trace to stderr
00078 void displayStackTrace(const struct StackFrame* frame);
00079 
00080 #ifndef __cplusplus
00081 
00082 //! dumps current stack trace to stderr, up to @a limit depth and skipping the top @a skip frames
00083 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00084 void displayCurrentStackTrace(unsigned int limit, unsigned int skip);
00085 
00086 //! repeatedly calls unrollStackFrame() until the root frame is reached or @a limit is hit, skipping the top @a skip frames
00087 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00088 struct StackFrame * recordStackTrace(unsigned int limit, unsigned int skip);
00089 //! repeatedly calls unrollStackFrame() until the root frame is reached or end of @a frame list is hit, skipping the top @a skip frames
00090 /*! 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) */
00091 struct StackFrame * recordOverStackTrace(struct StackFrame* frame, unsigned int skip);
00092 
00093 #else /* __cplusplus */
00094 
00095 //! dumps current stack trace to stderr, up to @a limit depth and skipping the top @a skip frames
00096 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00097 void displayCurrentStackTrace(unsigned int limit=-1U, unsigned int skip=0);
00098 
00099 //! repeatedly calls unrollStackFrame() until the root frame is reached or @a limit is hit, skipping the top @a skip frames
00100 /*! pass -1U for limit to request unlimited trace, and 0 to start with the function calling recordStackTrace */
00101 struct StackFrame * recordStackTrace(unsigned int limit=-1U, unsigned int skip=0);
00102 //! repeatedly calls unrollStackFrame() until the root frame is reached or end of @a frame list is hit, skipping the top @a skip frames
00103 /*! 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) */
00104 struct StackFrame * recordOverStackTrace(struct StackFrame* frame, unsigned int skip=0);
00105 
00106 }
00107 }
00108 
00109 #endif /* __cplusplus */
00110 
00111 /*! @file
00112  * @brief Describes functionality for performing stack traces
00113  * @author ejt (Creator)
00114  *
00115  * $Author: ejt $
00116  * $Name: tekkotsu-4_0 $
00117  * $Revision: 1.6 $
00118  * $State: Exp $
00119  * $Date: 2006/05/02 20:46:27 $
00120  */
00121 #endif

Tekkotsu v4.0
Generated Thu Nov 22 00:54:56 2007 by Doxygen 1.5.4