Virtual Unwinding

9/7/2007

To reconstruct the context that existed on entry to a routine, SEH for RISC processors uses a process called Virtual Unwinding to emulate a small subset of instructions in prolog and epilog code.

Virtual unwinding provides a syntactically efficient way of transferring control from the kernel exception handler to user-mode code.

In virtual unwinding, the kernel traverses the call stack to find an appropriate exception handler.

Starting with a CPU context record and an instruction address, the unwinding process interprets instructions in the prolog or epilog to reconstruct the context, as it existed before the function call.

Code elements for unwinding

The portion of the code that is reversed is known as the Prolog of the function. A Prolog consists of instructions that modify the stack pointer and set up the stack frame immediately upon entry to the function.

When a frame has been virtually unwound, the virtual context contains the stack pointer for the previous frame and the return address for the current function. Because the return address is very near the place where control left the previous function, the return address corresponds to the program counter of the previous frame.

With each successive program counter and stack pointer, the unwind process can iterate until there are no frames left on the stack.

The Virtual Unwinder uses a PDATA Structures to determine the procedure start, the procedure end, and the prolog end. A PDATA structure marks where a function begins and ends in the code stream, and the location of the function prolog.

Note

The compiler generates correct Prolog and Epilog sequences, and PDATA for functions that it compiles, but you must create appropriate code and PDATA for functions you write in assembly language.

Given a program counter associated with a specific stack frame, the Unwinder searches the PDATA table for the entry corresponding to the containing function. When the Unwinder finds the correct entry, it can unwind the function frame.

The PDATA structure also locates an exception handling routine associated with the function, if one exists.

The PDATA structure can also contain a pointer to an exception handler.

The subset of prolog and epilog code that the Virtual Unwinder emulates includes the following:

  • Adding or subtracting a value from a register
  • Loading or storing a register on the stack frame
  • Loading integer constants into registers
  • Moving between registers

The Virtual Unwinder ignores other instructions found in the prolog or epilog sequences.

Virtual Unwinder process

The following list shows the steps the Virtual Unwinder performs:

  1. Search the prolog for an instruction that saves the frame pointer, the stack pointer, or the link register.
    If the instruction is present, the instruction saves all permanent registers the Virtual Unwinder must restore.
    If the instruction is not present, the link register contains the return address, and the Virtual Unwinder updates only the program counter.
  2. Search for an instruction in the prolog that writes the frame pointer. The unwinding process restores all registers from this address down, starting from the lowest numbered register to the highest numbered register.
  3. Search for an instruction that writes the stack. If such an instruction exists, the unwinding process must reverse-execute the stack link. The right operand to this subtract is the stack size, which is a constant immediate value.
  4. If execution stops inside a prolog, the Virtual Unwinder determines if an instruction that saves the permanent registers executed, and if a stack link executed.
    • If the function has not saved the permanent registers, the Virtual Unwinder copies the value in the link register to the program counter register.
    • If the function saved the register values, and if no stack link executed, the Virtual Unwinder updates the permanent registers from the stack pointer.
    • If execution stopped in a prolog with a linked stack, the Virtual Unwinder reverse-executes the prolog.

Note

All functions that move the stack pointer must have an associated PDATA structure for SEH to work. These include any function that allocates stack space, calls other functions, saves permanent registers, or has an exception handler. A leaf function (that is, a function that calls no other functions) that does not modify a permanent register does not need PDATA. In this case, the Virtual Unwinder updates the program counter from the link register and continues to the next frame.

See Also

Reference

Prolog-Epilog Example
PDATA Structures

Concepts

SEH in RISC Environments