A thread can obtain its own context by calling a system library function defined as follows:
RtlCaptureContext( ContextRecord )
Arguments
ContextRecord
Address of an invocation context block into which the procedure context of the caller is written.
Function Value
None.
Remarks
The context corresponds to that of the called RtlCaptureContext() procedure. However, that context is the same as that of the caller except for the contents of R16, R26, and R28. The contents of R26 in the caller prior to the call can be obtained using RtlVirtualUnwind() (see below).
A thread can obtain the invocation context of the procedure preceding another procedure context by calling a system library function defined as:
RtlVirtualUnwind( ControlPc, FunctionEntry, ContextRecord, InFunction, EstablisherFrame, ContextPointers )
Arguments
ControlPc
Address where control left the function.
FunctionEntry
Address of the function table entry (which may be either a primary or secondary procedure descriptor, see Section 8.1) for the function. Note that the appropriate function table entry can be obtained using the function RtlLookupFunctionEntry() (see Section 8.2).
ContextRecord
Address of an invocation context block. The given context block is updated to represent the context of the previous (calling) frame.
InFunction
Address of an unsigned byte (type Boolean) where the value 0 or 1 is written. Zero indicates that the ControlPc value is in the prologue, the epilogue, or in a null frame-like region (see Section 8.1, Procedure Descriptor Representation) of the function. A value of 1 indicates that the ControlPc is in the body of the function; that is, that the function is current for exception-handling purposes (see Section 3.2.6, Entry and Exit Code Sequences).
EstablisherFrame
Pointer to a structure where both the real frame pointer value and the virtual frame pointer value of the context is written. The real frame pointer value is defined if and only if InFunction is 1.
ContextPointers
Address of a context pointer’s record.
Function Value
PreviousControlPc
Address where control left the previous frame.
Remarks
This procedure takes an invocation context block together with its associated procedure descriptor and updates the context to reflect the state of the caller at the point where it made the call.
For exception and interrupt frames, the ControlPc is obtained from the trap frame continuation address as follows. For faults, ControlPc is both the last instruction that executed in the previous frame and the next instruction to execute if control were to resume in that frame. For synchronous or asynchronous traps, the ControlPc is the continuation address. For normal call frames, the ControlPc "where control left the function" is the address of the call instruction and not the return address for that call.
If the given context corresponds to a leaf procedure, then the ControlPc can be obtained from the saved PC value found in the context record. Otherwise, the ControlPc should be the result of a previous call of this procedure for the previous context.
If a context pointer’s record is specified (non-null), then the address where each register is restored from is recorded in the appropriate field of the record. This record can then be used to modify the state of some currently active context when control returns to that context. See the Windows NT for Alpha Systems documentation for full details.
The operation of RtlVirtualUnwind(), which is also a building block for exception dispatching and unwinding, is based both on the procedure descriptor and the code of the procedure associated with the ControlPc.
If the ControlPc points to a reserved RET instruction (see Section 3.2.6), then the context of the caller is the same as the given context and the ControlPc of the caller is taken as the contents of the register holding the return address (which need not be R26) minus 4.
If the ControlPc points to a stack adjustment instruction that is part of a reserved return sequence, then the context of the caller is formed by adjusting the value of the SP and the ControlPc of the caller is taken from the contents of the register holding the return address minus 4.
Otherwise, the context of the caller is recreated by restoring saved registers and by incrementing the stack pointer if the function decremented it. This is done by reverse execution of instructions in the prologue. Instructions are processed in the reverse of the normal order and their normal effect is reversed: informally speaking, a store becomes a load, a subtract becomes an add, a move-to becomes a move-from, and so on.
If the ControlPc is within the prologue, then reverse execution begins at the last completely executed instruction: if the instruction at ControlPc caused a fault, then reverse execution begins at ControlPc minus 4; otherwise, at ControlPc. If the ControlPc is not within the prologue, then reverse execution begins with the last instruction of the prologue.
The instructions in the prologue are processed backwards sequentially. When reverse execution begins, and before the value of SP is used, it is assumed that either SP has a valid value or that FP has a valid value and a "MOV SP, FP" instruction will be encountered before SP is used.
Basically, the operations performed are:
See Section 3.2.6, Entry and Exit Code Sequences for a detailed description of the instructions that take part in reverse execution.