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
RevLine 
[5905]1/* $Id: oslibexcept.cpp,v 1.7 2001-06-04 21:18:40 sandervl Exp $ */
[1224]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>
[4224]19#include <wprocess.h>
[1224]20
[21999]21#include "oslibexcept.h"
22
[4224]23#define DBG_LOCALLOG DBG_oslibexcept
[2803]24#include "dbglocal.h"
25
[21999]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)
[1224]36{
[21999]37 memset(pWinReportRec, 0, sizeof(*pWinReportRec));
38 memcpy(pWinReportRec, pReportRec, sizeof(*pReportRec));
[1224]39
[21999]40 switch (pReportRec->ExceptionNum)
41 {
42 case XCPT_FLOAT_DENORMAL_OPERAND:
43 pWinReportRec->ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND;
[4224]44 break;
[21999]45 case XCPT_FLOAT_DIVIDE_BY_ZERO:
46 pWinReportRec->ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
[4224]47 break;
[21999]48 case XCPT_FLOAT_INEXACT_RESULT:
49 pWinReportRec->ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
[4224]50 break;
[21999]51 case XCPT_FLOAT_INVALID_OPERATION:
52 pWinReportRec->ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
[4224]53 break;
[21999]54 case XCPT_FLOAT_OVERFLOW:
55 pWinReportRec->ExceptionCode = EXCEPTION_FLT_OVERFLOW;
[4224]56 break;
[21999]57 case XCPT_FLOAT_STACK_CHECK:
58 pWinReportRec->ExceptionCode = EXCEPTION_FLT_STACK_CHECK;
[4224]59 break;
[21999]60 case XCPT_FLOAT_UNDERFLOW:
61 pWinReportRec->ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
[4224]62 break;
[21999]63 case XCPT_INTEGER_DIVIDE_BY_ZERO:
64 pWinReportRec->ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
[4224]65 break;
[21999]66 case XCPT_INTEGER_OVERFLOW:
67 pWinReportRec->ExceptionCode = EXCEPTION_INT_OVERFLOW;
[4224]68 break;
[21999]69 case XCPT_PRIVILEGED_INSTRUCTION:
70 pWinReportRec->ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
[4224]71 break;
[21999]72 case XCPT_BREAKPOINT:
73 pWinReportRec->ExceptionCode = EXCEPTION_BREAKPOINT;
[4224]74 break;
[21999]75 case XCPT_SINGLE_STEP:
76 pWinReportRec->ExceptionCode = EXCEPTION_SINGLE_STEP;
[4224]77 break;
[21999]78 case XCPT_ARRAY_BOUNDS_EXCEEDED:
79 pWinReportRec->ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
[4224]80 break;
[21999]81 case XCPT_DATATYPE_MISALIGNMENT:
82 pWinReportRec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
[4224]83 break;
[21999]84 case XCPT_ILLEGAL_INSTRUCTION:
85 pWinReportRec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
[4224]86 break;
[21999]87 case XCPT_INVALID_LOCK_SEQUENCE:
88 pWinReportRec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
[4224]89 break;
[21999]90 case XCPT_GUARD_PAGE_VIOLATION:
91 pWinReportRec->ExceptionCode = EXCEPTION_GUARD_PAGE;
[4224]92 break;
[21999]93 case XCPT_UNABLE_TO_GROW_STACK:
94 pWinReportRec->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
[4224]95 break;
[21999]96 case XCPT_IN_PAGE_ERROR:
97 pWinReportRec->ExceptionCode = EXCEPTION_IN_PAGE_ERROR;
[4224]98 break;
[21999]99 case XCPT_ACCESS_VIOLATION:
100 pWinReportRec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
[4224]101 break;
[21999]102 default: // no other exceptions should be dispatched to win32 apps
[4224]103 return FALSE;
[21999]104 }
[1224]105
[21999]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
[4224]109
[21999]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 }
[4224]132
[21999]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;
[4224]149 //TODO: First 7 dwords the same?
[21999]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 }
[4224]155
[21999]156 return TRUE;
157}
[1224]158
[21999]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 {
[22004]172 dprintf(("Win32 exception handler returned %s (%d)",
173 rc == ExceptionContinueSearch ? "ExceptionContinueSearch" :
174 "???", rc));
[21999]175 return FALSE;
176 }
[1224]177
[22004]178 dprintf(("Win32 exception handler returned ExceptionContinueExecution (%d)",
179 ExceptionContinueExecution));
[5750]180
[21999]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 }
[1224]190
[21999]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
[1224]201#if 0
[21999]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 }
[1224]210#endif
211
[21999]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 }
[1224]220
[21999]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));
[1224]230
[21999]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));
[1224]240
[21999]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));
[4224]248
[21999]249 if (pContextRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
250 {
251 ULONG ulCounter; /* temporary local counter for fp stack */
[4224]252
[21999]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]));
[4224]258
[21999]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:
[1224]329#endif
[21999]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);
[1224]350}
Note: See TracBrowser for help on using the repository browser.