Implemented stripped down SEH functionality
authorshort <>
Tue, 8 Apr 2003 17:42:51 +0000 (17:42 +0000)
committershort <>
Tue, 8 Apr 2003 17:42:51 +0000 (17:42 +0000)
ntoskrnl/ke/catch.c
ntoskrnl/rtl/i386/exception.c
ntoskrnl/rtl/i386/seh.s

index 6bdda14..2e151de 100644 (file)
@@ -28,7 +28,9 @@
 /* INCLUDES *****************************************************************/
 
 #include <ddk/ntddk.h>
 /* INCLUDES *****************************************************************/
 
 #include <ddk/ntddk.h>
+#ifndef LIBCAPTIVE
 #include <reactos/bugcodes.h>
 #include <reactos/bugcodes.h>
+#endif /* LIBCAPTIVE */
 #include <roscfg.h>
 #include <internal/ke.h>
 #include <internal/ldr.h>
 #include <roscfg.h>
 #include <internal/ke.h>
 #include <internal/ldr.h>
@@ -52,12 +54,15 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
                    BOOLEAN SearchFrames)
 {
   EXCEPTION_DISPOSITION Value;
                    BOOLEAN SearchFrames)
 {
   EXCEPTION_DISPOSITION Value;
+#ifndef LIBCAPTIVE
   CONTEXT TContext;
   CONTEXT TContext;
+#endif /* LIBCAPTIVE */
 
   DPRINT("KiDispatchException() called\n");
 
   /* PCR->KeExceptionDispatchCount++; */
 
 
   DPRINT("KiDispatchException() called\n");
 
   /* PCR->KeExceptionDispatchCount++; */
 
+#ifndef LIBCAPTIVE
   if (Context == NULL)
     {
       TContext.ContextFlags = CONTEXT_FULL;
   if (Context == NULL)
     {
       TContext.ContextFlags = CONTEXT_FULL;
@@ -70,6 +75,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
 
       Context = &TContext;
     }
 
       Context = &TContext;
     }
+#endif /* LIBCAPTIVE */
 
 #if 0
   if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) 
 
 #if 0
   if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) 
@@ -79,6 +85,9 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
 #endif
   if (PreviousMode == UserMode)
     {
 #endif
   if (PreviousMode == UserMode)
     {
+#ifdef LIBCAPTIVE
+      KeBugCheck(0);
+#else /* !LIBCAPTIVE */
       if (SearchFrames)
        {
          PULONG Stack;
       if (SearchFrames)
        {
          PULONG Stack;
@@ -121,6 +130,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
       /* If that fails then bugcheck */
       DbgPrint("Could not terminate thread\n");
       KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
       /* If that fails then bugcheck */
       DbgPrint("Could not terminate thread\n");
       KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
+#endif /* LIBCAPTIVE */
     }
   else
     {
     }
   else
     {
@@ -128,6 +138,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
 
       /* PreviousMode == KernelMode */
       
 
       /* PreviousMode == KernelMode */
       
+#ifndef LIBCAPTIVE
       if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
        {
          Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
       if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
        {
          Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
@@ -138,6 +149,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
          Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
        }
 #endif /* KDBG */
          Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
        }
 #endif /* KDBG */
+#endif /* LIBCAPTIVE */
       if (Action != kdHandleException)
        {
          Value = RtlpDispatchException (ExceptionRecord, Context);
       if (Action != kdHandleException)
        {
          Value = RtlpDispatchException (ExceptionRecord, Context);
@@ -149,16 +161,26 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
           */
          if (Value != ExceptionContinueExecution)
            {
           */
          if (Value != ExceptionContinueExecution)
            {
+#ifndef LIBCAPTIVE
              KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);       
              KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);       
+#else /* !LIBCAPTIVE */
+             KeBugCheck (0);         
+#endif /* LIBCAPTIVE */
            }
        }
       else
         {
            }
        }
       else
         {
+#ifndef LIBCAPTIVE
           KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
           KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
+#else /* !LIBCAPTIVE */
+         KeBugCheck(0);
+#endif /* LIBCAPTIVE */
         }
     }
 }
 
         }
     }
 }
 
