source: trunk/src/kernel32/oslibexcept.cpp

Last change on this file was 22004, checked in by dmik, 13 years ago

kernel32: Pick up register changes in try/except filter.

This is a regression of r21999. Fixes endless exceptions eventually
leading to program termination.

File size: 12.4 KB
Line 
1/* $Id: oslibexcept.cpp,v 1.7 2001-06-04 21:18:40 sandervl Exp $ */
2/*
3 * Exception handler util. procedures
4 *
5 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 */
8#define INCL_BASE
9#define INCL_DOSEXCEPTIONS
10#define INCL_DOSMEMMGR
11#define INCL_DOSPROCESS
12#include <os2wrap.h> //Odin32 OS/2 api wrappers
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <win32type.h>
17#include <misc.h>
18#include <exceptions.h>
19#include <wprocess.h>
20
21#include "oslibexcept.h"
22
23#define DBG_LOCALLOG DBG_oslibexcept
24#include "dbglocal.h"
25
26/**
27 * Converts the OS/2 exception information to the Win32 exception information.
28 *
29 * Returns TRUE on succes and FALSE otherwise.
30 */
31BOOL APIENTRY OSLibConvertExceptionInfo(PEXCEPTIONREPORTRECORD pReportRec,
32 PCONTEXTRECORD pContextRec,
33 PWINEXCEPTION_RECORD pWinReportRec,
34 PWINCONTEXT pWinContextRec,
35 TEB *pWinTEB)
36{
37 memset(pWinReportRec, 0, sizeof(*pWinReportRec));
38 memcpy(pWinReportRec, pReportRec, sizeof(*pReportRec));
39
40 switch (pReportRec->ExceptionNum)
41 {
42 case XCPT_FLOAT_DENORMAL_OPERAND:
43 pWinReportRec->ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND;
44 break;
45 case XCPT_FLOAT_DIVIDE_BY_ZERO:
46 pWinReportRec->ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
47 break;
48 case XCPT_FLOAT_INEXACT_RESULT:
49 pWinReportRec->ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
50 break;
51 case XCPT_FLOAT_INVALID_OPERATION:
52 pWinReportRec->ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
53 break;
54 case XCPT_FLOAT_OVERFLOW:
55 pWinReportRec->ExceptionCode = EXCEPTION_FLT_OVERFLOW;
56 break;
57 case XCPT_FLOAT_STACK_CHECK:
58 pWinReportRec->ExceptionCode = EXCEPTION_FLT_STACK_CHECK;
59 break;
60 case XCPT_FLOAT_UNDERFLOW:
61 pWinReportRec->ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
62 break;
63 case XCPT_INTEGER_DIVIDE_BY_ZERO:
64 pWinReportRec->ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
65 break;
66 case XCPT_INTEGER_OVERFLOW:
67 pWinReportRec->ExceptionCode = EXCEPTION_INT_OVERFLOW;
68 break;
69 case XCPT_PRIVILEGED_INSTRUCTION:
70 pWinReportRec->ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
71 break;
72 case XCPT_BREAKPOINT:
73 pWinReportRec->ExceptionCode = EXCEPTION_BREAKPOINT;
74 break;
75 case XCPT_SINGLE_STEP:
76 pWinReportRec->ExceptionCode = EXCEPTION_SINGLE_STEP;
77 break;
78 case XCPT_ARRAY_BOUNDS_EXCEEDED:
79 pWinReportRec->ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
80 break;
81 case XCPT_DATATYPE_MISALIGNMENT:
82 pWinReportRec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
83 break;
84 case XCPT_ILLEGAL_INSTRUCTION:
85 pWinReportRec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
86 break;
87 case XCPT_INVALID_LOCK_SEQUENCE:
88 pWinReportRec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
89 break;
90 case XCPT_GUARD_PAGE_VIOLATION:
91 pWinReportRec->ExceptionCode = EXCEPTION_GUARD_PAGE;
92 break;
93 case XCPT_UNABLE_TO_GROW_STACK:
94 pWinReportRec->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
95 break;
96 case XCPT_IN_PAGE_ERROR:
97 pWinReportRec->ExceptionCode = EXCEPTION_IN_PAGE_ERROR;
98 break;
99 case XCPT_ACCESS_VIOLATION:
100 pWinReportRec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
101 break;
102 default: // no other exceptions should be dispatched to win32 apps
103 return FALSE;
104 }
105
106 // TODO:
107 // According to the Wine folks the flags are the same in OS/2 and win32
108 // Let's assume for now the rest is identical as well
109
110 // copy context record info
111 memset(pWinContextRec, 0, sizeof(*pWinContextRec));
112 if (pContextRec->ContextFlags & CONTEXT_CONTROL)
113 {
114 pWinContextRec->ContextFlags |= WINCONTEXT_CONTROL;
115 pWinContextRec->Ebp = pContextRec->ctx_RegEbp;
116 pWinContextRec->Eip = pContextRec->ctx_RegEip;
117 pWinContextRec->SegCs = pContextRec->ctx_SegCs;
118 pWinContextRec->EFlags = pContextRec->ctx_EFlags;
119 pWinContextRec->Esp = pContextRec->ctx_RegEsp;
120 pWinContextRec->SegSs = pContextRec->ctx_SegSs;
121 }
122 if (pContextRec->ContextFlags & CONTEXT_INTEGER)
123 {
124 pWinContextRec->ContextFlags |= WINCONTEXT_INTEGER;
125 pWinContextRec->Edi = pContextRec->ctx_RegEdi;
126 pWinContextRec->Esi = pContextRec->ctx_RegEsi;
127 pWinContextRec->Ebx = pContextRec->ctx_RegEbx;
128 pWinContextRec->Edx = pContextRec->ctx_RegEdx;
129 pWinContextRec->Ecx = pContextRec->ctx_RegEcx;
130 pWinContextRec->Eax = pContextRec->ctx_RegEax;
131 }
132
133 if (pContextRec->ContextFlags & CONTEXT_SEGMENTS)
134 {
135 pWinContextRec->ContextFlags |= WINCONTEXT_SEGMENTS;
136 pWinContextRec->SegGs = pContextRec->ctx_SegGs;
137 // set Wn32 TEB if we run in switch FS mode
138 if (pWinTEB)
139 pWinContextRec->SegFs = pWinTEB->teb_sel;
140 else
141 pWinContextRec->SegFs = pContextRec->ctx_SegFs;
142 pWinContextRec->SegEs = pContextRec->ctx_SegEs;
143 pWinContextRec->SegDs = pContextRec->ctx_SegDs;
144 }
145
146 if (pContextRec->ContextFlags & CONTEXT_FLOATING_POINT)
147 {
148 pWinContextRec->ContextFlags |= WINCONTEXT_FLOATING_POINT;
149 //TODO: First 7 dwords the same?
150 memcpy(&pWinContextRec->FloatSave,
151 pContextRec->ctx_env, sizeof(pContextRec->ctx_env));
152 memcpy(&pWinContextRec->FloatSave.RegisterArea,
153 pContextRec->ctx_stack, sizeof(pContextRec->ctx_stack));
154 }
155
156 return TRUE;
157}
158
159/**
160 * Converts the Win32 exception handler result to the OS/2 exception handler
161 * result.
162 *
163 * Returns TRUE if the OS/2 exception handler result should be
164 * XCPT_CONTINUE_EXECUTION and FALSE otherwise.
165 */
166BOOL APIENTRY OSLibConvertExceptionResult(ULONG rc,
167 PWINCONTEXT pWinContextRec,
168 PCONTEXTRECORD pContextRec)
169{
170 if (rc != ExceptionContinueExecution)
171 {
172 dprintf(("Win32 exception handler returned %s (%d)",
173 rc == ExceptionContinueSearch ? "ExceptionContinueSearch" :
174 "???", rc));
175 return FALSE;
176 }
177
178 dprintf(("Win32 exception handler returned ExceptionContinueExecution (%d)",
179 ExceptionContinueExecution));
180
181 if (pWinContextRec->ContextFlags & WINCONTEXT_CONTROL)
182 {
183 pContextRec->ctx_RegEbp = pWinContextRec->Ebp;
184 pContextRec->ctx_RegEip = pWinContextRec->Eip;
185 pContextRec->ctx_SegCs = pWinContextRec->SegCs;
186 pContextRec->ctx_EFlags = pWinContextRec->EFlags;
187 pContextRec->ctx_RegEsp = pWinContextRec->Esp;
188 pContextRec->ctx_SegSs = pWinContextRec->SegSs;
189 }
190
191 if (pWinContextRec->ContextFlags & WINCONTEXT_INTEGER)
192 {
193 pContextRec->ctx_RegEdi = pWinContextRec->Edi;
194 pContextRec->ctx_RegEsi = pWinContextRec->Esi;
195 pContextRec->ctx_RegEbx = pWinContextRec->Ebx;
196 pContextRec->ctx_RegEdx = pWinContextRec->Edx;
197 pContextRec->ctx_RegEcx = pWinContextRec->Ecx;
198 pContextRec->ctx_RegEax = pWinContextRec->Eax;
199 }
200
201#if 0
202 // This is not a good idea
203 if (pWinContextRec->ContextFlags & WINCONTEXT_SEGMENTS)
204 {
205 pContextRec->ctx_SegGs = pWinContextRec->SegGs;
206 pContextRec->ctx_SegFs = pWinContextRec->SegFs;
207 pContextRec->ctx_SegEs = pWinContextRec->SegEs;
208 pContextRec->ctx_SegDs = pWinContextRec->SegDs;
209 }
210#endif
211
212 if (pWinContextRec->ContextFlags & WINCONTEXT_FLOATING_POINT)
213 {
214 //TODO: First 7 dwords the same?
215 memcpy(pContextRec->ctx_env, &pWinContextRec->FloatSave,
216 sizeof(pContextRec->ctx_env));
217 memcpy(pContextRec->ctx_stack, &pWinContextRec->FloatSave.RegisterArea,
218 sizeof(pContextRec->ctx_stack));
219 }
220
221 if (pContextRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
222 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n",
223 pContextRec->ctx_SegSs,
224 pContextRec->ctx_RegEsp,
225 pContextRec->ctx_EFlags));
226 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n",
227 pContextRec->ctx_SegCs,
228 pContextRec->ctx_RegEip,
229 pContextRec->ctx_RegEbp));
230
231 if (pContextRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
232 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n",
233 pContextRec->ctx_RegEax,
234 pContextRec->ctx_RegEbx,
235 pContextRec->ctx_RegEsi));
236 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n",
237 pContextRec->ctx_RegEcx,
238 pContextRec->ctx_RegEdx,
239 pContextRec->ctx_RegEdi));
240
241 if (pContextRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
242 dprintf((" DS=%04x ES=%08x"
243 " FS=%04x GS=%04x\n",
244 pContextRec->ctx_SegDs,
245 pContextRec->ctx_SegEs,
246 pContextRec->ctx_SegFs,
247 pContextRec->ctx_SegGs));
248
249 if (pContextRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
250 {
251 ULONG ulCounter; /* temporary local counter for fp stack */
252
253 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
254 pContextRec->ctx_env[0],
255 pContextRec->ctx_env[1],
256 pContextRec->ctx_env[2],
257 pContextRec->ctx_env[3]));
258
259 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
260 pContextRec->ctx_env[4],
261 pContextRec->ctx_env[5],
262 pContextRec->ctx_env[6]));
263
264 for (ulCounter = 0;
265 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
266 ulCounter ++)
267 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
268 ulCounter,
269 pContextRec->ctx_stack[0].losig,
270 pContextRec->ctx_stack[0].hisig,
271 pContextRec->ctx_stack[0].signexp));
272 }
273
274 return TRUE;
275}
276
277/**
278 * Dispatches OS/2 exception to win32 handler.
279 *
280 * Returns TRUE if the Win32 exception handler returned
281 * ExceptionContinueExecution and FALSE otherwise.
282 */
283BOOL APIENTRY OSLibDispatchExceptionWin32(PEXCEPTIONREPORTRECORD pReportRec,
284 PEXCEPTIONREGISTRATIONRECORD pRegistrationRec,
285 PCONTEXTRECORD pContextRec, PVOID p)
286{
287 WINEXCEPTION_RECORD winReportRec;
288 WINCONTEXT winContextRec;
289
290 ULONG rc;
291
292 TEB *pWinTEB = GetThreadTEB();
293
294 OSLibConvertExceptionInfo(pReportRec, pContextRec,
295 &winReportRec, &winContextRec, pWinTEB);
296
297 // It doesn't seem correct if we dispatch real exceptions to win32 apps
298 // Some just call RtlUnwind and continue as if they were processing an
299 // exception thrown by C++ code. (instead of real OS exception)
300
301 // We need to reset FS to its original (Win32) value, otherwise we'll likely
302 // fuck up the Win32 exception handlers. They could end up using the wrong
303 // exception chain if they access FS:[0] directly.
304 DWORD oldsel = SetReturnFS(pWinTEB->teb_sel);
305
306 switch(pReportRec->ExceptionNum)
307 {
308 case XCPT_FLOAT_DENORMAL_OPERAND:
309 case XCPT_FLOAT_DIVIDE_BY_ZERO:
310 case XCPT_FLOAT_INEXACT_RESULT:
311 case XCPT_FLOAT_INVALID_OPERATION:
312 case XCPT_FLOAT_OVERFLOW:
313 case XCPT_FLOAT_STACK_CHECK:
314 case XCPT_FLOAT_UNDERFLOW:
315 rc = RtlDispatchException(&winReportRec, &winContextRec);
316 break;
317
318 case XCPT_ACCESS_VIOLATION:
319 rc = RtlDispatchException(&winReportRec, &winContextRec);
320 break;
321
322 case XCPT_ILLEGAL_INSTRUCTION:
323 case XCPT_PRIVILEGED_INSTRUCTION:
324 case XCPT_INTEGER_DIVIDE_BY_ZERO:
325 case XCPT_UNABLE_TO_GROW_STACK:
326 case XCPT_GUARD_PAGE_VIOLATION:
327#ifndef DEBUG
328 case XCPT_BREAKPOINT:
329#endif
330 rc = RtlDispatchException(&winReportRec, &winContextRec);
331 break;
332
333#ifdef DEBUG
334 case XCPT_BREAKPOINT:
335#endif
336 case XCPT_INTEGER_OVERFLOW:
337 case XCPT_SINGLE_STEP:
338 case XCPT_ARRAY_BOUNDS_EXCEEDED:
339 case XCPT_DATATYPE_MISALIGNMENT:
340 case XCPT_INVALID_LOCK_SEQUENCE:
341 case XCPT_IN_PAGE_ERROR:
342 default:
343 SetFS(oldsel); //restore FS
344 return FALSE; //let's not dispatch those for now
345 }
346
347 SetFS(oldsel); //restore FS
348
349 return OSLibConvertExceptionResult(rc, &winContextRec, pContextRec);
350}
Note: See TracBrowser for help on using the repository browser.