We recommend using Visual Studio 2017

SEH in x86 Environments


In simplified terms, data structures associated with exception handling in an x86 environment are written onto the stack at runtime. The OS looks at these structures to locate appropriate exception-handling routines.

In an x86 environment, the FS register points to the current value of the Thread Information Block (TIB) structure. One element in the TIB structure is a pointer to an EXCEPTION_RECORD structure, which in turn contains a pointer to an exception handling callback function. Thus, each thread has its own exception callback function.

The x86 compiler builds exception-handling structures on the stack as it processes functions. The FS register always points to the TIB, which in turn contains a pointer to an EXCEPTION_RECORD structure. The EXCEPTION_RECORD structure points to the exception handler function.

EXCEPTION_RECORD structures form a linked list: the new EXCEPTION_RECORD structure contains a pointer to the previous EXCEPTION_RECORD structure, and so on. On Intel-based machines, the head of the list is always pointed to by the first DWORD in the thread information block, FS:[0] .

When an exception occurs, the system walks the list of EXCEPTION_RECORD structures until it finds a handler for the exception. When a handler is found, the system walks the list again, up to the node that handles the exception. During this second traversal, the system calls each handler function a second time with the exception flag set to EH_UNWINDING.

The API builds a dummy exception record structure containing the context and the exception callback function. After each callback, the corresponding exception frame is removed and the API moves on to the next frame. The API stops unwinding when it gets to the frame whose address was passed in as the first parameter.

After an exception is handled and all previous exception frames have been called to unwind, execution continues where the handling callback function indicates.

The code where execution resumes expects that the stack and frame pointers, the ESP and EBP registers on Intel CPUs, are set to their values within the stack frame that handled the exception.

Therefore, the handler that accepts an exception is responsible for setting the stack and frame pointers to values they had in the stack frame that contains the SEH code that handled the exception.