+#ifndef LIBCAPTIVE
+
 VOID STDCALL
 ExRaiseAccessViolation (VOID)
 {
 VOID STDCALL
 ExRaiseAccessViolation (VOID)
 {
@@ -171,6 +193,8 @@ ExRaiseDatatypeMisalignment (VOID)
   ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
 }
 
   ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
 }
 
+#endif /* LIBCAPTIVE */
+
 VOID STDCALL
 ExRaiseStatus (IN NTSTATUS Status)
 {
 VOID STDCALL
 ExRaiseStatus (IN NTSTATUS Status)
 {
@@ -195,7 +219,11 @@ NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
   KiDispatchException(ExceptionRecord,
                      Context,
                      PsGetCurrentThread()->Tcb.TrapFrame,
   KiDispatchException(ExceptionRecord,
                      Context,
                      PsGetCurrentThread()->Tcb.TrapFrame,
+#ifndef LIBCAPTIVE
                      ExGetPreviousMode(),
                      ExGetPreviousMode(),
+#else /* !LIBCAPTIVE */
+                     KernelMode,
+#endif /* LIBCAPTIVE */
                      SearchFrames);
   return(STATUS_SUCCESS);
 }
                      SearchFrames);
   return(STATUS_SUCCESS);
 }
@@ -204,7 +232,19 @@ NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
 VOID STDCALL
 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
 {
 VOID STDCALL
 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
 {
+#ifndef LIBCAPTIVE
   ZwRaiseException(ExceptionRecord, NULL, TRUE);
   ZwRaiseException(ExceptionRecord, NULL, TRUE);
+#else /* !LIBCAPTIVE */
+CONTEXT *LocalContext;
+
+  /* Do not use local variable to benefit from ElectricFence boundary checks */
+  LocalContext=ExAllocatePool(PagedPool,sizeof(LocalContext->ContextFlags));
+  LocalContext->ContextFlags=0;
+
+  NtRaiseException(ExceptionRecord, LocalContext, TRUE);
+
+  ExFreePool(LocalContext);
+#endif /* LIBCAPTIVE */
 }
 
 /* EOF */
 }
 
 /* EOF */
index 6cec442..a36deb0 100755 (executable)
@@ -18,6 +18,8 @@
 
 /* FUNCTIONS ***************************************************************/
 
 
 /* FUNCTIONS ***************************************************************/
 
+#ifndef LIBCAPTIVE
+
 #if 1
 VOID STDCALL
 MsvcrtDebug(ULONG Value)
 #if 1
 VOID STDCALL
 MsvcrtDebug(ULONG Value)
@@ -46,7 +48,12 @@ _except_handler2(
        return (EXCEPTION_DISPOSITION)0;
 }
 
        return (EXCEPTION_DISPOSITION)0;
 }
 
-void __cdecl
+#endif /* LIBCAPTIVE */
+
+void
+#ifndef LIBCAPTIVE
+__cdecl
+#endif /* LIBCAPTIVE */
 _global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame)
 {
    RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
 _global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame)
 {
    RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
@@ -55,6 +62,7 @@ __ret_label:
    return;
 }
 
    return;
 }
 
+#ifndef LIBCAPTIVE
 
 /* Implemented in except.s */
 
 
 /* Implemented in except.s */
 
@@ -70,12 +78,30 @@ RtlpCaptureContext(PCONTEXT pContext);
        (*(StackLimit)) = KeGetCurrentKPCR()->StackLimit; \
 }
 
        (*(StackLimit)) = KeGetCurrentKPCR()->StackLimit; \
 }
 
