\subsubsection{Class FrameStepper}\label{subsec:framestepper} \definedin{framestepper.h} The \code{FrameStepper} class is an interface that tells StackwalkerAPI how to walk through a specific type of stack frame. There may be many different ways of walking through a stack frame on a platform, e.g, on Linux/x86 there are different mechanisms for walking through system calls, signal handlers, regular functions, and frameless functions. A single \code{FrameStepper} describes how to walk through one of these types of stack frames. A user can create their own \code{FrameStepper} classes that tell StackwalkerAPI how to walk through new types of stack frames. A new \code{FrameStepper} object must be added to a \code{StepperGroup} before it can be used. In addition to walking through individual stack frames, a \code{FrameStepper} tells its \code{StepperGroup} when it can be used. The \code{FrameStepper} registers address ranges that cover objects in the target process' code space (such as functions). These address ranges should contain the objects that will create stack frames through which the \code{FrameStepper} can walk. If multiple \code{FrameStepper} objects have overlapping address ranges, then a priority value is used to determine which \code{FrameStepper} should be attempted first. \code{FrameStepper} is an interface class; it cannot be instantiated. Users who want to develop new \code{FrameStepper} objects should inherit from this class and implement the the desired virtual functions. The \code{getCallerFrame, getPriority}, and \code{getName} functions must be implemented; all others may be overridden if desired. \begin{apient} typedef enum { gcf_success, gcf_stackbottom, gcf_not_me, gcf_error } gcframe_ret_t \end{apient} \begin{apient} virtual gcframe_ret_t getCallerFrame(const Frame &in, Frame &out) = 0 \end{apient} \apidesc{ This method walks through a single stack frame and generates a Frame object that represents the caller's stack frame. Parameter in will be a Frame object that this FrameStepper is capable of walking through. Parameter out is an output parameter that this method should set to the Frame object that called in. There may be multiple ways of walking through a different types of stack frames. Each \code{FrameStepper} class should be able to walk through a type of stack frame. For example, on x86 one \code{FrameStepper} could be used to walk through stack frames generated by ABI-compliant functions; out's FP and RA are found by reading from in's FP, and out's SP is set to the word below in's FP. A different \code{FrameStepper} might be used to walk through stack frames created by functions that have optimized away their FP. In this case, in may have a FP that does not point out's FP and RA. The \code{FrameStepper} will need to use other mechanisms to discover out's FP or RA; perhaps the \code{FrameStepper} searches through the stack for the RA or performs analysis on the function that created the stack frame. If \code{getCallerFrame} successfully walks through in, it is required to set the following parameters in out. See Section~\ref{subsec:frame} for more details on the values that can be set in a Frame object: \begin{description} \item [Return Address (RA)] The RA should be set with the \code{Frame::setRA} method. \item [Stack Pointer (SP)] The SP should be set with the \code{Frame::setSP} method. \item [Frame Pointer (FP)] The FP should be set with the \code{Frame::setFP} method \end{description} Optionally, getCallerFrame can also set any of following parameters in out: \begin{description} \item [Return Address Location (RALocation)] The RALocation should be set with the \code{Frame::setRALocation()} method. \item [Stack Pointer Location (SPLocation)] The SPLocation should be set with the \code{Frame::setRALocation()} method. \item [Frame Pointer Location (FPLocation)] The FPLocation should be set with the \code{Frame::setFPLocation()} method. \end{description} If a location field in out is not set, then the appropriate \code{Frame::getRALocation}, \code{Frame::getSPLocation} or \code{Frame::getFPLocation} method will return \code{loc\_unknown}. \code{getCallerFrame} should return \code{gcf\_success} if it successfully walks through in and creates an \code{out} \code{Frame} object. It should return \code{gcf\_stackbottom} if in is the bottom of the stack and there are no stack frames below it. It should return \code{gcf\_not\_me} if in is not the correct type of stack frame for this \code{FrameStepper} to walk through. StackwalkerAPI will then attempt to locate another \code{FrameStepper} to handle \code{in} or abort the stackwalk. It should return \code{gcf\_error} if there was an error and the stack walk should be aborted. } \begin{apient} virtual void registerStepperGroup(StepperGroup *steppergroup) \end{apient} \apidesc{ This method is used to notify a \code{FrameStepper} when StackwalkerAPI adds it to a \code{StepperGroup}. The \code{StepperGroup} to which this \code{FrameStepper} is being added is passed in parameter steppergroup. This method can be used to initialize the \code{FrameStepper} (in addition to any \code{FrameStepper} constructor). } \begin{apient} virtual unsigned getPriority() const = 0 \end{apient} \apidesc{ This method is used by the \code{StepperGroup} to decide which \code{FrameStepper} to use if multiple \code{FrameStepper} objects are registered over the same address range (see addAddressRanges in Section~\ref{subsec:steppergroup} for more information about address ranges). This method returns an integer representing a priority level, the lower the number the higher the priority. The default \code{FrameStepper} objects provided by StackwalkerAPI all return priorities between \code{0x1000} and \code{0x2000}. If two \code{FrameStepper} objects have an overlapping address range, and they have the same priority, then the order in which they are used is undefined. } \begin{apient} FrameStepper(Walker *w); \end{apient} \apidesc{Constructor definition for all \code{FrameStepper} instances.} \begin{apient} virtual ProcessState *getProcessState(); \end{apient} \apidesc{Return the \code{ProcessState} used by the \code{FrameStepper}. Can be overridden if the user desires.} \begin{apient} virtual Walker *getWalker(); \end{apient} \apidesc{Return the \code{Walker} associated with the \code{FrameStepper}. Can be overridden if the user desires.} \begin{apient} typedef std::pair LibAddrPair; typedef enum { library_load, library_unload } lib_change_t; virtual void newLibraryNotification(LibAddrPair *libAddr, lib_change_t change); \end{apient} \apidesc{This function is called when a new library is loaded by the process; it should be implemented if the \code{FrameStepper} requires such information.} \begin{apient} virtual const char *getName() const = 0; \end{apient} \apidesc{Returns a name for the \code{FrameStepper}; must be implemented by the user.}