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

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

Added new logging feature

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