Windows Driver Kit: Kernel-Mode Driver Architecture
Unwind Procedure

The unwind code array is sorted into descending order. When an exception occurs, the operating system stores the complete context in a context record. The exception dispatch logic is then invoked, which repeatedly executes the following steps to find an exception handler:

  1. Use the current RIP stored in the context record to search for a RUNTIME_FUNCTION Structure table entry that describes the current function (or function portion, in the case of chained UNWIND_INFO Structure entries).
  2. If no function table entry is found, then execution occurs in a leaf function, and RSP will directly address the return pointer. The return pointer at [RSP] is stored in the updated context; the simulated RSP is incremented by 8, and step 1 is repeated.
  3. If a function table entry is found, RIP can lie within the following three regions:
    • In an epilog

      If the RIP is within an epilog, then control is leaving the function. There can be no exception handler associated with this exception for this function and the effects of the epilog must be continued to compute the context of the caller function. To determine if the RIP is within an epilog, the code stream is examined from RIP. If that code stream can be matched to the trailing portion of a valid epilog, as described in Epilog Code for x64 64-Bit, then execution occurs in an epilog and the remaining portion of the epilog is simulated, with the context record updated as each instruction is processed. After this step, step 1 is repeated.

    • In the prolog

      If the RIP lies within the prolog, then control has not entered the function. There can be no exception handler associated with this exception for this function and the effects of the prolog must be undone to compute the context of the caller function. The RIP is within the prolog if the distance from the function start to the RIP is less than or equal to the prolog size that is encoded in the UNWIND_INFO Structure. The effects of the prolog are unwound by scanning forward through the unwind codes array for the first entry with an offset less than or equal to the offset of the RIP from the function start, then undoing the effect of all remaining items in the unwind code array. Step 1 is then repeated.

    • In code that might be covered by an exception handler

      If the RIP is not within a prolog or epilog and the function has an exception handler (UNW_FLAG_EHANDLER is set), then the language-specific handler is called. The handler scans its data and calls filter functions as appropriate. The language-specific handler can return the exception that was handled or that the search is to be continued. It can also initiate an unwind directly.

  4. If the language-specific handler returns a handled status, then execution is continued using the original context record.
  5. If there is no language-specific handler or the handler returns a "continue search" status, then the context record must be unwound to the state of the caller. This is accomplished by processing all of the unwind code array elements, undoing the effect of each. Step 1 is then repeated.

When chained unwind information is involved, these basic steps are still followed. The only difference is that, while processing through the unwind code array to unwind a prolog's effects, once the end of the array is reached, the function then links to the parent unwind information and processes the entire unwind code array found there. This linking continues until the function arrives at unwind information without the UNW_CHAINED_INFO flag and finishes processing its unwind code array.

The smallest set of unwind data is 8 bytes. This would represent a function that only allocated 128 bytes or less of stack, and possibly saved one nonvolatile register. This is also the size of a chained unwind information structure for a zero-length prolog with no unwind codes.


Send feedback on this topic
Built on August 05, 2009
Page view tracker