+#endif /* LIBCAPTIVE */
+
+#ifndef LIBCAPTIVE
+
 #define SehpGetExceptionList() \
        (PEXCEPTION_REGISTRATION)(KeGetCurrentThread()->TrapFrame ->ExceptionList)
 
 #define SehpSetExceptionList(NewExceptionList) \
        KeGetCurrentThread()->TrapFrame->ExceptionList = (PVOID)(NewExceptionList)
 
 #define SehpGetExceptionList() \
        (PEXCEPTION_REGISTRATION)(KeGetCurrentThread()->TrapFrame ->ExceptionList)
 
 #define SehpSetExceptionList(NewExceptionList) \
        KeGetCurrentThread()->TrapFrame->ExceptionList = (PVOID)(NewExceptionList)
 
+#else /* !LIBCAPTIVE */
+
+extern guint32 fs_KPCR_ExceptionList;
+
+#define SehpGetExceptionList() \
+       (PEXCEPTION_REGISTRATION)(fs_KPCR_ExceptionList)
+
+#define SehpSetExceptionList(NewExceptionList) \
+       fs_KPCR_ExceptionList = (guint32)(PVOID)(NewExceptionList)
+
+#endif /* LIBCAPTIVE */
+
+#ifndef LIBCAPTIVE
+
 #define SehpCaptureContext(Context) \
 { \
        KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, (Context)); \
 #define SehpCaptureContext(Context) \
 { \
        KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, (Context)); \
@@ -92,6 +118,8 @@ AsmDebug(ULONG Value)
 
 /* Declare a few prototypes for the functions in except.s */
 
 
 /* Declare a few prototypes for the functions in except.s */
 
+#endif /* LIBCAPTIVE */
+
 EXCEPTION_DISPOSITION
 RtlpExecuteHandlerForException(
   PEXCEPTION_RECORD ExceptionRecord,
 EXCEPTION_DISPOSITION
 RtlpExecuteHandlerForException(
   PEXCEPTION_RECORD ExceptionRecord,
@@ -108,6 +136,7 @@ RtlpExecuteHandlerForUnwind(
   PVOID DispatcherContext,
   PEXCEPTION_HANDLER ExceptionHandler);
 
   PVOID DispatcherContext,
   PEXCEPTION_HANDLER ExceptionHandler);
 
+#ifndef LIBCAPTIVE
 
 #ifndef NDEBUG
 
 
 #ifndef NDEBUG
 
@@ -134,6 +163,8 @@ VOID RtlpDumpExceptionRegistrations(VOID)
 
 #endif /* NDEBUG */
 
 
 #endif /* NDEBUG */
 
+#endif /* LIBCAPTIVE */
+
 ULONG
 RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
        IN PCONTEXT  Context)
 ULONG
 RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
        IN PCONTEXT  Context)
@@ -245,7 +276,11 @@ RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
       else
       {
         /* Copy the (possibly changed) context back to the trap frame and return */
       else
       {
         /* Copy the (possibly changed) context back to the trap frame and return */
+#ifndef LIBCAPTIVE
         NtContinue(Context, FALSE);
         NtContinue(Context, FALSE);
+#else /* !LIBCAPTIVE */
+       KeBugCheck(0);
+#endif /* LIBCAPTIVE */
         return ExceptionContinueExecution;
       }
     }
         return ExceptionContinueExecution;
       }
     }
@@ -286,6 +321,8 @@ RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
   return ExceptionContinueExecution;  
 }
 
   return ExceptionContinueExecution;  
 }
 
+#ifndef LIBCAPTIVE
+
 VOID STDCALL
 RtlRaiseStatus(NTSTATUS Status)
 {
 VOID STDCALL
 RtlRaiseStatus(NTSTATUS Status)
 {
@@ -300,6 +337,8 @@ RtlRaiseStatus(NTSTATUS Status)
   RtlRaiseException (& ExceptionRecord);
 }
 
   RtlRaiseException (& ExceptionRecord);
 }
 
+#endif /* LIBCAPTIVE */
+
 VOID STDCALL
 RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
   PVOID ReturnAddress,
 VOID STDCALL
 RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
   PVOID ReturnAddress,
