/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: User-mode exception support for IA-32 * FILE: lib/ntdll/rtl/i386/except.s * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * NOTES: This file is shared with ntoskrnl/rtl/i386/except.s. * Please keep them in sync. */ #define EXCEPTION_UNWINDING 0x02 #define EREC_FLAGS 0x04 #define ExceptionContinueExecution 0 #define ExceptionContinueSearch 1 #define ExceptionNestedException 2 #define ExceptionCollidedUnwind 3 .globl _RtlpExecuteHandlerForException .globl _RtlpExecuteHandlerForUnwind #define CONTEXT_FLAGS 0x00 #define CONTEXT_SEGGS 0x8C #define CONTEXT_SEGFS 0x90 #define CONTEXT_SEGES 0x94 #define CONTEXT_SEGDS 0x98 #define CONTEXT_EDI 0x9C #define CONTEXT_ESI 0xA0 #define CONTEXT_EBX 0xA4 #define CONTEXT_EDX 0xA8 #define CONTEXT_ECX 0xAC #define CONTEXT_EAX 0xB0 #define CONTEXT_EBP 0xB4 #define CONTEXT_EIP 0xB8 #define CONTEXT_SEGCS 0xBC #define CONTEXT_EFLAGS 0xC0 #define CONTEXT_ESP 0xC4 #define CONTEXT_SEGSS 0xC8 #define RCC_CONTEXT 0x08 // EAX = value to print _do_debug: pushal pushl %eax call _AsmDebug@4 popal ret #ifndef __NTOSKRNL__ // // VOID // RtlpCaptureContext(PCONTEXT pContext); // // Parameters: // [ESP+08h] - PCONTEXT_X86 pContext // Registers: // None // Returns: // Nothing // Notes: // Grabs the current CPU context. .globl _RtlpCaptureContext _RtlpCaptureContext: pushl %ebp movl %esp, %ebp movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure cld pushf pop %eax movl %eax, CONTEXT_EFLAGS(%edx) xorl %eax, %eax movl %eax, CONTEXT_EAX(%edx) movl %eax, CONTEXT_EBX(%edx) movl %eax, CONTEXT_ECX(%edx) movl %eax, CONTEXT_EDX(%edx) movl %eax, CONTEXT_ESI(%edx) movl %eax, CONTEXT_EDI(%edx) movl %cs, %eax movl %eax, CONTEXT_SEGCS(%edx) movl %ds, %eax movl %eax, CONTEXT_SEGDS(%edx) movl %es, %eax movl %eax, CONTEXT_SEGES(%edx) movl %fs, %eax movl %eax, CONTEXT_SEGFS(%edx) movl %gs, %eax movl %eax, CONTEXT_SEGGS(%edx) movl %ss, %eax movl %eax, CONTEXT_SEGSS(%edx) // // STACK LAYOUT: - (ESP to put in context structure) // - RETURN ADDRESS OF CALLER OF CALLER // - EBP OF CALLER OF CALLER // ... // - RETURN ADDRESS OF CALLER // - EBP OF CALLER // ... // // Get return address of the caller of the caller of this function movl %ebp, %ebx //movl 4(%ebx), %eax // EAX = return address of caller movl (%ebx), %ebx // EBX = EBP of caller movl 4(%ebx), %eax // EAX = return address of caller of caller movl (%ebx), %ebx // EBX = EBP of caller of caller movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller addl $8, %ebx movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8 movl %ebp, %esp popl %ebp ret #endif /* !__NTOSKRNL__ */ #define REH_ERECORD 0x08 #define REH_RFRAME 0x0C #define REH_CONTEXT 0x10 #define REH_DCONTEXT 0x14 #define REH_EROUTINE 0x18 // Parameters: // None // Registers: // [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord // [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame // [EBP+10h] - PVOID Context // [EBP+14h] - PVOID DispatcherContext // [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine // EDX - Address of protecting exception handler // Returns: // EXCEPTION_DISPOSITION // Notes: // Setup the protecting exception handler and call the exception // handler in the right context. _RtlpExecuteHandler: pushl %ebp movl %esp, %ebp pushl REH_RFRAME(%ebp) pushl %edx pushl %fs:0x0 movl %esp, %fs:0x0 // Prepare to call the exception handler pushl REH_DCONTEXT(%ebp) pushl REH_CONTEXT(%ebp) pushl REH_RFRAME(%ebp) pushl REH_ERECORD(%ebp) // Now call the exception handler movl REH_EROUTINE(%ebp), %eax call *%eax cmpl $-1, %fs:0x0 jne .reh_stack_looks_ok // This should not happen pushl 0 pushl 0 pushl 0 pushl 0 call _RtlAssert@16 .reh_loop: jmp .reh_loop .reh_stack_looks_ok: movl %fs:0x0, %esp // Return to the 'front-end' for this function popl %fs:0x0 movl %ebp, %esp popl %ebp ret #define REP_ERECORD 0x04 #define REP_RFRAME 0x08 #define REP_CONTEXT 0x0C #define REP_DCONTEXT 0x10 // Parameters: // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame // [ESP+0Ch] - PCONTEXT Context // [ESP+10h] - PVOID DispatcherContext // Registers: // None // Returns: // EXCEPTION_DISPOSITION // Notes: // This exception handler protects the exception handling // mechanism by detecting nested exceptions. _RtlpExceptionProtector: movl $ExceptionContinueSearch, %eax movl REP_ERECORD(%esp), %ecx testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) jnz .rep_end // Unwinding is not taking place, so return ExceptionNestedException // Set DispatcherContext field to the exception registration for the // exception handler that executed when a nested exception occurred movl REP_DCONTEXT(%esp), %ecx movl REP_RFRAME(%esp), %eax movl %eax, (%ecx) movl $ExceptionNestedException, %eax .rep_end: ret // Parameters: // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame // [ESP+0Ch] - PCONTEXT Context // [ESP+10h] - PVOID DispatcherContext // [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler // Registers: // None // Returns: // EXCEPTION_DISPOSITION // Notes: // Front-end _RtlpExecuteHandlerForException: movl $_RtlpExceptionProtector, %edx jmp _RtlpExecuteHandler #define RUP_ERECORD 0x04 #define RUP_RFRAME 0x08 #define RUP_CONTEXT 0x0C #define RUP_DCONTEXT 0x10 // Parameters: // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame // [ESP+0Ch] - PCONTEXT Context // [ESP+10h] - PVOID DispatcherContext // Registers: // None // Returns: // EXCEPTION_DISPOSITION // Notes: // This exception handler protects the exception handling // mechanism by detecting collided unwinds. _RtlpUnwindProtector: movl $ExceptionContinueSearch, %eax movl %ecx, RUP_ERECORD(%esp) testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) jz .rup_end // Unwinding is taking place, so return ExceptionCollidedUnwind movl RUP_RFRAME(%esp), %ecx movl RUP_DCONTEXT(%esp), %edx // Set DispatcherContext field to the exception registration for the // exception handler that executed when a collision occurred movl RUP_RFRAME(%ecx), %eax movl %eax, (%edx) movl $ExceptionCollidedUnwind, %eax .rup_end: ret // Parameters: // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame // [ESP+0Ch] - PCONTEXT Context // [ESP+10h] - PVOID DispatcherContext // [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler // Registers: // None // Returns: // EXCEPTION_DISPOSITION _RtlpExecuteHandlerForUnwind: movl $_RtlpUnwindProtector, %edx jmp _RtlpExecuteHandler