migrate substitution keywords to SVN
[reactos.git] / reactos / ntoskrnl / rtl / i386 / except.s
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Kernel-mode exception support for IA-32
6 * FILE: ntoskrnl/rtl/i386/except.s
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * NOTES: This file is shared with lib/ntdll/rtl/i386/except.s.
9 * Please keep them in sync.
10 */
11
12 #define EXCEPTION_UNWINDING 0x02
13
14 #define EREC_FLAGS 0x04
15
16 #define ExceptionContinueExecution 0
17 #define ExceptionContinueSearch 1
18 #define ExceptionNestedException 2
19 #define ExceptionCollidedUnwind 3
20
21 .globl _RtlpExecuteHandlerForException
22 .globl _RtlpExecuteHandlerForUnwind
23
24 #define CONTEXT_FLAGS 0x00
25 #define CONTEXT_SEGGS 0x8C
26 #define CONTEXT_SEGFS 0x90
27 #define CONTEXT_SEGES 0x94
28 #define CONTEXT_SEGDS 0x98
29 #define CONTEXT_EDI 0x9C
30 #define CONTEXT_ESI 0xA0
31 #define CONTEXT_EBX 0xA4
32 #define CONTEXT_EDX 0xA8
33 #define CONTEXT_ECX 0xAC
34 #define CONTEXT_EAX 0xB0
35 #define CONTEXT_EBP 0xB4
36 #define CONTEXT_EIP 0xB8
37 #define CONTEXT_SEGCS 0xBC
38 #define CONTEXT_EFLAGS 0xC0
39 #define CONTEXT_ESP 0xC4
40 #define CONTEXT_SEGSS 0xC8
41
42
43 #define RCC_CONTEXT 0x08
44
45 // EAX = value to print
46 _do_debug:
47 pushal
48 pushl %eax
49 call _AsmDebug@4
50 popal
51 ret
52
53 #ifndef __NTOSKRNL__
54
55 //
56 // VOID
57 // RtlpCaptureContext(PCONTEXT pContext);
58 //
59 // Parameters:
60 // [ESP+08h] - PCONTEXT_X86 pContext
61 // Registers:
62 // None
63 // Returns:
64 // Nothing
65 // Notes:
66 // Grabs the current CPU context.
67 .globl _RtlpCaptureContext
68 _RtlpCaptureContext:
69 pushl %ebp
70 movl %esp, %ebp
71 movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure
72
73 cld
74 pushf
75 pop %eax
76 movl %eax, CONTEXT_EFLAGS(%edx)
77 xorl %eax, %eax
78 movl %eax, CONTEXT_EAX(%edx)
79 movl %eax, CONTEXT_EBX(%edx)
80 movl %eax, CONTEXT_ECX(%edx)
81 movl %eax, CONTEXT_EDX(%edx)
82 movl %eax, CONTEXT_ESI(%edx)
83 movl %eax, CONTEXT_EDI(%edx)
84 movl %cs, %eax
85 movl %eax, CONTEXT_SEGCS(%edx)
86 movl %ds, %eax
87 movl %eax, CONTEXT_SEGDS(%edx)
88 movl %es, %eax
89 movl %eax, CONTEXT_SEGES(%edx)
90 movl %fs, %eax
91 movl %eax, CONTEXT_SEGFS(%edx)
92 movl %gs, %eax
93 movl %eax, CONTEXT_SEGGS(%edx)
94 movl %ss, %eax
95 movl %eax, CONTEXT_SEGSS(%edx)
96
97 //
98 // STACK LAYOUT: - (ESP to put in context structure)
99 // - RETURN ADDRESS OF CALLER OF CALLER
100 // - EBP OF CALLER OF CALLER
101 // ...
102 // - RETURN ADDRESS OF CALLER
103 // - EBP OF CALLER
104 // ...
105 //
106
107 // Get return address of the caller of the caller of this function
108 movl %ebp, %ebx
109 //movl 4(%ebx), %eax // EAX = return address of caller
110 movl (%ebx), %ebx // EBX = EBP of caller
111
112 movl 4(%ebx), %eax // EAX = return address of caller of caller
113 movl (%ebx), %ebx // EBX = EBP of caller of caller
114
115 movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller
116 movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller
117 addl $8, %ebx
118 movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8
119
120 movl %ebp, %esp
121 popl %ebp
122 ret
123
124 #endif /* !__NTOSKRNL__ */
125
126 #define REH_ERECORD 0x08
127 #define REH_RFRAME 0x0C
128 #define REH_CONTEXT 0x10
129 #define REH_DCONTEXT 0x14
130 #define REH_EROUTINE 0x18
131
132 // Parameters:
133 // None
134 // Registers:
135 // [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord
136 // [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
137 // [EBP+10h] - PVOID Context
138 // [EBP+14h] - PVOID DispatcherContext
139 // [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine
140 // EDX - Address of protecting exception handler
141 // Returns:
142 // EXCEPTION_DISPOSITION
143 // Notes:
144 // Setup the protecting exception handler and call the exception
145 // handler in the right context.
146 _RtlpExecuteHandler:
147 pushl %ebp
148 movl %esp, %ebp
149 pushl REH_RFRAME(%ebp)
150
151 pushl %edx
152 pushl %fs:0x0
153 movl %esp, %fs:0x0
154
155 // Prepare to call the exception handler
156 pushl REH_DCONTEXT(%ebp)
157 pushl REH_CONTEXT(%ebp)
158 pushl REH_RFRAME(%ebp)
159 pushl REH_ERECORD(%ebp)
160
161 // Now call the exception handler
162 movl REH_EROUTINE(%ebp), %eax
163 call *%eax
164
165 cmpl $-1, %fs:0x0
166 jne .reh_stack_looks_ok
167
168 // This should not happen
169 pushl 0
170 pushl 0
171 pushl 0
172 pushl 0
173 call _RtlAssert@16
174
175 .reh_loop:
176 jmp .reh_loop
177
178 .reh_stack_looks_ok:
179 movl %fs:0x0, %esp
180
181 // Return to the 'front-end' for this function
182 popl %fs:0x0
183 movl %ebp, %esp
184 popl %ebp
185 ret
186
187
188 #define REP_ERECORD 0x04
189 #define REP_RFRAME 0x08
190 #define REP_CONTEXT 0x0C
191 #define REP_DCONTEXT 0x10
192
193 // Parameters:
194 // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
195 // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
196 // [ESP+0Ch] - PCONTEXT Context
197 // [ESP+10h] - PVOID DispatcherContext
198 // Registers:
199 // None
200 // Returns:
201 // EXCEPTION_DISPOSITION
202 // Notes:
203 // This exception handler protects the exception handling
204 // mechanism by detecting nested exceptions.
205 _RtlpExceptionProtector:
206 movl $ExceptionContinueSearch, %eax
207 movl REP_ERECORD(%esp), %ecx
208 testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
209 jnz .rep_end
210
211 // Unwinding is not taking place, so return ExceptionNestedException
212
213 // Set DispatcherContext field to the exception registration for the
214 // exception handler that executed when a nested exception occurred
215 movl REP_DCONTEXT(%esp), %ecx
216 movl REP_RFRAME(%esp), %eax
217 movl %eax, (%ecx)
218 movl $ExceptionNestedException, %eax
219
220 .rep_end:
221 ret
222
223
224 // Parameters:
225 // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
226 // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
227 // [ESP+0Ch] - PCONTEXT Context
228 // [ESP+10h] - PVOID DispatcherContext
229 // [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
230 // Registers:
231 // None
232 // Returns:
233 // EXCEPTION_DISPOSITION
234 // Notes:
235 // Front-end
236 _RtlpExecuteHandlerForException:
237 movl $_RtlpExceptionProtector, %edx
238 jmp _RtlpExecuteHandler
239
240
241 #define RUP_ERECORD 0x04
242 #define RUP_RFRAME 0x08
243 #define RUP_CONTEXT 0x0C
244 #define RUP_DCONTEXT 0x10
245
246 // Parameters:
247 // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
248 // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
249 // [ESP+0Ch] - PCONTEXT Context
250 // [ESP+10h] - PVOID DispatcherContext
251 // Registers:
252 // None
253 // Returns:
254 // EXCEPTION_DISPOSITION
255 // Notes:
256 // This exception handler protects the exception handling
257 // mechanism by detecting collided unwinds.
258 _RtlpUnwindProtector:
259 movl $ExceptionContinueSearch, %eax
260 movl %ecx, RUP_ERECORD(%esp)
261 testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
262 jz .rup_end
263
264 // Unwinding is taking place, so return ExceptionCollidedUnwind
265
266 movl RUP_RFRAME(%esp), %ecx
267 movl RUP_DCONTEXT(%esp), %edx
268
269 // Set DispatcherContext field to the exception registration for the
270 // exception handler that executed when a collision occurred
271 movl RUP_RFRAME(%ecx), %eax
272 movl %eax, (%edx)
273 movl $ExceptionCollidedUnwind, %eax
274
275 .rup_end:
276 ret
277
278
279 // Parameters:
280 // [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
281 // [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
282 // [ESP+0Ch] - PCONTEXT Context
283 // [ESP+10h] - PVOID DispatcherContext
284 // [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
285 // Registers:
286 // None
287 // Returns:
288 // EXCEPTION_DISPOSITION
289 _RtlpExecuteHandlerForUnwind:
290 movl $_RtlpUnwindProtector, %edx
291 jmp _RtlpExecuteHandler