@@ -309,7 +348,9 @@ RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
   PEXCEPTION_REGISTRATION ERHead;
   PEXCEPTION_RECORD pExceptRec;
   EXCEPTION_RECORD TempER;    
   PEXCEPTION_REGISTRATION ERHead;
   PEXCEPTION_RECORD pExceptRec;
   EXCEPTION_RECORD TempER;    
+#ifndef LIBCAPTIVE
   CONTEXT Context;
   CONTEXT Context;
+#endif /* LIBCAPTIVE */
 
   DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
 
 
   DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
 
@@ -350,6 +391,7 @@ RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
   }
 #endif /* NDEBUG */
 
   }
 #endif /* NDEBUG */
 
+#ifndef LIBCAPTIVE
   Context.ContextFlags =
     (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
 
   Context.ContextFlags =
     (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
 
@@ -361,6 +403,7 @@ RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
 
   Context.Esp += 0x10;
   Context.Eax = EaxValue;
 
   Context.Esp += 0x10;
   Context.Eax = EaxValue;
+#endif /* LIBCAPTIVE */
  
   // Begin traversing the list of EXCEPTION_REGISTRATION
   while ((ULONG_PTR)ERHead != (ULONG_PTR)-1)
  
   // Begin traversing the list of EXCEPTION_REGISTRATION
   while ((ULONG_PTR)ERHead != (ULONG_PTR)-1)
@@ -372,7 +415,11 @@ RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
     if (ERHead == RegistrationFrame)
     {
       DPRINT("Continueing execution\n");
     if (ERHead == RegistrationFrame)
     {
       DPRINT("Continueing execution\n");
+#ifndef LIBCAPTIVE
       NtContinue(&Context, FALSE);
       NtContinue(&Context, FALSE);
+#else /* !LIBCAPTIVE */
+      /* FIXME: What to do there? */
+#endif /* LIBCAPTIVE */
       return;
     }
     else
       return;
     }
     else
@@ -411,7 +458,11 @@ RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
       ReturnValue = RtlpExecuteHandlerForUnwind(
         pExceptRec,
         ERHead,
       ReturnValue = RtlpExecuteHandlerForUnwind(
         pExceptRec,
         ERHead,
+#ifndef LIBCAPTIVE
         &Context,
         &Context,
+#else /* !LIBCAPTIVE */
+       NULL,
+#endif /* LIBCAPTIVE */
         &NewERHead,
         ERHead->handler);
  
         &NewERHead,
         ERHead->handler);
  
@@ -466,10 +517,14 @@ RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
   DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n",
     RegistrationFrame);
 
   DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n",
     RegistrationFrame);
 
+#ifndef LIBCAPTIVE
   if ((ULONG_PTR)RegistrationFrame == (ULONG_PTR)-1)
     NtContinue(&Context, FALSE);
   else
     NtRaiseException(pExceptRec, &Context, 0);
   if ((ULONG_PTR)RegistrationFrame == (ULONG_PTR)-1)
     NtContinue(&Context, FALSE);
   else
     NtRaiseException(pExceptRec, &Context, 0);
+#else /* !LIBCAPTIVE */
+  KeBugCheck(0);
+#endif /* LIBCAPTIVE */
 }
 
 /* EOF */
 }
 
 /* EOF */
index 03ccd6b..72ea62d 100755 (executable)
 #define CONTEXT_EBX            0xA4
 #define CONTEXT_EIP            0xB8
 
 #define CONTEXT_EBX            0xA4
 #define CONTEXT_EIP            0xB8
 
+#define __local_unwind2 _local_unwind2 /* LIBCAPTIVE */
+#define __except_handler3 _except_handler3     /* LIBCAPTIVE */
+#define __global_unwind2 _global_unwind2       /* LIBCAPTIVE */
+
+#if 0  /* LIBCAPTIVE */
 .globl __local_unwind2
 .globl __local_unwind2
+#endif /* LIBCAPTIVE */
 .globl __except_handler3
 
 .globl __except_handler3
 
