source: trunk/src/kernel32/exceptions.cpp@ 1811

Last change on this file since 1811 was 1811, checked in by sandervl, 26 years ago

Rewrite of PE loader code, EB's fixes + VirtualProtect bugfix

File size: 36.6 KB
Line 
1/* $Id: exceptions.cpp,v 1.30 1999-11-22 20:35:49 sandervl Exp $ */
2
3/*
4 * Win32 Device IOCTL API functions for OS/2
5 *
6 * Ported Wine exception handling code
7 *
8 * Copyright 1998 Sander van Leeuwen (OS/2 port)
9 *
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 *
14 * (dlls\ntdll\exception.c)
15 *
16 * Copyright 1999 Turchanov Sergey
17 * Copyright 1999 Alexandre Julliard
18 *
19 * (win32\except.c)
20 *
21 * Win32 exception functions
22 *
23 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
24 *
25 * Notes:
26 * What really happens behind the scenes of those new
27 * __try{...}__except(..){....} and
28 * __try{...}__finally{...}
29 * statements is simply not documented by Microsoft. There could be different
30 * reasons for this:
31 * One reason could be that they try to hide the fact that exception
32 * handling in Win32 looks almost the same as in OS/2 2.x.
33 * Another reason could be that Microsoft does not want others to write
34 * binary compatible implementations of the Win32 API (like us).
35 *
36 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
37 * compatability may be valid reasons to keep some things undocumented.
38 * But exception handling is so basic to Win32 that it should be
39 * documented!
40 *
41 * Fixmes:
42 * -Most functions need better parameter checking.
43 * -I do not know how to handle exceptions within an exception handler.
44 * or what is done when ExceptionNestedException is returned from an
45 * exception handler
46 * -Real exceptions are not yet implemented. only the exception functions
47 * are implemented. A real implementation needs some new code in
48 * loader/signal.c. There would also be a need for showing debugging
49 * information in UnhandledExceptionFilter.
50 *
51 */
52#define INCL_MISC
53#define INCL_BASE
54#define INCL_WINBUTTONS
55#include <os2wrap.h> //Odin32 OS/2 api wrappers
56#include <stdio.h>
57#include <stdlib.h>
58#include <assert.h>
59#include <string.h>
60#include <builtin.h>
61#include "exceptions.h"
62#include "exceptutil.h"
63#include <misc.h>
64#include "mmap.h"
65#include <wprocess.h>
66#include "oslibexcept.h"
67
68//Global Process Unhandled exception filter
69static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
70static UINT CurrentErrorMode = SEM_FAILCRITICALERRORS;
71static PEXCEPTION_HANDLER StartupCodeHandler = NULL;
72
73extern "C" PWINEXCEPTION_FRAME GetExceptionRecord(ULONG offset, ULONG segment);
74
75LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo);
76void KillWin32Process(void);
77
78
79/*****************************************************************************
80 * Name : UINT SetErrorMode
81 * Purpose :
82 * Parameters: UINT fuErrorMode
83 * Variables :
84 * Result :
85 * Remark :
86 * Status :
87 *
88 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
89 *****************************************************************************/
90
91UINT WIN32API SetErrorMode(UINT fuErrorMode)
92{
93 UINT oldmode = CurrentErrorMode;
94
95 dprintf(("KERNEL32: SetErrorMode(%08xh)\n",
96 fuErrorMode));
97 CurrentErrorMode = fuErrorMode;
98
99 if(fuErrorMode & SEM_FAILCRITICALERRORS || fuErrorMode & SEM_NOOPENFILEERRORBOX)
100 DosError(FERR_DISABLEHARDERR);
101 else
102 DosError(FERR_ENABLEHARDERR);
103
104 // SEM_NOGPFAULTERRORBOX and SEM_NOALIGNMENTFAULTEXCEPT --> UnhandledExceptionFilter()
105
106 return(oldmode);
107}
108
109/*****************************************************************************
110 * Name : VOID _Pascal OS2RaiseException
111 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
112 * Parameters: ...
113 * Variables :
114 * Result :
115 * Remark :
116 * Status :
117 *
118 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
119 *****************************************************************************/
120
121void WIN32API RtlRaiseException(WINEXCEPTION_RECORD *rec, WINCONTEXT *context);
122
123VOID _Pascal OS2RaiseException(DWORD dwExceptionCode,
124 DWORD dwExceptionFlags,
125 DWORD cArguments,
126 DWORD *lpArguments,
127 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
128 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
129 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
130 DWORD es, DWORD fs, DWORD gs, DWORD ss)
131{
132 WINEXCEPTION_RECORD record;
133 WINEXCEPTION_POINTERS ExceptionInfo;
134 WINCONTEXT context;
135 int rc;
136 int i;
137
138 dprintf(("KERNEL32: RaiseException(%08xh)\n",
139 dwExceptionCode));
140
141 /* compose an exception record */
142 record.ExceptionCode = dwExceptionCode;
143 record.ExceptionFlags = dwExceptionFlags;
144 record.ExceptionRecord = NULL;
145 record.NumberParameters = cArguments;
146 record.ExceptionAddress = (LPVOID)eip;
147
148 memset(&context, 0, sizeof(context));
149 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
150 context.SegGs = gs;
151 context.SegFs = fs;
152 context.SegEs = es;
153 context.SegDs = ds;
154 context.Edi = edi;
155 context.Esi = esi;
156 context.Ebx = ebx;
157 context.Edx = edx;
158 context.Ecx = ecx;
159 context.Eax = eax;
160 context.Ebp = ebp;
161 context.Eip = eip;
162 context.SegCs = cs;
163 context.EFlags = flags;
164 context.Esp = esp;
165 context.SegSs = ss;
166
167 if(lpArguments)
168 {
169 for(i=0;
170 i<cArguments;
171 i++)
172 record.ExceptionInformation[i] = lpArguments[i];
173 }
174
175 rc = RtlDispatchException(&record, &context);
176
177 // and finally, the unhandled exception filter
178 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL)
179 {
180 ExceptionInfo.ExceptionRecord = &record;
181 ExceptionInfo.ContextRecord = &context;
182
183 rc = UnhandledExceptionFilter(&ExceptionInfo);
184 }
185
186 // terminate the process
187 if(rc != ExceptionContinueExecution ||
188 record.ExceptionFlags & EH_NONCONTINUABLE)
189 {
190 dprintf(("KERNEL32: RaiseException terminating process.\n"));
191 DosExit(EXIT_PROCESS, 0);
192 }
193
194 return;
195}
196//******************************************************************************
197//******************************************************************************
198DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
199{
200 PWINEXCEPTION_FRAME pframe, dispatch, nested_frame;
201 int rc;
202
203 // get chain of exception frames
204 rc = ExceptionContinueSearch;
205
206 nested_frame = NULL;
207 TEB *winteb = GetThreadTEB();
208 pframe = (PWINEXCEPTION_FRAME)winteb->except;
209
210 // walk the exception chain
211 while( (pframe != NULL) && (pframe != ((void *)0xFFFFFFFF)) )
212 {
213 dispatch=0;
214
215 dprintf(("Calling exception handler %x", pframe->Handler));
216 /* Check frame address */
217 if (((void*)pframe < winteb->stack_low) ||
218 ((void*)(pframe+1) > winteb->stack_top) ||
219 (int)pframe & 3)
220 {
221 pRecord->ExceptionFlags |= EH_STACK_INVALID;
222 break;
223 }
224
225 rc = pframe->Handler(pRecord,
226 pframe,
227 pContext,
228 dispatch);
229
230 if (pframe == nested_frame)
231 {
232 /* no longer nested */
233 nested_frame = NULL;
234 pRecord->ExceptionFlags &= ~EH_NESTED_CALL;
235 }
236
237 dprintf(("exception handler returned %x", rc));
238
239 switch(rc)
240 {
241 case ExceptionContinueExecution:
242 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) return rc;
243 break;
244 case ExceptionContinueSearch:
245 break;
246 case ExceptionNestedException:
247 if (nested_frame < dispatch) nested_frame = dispatch;
248 pRecord->ExceptionFlags |= EH_NESTED_CALL;
249 break;
250 default:
251 break;
252 }
253
254 pframe = pframe->Prev;
255 }
256 return rc;
257}
258/*****************************************************************************
259 * Name : int _Pascal OS2RtlUnwind
260 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
261 * Parameters: ...
262 * Variables :
263 * Result :
264 * Remark :
265 * Status :
266 *
267 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
268 *****************************************************************************/
269
270int _Pascal OS2RtlUnwind(PWINEXCEPTION_FRAME pEndFrame,
271 LPVOID unusedEip,
272 PWINEXCEPTION_RECORD pRecord,
273 DWORD returnEax,
274 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
275 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
276 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
277 DWORD es, DWORD fs, DWORD gs, DWORD ss)
278{
279 PWINEXCEPTION_FRAME frame, dispatch;
280 WINEXCEPTION_RECORD record, newrec;
281 WINCONTEXT context;
282 int rc;
283
284 dprintf(("KERNEL32: RtlUnwind %x %x\n", pEndFrame, pRecord));
285
286 memset(&context, 0, sizeof(context));
287 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
288 context.SegGs = gs;
289 context.SegFs = fs;
290 context.SegEs = es;
291 context.SegDs = ds;
292 context.Edi = edi;
293 context.Esi = esi;
294 context.Ebx = ebx;
295 context.Edx = edx;
296 context.Ecx = ecx;
297 context.Eax = returnEax;
298 context.Ebp = ebp;
299 context.Eip = eip;
300 context.SegCs = cs;
301 context.EFlags = flags;
302 context.Esp = esp;
303 context.SegSs = ss;
304
305 /* build an exception record, if we do not have one */
306 if(!pRecord)
307 {
308 record.ExceptionCode = STATUS_INVALID_DISPOSITION;
309 record.ExceptionFlags = 0;
310 record.ExceptionRecord = NULL;
311 record.ExceptionAddress = (LPVOID)eip;
312 record.NumberParameters = 0;
313 pRecord = &record;
314 }
315
316 if(pEndFrame) pRecord->ExceptionFlags |= EH_UNWINDING;
317 else pRecord->ExceptionFlags |= EH_UNWINDING | EH_EXIT_UNWIND;
318
319 /* get chain of exception frames */
320 TEB *winteb = GetThreadTEB();
321 frame = (PWINEXCEPTION_FRAME)winteb->except;
322
323 while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
324 {
325 /* Check frame address */
326 if (pEndFrame && (frame > pEndFrame))
327 {
328 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
329 newrec.ExceptionFlags = EH_NONCONTINUABLE;
330 newrec.ExceptionRecord = pRecord;
331 newrec.NumberParameters = 0;
332 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
333 DosExit(EXIT_THREAD, 0);
334 }
335 if (((void*)frame < winteb->stack_low) ||
336 ((void*)(frame+1) > winteb->stack_top) ||
337 (int)frame & 3)
338 {
339 newrec.ExceptionCode = STATUS_BAD_STACK;
340 newrec.ExceptionFlags = EH_NONCONTINUABLE;
341 newrec.ExceptionRecord = pRecord;
342 newrec.NumberParameters = 0;
343 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
344 DosExit(EXIT_THREAD, 0);
345 }
346
347 /* Call handler */
348 dprintf(("Calling exception handler %x", frame->Handler));
349 switch(frame->Handler(pRecord, frame, &context, &dispatch ))
350 {
351 case ExceptionContinueSearch:
352 break;
353 case ExceptionCollidedUnwind:
354 frame = dispatch;
355 break;
356 default:
357 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
358 newrec.ExceptionFlags = EH_NONCONTINUABLE;
359 newrec.ExceptionRecord = pRecord;
360 newrec.NumberParameters = 0;
361 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
362 DosExit(EXIT_THREAD, 0);
363 break;
364 }
365 SetExceptionChain((DWORD)frame->Prev);
366 frame = frame->Prev;
367 }
368 return(0);
369}
370
371
372/*****************************************************************************
373 * Name : LONG WIN32API UnhandledExceptionFilter
374 * Purpose :
375 * Parameters: ...
376 * Variables :
377 * Result :
378 * Remark :
379 * Status :
380 *
381 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
382 *****************************************************************************/
383
384LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo)
385{
386 char message[72];
387 DWORD rc;
388
389 // @@@PH: experimental change to have more control over exception handling
390#pragma pack(4)
391 typedef struct
392 {
393 ULONG cb; /* Size of fixed part of structure */
394 HPOINTER hIcon; /* Icon handle */
395 ULONG cButtons; /* Number of buttons */
396 ULONG flStyle; /* Icon style flags (MB_ICONQUESTION, etc...)*/
397 HWND hwndNotify; /* Reserved */
398 MB2D mb2d[4]; /* Array of button definitions */
399 } myMB2INFO;
400#pragma pack()
401
402 myMB2INFO mb2InfoExceptionBox = { 20, // size of structure
403 NULLHANDLE, // icon handle
404 4, // number of buttons
405 MB_ICONHAND, // icon style
406 NULLHANDLE, // reserved
407 { {"continue ~search", 100, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
408 {"continue ~execution", 101, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
409 {"execute ~handler", 102, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE | BS_DEFAULT},
410 {"~terminate process", 103, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE} }
411 };
412
413 dprintf(("KERNEL32: UnhandledExceptionFilter\n"));
414
415 if(CurrentUnhExceptionFlt && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)))
416 {
417 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo);
418 if(rc != WINEXCEPTION_CONTINUE_SEARCH)
419 return rc;
420 }
421
422 sprintf(message,
423 "Unhandled exception 0x%08lx at address 0x%08lx.",
424 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
425 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
426/*
427 rc = WinMessageBox2(HWND_DESKTOP,
428 HWND_DESKTOP,
429 message,
430 "Oh, nooo!",
431 0,
432 (PMB2INFO)&mb2InfoExceptionBox);
433 switch (rc)
434 {
435 case 100:
436 return WINEXCEPTION_CONTINUE_SEARCH;
437
438 case 101:
439 return WINEXCEPTION_CONTINUE_EXECUTION;
440
441 case 102:
442 return WINEXCEPTION_EXECUTE_HANDLER;
443
444 case 103:
445 KillWin32Process();
446 // fall-through
447
448 default:
449 return WINEXCEPTION_EXECUTE_HANDLER;
450 }
451*/
452 rc = WinMessageBox(HWND_DESKTOP,
453 HWND_DESKTOP,
454 message,
455 "Oh, nooo!",
456 0,
457 MB_ABORTRETRYIGNORE | MB_ERROR);
458 switch (rc)
459 {
460 case MBID_IGNORE:
461 return WINEXCEPTION_CONTINUE_EXECUTION;
462
463 case MBID_ABORT:
464 KillWin32Process();
465 // fall-through
466
467 case MBID_RETRY:
468 default:
469 return WINEXCEPTION_EXECUTE_HANDLER;
470 }
471}
472
473
474/*****************************************************************************
475 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
476 * Purpose :
477 * Parameters: ...
478 * Variables :
479 * Result :
480 * Remark :
481 * Status :
482 *
483 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
484 *****************************************************************************/
485
486LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
487{
488 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
489
490 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %X\n",
491 lpTopLevelExceptionFilter));
492
493 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
494
495 return(old);
496}
497
498
499/*****************************************************************************
500 * Name : KillWin32Process
501 * Purpose :
502 * Parameters: ...
503 * Variables :
504 * Result :
505 * Remark :
506 * Status :
507 *
508 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
509 *****************************************************************************/
510
511
512//******************************************************************************
513extern "C" ULONG getEAX();
514extern "C" ULONG getEBX();
515//******************************************************************************
516void KillWin32Process(void)
517{
518 char excptmsg[64];
519 ULONG excptaddr, excptnr;
520
521 excptnr = getEAX();
522 excptaddr = getEBX();
523
524 //Restore original OS/2 TIB selector
525 RestoreOS2FS();
526
527 SetExceptionChain((ULONG)-1);
528 DosExit(EXIT_PROCESS, 666);
529}
530
531
532//******************************************************************************
533APIRET APIENTRY DosQueryModFromEIP (PULONG pulModule,
534 PULONG pulObject,
535 ULONG ulBufferLength,
536 PSZ pszBuffer,
537 PULONG pulOffset,
538 ULONG ulEIP);
539//******************************************************************************
540
541
542/*****************************************************************************
543 * Name : void static dprintfException
544 * Purpose : log the exception to win32os2.log
545 * Parameters: ...
546 * Variables :
547 * Result :
548 * Remark :
549 * Status :
550 *
551 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
552 *****************************************************************************/
553
554void static dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
555 PEXCEPTIONREGISTRATIONRECORD pERegRec,
556 PCONTEXTRECORD pCtxRec,
557 PVOID p)
558{
559 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
560 char szData[128]; /* local storage for excpt dep. information */
561 char szData2[128]; /* local storage for excpt dep. information */
562 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
563 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
564 BOOL fExcptFatal = TRUE; /* fatal exception ? */
565 BOOL fExcptPortable = TRUE; /* portability of exception */
566 PPIB pPIB; /* process information block */
567 PTIB pTIB; /* thread information block */
568 ULONG ulModule; /* module number */
569 ULONG ulObject; /* object number within the module */
570 CHAR szModule[260]; /* buffer for the module name */
571 ULONG ulOffset; /* offset within the object within the module */
572
573 szData[0] = 0; /* initialize */
574 szData2[0] = 0; /* initialize */
575 switch(pERepRec->ExceptionNum) /* take according action */
576 {
577 /* portable, non-fatal software-generated exceptions */
578 case XCPT_GUARD_PAGE_VIOLATION:
579 pszExceptionName = "Guard Page Violation";
580 sprintf(szData,
581 "R/W %08xh at %08xh.",
582 pERepRec->ExceptionInfo[0],
583 pERepRec->ExceptionInfo[1]);
584 fExcptSoftware = TRUE;
585 fExcptFatal = FALSE;
586 rc = XCPT_CONTINUE_EXECUTION;
587 break;
588
589 case XCPT_UNABLE_TO_GROW_STACK:
590 pszExceptionName = "Unable To Grow Stack";
591 fExcptSoftware = TRUE;
592 fExcptFatal = FALSE;
593 rc = XCPT_CONTINUE_EXECUTION;
594 break;
595
596 /* portable, fatal, hardware-generated exceptions */
597 case XCPT_ACCESS_VIOLATION:
598 pszExceptionName = "Access Violation";
599 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
600 pERepRec->ExceptionInfo[1]); */
601 switch (pERepRec->ExceptionInfo[0])
602 {
603 case XCPT_READ_ACCESS:
604 sprintf (szData,
605 "Read Access at address %08xh",
606 pERepRec->ExceptionInfo[1]);
607 break;
608
609 case XCPT_WRITE_ACCESS:
610 sprintf (szData,
611 "Write Access at address %08x",
612 pERepRec->ExceptionInfo[1]);
613 break;
614
615 case XCPT_SPACE_ACCESS:
616 sprintf (szData,
617 "Space Access at selector %08x",
618 pERepRec->ExceptionInfo[1]);
619 break;
620
621 case XCPT_LIMIT_ACCESS:
622 strcpy (szData,
623 "Limit Access");
624 break;
625
626 case XCPT_UNKNOWN_ACCESS:
627 strcpy (szData,
628 "Unknown Access");
629 break;
630
631 default:
632 strcpy (szData,
633 "(Invalid Access Code)");
634 break;
635 }
636 break;
637
638 case XCPT_INTEGER_DIVIDE_BY_ZERO:
639 pszExceptionName = "Division By Zero (Integer)";
640 break;
641
642 case XCPT_FLOAT_DIVIDE_BY_ZERO:
643 pszExceptionName = "Division By Zero (Float)";
644 break;
645
646 case XCPT_FLOAT_INVALID_OPERATION:
647 pszExceptionName = "Invalid Floating Point Operation";
648 break;
649
650 case XCPT_ILLEGAL_INSTRUCTION:
651 pszExceptionName = "Illegal Instruction";
652 break;
653
654 case XCPT_PRIVILEGED_INSTRUCTION:
655 pszExceptionName = "Privileged Instruction";
656 break;
657
658 case XCPT_INTEGER_OVERFLOW:
659 pszExceptionName = "Integer Overflow";
660 break;
661
662 case XCPT_FLOAT_OVERFLOW:
663 pszExceptionName = "Floating Point Overflow";
664 break;
665
666 case XCPT_FLOAT_UNDERFLOW:
667 pszExceptionName = "Floating Point Underflow";
668 break;
669
670 case XCPT_FLOAT_DENORMAL_OPERAND:
671 pszExceptionName = "Floating Point Denormal Operand";
672 break;
673
674 case XCPT_FLOAT_INEXACT_RESULT:
675 pszExceptionName = "Floating Point Inexact Result";
676 break;
677
678 case XCPT_FLOAT_STACK_CHECK:
679 pszExceptionName = "Floating Point Stack Check";
680 break;
681
682 case XCPT_DATATYPE_MISALIGNMENT:
683 pszExceptionName = "Datatype Misalignment";
684 sprintf(szData,
685 "R/W %08x alignment %08x at %08x.",
686 pERepRec->ExceptionInfo[0],
687 pERepRec->ExceptionInfo[1],
688 pERepRec->ExceptionInfo[2]);
689 break;
690
691 case XCPT_BREAKPOINT:
692 pszExceptionName = "Breakpoint (don't debug me! :)";
693 break;
694
695 case XCPT_SINGLE_STEP:
696 pszExceptionName = "Single Step (don't debug me! :)";
697 break;
698
699 /* portable, fatal, software-generated exceptions */
700 case XCPT_IN_PAGE_ERROR:
701 pszExceptionName = "In Page Error";
702 sprintf(szData,
703 "at %08x.",
704 pERepRec->ExceptionInfo[0]);
705 fExcptSoftware = TRUE;
706 break;
707
708 case XCPT_PROCESS_TERMINATE:
709 pszExceptionName = "Process Termination";
710 fExcptSoftware = TRUE;
711 break;
712
713 case XCPT_ASYNC_PROCESS_TERMINATE:
714 pszExceptionName = "Process Termination (async)";
715 sprintf(szData,
716 "terminating thread TID=%u",
717 pERepRec->ExceptionInfo[0]);
718 fExcptSoftware = TRUE;
719 break;
720
721 case XCPT_NONCONTINUABLE_EXCEPTION:
722 pszExceptionName = "Noncontinuable Exception";
723 fExcptSoftware = TRUE;
724 break;
725
726 case XCPT_INVALID_DISPOSITION:
727 pszExceptionName = "Invalid Disposition";
728 fExcptSoftware = TRUE;
729 break;
730
731 /* non-portable, fatal exceptions */
732 case XCPT_INVALID_LOCK_SEQUENCE:
733 pszExceptionName = "Invalid Lock Sequence";
734 fExcptSoftware = TRUE;
735 fExcptPortable = FALSE;
736 break;
737
738 case XCPT_ARRAY_BOUNDS_EXCEEDED:
739 pszExceptionName = "Array Bounds Exceeded";
740 fExcptSoftware = TRUE;
741 fExcptPortable = FALSE;
742 break;
743
744 /* unwind operation exceptions */
745 case XCPT_UNWIND:
746 pszExceptionName = "Unwind Exception";
747 fExcptSoftware = TRUE;
748 fExcptPortable = FALSE;
749 break;
750
751 case XCPT_BAD_STACK:
752 pszExceptionName = "Unwind Exception, Bad Stack";
753 fExcptSoftware = TRUE;
754 fExcptPortable = FALSE;
755 break;
756
757 case XCPT_INVALID_UNWIND_TARGET:
758 pszExceptionName = "Unwind Exception, Invalid Target";
759 fExcptSoftware = TRUE;
760 fExcptPortable = FALSE;
761 break;
762
763 /* fatal signal exceptions */
764 case XCPT_SIGNAL:
765 pszExceptionName = "Signal";
766 sprintf(szData,
767 "Signal Number = %08x",
768 pERepRec->ExceptionInfo[0]);
769 fExcptSoftware = TRUE;
770 fExcptPortable = FALSE;
771
772 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
773 {
774 case XCPT_SIGNAL_INTR:
775 pszExceptionName = "Signal (Interrupt)";
776 break;
777
778 case XCPT_SIGNAL_KILLPROC:
779 pszExceptionName = "Signal (Kill Process)";
780 break;
781
782 case XCPT_SIGNAL_BREAK:
783 pszExceptionName = "Signal (Break)";
784 break;
785 }
786 break;
787
788 default:
789 pszExceptionName = "(unknown exception code)";
790 sprintf(szData,
791 "Exception Code = %08x",
792 pERepRec->ExceptionNum);
793 }
794
795
796 /* now dump the information to the logfile */
797 dprintf(("---[Exception Information]------------\n"));
798 sprintf(szData2,
799 " %s (",
800 pszExceptionName);
801
802 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
803 strcat (szData2, "software generated,");
804 else
805 strcat (szData2, "hardware generated,");
806
807 if (fExcptPortable == TRUE) /* portable exception ? */
808 strcat (szData2, "portable,");
809 else
810 strcat (szData2, "non-portable,");
811
812 if (fExcptFatal == TRUE) /* fatal exception ? */
813 strcat (szData2, "fatal");
814 else
815 strcat (szData2, "non-fatal");
816
817 strcat (szData2, /* add trailing brace */
818 ")\n");
819
820
821 dprintf((szData2));
822
823 if (szData[0] != 0) /* see if there is an additional entry */
824 dprintf((" %s\n",
825 szData));
826
827 rc = DosQueryModFromEIP(&ulModule,
828 &ulObject,
829 sizeof(szModule),
830 szModule,
831 &ulOffset,
832 (ULONG)pERepRec->ExceptionAddress);
833
834 dprintf((" Exception Address = %08x ",
835 pERepRec->ExceptionAddress));
836
837 if (rc == NO_ERROR)
838 dprintf(("%s (#%u), obj #%u:%08x\n",
839 szModule,
840 ulModule,
841 ulObject,
842 ulOffset));
843 else
844 dprintf(("\n"));
845
846
847 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
848 &pPIB);
849 if (rc == NO_ERROR)
850 {
851 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
852 pTIB->tib_ordinal,
853 pTIB->tib_ptib2->tib2_ultid,
854 pTIB->tib_ptib2->tib2_ulpri));
855
856 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
857 pPIB->pib_ulpid,
858 pPIB->pib_ulppid,
859 pPIB->pib_flstatus));
860 }
861
862 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
863 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n"
864 " CS:EIP=%04x:%08x EBP =%08x\n",
865 pCtxRec->ctx_SegSs,
866 pCtxRec->ctx_RegEsp,
867 pCtxRec->ctx_EFlags,
868 pCtxRec->ctx_SegCs,
869 pCtxRec->ctx_RegEip,
870 pCtxRec->ctx_RegEbp));
871
872 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
873 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n"
874 " ECX=%08x EDX=%08x EDI=%08x\n",
875 pCtxRec->ctx_RegEax,
876 pCtxRec->ctx_RegEbx,
877 pCtxRec->ctx_RegEsi,
878 pCtxRec->ctx_RegEcx,
879 pCtxRec->ctx_RegEdx,
880 pCtxRec->ctx_RegEdi));
881
882 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
883 dprintf((" DS=%04x ES=%08x"
884 " FS=%04x GS=%04x\n",
885 pCtxRec->ctx_SegDs,
886 pCtxRec->ctx_SegEs,
887 pCtxRec->ctx_SegFs,
888 pCtxRec->ctx_SegGs));
889
890 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
891 {
892 ULONG ulCounter; /* temporary local counter for fp stack */
893
894 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
895 pCtxRec->ctx_env[0],
896 pCtxRec->ctx_env[1],
897 pCtxRec->ctx_env[2],
898 pCtxRec->ctx_env[3]));
899
900 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
901 pCtxRec->ctx_env[4],
902 pCtxRec->ctx_env[5],
903 pCtxRec->ctx_env[6]));
904
905 for (ulCounter = 0;
906 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
907 ulCounter ++)
908 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
909 ulCounter,
910 pCtxRec->ctx_stack[0].losig,
911 pCtxRec->ctx_stack[0].hisig,
912 pCtxRec->ctx_stack[0].signexp));
913 }
914
915 dprintf(("---[End Of Exception Information]-----\n"));
916}
917
918
919/*****************************************************************************
920 * Name : ERR _System OS2ExceptionHandler
921 * Purpose :
922 * Parameters: ...
923 * Variables :
924 * Result :
925 * Remark :
926 * Status :
927 *
928 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
929 *****************************************************************************/
930 /* from PPC DDK */
931#ifndef XCPT_CONTINUE_STOP
932#define XCPT_CONTINUE_STOP 0x00716668
933#endif
934
935ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
936 PEXCEPTIONREGISTRATIONRECORD pERegRec,
937 PCONTEXTRECORD pCtxRec,
938 PVOID p)
939{
940 /* Access violation at a known location */
941 switch(pERepRec->ExceptionNum)
942 {
943 case XCPT_FLOAT_DENORMAL_OPERAND:
944 case XCPT_FLOAT_DIVIDE_BY_ZERO:
945 case XCPT_FLOAT_INEXACT_RESULT:
946// case XCPT_FLOAT_INVALID_OPERATION:
947 case XCPT_FLOAT_OVERFLOW:
948 case XCPT_FLOAT_STACK_CHECK:
949 case XCPT_FLOAT_UNDERFLOW:
950 dprintfException(pERepRec, pERegRec, pCtxRec, p);
951 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
952 if(fIsOS2Image == FALSE) //Only for real win32 apps
953 {
954 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
955 {
956 pCtxRec->ctx_env[0] |= 0x1F;
957 pCtxRec->ctx_stack[0].losig = 0;
958 pCtxRec->ctx_stack[0].hisig = 0;
959 pCtxRec->ctx_stack[0].signexp = 0;
960 }
961 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
962 return (XCPT_CONTINUE_EXECUTION);
963 }
964 else
965 {
966 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
967 return (XCPT_CONTINUE_SEARCH);
968 }
969
970 case XCPT_PROCESS_TERMINATE:
971 case XCPT_ASYNC_PROCESS_TERMINATE:
972 dprintfException(pERepRec, pERegRec, pCtxRec, p);
973 SetExceptionChain((ULONG)-1);
974 return (XCPT_CONTINUE_SEARCH);
975
976 case XCPT_ACCESS_VIOLATION:
977 {
978 Win32MemMap *map;
979 BOOL fWriteAccess = FALSE;
980 ULONG offset, accessflag;
981
982 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
983 goto continueFail;
984 }
985 switch(pERepRec->ExceptionInfo[0]) {
986 case XCPT_READ_ACCESS:
987 accessflag = MEMMAP_ACCESS_READ;
988 break;
989 case XCPT_WRITE_ACCESS:
990 accessflag = MEMMAP_ACCESS_WRITE;
991 fWriteAccess = TRUE;
992 break;
993 case XCPT_EXECUTE_ACCESS:
994 accessflag = MEMMAP_ACCESS_EXECUTE;
995 break;
996 default:
997 goto continueFail;
998 }
999
1000 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1001 if(map == NULL) {
1002 goto continueFail;
1003 }
1004 if(map->commitPage(offset, fWriteAccess) == TRUE)
1005 return (XCPT_CONTINUE_EXECUTION);
1006
1007 //no break;
1008 }
1009continueFail:
1010
1011 case XCPT_BREAKPOINT:
1012 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1013 case XCPT_DATATYPE_MISALIGNMENT:
1014 case XCPT_ILLEGAL_INSTRUCTION:
1015 case XCPT_PRIVILEGED_INSTRUCTION:
1016 case XCPT_INVALID_LOCK_SEQUENCE:
1017 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1018 case XCPT_INTEGER_OVERFLOW:
1019 case XCPT_SINGLE_STEP:
1020 case XCPT_UNABLE_TO_GROW_STACK:
1021 case XCPT_IN_PAGE_ERROR:
1022CrashAndBurn:
1023 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1024 if(fIsOS2Image == FALSE) //Only for real win32 apps
1025 {
1026 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1027 {
1028 return (XCPT_CONTINUE_EXECUTION);
1029 }
1030 }
1031 else return XCPT_CONTINUE_SEARCH; //pass on to OS/2 RTL or app exception handler
1032
1033 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1034 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1035 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1036 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1037 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1038 return (XCPT_CONTINUE_EXECUTION);
1039
1040 //@@@PH: growing thread stacks might need special treatment
1041 case XCPT_GUARD_PAGE_VIOLATION:
1042 dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue)\n"));
1043 return (XCPT_CONTINUE_SEARCH);
1044
1045 case XCPT_SIGNAL:
1046 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1047 {
1048 SetExceptionChain((ULONG)-1);
1049 return (XCPT_CONTINUE_SEARCH);
1050 }
1051 goto CrashAndBurn;
1052
1053 default: //non-continuable exceptions
1054 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1055 return (XCPT_CONTINUE_SEARCH);
1056 }
1057 return (XCPT_CONTINUE_SEARCH);
1058}
1059
1060/*****************************************************************************
1061 * Name : void OS2SetExceptionHandler
1062 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1063 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1064 * Variables :
1065 * Result :
1066 * Remark :
1067 * Status :
1068 *
1069 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1070 *****************************************************************************/
1071void OS2SetExceptionHandler(void *exceptframe)
1072{
1073 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1074
1075 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)-1;
1076 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1077
1078 /* disable trap popups */
1079// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1080
1081 DosSetExceptionHandler(pExceptRec);
1082 dprintf(("OS2SetExceptionHandler: exception chain %x (old %x)", pExceptRec, pExceptRec->prev_structure));
1083}
1084
1085/*****************************************************************************
1086 * Name : void OS2UnsetExceptionHandler
1087 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1088 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1089 * Variables :
1090 * Result :
1091 * Remark :
1092 * Status :
1093 *
1094 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1095 *****************************************************************************/
1096void OS2UnsetExceptionHandler(void *exceptframe)
1097{
1098 DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)exceptframe);
1099}
1100
1101void SetOS2ExceptionChain(ULONG val)
1102{
1103 USHORT sel = GetFS();
1104
1105 SetExceptionChain(val);
1106 SetFS(sel);
1107}
1108
1109/*****************************************************************************
1110 * Name : void ReplaceExceptionHandler
1111 * Purpose :
1112 * Parameters: ...
1113 * Variables :
1114 * Result :
1115 * Remark :
1116 * Status :
1117 *
1118 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
1119 *****************************************************************************/
1120
1121//******************************************************************************
1122//SvL: Replace original startup code exception handler
1123extern BOOL fExeStarted;
1124//******************************************************************************
1125void ReplaceExceptionHandler()
1126{
1127 static BOOL fRegistered = FALSE;
1128 PWINEXCEPTION_FRAME orgframe;
1129 APIRET rc;
1130 ULONGULONG_W timerval;
1131
1132 DisableFPUExceptions();
1133
1134 if(fExeStarted == FALSE)
1135 return;
1136
1137 orgframe = (PWINEXCEPTION_FRAME)QueryExceptionChain();
1138 if((int)orgframe == 0 ||
1139 (int)orgframe == -1)
1140 return;
1141
1142 dprintf(("KERNEL32: ReplaceExceptionHandler\n"));
1143
1144 StartupCodeHandler = orgframe->Handler;
1145 orgframe->Handler = (PEXCEPTION_HANDLER)OS2ExceptionHandler;
1146 orgframe->Prev = (_WINEXCEPTION_FRAME *)0;
1147 SetExceptionChain((ULONG)-1);
1148
1149#if 0
1150 if(fRegistered == FALSE)
1151 {
1152#endif
1153
1154 dprintf(("KERNEL32: ReplaceExceptionHandler: New exception frame at %X\n",
1155 orgframe));
1156 rc = DosSetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)orgframe);
1157 fRegistered = TRUE;
1158
1159#if 0
1160 }
1161 else
1162 {
1163 while(orgframe && orgframe->Handler != (PEXCEPTION_HANDLER)OS2ExceptionHandler)
1164 {
1165 orgframe = orgframe->Prev;
1166 }
1167
1168 dprintf(("KERNEL32: ReplaceExceptionHandler: Restore old exception frame %X\n",
1169 orgframe));
1170 if(orgframe)
1171 {
1172 orgframe->Prev = (_WINEXCEPTION_FRAME *)0;
1173 SetExceptionChain((ULONG)orgframe);
1174 }
1175 }
1176#endif
1177}
1178
Note: See TracBrowser for help on using the repository browser.