Note that the virtual frame pointer of an invocation is not the value
used by the procedure itself for addressing. The contents of the SP register
are modified in the procedure prologue and the resulting real frame pointer
value is then sometimes copied into FP (as in the case of a variable size
stack frame). The real frame pointer is always used for addressing local
storage throughout the remainder of the procedure.
The real frame pointer is not, by itself, sufficient to unambiguously
identify all possible procedure invocations. For example, a null frame procedure
has the same real frame pointer as its caller because the null frame procedure
allocates no stack storage. This ambiguity is of no consequence for the purposes
of this calling standard because the real frame pointer value is always used
in combination with a program counter value that identifies an instruction
within a particular procedure.
The static link used in calling nested procedures in languages such
as Pascal and Ada is usually the virtual frame pointer or the real frame pointer
value. The choice is implementation-dependent and can vary from language
to language and release to release.
The full context of a specific procedure invocation is provided through
the use of the sigcontext data structure.
The sigcontext structure is defined
in the file /usr/include/signal.h.
7.1 Referencing a Procedure Invocation
When a reference to a
specific procedure invocation is made at run time, the virtual frame pointer
or the real frame pointer for that invocation can be used. The virtual frame pointer
of a procedure invocation is the
contents of the stack pointer
at the
entry point of the procedure. The real frame pointer
of a procedure is the contents of the
stack pointer after the size of the fixed part of the stack frame has been
subtracted from the virtual frame pointer.
7.2 Providing a Procedure Invocation Context
A thread can
obtain its own context by calling a system library function defined as follows:
exc_capture_context (ContextRecord)
Arguments:
ContextRecord | Address of a sigcontext structure into which the procedure context of the caller is written |
exc_virtual_unwind (FunctionEntry, ContextRecord)
FunctionEntry | Address of the function table entry for the function. If zero, the function table entry is looked up using the PC from ContextRecord. |
ContextRecord | Address of a sigcontext structure. The given structure is updated to represent the context of the previous (calling) frame. |
InPrologueOrEpilogue | If 1, indicates that the resulting program counter value in the given ContextRecord is within the prologue or the epilogue code of the function. If zero, indicates that the program counter is in the body of the function. |
There are two steps for performing call chain navigation:
For the current routine, an initial sigcontext structure
can be obtained by calling exc_capture_context().
Compilers are allowed to optimize high-level language procedure calls
so that they do not appear in the call chain. For example, inline procedures
never appear in the call chain.
No assumptions should be made about the relative positions of any memory
used for procedure frame information. There is no guarantee that successive
stack frames will always appear at higher addresses.
7.3 Walking the Call Chain
During program execution,
it is sometimes necessary to navigate (walk) the call chain. For example,
frame-based exception handling requires call chain navigation. Call-chain
navigation is possible only in the reverse direction; for example, latest-to-earliest
procedure, or top to bottom procedure.