+#if 0  /* LIBCAPTIVE */
+
 // EAX = value to print
 _do_debug:
        pushal
 // EAX = value to print
 _do_debug:
        pushal
@@ -65,17 +73,18 @@ _do_debug:
        popal
        ret
 
        popal
        ret
 
+#endif /* LIBCAPTIVE */
+
 #define LU2_TRYLEVEL   0x08
 #define LU2_REGFRAME   0x04
 
 //
 // void
 #define LU2_TRYLEVEL   0x08
 #define LU2_REGFRAME   0x04
 
 //
 // void
-// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,
-//                           LONG TryLevel)
+// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,LONG TryLevel)
 //
 // Parameters:
 //
 // Parameters:
-//   [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
-//   [EDX+04h] - LONG TryLevel
+//   [EDX+08h] - LONG TryLevel
+//   [EDX+04h] - PEXCEPTION_REGISTRATION RegistrationFrame
 // Registers:
 //   EBP - EBP of call frame we are unwinding
 // Returns:
 // Registers:
 //   EBP - EBP of call frame we are unwinding
 // Returns:
@@ -83,6 +92,7 @@ _do_debug:
 // Notes:
 //   Run all termination handlers for a call frame from the current
 //   try-level up to (but not including) the given stop try-level.
 // Notes:
 //   Run all termination handlers for a call frame from the current
 //   try-level up to (but not including) the given stop try-level.
+#if 0
 __local_unwind2:
     // Setup our call frame so we can access parameters using EDX
     //pushl    %ebp
 __local_unwind2:
     // Setup our call frame so we can access parameters using EDX
     //pushl    %ebp
@@ -145,6 +155,7 @@ __local_unwind2:
        //movl  %esi, %esp
     //popl     %ebp
     ret
        //movl  %esi, %esp
     //popl     %ebp
     ret
+#endif
 
 #define EH3_DISPCONTEXT        0x14
 #define EH3_CONTEXT            0x10
 
 #define EH3_DISPCONTEXT        0x14
 #define EH3_CONTEXT            0x10
@@ -170,21 +181,24 @@ __except_handler3:
     // Setup our call frame so we can access parameters using EBP
     pushl    %ebp                              // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
     movl     %esp, %ebp
     // Setup our call frame so we can access parameters using EBP
     pushl    %ebp                              // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
     movl     %esp, %ebp
+    pushl    %ebx      /* LIBCAPTIVE */
+    pushl    %esi      /* LIBCAPTIVE */
+    pushl    %edi      /* LIBCAPTIVE */
 
     // Don't trust the direction flag to be cleared
     cld
 
 
     // Don't trust the direction flag to be cleared
     cld
 
+    // Keep a pointer to the exception registration in EBX
+    movl     EH3_REGFRAME(%ebp), %ebx
+
     // Either we're called to handle an exception or we're called to unwind    
     movl       EH3_ERECORD(%ebp), %eax
     testl      $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
     jnz                .eh3_unwind
 
     // Either we're called to handle an exception or we're called to unwind    
     movl       EH3_ERECORD(%ebp), %eax
     testl      $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
     jnz                .eh3_unwind
 
-    // Keep a pointer to the exception registration in EBX
-    movl     EH3_REGFRAME(%ebp), %ebx
-
     // Build an EXCEPTION_POINTERS structure on the stack and store it's
     // address in the EXCEPTION_REGISTRATION structure
     // Build an EXCEPTION_POINTERS structure on the stack and store it's
     // address in the EXCEPTION_REGISTRATION structure
-    movl     EH3_CONTEXT(%esp), %eax
+    movl     EH3_CONTEXT(%ebp), %eax
     pushl    %ebx                                              // Registration frame
     pushl    %eax                                              // Context
     movl     %esp, ER_EPOINTERS(%ebx)  // Pointer to EXCEPTION_REGISTRATION on the stack
     pushl    %ebx                                              // Registration frame
     pushl    %eax                                              // Context
     movl     %esp, ER_EPOINTERS(%ebx)  // Pointer to EXCEPTION_REGISTRATION on the stack
