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