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

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

added extra check for fs corruption during dll attach

File size: 36.7 KB
Line 
1/* $Id: exceptions.cpp,v 1.37 2000-03-18 19:49:43 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();
518VOID WIN32API ExitProcess(DWORD exitcode);
519//******************************************************************************
520void KillWin32Process(void)
521{
522 static BOOL fEntry = FALSE;
523
524 if(fEntry == FALSE) {
525 fEntry = TRUE;
526 ExitProcess(666);
527 return;
528 }
529 //Restore original OS/2 TIB selector
530 RestoreOS2FS();
531
532 SetExceptionChain((ULONG)-1);
533 DosExit(EXIT_PROCESS, 666);
534}
535
536
537//******************************************************************************
538APIRET APIENTRY DosQueryModFromEIP (PULONG pulModule,
539 PULONG pulObject,
540 ULONG ulBufferLength,
541 PSZ pszBuffer,
542 PULONG pulOffset,
543 ULONG ulEIP);
544//******************************************************************************
545
546
547/*****************************************************************************
548 * Name : void static dprintfException
549 * Purpose : log the exception to win32os2.log
550 * Parameters: ...
551 * Variables :
552 * Result :
553 * Remark :
554 * Status :
555 *
556 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
557 *****************************************************************************/
558
559void static dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
560 PEXCEPTIONREGISTRATIONRECORD pERegRec,
561 PCONTEXTRECORD pCtxRec,
562 PVOID p)
563{
564 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
565 char szData[128]; /* local storage for excpt dep. information */
566 char szData2[128]; /* local storage for excpt dep. information */
567 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
568 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
569 BOOL fExcptFatal = TRUE; /* fatal exception ? */
570 BOOL fExcptPortable = TRUE; /* portability of exception */
571 PPIB pPIB; /* process information block */
572 PTIB pTIB; /* thread information block */
573 ULONG ulModule; /* module number */
574 ULONG ulObject; /* object number within the module */
575 CHAR szModule[260]; /* buffer for the module name */
576 ULONG ulOffset; /* offset within the object within the module */
577
578 szData[0] = 0; /* initialize */
579 szData2[0] = 0; /* initialize */
580 switch(pERepRec->ExceptionNum) /* take according action */
581 {
582 /* portable, non-fatal software-generated exceptions */
583 case XCPT_GUARD_PAGE_VIOLATION:
584 pszExceptionName = "Guard Page Violation";
585 sprintf(szData,
586 "R/W %08xh at %08xh.",
587 pERepRec->ExceptionInfo[0],
588 pERepRec->ExceptionInfo[1]);
589 fExcptSoftware = TRUE;
590 fExcptFatal = FALSE;
591 rc = XCPT_CONTINUE_EXECUTION;
592 break;
593
594 case XCPT_UNABLE_TO_GROW_STACK:
595 pszExceptionName = "Unable To Grow Stack";
596 fExcptSoftware = TRUE;
597 fExcptFatal = FALSE;
598 rc = XCPT_CONTINUE_EXECUTION;
599 break;
600
601 /* portable, fatal, hardware-generated exceptions */
602 case XCPT_ACCESS_VIOLATION:
603 pszExceptionName = "Access Violation";
604 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
605 pERepRec->ExceptionInfo[1]); */
606 switch (pERepRec->ExceptionInfo[0])
607 {
608 case XCPT_READ_ACCESS:
609 sprintf (szData,
610 "Read Access at address %08xh",
611 pERepRec->ExceptionInfo[1]);
612 break;
613
614 case XCPT_WRITE_ACCESS:
615 sprintf (szData,
616 "Write Access at address %08x",
617 pERepRec->ExceptionInfo[1]);
618 break;
619
620 case XCPT_SPACE_ACCESS:
621 sprintf (szData,
622 "Space Access at selector %08x",
623 pERepRec->ExceptionInfo[1]);
624 break;
625
626 case XCPT_LIMIT_ACCESS:
627 strcpy (szData,
628 "Limit Access");
629 break;
630
631 case XCPT_UNKNOWN_ACCESS:
632 strcpy (szData,
633 "Unknown Access");
634 break;
635
636 default:
637 strcpy (szData,
638 "(Invalid Access Code)");
639 break;
640 }
641 break;
642
643 case XCPT_INTEGER_DIVIDE_BY_ZERO:
644 pszExceptionName = "Division By Zero (Integer)";
645 break;
646
647 case XCPT_FLOAT_DIVIDE_BY_ZERO:
648 pszExceptionName = "Division By Zero (Float)";
649 break;
650
651 case XCPT_FLOAT_INVALID_OPERATION:
652 pszExceptionName = "Invalid Floating Point Operation";
653 break;
654
655 case XCPT_ILLEGAL_INSTRUCTION:
656 pszExceptionName = "Illegal Instruction";
657 break;
658
659 case XCPT_PRIVILEGED_INSTRUCTION:
660 pszExceptionName = "Privileged Instruction";
661 break;
662
663 case XCPT_INTEGER_OVERFLOW:
664 pszExceptionName = "Integer Overflow";
665 break;
666
667 case XCPT_FLOAT_OVERFLOW:
668 pszExceptionName = "Floating Point Overflow";
669 break;
670
671 case XCPT_FLOAT_UNDERFLOW:
672 pszExceptionName = "Floating Point Underflow";
673 break;
674
675 case XCPT_FLOAT_DENORMAL_OPERAND:
676 pszExceptionName = "Floating Point Denormal Operand";
677 break;
678
679 case XCPT_FLOAT_INEXACT_RESULT:
680 pszExceptionName = "Floating Point Inexact Result";
681 break;
682
683 case XCPT_FLOAT_STACK_CHECK:
684 pszExceptionName = "Floating Point Stack Check";
685 break;
686
687 case XCPT_DATATYPE_MISALIGNMENT:
688 pszExceptionName = "Datatype Misalignment";
689 sprintf(szData,
690 "R/W %08x alignment %08x at %08x.",
691 pERepRec->ExceptionInfo[0],
692 pERepRec->ExceptionInfo[1],
693 pERepRec->ExceptionInfo[2]);
694 break;
695
696 case XCPT_BREAKPOINT:
697 pszExceptionName = "Breakpoint (don't debug me! :)";
698 break;
699
700 case XCPT_SINGLE_STEP:
701 pszExceptionName = "Single Step (don't debug me! :)";
702 break;
703
704 /* portable, fatal, software-generated exceptions */
705 case XCPT_IN_PAGE_ERROR:
706 pszExceptionName = "In Page Error";
707 sprintf(szData,
708 "at %08x.",
709 pERepRec->ExceptionInfo[0]);
710 fExcptSoftware = TRUE;
711 break;
712
713 case XCPT_PROCESS_TERMINATE:
714 pszExceptionName = "Process Termination";
715 fExcptSoftware = TRUE;
716 break;
717
718 case XCPT_ASYNC_PROCESS_TERMINATE:
719 pszExceptionName = "Process Termination (async)";
720 sprintf(szData,
721 "terminating thread TID=%u",
722 pERepRec->ExceptionInfo[0]);
723 fExcptSoftware = TRUE;
724 break;
725
726 case XCPT_NONCONTINUABLE_EXCEPTION:
727 pszExceptionName = "Noncontinuable Exception";
728 fExcptSoftware = TRUE;
729 break;
730
731 case XCPT_INVALID_DISPOSITION:
732 pszExceptionName = "Invalid Disposition";
733 fExcptSoftware = TRUE;
734 break;
735
736 /* non-portable, fatal exceptions */
737 case XCPT_INVALID_LOCK_SEQUENCE:
738 pszExceptionName = "Invalid Lock Sequence";
739 fExcptSoftware = TRUE;
740 fExcptPortable = FALSE;
741 break;
742
743 case XCPT_ARRAY_BOUNDS_EXCEEDED:
744 pszExceptionName = "Array Bounds Exceeded";
745 fExcptSoftware = TRUE;
746 fExcptPortable = FALSE;
747 break;
748
749 /* unwind operation exceptions */
750 case XCPT_UNWIND:
751 pszExceptionName = "Unwind Exception";
752 fExcptSoftware = TRUE;
753 fExcptPortable = FALSE;
754 break;
755
756 case XCPT_BAD_STACK:
757 pszExceptionName = "Unwind Exception, Bad Stack";
758 fExcptSoftware = TRUE;
759 fExcptPortable = FALSE;
760 break;
761
762 case XCPT_INVALID_UNWIND_TARGET:
763 pszExceptionName = "Unwind Exception, Invalid Target";
764 fExcptSoftware = TRUE;
765 fExcptPortable = FALSE;
766 break;
767
768 /* fatal signal exceptions */
769 case XCPT_SIGNAL:
770 pszExceptionName = "Signal";
771 sprintf(szData,
772 "Signal Number = %08x",
773 pERepRec->ExceptionInfo[0]);
774 fExcptSoftware = TRUE;
775 fExcptPortable = FALSE;
776
777 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
778 {
779 case XCPT_SIGNAL_INTR:
780 pszExceptionName = "Signal (Interrupt)";
781 break;
782
783 case XCPT_SIGNAL_KILLPROC:
784 pszExceptionName = "Signal (Kill Process)";
785 break;
786
787 case XCPT_SIGNAL_BREAK:
788 pszExceptionName = "Signal (Break)";
789 break;
790 }
791 break;
792
793 default:
794 pszExceptionName = "(unknown exception code)";
795 sprintf(szData,
796 "Exception Code = %08x",
797 pERepRec->ExceptionNum);
798 }
799
800
801 /* now dump the information to the logfile */
802 dprintf(("---[Exception Information]------------\n"));
803 sprintf(szData2,
804 " %s (",
805 pszExceptionName);
806
807 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
808 strcat (szData2, "software generated,");
809 else
810 strcat (szData2, "hardware generated,");
811
812 if (fExcptPortable == TRUE) /* portable exception ? */
813 strcat (szData2, "portable,");
814 else
815 strcat (szData2, "non-portable,");
816
817 if (fExcptFatal == TRUE) /* fatal exception ? */
818 strcat (szData2, "fatal");
819 else
820 strcat (szData2, "non-fatal");
821
822 strcat (szData2, /* add trailing brace */
823 ")\n");
824
825
826 dprintf((szData2));
827
828 if (szData[0] != 0) /* see if there is an additional entry */
829 dprintf((" %s\n",
830 szData));
831
832 rc = DosQueryModFromEIP(&ulModule,
833 &ulObject,
834 sizeof(szModule),
835 szModule,
836 &ulOffset,
837 (ULONG)pERepRec->ExceptionAddress);
838
839 dprintf((" Exception Address = %08x ",
840 pERepRec->ExceptionAddress));
841
842 if (rc == NO_ERROR)
843 dprintf(("%s (#%u), obj #%u:%08x\n",
844 szModule,
845 ulModule,
846 ulObject,
847 ulOffset));
848 else
849 dprintf(("\n"));
850
851
852 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
853 &pPIB);
854 if (rc == NO_ERROR)
855 {
856 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
857 pTIB->tib_ordinal,
858 pTIB->tib_ptib2->tib2_ultid,
859 pTIB->tib_ptib2->tib2_ulpri));
860
861 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
862 pPIB->pib_ulpid,
863 pPIB->pib_ulppid,
864 pPIB->pib_flstatus));
865 }
866
867 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
868 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n"
869 " CS:EIP=%04x:%08x EBP =%08x\n",
870 pCtxRec->ctx_SegSs,
871 pCtxRec->ctx_RegEsp,
872 pCtxRec->ctx_EFlags,
873 pCtxRec->ctx_SegCs,
874 pCtxRec->ctx_RegEip,
875 pCtxRec->ctx_RegEbp));
876
877 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
878 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n"
879 " ECX=%08x EDX=%08x EDI=%08x\n",
880 pCtxRec->ctx_RegEax,
881 pCtxRec->ctx_RegEbx,
882 pCtxRec->ctx_RegEsi,
883 pCtxRec->ctx_RegEcx,
884 pCtxRec->ctx_RegEdx,
885 pCtxRec->ctx_RegEdi));
886
887 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
888 dprintf((" DS=%04x ES=%08x"
889 " FS=%04x GS=%04x\n",
890 pCtxRec->ctx_SegDs,
891 pCtxRec->ctx_SegEs,
892 pCtxRec->ctx_SegFs,
893 pCtxRec->ctx_SegGs));
894
895 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
896 {
897 ULONG ulCounter; /* temporary local counter for fp stack */
898
899 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
900 pCtxRec->ctx_env[0],
901 pCtxRec->ctx_env[1],
902 pCtxRec->ctx_env[2],
903 pCtxRec->ctx_env[3]));
904
905 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
906 pCtxRec->ctx_env[4],
907 pCtxRec->ctx_env[5],
908 pCtxRec->ctx_env[6]));
909
910 for (ulCounter = 0;
911 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
912 ulCounter ++)
913 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
914 ulCounter,
915 pCtxRec->ctx_stack[0].losig,
916 pCtxRec->ctx_stack[0].hisig,
917 pCtxRec->ctx_stack[0].signexp));
918 }
919
920 dprintf(("---[End Of Exception Information]-----\n"));
921}
922
923
924/*****************************************************************************
925 * Name : ERR _System OS2ExceptionHandler
926 * Purpose :
927 * Parameters: ...
928 * Variables :
929 * Result :
930 * Remark :
931 * Status :
932 *
933 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
934 *****************************************************************************/
935 /* from PPC DDK */
936#ifndef XCPT_CONTINUE_STOP
937#define XCPT_CONTINUE_STOP 0x00716668
938#endif
939
940//in misc.cpp
941void CheckLogException();
942
943ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
944 PEXCEPTIONREGISTRATIONRECORD pERegRec,
945 PCONTEXTRECORD pCtxRec,
946 PVOID p)
947{
948 /* Access violation at a known location */
949 switch(pERepRec->ExceptionNum)
950 {
951 case XCPT_FLOAT_DENORMAL_OPERAND:
952 case XCPT_FLOAT_DIVIDE_BY_ZERO:
953 case XCPT_FLOAT_INEXACT_RESULT:
954// case XCPT_FLOAT_INVALID_OPERATION:
955 case XCPT_FLOAT_OVERFLOW:
956 case XCPT_FLOAT_STACK_CHECK:
957 case XCPT_FLOAT_UNDERFLOW:
958 dprintfException(pERepRec, pERegRec, pCtxRec, p);
959 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
960 if(fIsOS2Image == FALSE) //Only for real win32 apps
961 {
962 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
963 {
964 pCtxRec->ctx_env[0] |= 0x1F;
965 pCtxRec->ctx_stack[0].losig = 0;
966 pCtxRec->ctx_stack[0].hisig = 0;
967 pCtxRec->ctx_stack[0].signexp = 0;
968 }
969 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
970 return (XCPT_CONTINUE_EXECUTION);
971 }
972 else
973 {
974 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
975 return (XCPT_CONTINUE_SEARCH);
976 }
977
978 case XCPT_PROCESS_TERMINATE:
979 case XCPT_ASYNC_PROCESS_TERMINATE:
980 dprintfException(pERepRec, pERegRec, pCtxRec, p);
981 SetExceptionChain((ULONG)-1);
982 return (XCPT_CONTINUE_SEARCH);
983
984 case XCPT_ACCESS_VIOLATION:
985 {
986 Win32MemMap *map;
987 BOOL fWriteAccess = FALSE;
988 ULONG offset, accessflag;
989
990 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
991 goto continueFail;
992 }
993 switch(pERepRec->ExceptionInfo[0]) {
994 case XCPT_READ_ACCESS:
995 accessflag = MEMMAP_ACCESS_READ;
996 break;
997 case XCPT_WRITE_ACCESS:
998 accessflag = MEMMAP_ACCESS_WRITE;
999 fWriteAccess = TRUE;
1000 break;
1001 case XCPT_EXECUTE_ACCESS:
1002 accessflag = MEMMAP_ACCESS_EXECUTE;
1003 break;
1004 default:
1005 goto continueFail;
1006 }
1007
1008 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1009 if(map == NULL) {
1010 goto continueFail;
1011 }
1012 if(map->commitPage(offset, fWriteAccess) == TRUE)
1013 return (XCPT_CONTINUE_EXECUTION);
1014
1015 //no break;
1016 }
1017continueFail:
1018
1019////#define DEBUGSTACK
1020#ifdef DEBUGSTACK
1021 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1022 ULONG *stackptr;
1023 APIRET rc;
1024 int i;
1025 ULONG ulOffset, ulModule, ulObject;
1026 CHAR szModule[CCHMAXPATH];
1027
1028 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1029 dprintf(("Stack DUMP:"));
1030 for(i=0;i<16;i++) {
1031 rc = DosQueryModFromEIP(&ulModule,
1032 &ulObject,
1033 sizeof(szModule),
1034 szModule,
1035 &ulOffset,
1036 (ULONG)*stackptr);
1037
1038 if (rc == NO_ERROR)
1039 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1040 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1041 stackptr++;
1042 }
1043 dprintf(("Stack DUMP END"));
1044 }
1045#endif
1046
1047 case XCPT_BREAKPOINT:
1048 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1049 case XCPT_DATATYPE_MISALIGNMENT:
1050 case XCPT_ILLEGAL_INSTRUCTION:
1051 case XCPT_PRIVILEGED_INSTRUCTION:
1052 case XCPT_INVALID_LOCK_SEQUENCE:
1053 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1054 case XCPT_INTEGER_OVERFLOW:
1055 case XCPT_SINGLE_STEP:
1056 case XCPT_UNABLE_TO_GROW_STACK:
1057 case XCPT_IN_PAGE_ERROR:
1058CrashAndBurn:
1059 CheckLogException();
1060 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1061 if(fIsOS2Image == FALSE) //Only for real win32 apps
1062 {
1063 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1064 {
1065 return (XCPT_CONTINUE_EXECUTION);
1066 }
1067 }
1068 else return XCPT_CONTINUE_SEARCH; //pass on to OS/2 RTL or app exception handler
1069
1070 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1071 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1072 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1073 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1074 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1075 return (XCPT_CONTINUE_EXECUTION);
1076
1077 //@@@PH: growing thread stacks might need special treatment
1078 case XCPT_GUARD_PAGE_VIOLATION:
1079 dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue)\n"));
1080 return (XCPT_CONTINUE_SEARCH);
1081
1082 case XCPT_SIGNAL:
1083 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1084 {
1085 SetExceptionChain((ULONG)-1);
1086 return (XCPT_CONTINUE_SEARCH);
1087 }
1088 goto CrashAndBurn;
1089
1090 default: //non-continuable exceptions
1091 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1092 return (XCPT_CONTINUE_SEARCH);
1093 }
1094 return (XCPT_CONTINUE_SEARCH);
1095}
1096
1097/*****************************************************************************
1098 * Name : void OS2SetExceptionHandler
1099 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1100 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1101 * Variables :
1102 * Result :
1103 * Remark :
1104 * Status :
1105 *
1106 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1107 *****************************************************************************/
1108void OS2SetExceptionHandler(void *exceptframe)
1109{
1110 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1111
1112 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1113 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1114
1115 /* disable trap popups */
1116// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1117
1118 DosSetExceptionHandler(pExceptRec);
1119 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1120 PrintExceptionChain();
1121}
1122
1123#ifdef DEBUG
1124void PrintExceptionChain()
1125{
1126 USHORT sel = RestoreOS2FS();
1127 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1128
1129 dprintf(("Exception chain list:"));
1130 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1131 dprintf(("record %x", pExceptRec));
1132 pExceptRec = pExceptRec->prev_structure;
1133 }
1134 SetFS(sel);
1135}
1136#endif
1137
1138
1139/*****************************************************************************
1140 * Name : void OS2UnsetExceptionHandler
1141 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1142 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1143 * Variables :
1144 * Result :
1145 * Remark :
1146 * Status :
1147 *
1148 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1149 *****************************************************************************/
1150void OS2UnsetExceptionHandler(void *exceptframe)
1151{
1152 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1153
1154 DosUnsetExceptionHandler(pExceptRec);
1155 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1156 PrintExceptionChain();
1157}
1158
1159void SetOS2ExceptionChain(ULONG val)
1160{
1161 USHORT sel = GetFS();
1162
1163 SetExceptionChain(val);
1164 SetFS(sel);
1165}
1166
1167int _System CheckCurFS()
1168{
1169 USHORT sel = RestoreOS2FS();
1170 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1171
1172 if(sel == 0x150b) {
1173 SetFS(sel);
1174 return FALSE;
1175 }
1176 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1177 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1178 SetFS(sel);
1179 return FALSE;
1180 }
1181 SetFS(sel);
1182 return TRUE;
1183}
1184
Note: See TracBrowser for help on using the repository browser.