@@ -249,6 +263,7 @@ __except_handler3:
 
     // Change the context structure so _except_finish is called in the
     // correct context since we return ExceptionContinueExecution.
 
     // Change the context structure so _except_finish is called in the
     // correct context since we return ExceptionContinueExecution.
+#if 0  /* LIBCAPTIVE */
     movl     EH3_CONTEXT(%ebp), %eax
     
     movl     %edi, CONTEXT_EDI(%eax)           // Stop try-level
     movl     EH3_CONTEXT(%ebp), %eax
     
     movl     %edi, CONTEXT_EDI(%eax)           // Stop try-level
@@ -257,6 +272,11 @@ __except_handler3:
 
     movl     $ExceptionContinueExecution, %eax
     jmp      .eh3_return
 
     movl     $ExceptionContinueExecution, %eax
     jmp      .eh3_return
+#else /* !LIBCAPTIVE */
+    // pass %edi
+    // pass %ebx
+    jmp      _except_finish
+#endif /* LIBCAPTIVE */
 
     // Filter returned: EXCEPTION_CONTINUE_SEARCH
 .eh3_continue:
 
     // Filter returned: EXCEPTION_CONTINUE_SEARCH
 .eh3_continue:
@@ -287,8 +307,8 @@ __except_handler3:
     // Perform local unwinding
 .eh3_unwind:
 
     // Perform local unwinding
 .eh3_unwind:
 
-    movl     $ExceptionContinueSearch, %eax
     testl    $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
     testl    $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
+    movl     $ExceptionContinueSearch, %eax
     jnz      .eh3_return
 
        // Save some important registers
     jnz      .eh3_return
 
        // Save some important registers
@@ -297,7 +317,15 @@ __except_handler3:
     lea                 ER_EBP(%ebx), %ebp
     pushl    $-1
     pushl    %ebx
     lea                 ER_EBP(%ebx), %ebp
     pushl    $-1
     pushl    %ebx
+
+#if 0  /* LIBCAPTIVE */
     call     __local_unwind2
     call     __local_unwind2
+#else /* !LIBCAPTIVE */
+    .extern  _local_unwind2_addr
+    movl     _local_unwind2_addr,%eax
+               call     *%eax
+#endif /* LIBCAPTIVE */
+
     addl     $8, %esp
 
        // Restore some important registers
     addl     $8, %esp
 
        // Restore some important registers
@@ -308,7 +336,13 @@ __except_handler3:
     // Get me out of here
 .eh3_return:
 
     // Get me out of here
 .eh3_return:
 
-       movl    %ebp, %esp
+    lea     -3*4(%ebp),%esp    /* LIBCAPTIVE */
+    popl    %edi       /* LIBCAPTIVE */
+    popl    %esi       /* LIBCAPTIVE */
+    popl    %ebx       /* LIBCAPTIVE */
+#if 0  /* LIBCAPTIVE */
+    movl       %ebp, %esp
+#endif /* LIBCAPTIVE */
     popl       %ebp
     ret
 
     popl       %ebp
     ret
 
@@ -337,7 +371,15 @@ _except_finish:
 
     // Pointer to exception registration structure
     pushl    %ebx
 
     // Pointer to exception registration structure
     pushl    %ebx
+
+#if 0  /* LIBCAPTIVE */
     call     __local_unwind2
     call     __local_unwind2
+#else /* !LIBCAPTIVE */
+    .extern  _local_unwind2_addr
+    movl     _local_unwind2_addr,%eax
+               call     *%eax
+#endif /* LIBCAPTIVE */
+
     addl     $8, %esp
 
        // Restore some important registers
     addl     $8, %esp
 
        // Restore some important registers
@@ -363,4 +405,5 @@ _except_finish:
     call    *%eax
 
     // We should never get here
     call    *%eax
 
     // We should never get here
+               hlt
     ret
     ret