Exception Handling in Windows driver

Thanks.

On Thu, Aug 29, 2013 at 4:07 AM, wrote:

> > Because x86 impl is older, it is as old as early 90ies (as Win32 and
> > NT kernel), and requires execution overhead of filling _SEH_Rec (2
> > pointers + some more stuff) on each function prolog. It also eats the
> > stack space for _SEH_Rec structures.
> >
> > x64 (and also the newer GCC stuff for x86) uses zero-overhead, newer
> > approach.
> >
> > To look at these details, run the MS’s compiler in “generate
> assembler
> > text” mode, which is IIRC /FA command line switch.
>
> This can be a fascinating and informative exercise. Especially with the
> 64-bit compiler with full optimizations enabled. And no matter what you
> see from /FA, if you use LTCG you will see even more amazing
> optimizations. The ability to collapse C++ template code to a single
> function, for example, is quite awesome.
>
> In my assembly-code course (which I never taught, because I was forced
> into retirement by medical issues), I used both 32-bit and 64-bit output,
> and often would compare the two.
>
> The x86 is simply a way of doing nested setjmp/longjmp in a fashion that
> is both well-structured and visible to the compiler (many optimizations do
> not work correctly around a setjmp, because in the normal course of code
> generation the compiler failed to recognize that all registers are
> volatile around a setjmp. I remember finding these bugs in early
> compilers.
> joe
> >
> > –
> > Maxim S. Shatskih
> > Microsoft MVP on File System And Storage
> > xxxxx@storagecraft.com
> > http://www.storagecraft.com
> >
> > “Piyus Kedia” wrote in message news:xxxxx@ntdev.
> …
> > Hi,
> >
> >
> > I was wondering if you know why x86 and non-x86 architectures use
> > different implementations for exception handling. Can you please also
> tell
> > us if the kernel exception handler follows a similar implementation for
> > different architectures?
> >
> >
> > Thanks,
> >
> > Piyus
> >
> >
> >
> >
> > On Tue, Aug 27, 2013 at 1:39 PM, Skywing
> > wrote:
> >
> > Let’s take a step back for a moment (for the archives only), as this
> > description is a bit misleading.
> >
> > First, a high level, logical overview, from the operating system layer
> > (excluding more complicated corner cases like nested unwinds, frame
> > consolidation unwinds, and collided exceptions):
> >
> > The NT Structured Exception Handling (SEH) model implements a two-part
> > method for handling exceptions. In this model, the first part of
> > exception handling is known as “dispatching”, and involves logically
> > searching for a handler function that wants to accept the given
> exception.
> > The second part of exception handling is known as “unwinding”, and
> > involves logically tearing down the state of frames in between the frame
> > causing the exception, and the frame that handled (i.e. accepted) the
> > exception.
> >
> > Each function in a program has the opportunity to declare a single
> logical
> > handler, typically termed the “language-specific handler”, which is
> > logically called during each of the two parts of exception handling
> > (dispatch, and the unwind), as appropriate.
> >
> > When an exception occurs, the operating system initiates the first phase
> > of exception handling, dispatching. The exception dispatcher logically
> > searches backwards through the call stack; each frame on the stack is
> > inspected to see if it contains an exception handler; if so, that handler
> > is invoked for exception dispatch. The handler is given the opportunity
> > to handle the exception; if it decline to do so, the exception dispatcher
> > searches the next frame to see if it wants to handle the exception, and
> so
> > on. (If nobody handles the exception, the process crashes or a bugcheck
> > occurs, depending on whether this is user mode or kernel mode.)
> >
> > If the handler does want to handle the exception, it has two choices; the
> > first of which is to ask the exception dispatcher to just re-try
> execution
> > of the code that raised exception (typically after adjusting the state of
> > the program). If this happens, then exception dispatching is logically
> > completed. Otherwise, the exception handler is responsible for invoking
> > the unwinder (via RtlUnwindEx -
> >
> http://msdn.microsoft.com/en-us/library/windows/apps/ms680615(v=vs.85).aspx
> > - or, RtlUnwind on native x86 only), specifying a target IP and frame
> > pointer to unwind to.
> >
> > The unwinder searches the stack downwards from the point where the
> > exception occurs, frame by frame, aiming to reach the specified target
> > frame pointer. Along the way, each intervening frame is logically
> > inspected to see if it contains an exception handler; if so, that handler
> > is invoked for unwind. The handler performs whatever necessary cleanup
> > tasks are necessary for that stack frame (such as running C++ object
> > destructors, etc.), and then returns back to the unwinder. In this way,
> > each intervening frame that participates in exception handling is given
> > the chance to clean up appropriately.
> >
> > Once the unwinder reaches the target frame, it arranges for control to
> > resume at the target IP, and unwinding logically completes; the program
> > picks off running again in the target frame, at whatever code resides at
> > the target IP. Control is transferred directly by the unwinder, which
> > does not return to its caller.
> >
> >
> > This more or less describes a simple, high level view of how the
> operating
> > system itself approaches exception handling. There are other nuances and
> > complexities for various corner cases, which you can research online if
> > you are particularly interested in; I’ll not cover them here for
> brevity’s
> > sake. Now, most programs do not use “raw” exception handling (except for
> > the very rare function written in assembler that participates in
> exception
> > handling directly). Most programs use a high level language like C or
> C++
> > with a compiler that supports SEH; the compiler provides a
> > “language-specific handler” that is called each time the operating system
> > asks a function written in that language to participate in exception
> > handling.
> >
> > The language-specific handler handles various tasks like supporting the
> > concept of nested try/ except blocks, or __finally blocks, in C
> > (http://msdn.microsoft.com/en-us/library/s58ftw19.aspx). In C++, it
> > handles details like arranging for C++ objects to be destructed at
> > appropriate times, as well as abstracting the details of SEH away in
> favor
> > of the standard C++ exception handling model that is externally visible
> to
> > C++ programs. In effect, the language-specific handler’s purpose is to
> > adhere to the operating system level contract for exception handling, and
> > then provide whatever per-function, per-language behavior is required,
> > such as nested try scopes, etc. Based on the underlying primitives
> > exposed for exception dispatch and unwind, you can likely imagine some
> > logical ways that, for example, the high level__try/ except and
> >
finally constructs might be implemented by a C compiler and its
> > corresponding language-specific handler.
> >
> > Various other high-level constructs heavily leverage this framework for
> > various means; for example, safe setjmp and longjmp utilize the unwinder
> > infrastructure to tear down state in intervening frames in a safe
> fashion.
> >
> >
> > Now, the above is only part of the story; different architectures map the
> > high level exception handling model to their local peculiarities in
> > various ways. The standard, modern approach that we take is that each
> > executable has an exception directory that contains a table of functions
> > and, indirectly, a description of each function’s language-specific
> > exception handler (and other minutia needed to unwind the processor
> > nonvolatile register state through the function). Every architecture
> > except x86 implements this approach (for example, AMD64 and ARM do, and
> > IA64 did, etc.), and it would be the one that I would strongly recommend
> > that you study first when learning about the NT exception handling model.
> > In this model, the operating system looks up a function in its table of
> > functions that support exception handling, and, if it finds a match, it
> > can then learn what the language-specific exception handler for that
> > function is, etc. The exception dispatcher and unwinder look up
> exception
> > handling and unwinding information for each frame visited in this
> fashion.
> >
> > The AMD64 exception handling ABI is fairly well documented on MSDN
> > (http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx), for suggested
> > reading.
> >
> > On native x86, which is by far the odd-ball out, a somewhat different
> > implementation is used. Ignoring later bolt-ons like SafeSEH for the
> > moment, instead of a static description of exception handlers, the x86
> > maintains a linked list of frames that participate in exception handling,
> > the list head of which is in turn stored in a per-thread location
> > (NT_TIB.ExceptionList, what Maxim alludes to below with fs:[0]). Frames
> > participating in exception handling are logically pushed on to this list
> > during frame establishment, and popped off during unwind or frame
> > de-establishment. The unwinder implementation is minimalistic compared
> to
> > other architectures as all registers except the frame pointer are
> > considered volatile across an x86 unwind; at heart, it simply removes
> > entries from the frame chain and invokes exception handlers as
> > appropriate. The same high level SEH model is ultimately implemented,
> but
> > in a different way.
> >
> >
> > Again, this is only a high level overview and glosses over various
> details
> > for more complicated edge conditions, for which there are other
> references
> > available.
> >
> > - S (Msft)
> > (Exception handling guy.)
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S.
> Shatskih
> > Sent: Monday, August 26, 2013 11:50 PM
> > To: Windows System Software Devs Interest List
> >
> > Subject: Re:[ntdev] Exception Handling in Windows driver
> >
> >>determine the handler behaviour (like Linux’s page fault handler
> >>compares the faulting PC against an exception table, to allow functions
> >> like copy_from_user to fault).
> >
> > Oh yes, Windows is similar.
> >
> > Each function which contrains __try has a hidden _SEH_Rec local var,
> which
> > is a small structure.
> >
> > On function entrance, the _SEH_Rec is put to the top of their list, the
> > current list head is kept at fs:[0] thread/processor local storage.
> >
> > Also, the _SEH_Rec has a pointer to this function’s constant table, which
> > also has the address of the__except operator in the function.
> >
> > When exception occurs, the _SEH_Rec list is scanned and EIP is compared
> to
> > each function’s constant table, and the matching one is executed. Then
> the
> > filter expression (which is inside __except()) is executed, and then
> > RtlUnwind.
> >
> > –
> > Maxim S. Shatskih
> > Microsoft MVP on File System And Storage xxxxx@storagecraft.com
> > http://www.storagecraft.com
> >
> >
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
> >
> > OSR is HIRING!! See http://www.osr.com/careers
> >
> > For our schedule of WDF, WDM, debugging and other seminars visit:
> > http://www.osr.com/seminars
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
> >
> > OSR is HIRING!! See http://www.osr.com/careers
> >
> > For our schedule of WDF, WDM, debugging and other seminars visit:
> > http://www.osr.com/seminars
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
> >
> > OSR is HIRING!! See http://www.osr.com/careers
> >
> > For our schedule of WDF, WDM, debugging and other seminars visit:
> > http://www.osr.com/seminars
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
> >
>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

http://www.microsoft.com/msj/0197/Exception/Exception.aspx

“Piyus Kedia” wrote in message news:xxxxx@ntdev…
Thanks.

On Thu, Aug 29, 2013 at 4:07 AM, wrote:

> Because x86 impl is older, it is as old as early 90ies (as Win32 and
> NT kernel), and requires execution overhead of filling _SEH_Rec (2
> pointers + some more stuff) on each function prolog. It also eats the
> stack space for _SEH_Rec structures.
>
> x64 (and also the newer GCC stuff for x86) uses zero-overhead, newer
> approach.
>
> To look at these details, run the MS’s compiler in “generate assembler
> text” mode, which is IIRC /FA command line switch.

This can be a fascinating and informative exercise. Especially with the
64-bit compiler with full optimizations enabled. And no matter what you
see from /FA, if you use LTCG you will see even more amazing
optimizations. The ability to collapse C++ template code to a single
function, for example, is quite awesome.

In my assembly-code course (which I never taught, because I was forced
into retirement by medical issues), I used both 32-bit and 64-bit output,
and often would compare the two.

The x86 is simply a way of doing nested setjmp/longjmp in a fashion that
is both well-structured and visible to the compiler (many optimizations do
not work correctly around a setjmp, because in the normal course of code
generation the compiler failed to recognize that all registers are
volatile around a setjmp. I remember finding these bugs in early
compilers.
joe

>
> –
> Maxim S. Shatskih
> Microsoft MVP on File System And Storage
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
> “Piyus Kedia” wrote in message news:xxxxx@ntdev…
> Hi,
>
>
> I was wondering if you know why x86 and non-x86 architectures use
> different implementations for exception handling. Can you please also tell
> us if the kernel exception handler follows a similar implementation for
> different architectures?
>
>
> Thanks,
>
> Piyus
>
>
>
>
> On Tue, Aug 27, 2013 at 1:39 PM, Skywing
> wrote:
>
> Let’s take a step back for a moment (for the archives only), as this
> description is a bit misleading.
>
> First, a high level, logical overview, from the operating system layer
> (excluding more complicated corner cases like nested unwinds, frame
> consolidation unwinds, and collided exceptions):
>
> The NT Structured Exception Handling (SEH) model implements a two-part
> method for handling exceptions. In this model, the first part of
> exception handling is known as “dispatching”, and involves logically
> searching for a handler function that wants to accept the given exception.
> The second part of exception handling is known as “unwinding”, and
> involves logically tearing down the state of frames in between the frame
> causing the exception, and the frame that handled (i.e. accepted) the
> exception.
>
> Each function in a program has the opportunity to declare a single logical
> handler, typically termed the “language-specific handler”, which is
> logically called during each of the two parts of exception handling
> (dispatch, and the unwind), as appropriate.
>
> When an exception occurs, the operating system initiates the first phase
> of exception handling, dispatching. The exception dispatcher logically
> searches backwards through the call stack; each frame on the stack is
> inspected to see if it contains an exception handler; if so, that handler
> is invoked for exception dispatch. The handler is given the opportunity
> to handle the exception; if it decline to do so, the exception dispatcher
> searches the next frame to see if it wants to handle the exception, and so
> on. (If nobody handles the exception, the process crashes or a bugcheck
> occurs, depending on whether this is user mode or kernel mode.)
>
> If the handler does want to handle the exception, it has two choices; the
> first of which is to ask the exception dispatcher to just re-try execution
> of the code that raised exception (typically after adjusting the state of
> the program). If this happens, then exception dispatching is logically
> completed. Otherwise, the exception handler is responsible for invoking
> the unwinder (via RtlUnwindEx -
> http://msdn.microsoft.com/en-us/library/windows/apps/ms680615(v=vs.85).aspx
> - or, RtlUnwind on native x86 only), specifying a target IP and frame
> pointer to unwind to.
>
> The unwinder searches the stack downwards from the point where the
> exception occurs, frame by frame, aiming to reach the specified target
> frame pointer. Along the way, each intervening frame is logically
> inspected to see if it contains an exception handler; if so, that handler
> is invoked for unwind. The handler performs whatever necessary cleanup
> tasks are necessary for that stack frame (such as running C++ object
> destructors, etc.), and then returns back to the unwinder. In this way,
> each intervening frame that participates in exception handling is given
> the chance to clean up appropriately.
>
> Once the unwinder reaches the target frame, it arranges for control to
> resume at the target IP, and unwinding logically completes; the program
> picks off running again in the target frame, at whatever code resides at
> the target IP. Control is transferred directly by the unwinder, which
> does not return to its caller.
>
>
> This more or less describes a simple, high level view of how the operating
> system itself approaches exception handling. There are other nuances and
> complexities for various corner cases, which you can research online if
> you are particularly interested in; I’ll not cover them here for brevity’s
> sake. Now, most programs do not use “raw” exception handling (except for
> the very rare function written in assembler that participates in exception
> handling directly). Most programs use a high level language like C or C++
> with a compiler that supports SEH; the compiler provides a
> “language-specific handler” that is called each time the operating system
> asks a function written in that language to participate in exception
> handling.
>
> The language-specific handler handles various tasks like supporting the
> concept of nested try/ except blocks, or __finally blocks, in C
> (http://msdn.microsoft.com/en-us/library/s58ftw19.aspx). In C++, it
> handles details like arranging for C++ objects to be destructed at
> appropriate times, as well as abstracting the details of SEH away in favor
> of the standard C++ exception handling model that is externally visible to
> C++ programs. In effect, the language-specific handler’s purpose is to
> adhere to the operating system level contract for exception handling, and
> then provide whatever per-function, per-language behavior is required,
> such as nested try scopes, etc. Based on the underlying primitives
> exposed for exception dispatch and unwind, you can likely imagine some
> logical ways that, for example, the high level__try/ except and
>
finally constructs might be implemented by a C compiler and its
> corresponding language-specific handler.
>
> Various other high-level constructs heavily leverage this framework for
> various means; for example, safe setjmp and longjmp utilize the unwinder
> infrastructure to tear down state in intervening frames in a safe fashion.
>
>
> Now, the above is only part of the story; different architectures map the
> high level exception handling model to their local peculiarities in
> various ways. The standard, modern approach that we take is that each
> executable has an exception directory that contains a table of functions
> and, indirectly, a description of each function’s language-specific
> exception handler (and other minutia needed to unwind the processor
> nonvolatile register state through the function). Every architecture
> except x86 implements this approach (for example, AMD64 and ARM do, and
> IA64 did, etc.), and it would be the one that I would strongly recommend
> that you study first when learning about the NT exception handling model.
> In this model, the operating system looks up a function in its table of
> functions that support exception handling, and, if it finds a match, it
> can then learn what the language-specific exception handler for that
> function is, etc. The exception dispatcher and unwinder look up exception
> handling and unwinding information for each frame visited in this fashion.
>
> The AMD64 exception handling ABI is fairly well documented on MSDN
> (http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx), for suggested
> reading.
>
> On native x86, which is by far the odd-ball out, a somewhat different
> implementation is used. Ignoring later bolt-ons like SafeSEH for the
> moment, instead of a static description of exception handlers, the x86
> maintains a linked list of frames that participate in exception handling,
> the list head of which is in turn stored in a per-thread location
> (NT_TIB.ExceptionList, what Maxim alludes to below with fs:[0]). Frames
> participating in exception handling are logically pushed on to this list
> during frame establishment, and popped off during unwind or frame
> de-establishment. The unwinder implementation is minimalistic compared to
> other architectures as all registers except the frame pointer are
> considered volatile across an x86 unwind; at heart, it simply removes
> entries from the frame chain and invokes exception handlers as
> appropriate. The same high level SEH model is ultimately implemented, but
> in a different way.
>
>
> Again, this is only a high level overview and glosses over various details
> for more complicated edge conditions, for which there are other references
> available.
>
> - S (Msft)
> (Exception handling guy.)
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
> Sent: Monday, August 26, 2013 11:50 PM
> To: Windows System Software Devs Interest List
>
> Subject: Re:[ntdev] Exception Handling in Windows driver
>
>>determine the handler behaviour (like Linux’s page fault handler
>>compares the faulting PC against an exception table, to allow functions
>> like copy_from_user to fault).
>
> Oh yes, Windows is similar.
>
> Each function which contrains __try has a hidden _SEH_Rec local var, which
> is a small structure.
>
> On function entrance, the _SEH_Rec is put to the top of their list, the
> current list head is kept at fs:[0] thread/processor local storage.
>
> Also, the _SEH_Rec has a pointer to this function’s constant table, which
> also has the address of the__except operator in the function.
>
> When exception occurs, the _SEH_Rec list is scanned and EIP is compared to
> each function’s constant table, and the matching one is executed. Then the
> filter expression (which is inside __except()) is executed, and then
> RtlUnwind.
>
> –
> Maxim S. Shatskih
> Microsoft MVP on File System And Storage xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks a lot. It is a very nice link.

On Thu, Aug 29, 2013 at 7:21 AM, m wrote:

> http://www.microsoft.com/msj/0197/Exception/Exception.aspx
>
>
>
> “Piyus Kedia” wrote in message news:xxxxx@ntdev.
> …
> Thanks.
>
>
> On Thu, Aug 29, 2013 at 4:07 AM, wrote:
>
>> > Because x86 impl is older, it is as old as early 90ies (as Win32 and
>> > NT kernel), and requires execution overhead of filling _SEH_Rec (2
>> > pointers + some more stuff) on each function prolog. It also eats the
>> > stack space for _SEH_Rec structures.
>> >
>> > x64 (and also the newer GCC stuff for x86) uses zero-overhead, newer
>> > approach.
>> >
>> > To look at these details, run the MS’s compiler in “generate
>> assembler
>> > text” mode, which is IIRC /FA command line switch.
>>
>> This can be a fascinating and informative exercise. Especially with the
>> 64-bit compiler with full optimizations enabled. And no matter what you
>> see from /FA, if you use LTCG you will see even more amazing
>> optimizations. The ability to collapse C++ template code to a single
>> function, for example, is quite awesome.
>>
>> In my assembly-code course (which I never taught, because I was forced
>> into retirement by medical issues), I used both 32-bit and 64-bit output,
>> and often would compare the two.
>>
>> The x86 is simply a way of doing nested setjmp/longjmp in a fashion that
>> is both well-structured and visible to the compiler (many optimizations do
>> not work correctly around a setjmp, because in the normal course of code
>> generation the compiler failed to recognize that all registers are
>> volatile around a setjmp. I remember finding these bugs in early
>> compilers.
>> joe
>> >
>> > –
>> > Maxim S. Shatskih
>> > Microsoft MVP on File System And Storage
>> > xxxxx@storagecraft.com
>> > http://www.storagecraft.com
>> >
>> > “Piyus Kedia” wrote in message
>> news:xxxxx@ntdev…
>> > Hi,
>> >
>> >
>> > I was wondering if you know why x86 and non-x86 architectures use
>> > different implementations for exception handling. Can you please also
>> tell
>> > us if the kernel exception handler follows a similar implementation for
>> > different architectures?
>> >
>> >
>> > Thanks,
>> >
>> > Piyus
>> >
>> >
>> >
>> >
>> > On Tue, Aug 27, 2013 at 1:39 PM, Skywing
>> > wrote:
>> >
>> > Let’s take a step back for a moment (for the archives only), as this
>> > description is a bit misleading.
>> >
>> > First, a high level, logical overview, from the operating system layer
>> > (excluding more complicated corner cases like nested unwinds, frame
>> > consolidation unwinds, and collided exceptions):
>> >
>> > The NT Structured Exception Handling (SEH) model implements a two-part
>> > method for handling exceptions. In this model, the first part of
>> > exception handling is known as “dispatching”, and involves logically
>> > searching for a handler function that wants to accept the given
>> exception.
>> > The second part of exception handling is known as “unwinding”, and
>> > involves logically tearing down the state of frames in between the frame
>> > causing the exception, and the frame that handled (i.e. accepted) the
>> > exception.
>> >
>> > Each function in a program has the opportunity to declare a single
>> logical
>> > handler, typically termed the “language-specific handler”, which is
>> > logically called during each of the two parts of exception handling
>> > (dispatch, and the unwind), as appropriate.
>> >
>> > When an exception occurs, the operating system initiates the first phase
>> > of exception handling, dispatching. The exception dispatcher logically
>> > searches backwards through the call stack; each frame on the stack is
>> > inspected to see if it contains an exception handler; if so, that
>> handler
>> > is invoked for exception dispatch. The handler is given the opportunity
>> > to handle the exception; if it decline to do so, the exception
>> dispatcher
>> > searches the next frame to see if it wants to handle the exception, and
>> so
>> > on. (If nobody handles the exception, the process crashes or a bugcheck
>> > occurs, depending on whether this is user mode or kernel mode.)
>> >
>> > If the handler does want to handle the exception, it has two choices;
>> the
>> > first of which is to ask the exception dispatcher to just re-try
>> execution
>> > of the code that raised exception (typically after adjusting the state
>> of
>> > the program). If this happens, then exception dispatching is logically
>> > completed. Otherwise, the exception handler is responsible for invoking
>> > the unwinder (via RtlUnwindEx -
>> >
>> http://msdn.microsoft.com/en-us/library/windows/apps/ms680615(v=vs.85).aspx
>> > - or, RtlUnwind on native x86 only), specifying a target IP and frame
>> > pointer to unwind to.
>> >
>> > The unwinder searches the stack downwards from the point where the
>> > exception occurs, frame by frame, aiming to reach the specified target
>> > frame pointer. Along the way, each intervening frame is logically
>> > inspected to see if it contains an exception handler; if so, that
>> handler
>> > is invoked for unwind. The handler performs whatever necessary cleanup
>> > tasks are necessary for that stack frame (such as running C++ object
>> > destructors, etc.), and then returns back to the unwinder. In this way,
>> > each intervening frame that participates in exception handling is given
>> > the chance to clean up appropriately.
>> >
>> > Once the unwinder reaches the target frame, it arranges for control to
>> > resume at the target IP, and unwinding logically completes; the program
>> > picks off running again in the target frame, at whatever code resides at
>> > the target IP. Control is transferred directly by the unwinder, which
>> > does not return to its caller.
>> >
>> >
>> > This more or less describes a simple, high level view of how the
>> operating
>> > system itself approaches exception handling. There are other nuances
>> and
>> > complexities for various corner cases, which you can research online if
>> > you are particularly interested in; I’ll not cover them here for
>> brevity’s
>> > sake. Now, most programs do not use “raw” exception handling (except
>> for
>> > the very rare function written in assembler that participates in
>> exception
>> > handling directly). Most programs use a high level language like C or
>> C++
>> > with a compiler that supports SEH; the compiler provides a
>> > “language-specific handler” that is called each time the operating
>> system
>> > asks a function written in that language to participate in exception
>> > handling.
>> >
>> > The language-specific handler handles various tasks like supporting the
>> > concept of nested try/ except blocks, or __finally blocks, in C
>> > (http://msdn.microsoft.com/en-us/library/s58ftw19.aspx). In C++, it
>> > handles details like arranging for C++ objects to be destructed at
>> > appropriate times, as well as abstracting the details of SEH away in
>> favor
>> > of the standard C++ exception handling model that is externally visible
>> to
>> > C++ programs. In effect, the language-specific handler’s purpose is to
>> > adhere to the operating system level contract for exception handling,
>> and
>> > then provide whatever per-function, per-language behavior is required,
>> > such as nested try scopes, etc. Based on the underlying primitives
>> > exposed for exception dispatch and unwind, you can likely imagine some
>> > logical ways that, for example, the high level__try/ except and
>> >
finally constructs might be implemented by a C compiler and its
>> > corresponding language-specific handler.
>> >
>> > Various other high-level constructs heavily leverage this framework for
>> > various means; for example, safe setjmp and longjmp utilize the unwinder
>> > infrastructure to tear down state in intervening frames in a safe
>> fashion.
>> >
>> >
>> > Now, the above is only part of the story; different architectures map
>> the
>> > high level exception handling model to their local peculiarities in
>> > various ways. The standard, modern approach that we take is that each
>> > executable has an exception directory that contains a table of functions
>> > and, indirectly, a description of each function’s language-specific
>> > exception handler (and other minutia needed to unwind the processor
>> > nonvolatile register state through the function). Every architecture
>> > except x86 implements this approach (for example, AMD64 and ARM do, and
>> > IA64 did, etc.), and it would be the one that I would strongly recommend
>> > that you study first when learning about the NT exception handling
>> model.
>> > In this model, the operating system looks up a function in its table of
>> > functions that support exception handling, and, if it finds a match, it
>> > can then learn what the language-specific exception handler for that
>> > function is, etc. The exception dispatcher and unwinder look up
>> exception
>> > handling and unwinding information for each frame visited in this
>> fashion.
>> >
>> > The AMD64 exception handling ABI is fairly well documented on MSDN
>> > (http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx), for suggested
>> > reading.
>> >
>> > On native x86, which is by far the odd-ball out, a somewhat different
>> > implementation is used. Ignoring later bolt-ons like SafeSEH for the
>> > moment, instead of a static description of exception handlers, the x86
>> > maintains a linked list of frames that participate in exception
>> handling,
>> > the list head of which is in turn stored in a per-thread location
>> > (NT_TIB.ExceptionList, what Maxim alludes to below with fs:[0]). Frames
>> > participating in exception handling are logically pushed on to this list
>> > during frame establishment, and popped off during unwind or frame
>> > de-establishment. The unwinder implementation is minimalistic compared
>> to
>> > other architectures as all registers except the frame pointer are
>> > considered volatile across an x86 unwind; at heart, it simply removes
>> > entries from the frame chain and invokes exception handlers as
>> > appropriate. The same high level SEH model is ultimately implemented,
>> but
>> > in a different way.
>> >
>> >
>> > Again, this is only a high level overview and glosses over various
>> details
>> > for more complicated edge conditions, for which there are other
>> references
>> > available.
>> >
>> > - S (Msft)
>> > (Exception handling guy.)
>> >
>> >
>> > -----Original Message-----
>> > From: xxxxx@lists.osr.com
>> > [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S.
>> Shatskih
>> > Sent: Monday, August 26, 2013 11:50 PM
>> > To: Windows System Software Devs Interest List
>> >
>> > Subject: Re:[ntdev] Exception Handling in Windows driver
>> >
>> >>determine the handler behaviour (like Linux’s page fault handler
>> >>compares the faulting PC against an exception table, to allow functions
>> >> like copy_from_user to fault).
>> >
>> > Oh yes, Windows is similar.
>> >
>> > Each function which contrains __try has a hidden _SEH_Rec local var,
>> which
>> > is a small structure.
>> >
>> > On function entrance, the _SEH_Rec is put to the top of their list, the
>> > current list head is kept at fs:[0] thread/processor local storage.
>> >
>> > Also, the _SEH_Rec has a pointer to this function’s constant table,
>> which
>> > also has the address of the__except operator in the function.
>> >
>> > When exception occurs, the _SEH_Rec list is scanned and EIP is compared
>> to
>> > each function’s constant table, and the matching one is executed. Then
>> the
>> > filter expression (which is inside __except()) is executed, and then
>> > RtlUnwind.
>> >
>> > –
>> > Maxim S. Shatskih
>> > Microsoft MVP on File System And Storage xxxxx@storagecraft.com
>> > http://www.storagecraft.com
>> >
>> >
>> >
>> > —
>> > NTDEV is sponsored by OSR
>> >
>> > Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>> >
>> > OSR is HIRING!! See http://www.osr.com/careers
>> >
>> > For our schedule of WDF, WDM, debugging and other seminars visit:
>> > http://www.osr.com/seminars
>> >
>> > To unsubscribe, visit the List Server section of OSR Online at
>> > http://www.osronline.com/page.cfm?name=ListServer
>> >
>> > —
>> > NTDEV is sponsored by OSR
>> >
>> > Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>> >
>> > OSR is HIRING!! See http://www.osr.com/careers
>> >
>> > For our schedule of WDF, WDM, debugging and other seminars visit:
>> > http://www.osr.com/seminars
>> >
>> > To unsubscribe, visit the List Server section of OSR Online at
>> > http://www.osronline.com/page.cfm?name=ListServer
>> >
>> > —
>> > NTDEV is sponsored by OSR
>> >
>> > Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>> >
>> > OSR is HIRING!! See http://www.osr.com/careers
>> >
>> > For our schedule of WDF, WDM, debugging and other seminars visit:
>> > http://www.osr.com/seminars
>> >
>> > To unsubscribe, visit the List Server section of OSR Online at
>> > http://www.osronline.com/page.cfm?name=ListServer
>> >
>>
>>
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>>
>> OSR is HIRING!! See http://www.osr.com/careers
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>