Changeset 4224 for trunk/src/kernel32/exceptions.cpp
- Timestamp:
- Sep 8, 2000, 8:07:52 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/exceptions.cpp
r3872 r4224 1 /* $Id: exceptions.cpp,v 1.42 2000-07-20 18:06:59 sandervl Exp $ */ 1 /* $Id: exceptions.cpp,v 1.43 2000-09-08 18:07:49 sandervl Exp $ */ 2 3 /* WARNING: Compiling this module with ICC with optimizations turned on */ 4 /* currently breaks this module. To get correct code, it is not necessary */ 5 /* to turn all optimizations off, just use the -Op- flag. */ 2 6 3 7 /* … … 67 71 #include "exceptstackdump.h" 68 72 69 #define DBG_LOCALLOG 73 #define DBG_LOCALLOG DBG_exceptions 70 74 #include "dbglocal.h" 71 75 … … 80 84 void KillWin32Process(void); 81 85 86 #ifdef DEBUG 87 void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe); 88 #else 89 #define PrintWin32ExceptionChain(a) 90 #endif 82 91 83 92 /***************************************************************************** … … 142 151 dprintf(("KERNEL32: RaiseException(%08xh)\n", 143 152 dwExceptionCode)); 153 154 memset(&record, 0, sizeof(record)); 144 155 145 156 /* compose an exception record */ … … 182 193 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL) 183 194 { 195 dprintf(("KERNEL32: RaiseException calling UnhandledExceptionFilter.\n")); 196 184 197 ExceptionInfo.ExceptionRecord = &record; 185 198 ExceptionInfo.ContextRecord = &context; 186 199 187 200 rc = UnhandledExceptionFilter(&ExceptionInfo); 201 //FIXME: UnhandledExceptionFilter does NOT return the same values as 202 // other filters!! 188 203 } 189 204 … … 196 211 } 197 212 213 dprintf(("KERNEL32: RaiseException returns.\n")); 198 214 return; 199 215 } 216 217 200 218 //****************************************************************************** 201 219 //****************************************************************************** … … 212 230 pframe = (PWINEXCEPTION_FRAME)winteb->except; 213 231 232 dprintf(("KERNEL32: RtlDispatchException entered")); 233 234 PrintWin32ExceptionChain(pframe); 235 214 236 // walk the exception chain 215 237 while( (pframe != NULL) && (pframe != ((void *)0xFFFFFFFF)) ) 216 238 { 217 dispatch=0; 218 219 dprintf(("Calling exception handler %x", pframe->Handler)); 239 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pframe, pframe->Prev)); 240 if (pframe == pframe->Prev) { 241 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!")); 242 return 0; 243 } 244 245 dispatch=0; 246 220 247 /* Check frame address */ 221 248 if (((void*)pframe < winteb->stack_low) || … … 223 250 (int)pframe & 3) 224 251 { 252 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X", 253 winteb->stack_low, winteb->stack_top, pframe)); 254 225 255 pRecord->ExceptionFlags |= EH_STACK_INVALID; 226 256 break; 227 257 } 228 258 229 rc = pframe->Handler(pRecord, 259 dprintf(("KERNEL32: RtlDispatchException - calling exception handler %08X", pframe->Handler)); 260 261 rc = pframe->Handler(pRecord, 230 262 pframe, 231 263 pContext, 232 264 dispatch); 265 266 dprintf(("KERNEL32: RtlDispatchException - exception handler returned %#x", rc)); 267 PrintWin32ExceptionChain(pframe); 233 268 234 269 if (pframe == nested_frame) … … 239 274 } 240 275 241 dprintf(("exception handler returned %x", rc));242 276 243 277 switch(rc) 244 278 { 245 279 case ExceptionContinueExecution: 246 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) return rc; 280 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) { 281 dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc)); 282 return rc; 283 } 247 284 break; 248 285 case ExceptionContinueSearch: … … 256 293 } 257 294 295 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pframe, pframe->Prev)); 296 if (pframe == pframe->Prev) { 297 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!")); 298 break; 299 } 258 300 pframe = pframe->Prev; 259 301 } 302 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc)); 303 PrintWin32ExceptionChain(pframe); 260 304 return rc; 261 305 } … … 284 328 WINEXCEPTION_RECORD record, newrec; 285 329 WINCONTEXT context; 286 int rc; 287 288 dprintf(("KERNEL32: RtlUnwind %x %x\n", pEndFrame, pRecord)); 330 DWORD rc; 331 332 dprintf(("KERNEL32: RtlUnwind pEndFrame=%08X, unusedEip=%08X, pRecord=%08X, returnEax=%#x\n", pEndFrame, unusedEip, pRecord, returnEax)); 333 289 334 290 335 memset(&context, 0, sizeof(context)); … … 310 355 if(!pRecord) 311 356 { 357 memset(&record, 0, sizeof(record)); 312 358 record.ExceptionCode = STATUS_UNWIND; 313 359 record.ExceptionFlags = 0; … … 324 370 TEB *winteb = GetThreadTEB(); 325 371 frame = (PWINEXCEPTION_FRAME)winteb->except; 372 373 PrintWin32ExceptionChain(frame); 326 374 327 375 while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame)) … … 334 382 newrec.ExceptionRecord = pRecord; 335 383 newrec.NumberParameters = 0; 336 337 384 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 385 DosExit(EXIT_THREAD, 0); 338 386 } 339 387 if (((void*)frame < winteb->stack_low) || … … 345 393 newrec.ExceptionRecord = pRecord; 346 394 newrec.NumberParameters = 0; 347 348 395 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 396 DosExit(EXIT_THREAD, 0); 349 397 } 350 398 351 399 /* Call handler */ 352 dprintf(("Calling exception handler %x", frame->Handler)); 353 switch(frame->Handler(pRecord, frame, &context, &dispatch )) 400 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler)); 401 rc = frame->Handler(pRecord, frame, &context, &dispatch); 402 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc)); 403 switch (rc) 354 404 { 355 405 case ExceptionContinueSearch: … … 363 413 newrec.ExceptionRecord = pRecord; 364 414 newrec.NumberParameters = 0; 365 366 415 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 416 DosExit(EXIT_THREAD, 0); 367 417 break; 368 418 } 419 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev)); 369 420 SetExceptionChain((DWORD)frame->Prev); 370 421 frame = frame->Prev; 371 } 422 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev)); 423 } 424 425 426 /* Note: I _think_ that on Win32, RtlUnwind unwinds exception handlers up */ 427 /* and _including_ the handler in pEndFrame argument. My reasons are: */ 428 /* - MSVCRT sometimes calls RtlUnwind with the address of the very first */ 429 /* exception handler - could be just inefficient code */ 430 /* - after a call to RtlUnwind, MSVCRT in some cases tries to restore */ 431 /* the original exception handler. If RtlUnwind didn't remove it, */ 432 /* the exception chain gets looped, spelling very bad mojo! */ 433 if (frame == pEndFrame) 434 { 435 /* Just repeat what we did in the while loop above */ 436 /* Check frame address */ 437 if (pEndFrame && (frame > pEndFrame)) 438 { 439 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; 440 newrec.ExceptionFlags = EH_NONCONTINUABLE; 441 newrec.ExceptionRecord = pRecord; 442 newrec.NumberParameters = 0; 443 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 444 DosExit(EXIT_THREAD, 0); 445 } 446 if (((void*)frame < winteb->stack_low) || 447 ((void*)(frame+1) > winteb->stack_top) || 448 (int)frame & 3) 449 { 450 newrec.ExceptionCode = STATUS_BAD_STACK; 451 newrec.ExceptionFlags = EH_NONCONTINUABLE; 452 newrec.ExceptionRecord = pRecord; 453 newrec.NumberParameters = 0; 454 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 455 DosExit(EXIT_THREAD, 0); 456 } 457 458 /* Call handler */ 459 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler)); 460 rc = frame->Handler(pRecord, frame, &context, &dispatch); 461 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc)); 462 switch (rc) 463 { 464 case ExceptionContinueSearch: 465 break; 466 case ExceptionCollidedUnwind: 467 frame = dispatch; 468 break; 469 default: 470 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION; 471 newrec.ExceptionFlags = EH_NONCONTINUABLE; 472 newrec.ExceptionRecord = pRecord; 473 newrec.NumberParameters = 0; 474 dprintf(("KERNEL32: RtlUnwind terminating thread.\n")); 475 DosExit(EXIT_THREAD, 0); 476 break; 477 } 478 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev)); 479 SetExceptionChain((DWORD)frame->Prev); 480 frame = frame->Prev; 481 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev)); 482 } 483 484 dprintf(("KERNEL32: RtlUnwind returning.\n")); 485 PrintWin32ExceptionChain(frame); 372 486 return(0); 373 487 } … … 415 529 }; 416 530 417 dprintf(("KERNEL32: UnhandledExceptionFilter\n")); 418 419 if(CurrentUnhExceptionFlt && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX))) 531 dprintf(("KERNEL32: Default UnhandledExceptionFilter, CurrentErrorMode=%X", CurrentErrorMode)); 532 533 // We must not care about ErrorMode here!! The app expects that its own 534 // UnhandledExceptionFilter will be cared even if it never touched ErrorMode. 535 if(CurrentUnhExceptionFlt) // && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX))) 420 536 { 537 dprintf(("KERNEL32: Calling user UnhandledExceptionFilter")); 421 538 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo); 422 539 if(rc != WINEXCEPTION_CONTINUE_SEARCH) … … 492 609 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt; 493 610 494 dprintf(("KERNEL32: SetUnhandledExceptionFilter to % X\n",611 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n", 495 612 lpTopLevelExceptionFilter)); 496 613 … … 524 641 525 642 if(fEntry == FALSE) { 526 527 528 643 fEntry = TRUE; 644 ExitProcess(666); 645 return; 529 646 } 530 647 //Restore original OS/2 TIB selector … … 857 974 858 975 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */ 859 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n" 860 " CS:EIP=%04x:%08x EBP =%08x\n", 976 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n", 861 977 pCtxRec->ctx_SegSs, 862 978 pCtxRec->ctx_RegEsp, 863 pCtxRec->ctx_EFlags, 979 pCtxRec->ctx_EFlags)); 980 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n", 864 981 pCtxRec->ctx_SegCs, 865 982 pCtxRec->ctx_RegEip, … … 867 984 868 985 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */ 869 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n" 870 " ECX=%08x EDX=%08x EDI=%08x\n", 986 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n", 871 987 pCtxRec->ctx_RegEax, 872 988 pCtxRec->ctx_RegEbx, 873 pCtxRec->ctx_RegEsi, 989 pCtxRec->ctx_RegEsi)); 990 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n", 874 991 pCtxRec->ctx_RegEcx, 875 992 pCtxRec->ctx_RegEdx, … … 877 994 878 995 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */ 879 dprintf((" DS=%04x ES=%08x" 880 " FS=%04x GS=%04x\n", 996 dprintf((" DS=%04x ES=%08x", 881 997 pCtxRec->ctx_SegDs, 882 pCtxRec->ctx_SegEs, 998 pCtxRec->ctx_SegEs)); 999 dprintf((" FS=%04x GS=%04x\n", 883 1000 pCtxRec->ctx_SegFs, 884 1001 pCtxRec->ctx_SegGs)); … … 936 1053 PVOID p) 937 1054 { 1055 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution 1056 // of this exception handler. We better bail out ASAP or we'll likely 1057 // recurse infinitely until we run out of stack space!! 1058 if (pERepRec->fHandlerFlags & EH_NESTED_CALL) 1059 return XCPT_CONTINUE_SEARCH; 1060 938 1061 //SvL: Check if exception inside debug fprintf -> if so, clear lock so 939 1062 // next dprintf won't wait forever 940 1063 CheckLogException(); 1064 941 1065 942 1066 /* Access violation at a known location */ … … 950 1074 case XCPT_FLOAT_STACK_CHECK: 951 1075 case XCPT_FLOAT_UNDERFLOW: 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 1076 dprintfException(pERepRec, pERegRec, pCtxRec, p); 1077 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n")); 1078 if(fIsOS2Image == FALSE) //Only for real win32 apps 1079 { 1080 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE) 1081 { 1082 pCtxRec->ctx_env[0] |= 0x1F; 1083 pCtxRec->ctx_stack[0].losig = 0; 1084 pCtxRec->ctx_stack[0].hisig = 0; 1085 pCtxRec->ctx_stack[0].signexp = 0; 1086 } 1087 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n")); 1088 return (XCPT_CONTINUE_EXECUTION); 1089 } 1090 else 1091 { 1092 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n")); 1093 return (XCPT_CONTINUE_SEARCH); 1094 } 971 1095 972 1096 case XCPT_PROCESS_TERMINATE: 973 1097 case XCPT_ASYNC_PROCESS_TERMINATE: 974 975 976 1098 dprintfException(pERepRec, pERegRec, pCtxRec, p); 1099 SetExceptionChain((ULONG)-1); 1100 return (XCPT_CONTINUE_SEARCH); 977 1101 978 1102 case XCPT_ACCESS_VIOLATION: 979 { 1103 { 980 1104 Win32MemMap *map; 981 1105 BOOL fWriteAccess = FALSE; 982 1106 ULONG offset, accessflag; 983 1107 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1108 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) { 1109 goto continueFail; 1110 } 1111 switch(pERepRec->ExceptionInfo[0]) { 1112 case XCPT_READ_ACCESS: 1113 accessflag = MEMMAP_ACCESS_READ; 1114 break; 1115 case XCPT_WRITE_ACCESS: 1116 accessflag = MEMMAP_ACCESS_WRITE; 1117 fWriteAccess = TRUE; 1118 break; 1119 case XCPT_EXECUTE_ACCESS: 1120 accessflag = MEMMAP_ACCESS_EXECUTE; 1121 break; 1122 default: 1123 goto continueFail; 1124 } 1125 1126 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag); 1127 if(map == NULL) { 1128 goto continueFail; 1129 } 1130 if(map->commitPage(offset, fWriteAccess) == TRUE) 1131 return (XCPT_CONTINUE_EXECUTION); 1132 1133 //no break; 1010 1134 } 1011 1135 continueFail: … … 1014 1138 #ifdef DEBUGSTACK 1015 1139 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) { 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1140 ULONG *stackptr; 1141 APIRET rc; 1142 int i; 1143 ULONG ulOffset, ulModule, ulObject; 1144 CHAR szModule[CCHMAXPATH]; 1145 1146 stackptr = (ULONG *)pCtxRec->ctx_RegEsp; 1147 dprintf(("Stack DUMP:")); 1148 for(i=0;i<16;i++) { 1149 rc = DosQueryModFromEIP(&ulModule, 1150 &ulObject, 1027 1151 sizeof(szModule), 1028 1152 szModule, … … 1030 1154 (ULONG)*stackptr); 1031 1155 1032 1033 1034 elsedprintf(("0x%8x: 0x%8x", stackptr, *stackptr));1035 1036 1037 1156 if (rc == NO_ERROR) 1157 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset)); 1158 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr)); 1159 stackptr++; 1160 } 1161 dprintf(("Stack DUMP END")); 1038 1162 } 1039 1163 #endif … … 1052 1176 CrashAndBurn: 1053 1177 #ifdef DEBUG 1054 1055 1056 1057 1178 dprintfException(pERepRec, pERegRec, pCtxRec, p); 1179 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) { 1180 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p); 1181 } 1058 1182 #endif 1059 1060 1061 1062 1063 1064 1065 1066 elsereturn XCPT_CONTINUE_SEARCH; //pass on to OS/2 RTL or app exception handler1067 1068 1069 1070 1071 1072 1073 1183 if(fIsOS2Image == FALSE) //Only for real win32 apps 1184 { 1185 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE) 1186 { 1187 return (XCPT_CONTINUE_EXECUTION); 1188 } 1189 } 1190 else return XCPT_CONTINUE_SEARCH; //pass on to OS/2 RTL or app exception handler 1191 1192 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n")); 1193 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process; 1194 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10; 1195 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum; 1196 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip; 1197 return (XCPT_CONTINUE_EXECUTION); 1074 1198 1075 1199 //@@@PH: growing thread stacks might need special treatment 1076 1200 case XCPT_GUARD_PAGE_VIOLATION: 1077 dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue )\n"));1201 dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)")); 1078 1202 return (XCPT_CONTINUE_SEARCH); 1079 1203 … … 1081 1205 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */ 1082 1206 { 1083 1084 1207 SetExceptionChain((ULONG)-1); 1208 return (XCPT_CONTINUE_SEARCH); 1085 1209 } 1086 1210 goto CrashAndBurn; 1087 1211 1088 1212 default: //non-continuable exceptions 1089 1213 dprintfException(pERepRec, pERegRec, pCtxRec, p); 1090 1214 return (XCPT_CONTINUE_SEARCH); 1091 1215 } … … 1129 1253 dprintf(("Exception chain list:")); 1130 1254 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) { 1131 1132 1255 dprintf(("record %x", pExceptRec)); 1256 pExceptRec = pExceptRec->prev_structure; 1133 1257 } 1134 1258 SetFS(sel); 1135 1259 } 1260 1261 void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe) 1262 { 1263 dprintf(("Win32 exception chain:")); 1264 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) { 1265 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler)); 1266 if (pframe == pframe->Prev) { 1267 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe)); 1268 break; 1269 } 1270 pframe = pframe->Prev; 1271 } 1272 } 1273 1136 1274 #endif 1137 1275 … … 1173 1311 1174 1312 if(sel == 0x150b) { 1175 1176 1313 SetFS(sel); 1314 return FALSE; 1177 1315 } 1178 1316 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain(); 1179 1317 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) { 1180 1181 1318 SetFS(sel); 1319 return FALSE; 1182 1320 } 1183 1321 SetFS(sel);
Note:
See TracChangeset
for help on using the changeset viewer.