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

Last change on this file since 3483 was 3483, checked in by sandervl, 25 years ago

added exception stack dump code; GetLocaleInfoA fixes

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